Files
msd-core/docs/tutorials/build-your-first-capability.md
Tom Boucher f52a7a5f77 feat(#1245): add capability ecosystem ADR, PRD, and developer documentation (#1248)
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>
2026-06-14 17:51:43 -04:00

220 lines
7.0 KiB
Markdown

# 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:
```bash
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:
```bash
mkdir -p capabilities/hello-note/fragments
```
Your project tree now looks like this:
```text
~/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:
```bash
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`:
```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:
- `version` is required in 1.6.0. Use semver.
- `engines.gsd` is 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 `steps` attaches at `plan:pre`. `produces` tells the registry that this step writes `HELLO.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:
```bash
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
```bash
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:
```bash
gsd capability hooks plan:pre
```
Expected output (abbreviated):
```json
[
{
"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:
```bash
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:
```bash
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:
```bash
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:
```bash
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](../how-to/publish-a-capability.md) — package and share your capability via a URL or registry.
- [Import a capability from a URL](../how-to/import-a-capability-from-a-url.md) — install a third-party capability from a git URL, tarball, or npm package.
- [Capability manifest reference](../reference/capability-manifest.md) — all fields, types, and validation rules for `capability.json`.
- [Capability trust model](../explanation/capability-trust-model.md) — why declarative capabilities need no consent prompt and how executable surfaces are disclosed.