Skip to content

Export a task node as a Claude Code skill

MCP onlyIntermediate~10 min

A Hadron task node carries an actionable procedure — instructions an AI agent can follow to do real work. You can publish any task node as a Claude Code skill: a SKILL.md file that Claude Code auto-loads and triggers from a plain-English request.

Source-of-truth note: the node is canonical; the exported SKILL.md is a generated artifact. To change a skill's behavior, edit the node and re-export — never hand-edit the file. A re-export overwrites it.

How it works

Hadron task node  ──export──▶  ~/.claude/skills/<name>/SKILL.md  ──▶  Claude Code auto-triggers it
  (source of truth)              (generated; do not edit)

The export reads the node, composes a SKILL.md whose frontmatter comes from the node's exports declaration and whose body is the node's content copied verbatim, and writes it into a Claude Code skills directory. It is a one-way publishing pipeline.

You can run it two ways:

  • Ask an agent. If Claude Code has the hadron-export-task-as-claude-skill skill installed, just say "export <urn> as a skill." That skill is itself published from the canonical node hrn:node:hadronmemory.com:hadron-mcp:export-task-as-claude-skill.
  • By hand. Follow the procedure below — it needs only hadron_get_node (or the hadron CLI) plus a text editor.

Installing everything at once

To install every skill your memories publish, and keep them current, you don't need this page's procedure: hadron skill export does it in one command. See Install and update your Hadron skills. This page is about publishing a node as a skill, which is the declaration that command reads.

Prerequisites

The source node must satisfy all four, or the export should stop:

  1. isRunnable: true — the skill surface is built from runnable nodes. nodeType: task is the convention and reads clearly, but isRunnable is the gate.
  2. properties.exports.claudeSkill.name — kebab-case, 64 characters or fewer. Becomes the skill name and its directory name (~/.claude/skills/<name>/). The name is stored, not derived — there is no prefix option and no org prefix field, so whatever prefix you want is part of the name you write.
  3. properties.exports.claudeSkill.description — a trigger-shaped description ("Use when… Handles the gotchas…"), 1024 characters or fewer. Becomes the SKILL.md description that drives auto-triggering. Claude Code truncates a longer one in its listing, so trigger phrases past the cut never fire.
  4. properties.exports.claudeSkill.enable: true — the opt-in. See below; this is the one people miss.

If any are missing, stop and report — don't invent values. The strictness is deliberate: it keeps nodes that weren't designed as skills from being published by accident.

enable defaults to OFF, and a declaration alone ships nothing

A memory holds many runnable nodes that were never meant to be skills, so publishing is an explicit opt-in: enable must be true, and it defaults to false when absent.

That matters most if you are following an older version of this page. The retired top-level properties.skill and properties.claudeSkill are still read as aliases for the claudeSkill host, so nothing has to be migrated to keep working — but they go through the same parse, so a node carrying only {name, description} is declared and not enabled. It lints, it reads as declared, and it publishes nothing.

If a skill you expected has gone quiet, this is the first thing to check. hadron skill lint reports a declaration whether or not it is enabled, deliberately — a broken name is worth knowing about before somebody turns it on.

You also need:

Prepare the node

Declare the export on the runnable node — via hadron_create_node's properties, the portal, or Git-sync (see Adding nodes to a memory). properties.exports is keyed by skill host, so one node can carry a declaration per host:

{
  "exports": {
    "claudeSkill": {
      "name": "mm-briefing",
      "description": "Generate the morning briefing — open PRs awaiting review plus recent tasks. Use when the user asks for 'my briefing', 'what's on my plate', or 'catch me up'. Handles the gotchas — only open PRs, identity resolves from the authenticated user.",
      "enable": true
    }
  }
}

If a node already carries a retired top-level skill or claudeSkill key, exports.claudeSkill wins — so you can add the new shape beside the old one and the node behaves as migrated.

Keep the node content as the skill body only — no frontmatter. The frontmatter is composed from properties at export time.

Procedure (by hand)

hadron skill export won't update a file written this way on its own

A SKILL.md written by this procedure into your user skills folder (~/.claude/skills) has no node id in its header, so hadron skill export won't update it on its own: it reports the file as skipped and leaves it, until you take it over with --force. A copy in a project folder (<repo-root>/.claude/skills) is outside what the command manages at all: it stays at the version you wrote until you update or remove it by hand. If you'll want the command to manage the skill, use the command from the start. To migrate user-folder files you already wrote by hand, see Skills you exported by hand earlier.

Step 1 — Read the source node

With the MCP tool:

hadron_get_node hrn:node:<org>:<memory>:<loc>

or with the CLI:

hadron node get hrn:node:<org>:<memory>:<loc>

Step 2 — Validate

Confirm the four prerequisites above — including enable: true, which is the one most often missing. On any failure, stop and report which one it is.

Step 3 — Choose the output path

Resolve <name> from properties.exports.claudeSkill.name, then pick a skills root:

Target Path Use when
User-global (default) ~/.claude/skills/<name>/SKILL.md You want the skill in every project; it shouldn't ship in a repo.
Project <repo-root>/.claude/skills/<name>/SKILL.md You want it version-controlled with the codebase and shared with the team.

Create the parent directory if it doesn't exist.

Step 4 — Compose the SKILL.md

---
name: <properties.exports.claudeSkill.name>
description: <properties.exports.claudeSkill.description>
---

<!-- Generated from <source URN> -->
<!-- Edit the source node and re-export; do not edit this file directly. -->

<the node's `content` body, verbatim>

Copy the node body exactly — don't reflow, summarize, or add headings. The provenance comment makes the source-of-truth contract visible in the file.

Step 5 — Write the file

Write to the resolved path, overwriting any existing file. A re-export is meant to replace the old skill, because the node is the source of truth.

Step 6 — Restart Claude Code

Claude Code loads skills at session start. Quit and relaunch (claude) so the new or updated skill is picked up — a running session won't see it.

Verify

In a fresh Claude Code session, trigger the skill with one of the phrasings from its description. It should fire and run the node's procedure. You can also confirm the file landed:

cat ~/.claude/skills/<name>/SKILL.md # or .claude/skills/<name>/SKILL.md for project-specific skills

Gotchas

  • The node is the source of truth, not the SKILL.md. To change behavior, edit the node and re-export. The provenance comment in the file says so.
  • One-way pipeline. Never copy edits from the SKILL.md back into the node.
  • Body is verbatim; frontmatter is composed. The node content is the skill body; the --- frontmatter is built from properties.exports.<host>. Don't put frontmatter in the node body.
  • Names are case-sensitive. Use properties.exports.claudeSkill.name exactly.
  • A declaration is not a publication. enable defaults to off. This is the single most common reason an exported skill never appears.
  • The name's prefix is not checked. With no prefix source there is nothing to check it against, so a typo like hadon-foo lints clean. Read the name yourself.
  • Skills load at session start. Write the file, then restart Claude Code.
  • A missing declaration stops the export. That's a feature, not a bug — it prevents accidental publication.