-
Notifications
You must be signed in to change notification settings - Fork 2
Extending FeatherSpec
Adding to FeatherSpec means adding Markdown files. There is no registry, no manifest and no build step.
A command needs two files that share the same stem:
1 · The body — .claude/commands/sdd-mytask.md
---
description: One-line summary shown in the / menu.
argument-hint: "[thing]"
disable-model-invocation: true
---
<!-- Single source for the /sdd-mytask workflow. Claude Code runs this file directly;
GitHub Copilot reaches it through the one-line loader in
.github/prompts/sdd-mytask.prompt.md. Deliberately no shell injection and no
argument-variable substitution: Copilot supports neither. -->
# /sdd-mytask
Do something. The user may name a thing after the command; if none is given, list the
candidates and ask.2 · The Copilot loader — .github/prompts/sdd-mytask.prompt.md
---
name: sdd-mytask
description: One-line summary shown in the / menu.
argument-hint: "[thing]"
---
# /sdd-mytask
Follow [`.claude/commands/sdd-mytask.md`](../../.claude/commands/sdd-mytask.md) exactly — read
that file first and treat it as your instructions for this turn. It is the single source for
this workflow; this file only points at it and holds no rules of its own.
Anything the user typed after the command is the argument the workflow refers to.The loader is the same three fields plus name:, and a single line pointing at the body. It
never holds a rule of its own.
Invoked as /sdd-mytask in both tools. Claude Code picks up new command files without a
restart; VS Code may need a full restart, not just a window reload.
Because both tools execute the same text, the body is written to the lowest common denominator:
| Don't | Do instead |
|---|---|
!`git status` |
"Run git status --short and use the result." |
$ARGUMENTS, $0, $1
|
"The user may name X after the command; if none is given, ask." |
Naming a tool (WebFetch, #fetch) |
Name the capability: "your web search or fetch capability" — and say what to do when it is missing |
| Assuming a terminal tool name | State the command to run |
Keep the HTML comment at the top. It is what stops the next person reintroducing Claude-only syntax. See Design Decisions.
If your command changes DocLanguage, the architecture: snapshot or a style preference, it
must write to AGENTS.md — that is the only place those live. Never introduce a second store.
One file, no loader needed — both tools read .claude/rules/.
.claude/rules/mytopic.md:
---
paths:
- src/**/*.ts
---
# My topic rules
- Keep it concise.paths: is a YAML list, even for a single entry. The rule loads when a matching file is
read — which also means it may not be loaded when a file is being created. If your rule
must apply at creation time, state the essentials inline in the command that creates the file,
the way /sdd-specify and /sdd-plan do, and note why.
Omitting paths: makes VS Code default to ** (always on). Prefer a scope: an always-on rule
belongs in AGENTS.md instead.
| It is… | Put it in |
|---|---|
| policy — a lifecycle, a file set, a non-negotiable | AGENTS.md |
| craft — how to write files of a particular kind | .claude/rules/<topic>.md |
| mutable state — language, architecture, style preferences |
AGENTS.md, and nowhere else |
FeatherSpec ships no skills on purpose: both tools read every skill's name and description up front, so each skill costs context on every request.
Add one only when a workflow genuinely needs the model to trigger it on its own, without you
typing anything. Both tools read .claude/skills/<name>/SKILL.md, so a skill is shared without a
loader.
.github/agents/<Name>.agent.md is a Copilot-only persona you pick from the agent dropdown.
Claude Code has no persona picker — its equivalent is AGENTS.md plus /sdd-overview.
Do not move a persona file into .claude/agents/ expecting the same behaviour: in Claude Code
that folder defines an isolated subagent with its own context window, not a persona for your
conversation.
See Configuration — including the VS Code caveat that hook matchers are
ignored, so a shared hook must filter on tool_name inside the script.
Start here
Reference
Design & interop
- Interop Matrix
- Design Decisions
- Specify Method
- Committing to One Tool
- Migrating from the predecessor
Help