Skip to main content

Authoring Claude Extensions

Plugin: tsh-core
Invoke: /tsh-core:authoring-claude-extensions (also loaded automatically when a request matches its description)
Used by: managing-claude-context (hands skill, subagent, hook and plugin work to it)

Two jobs, in order: decide which primitive the need calls for, then build that primitive correctly. The first job is where the expensive mistakes happen: a correctly written extension in the wrong primitive still fails, and it fails invisibly, because the file looks right in review.

The skill covers skills, subagents, hooks and plugins. If the answer is a memory file (CLAUDE.md, a .claude/rules/ file or a decision record), it stops and hands off to managing-claude-context, which owns the memory layer. Writing an MCP server, agent teams, code intelligence and artifacts are not covered; bundling an existing MCP server in a plugin is a one-line .mcp.json at the plugin root.

Key Areas​

AreaCoverage
Choosing the primitiveRoutes on what just happened to you rather than on the artifact you have in mind: guidance needed while creating a file is a skill, guidance for editing existing files is a path-scoped rule, a procedure pasted into chat for the third time is a skill, a side task that floods the conversation is a subagent, something that must happen every time is a hook, a second repository needing the setup is a plugin
Timing over subject matterA path-scoped rule fires when Claude reads a matching file, not when it writes one, so creation-time guidance can never arrive through a rule. The symptom: the convention is honoured on edits and ignored on creation
SkillsFrontmatter, a description phrased the way a person would ask (the only thing routing sees), disable-model-invocation and user-invocable, progressive disclosure above about 150 lines, references of at most 300 lines each with a "Load when" column
SubagentsThe frontmatter field set, restricting tools deliberately, what a subagent starts with (and what it does not get), and the rule that plugin-shipped subagents cannot declare hooks, mcpServers or permissionMode
HooksEvents and which of them can block, matchers, handler types, exit codes, where hooks are registered, and failing safely. A hook is the right choice only when "usually followed" is not good enough
PluginsDirectory layout and the manifest trap, namespacing, path variables, what a plugin cannot ship, marketplaces and versioning

How It Works​

  1. Read what exists. List the skills, agents and hooks already present at project, user and plugin scope and run /context. An extension that duplicates one already installed makes both worse.
  2. Choose the primitive by asking when the guidance is needed, whether it must be guaranteed, and whose context pays. If the answer is a memory file, hand off to managing-claude-context.
  3. Confirm the trigger exists. Name the moment the extension will fire and check that moment is real.
  4. Write it, reading the reference for that primitive first and writing the routing surface (description, when_to_use, matcher) before the body.
  5. Verify it loads and routes. Run /context, then test routing with a request that does not name the extension.
  6. Report which primitive was chosen and which was rejected, and why.

Rules It Enforces​

RuleWhy
Decide the primitive before writing a lineThe wrong primitive loads fine and fails invisibly
Use a hook, not an instruction, when something must hold regardless of what Claude decidesInstructions are context, not enforcement
Never ship two extensions whose descriptions overlapRouting between near-identical descriptions is a coin flip, and the loser is silently never invoked
Never declare hooks, mcpServers or permissionMode in a plugin-shipped subagentClaude Code ignores those fields there
Verify with /context and an un-named requestLoading and routing are different failures, and only one is visible
Never set a status, enable a hook or mark something enforced that the team has not agreed toEnforcement is a team decision

What It Does Not Do​

  • Write product code, tests or infrastructure.
  • Decide what a team's workflow should be; it packages workflows the team already has.
  • Author CLAUDE.md, .claude/rules/ or decision records.
  • Configure MCP servers or permissions. A single hook wired into one repository's settings.json is Claude Code's own configuration, not an extension to author here; the skill picks the hook up once it ships inside a plugin or has to reach a second repository.

Reference Files​

ReferenceLoad when
choosing-the-primitive.mdThe routing table gives more than one plausible answer, every time
authoring-a-skill.mdWriting or restructuring any SKILL.md
authoring-a-subagent.mdWriting or changing a subagent
authoring-a-hook.mdWriting a hook, or deciding whether something needs enforcing
packaging-a-plugin.mdBundling extensions for another repository or a marketplace
  • managing-claude-context: owns CLAUDE.md, path-scoped rules and the decision index. The split: "I want to build something" goes to this skill, "I want this repo's memory files to be right" goes there.

Source​