Phase 0 of the Capability Ecosystem epic (#1244): the design record and the third-party-author documentation set, with no runtime or code changes. - docs/adr/1244-capability-ecosystem.md — architecture decision record (amends/extends ADR-857 Decisions 7 & 8) - docs/prd/1244-capability-ecosystem.md — product requirements - Diataxis docs: tutorial, how-to (publish/import/version/remove), reference (manifest schema, /gsd:capability command, capability matrix), explanation (trust model); cross-links added to develop-a-capability.md Refs #1244 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
7.0 KiB
Build Your First Capability
In this tutorial you will build a tiny, fully declarative GSD capability from scratch and watch it act inside your project's loop. By the end you will have a working capability installed, visible in gsd capability list, and firing at the plan:pre extension point.
No code is required. Declarative capabilities — those that own only prompt fragments and hook declarations, with no executable hook scripts or MCP servers — require no trust prompt at install time.
We will build a capability called hello-note. It registers a step at the plan:pre extension point that injects a short greeting fragment into the planner's context and declares that it produces a file called HELLO.md.
Before you begin
You need:
- GSD 1.6.0 or later (
gsd --version). - A throwaway project directory. Create one now:
mkdir ~/hello-demo && cd ~/hello-demo
gsd init
You will work inside ~/hello-demo for the rest of this tutorial.
Step 1 — Scaffold the capability folder
Capabilities live in a capabilities/<id>/ folder. Create the folder structure:
mkdir -p capabilities/hello-note/fragments
Your project tree now looks like this:
~/hello-demo/
.gsd/
capabilities/
hello-note/
fragments/ ← prompt fragments live here
Step 2 — Write the prompt fragment
The fragment is a short Markdown file that will be injected into the planner's context when the plan:pre hook fires. Create it:
cat > capabilities/hello-note/fragments/plan-pre.md << 'EOF'
## Hello from hello-note
This planning session was started with the hello-note capability active.
Record a brief note in HELLO.md summarising the plan goal in one sentence.
EOF
Notice that the fragment is plain prose. The capability system inlines it into the agent prompt at dispatch time.
Step 3 — Write capability.json
Create the manifest at capabilities/hello-note/capability.json:
{
"id": "hello-note",
"role": "feature",
"version": "0.1.0",
"title": "Hello Note",
"description": "Injects a greeting note step at plan:pre and produces HELLO.md.",
"tier": "standard",
"requires": [],
"engines": { "gsd": ">=1.6.0" },
"runtimeCompat": { "supported": ["*"], "unsupported": [] },
"skills": [],
"agents": [],
"config": {},
"steps": [
{
"point": "plan:pre",
"fragment": { "path": "fragments/plan-pre.md" },
"produces": ["HELLO.md"],
"consumes": [],
"onError": "skip"
}
],
"contributions": [],
"gates": []
}
A few things to notice:
versionis required in 1.6.0. Use semver.engines.gsdis a hard gate: GSD will refuse to install or load this capability on any version older than 1.6.0.role: "feature"means this capability adds optional behaviour to the loop — it is not a runtime descriptor.- The single entry in
stepsattaches atplan:pre.producestells the registry that this step writesHELLO.md, which lets the registry order hooks and detect unsatisfied dependencies in more complex setups. onError: "skip"means the loop continues even if this step fails. For a first capability that is the safe choice.
No ref.agent or ref.skill is declared here because this is a fragment-only step: the planner receives the fragment text inline and acts on it. This keeps the capability completely declarative.
Step 4 — Install the capability into your project
Install from the local path with --scope project so it is scoped only to this demo project:
gsd capability install ./capabilities/hello-note --scope project
You will see output similar to:
Installing hello-note 0.1.0 …
Role : feature
Scope : project
Hooks : 1 (plan:pre step)
Executable surfaces : none
✔ hello-note installed.
Because hello-note declares no executable surfaces (no hook scripts, no MCP servers, no command modules) GSD copies the files to the project capability ledger without displaying a consent prompt. That is intentional — declarative capabilities are safe to install without reviewing runnable code.
Step 5 — Confirm the installation
gsd capability list
You will see at least one row for hello-note:
id version role scope status
hello-note 0.1.0 feature project enabled
You can also query the active hook set for the plan:pre point:
gsd capability hooks plan:pre
Expected output (abbreviated):
[
{
"capability": "hello-note",
"point": "plan:pre",
"kind": "step",
"produces": ["HELLO.md"],
"fragment": { "inline": "## Hello from hello-note\n…" }
}
]
Notice that fragment.inline now contains the materialised text from fragments/plan-pre.md. The capability system inlined it at install time.
Step 6 — Trigger the loop step
Start a planning session. The planner will receive the hello-note fragment as part of its context:
gsd plan
Watch the planner output. You will see a line noting that hello-note contributed a plan:pre step. The planner will produce HELLO.md in your project's planning directory as directed by the fragment.
If you are running in an environment where the planner agent is not configured, you can inspect what the resolver would dispatch without running the full agent:
gsd loop render-hooks plan:pre --raw
The JSON output will include your hello-note step with its inlined fragment, confirming that the capability is wired into the loop.
Step 7 — Disable the capability
When you want to stop the step from firing, disable the capability:
gsd capability disable hello-note
Run gsd capability list again. The status column will now show disabled. Run gsd loop render-hooks plan:pre --raw and you will see that hello-note is absent from the active hook set. Disabled capabilities are removed from the resolver output by construction — there is nothing feature-specific for the loop to run.
To re-enable it:
gsd capability enable hello-note
You have built your first capability
You scaffolded a capability folder, wrote a manifest with a single plan:pre step, installed it into a project-scoped ledger without a trust prompt, confirmed it in the active hook set, watched it contribute to the planning loop, and disabled it cleanly.
The capability you built is fully declarative: it owns a prompt fragment and a hook declaration, and no executable code was involved at any point.
Where next
- Publish a capability — package and share your capability via a URL or registry.
- Import a capability from a URL — install a third-party capability from a git URL, tarball, or npm package.
- Capability manifest reference — all fields, types, and validation rules for
capability.json. - Capability trust model — why declarative capabilities need no consent prompt and how executable surfaces are disclosed.