Skill forge
Every developer tool shipped an MCP server in 2025. In 2026 the missing artifact is a skill: the instructions an agent loads before it writes code against your product. An MCP server gives an agent capabilities. A skill gives it judgement — which call to reach for, what the constraints are, what mistake it is about to make.
This drafts that artifact from the product's actual surface, then hands it over for review.
Applies to
| Project types | Any product an agent writes code against — APIs, SDKs, CLIs, frameworks, platforms, MCP servers |
| Stage | Once the surface is stable enough that instructions will not be wrong next week. A skill describing a moving API is worse than none |
| Needs | The repository, or an OpenAPI/GraphQL schema, or reference docs. It reads the surface, not a description of it |
| Skip if | The product has no programmable surface, or the workflow is a single call with no failure modes — that belongs in the README |
Best on products where agents reliably get something wrong: an auth dance, a required ordering, pagination, idempotency, a footgun the docs mention once.
How to use
/agentrel:skill-forge forge a skill for this repository
/agentrel:skill-forge ./packages/sdk scope it to one package
/agentrel:skill-forge https://docs.acme.com forge from public docs
/agentrel:skill-forge --job "send an invoice" name the job explicitly
Writes drafts to ./skill-draft/<skill-name>/ and prints what was written. Never
overwrites: if the directory exists, the run writes a numbered sibling and says so. Review
and move the files yourself — publishing is a human decision.
Read references/authoring-standard.md before writing any file. It holds the frontmatter
rules, the size budget, and the template. Do not write a SKILL.md from memory of what skills
look like — the failure mode of that is a 400-line file no agent will load usefully.
1. Inventory the real surface
Describe what exists. A skill that claims a method the SDK does not have is worse than no skill, because the agent will confidently write the call and the user will blame the product.
| Signal | Where to look |
|---|---|
| Callable surface | openapi.{json,yaml}, schema.graphql, exported functions, CLI --help, ListTools |
| Required sequences | Auth flows, resource creation order, anything a test does before the interesting call |
| Constraints | Rate limits, pagination, idempotency keys, required headers, enum values |
| Failure modes | Error types and codes, retry semantics, what a 4xx actually means here |
| Existing guidance | README, quickstart, AGENTS.md, support answers to repeated questions |
| Known footguns | Issues labelled confusion or docs, FAQ entries, "note that…" asides in the docs |
Record the version or commit you read. A skill without a version reference cannot be audited later, and the first question a maintainer asks is "which release is this describing".
2. Choose one job
A skill is not a documentation port. It is instructions for one job, invoked when a user asks for that job. Pick the highest-frequency, highest-failure task and name it in a verb phrase — "send an invoice", "run a migration", "query a dataset".
Signals for the right job: it appears in the quickstart, it recurs in support questions, agents get it wrong today, and it has more than one step.
If the product genuinely has three unrelated jobs, forge three skills and say so. Do not merge them — a description covering three jobs matches none of them well when the dispatcher is choosing.
3. Write the frontmatter
The description is the whole distribution mechanism. It is not read by a human deciding to install; it is read by a model deciding whether to load the skill mid-task. Write it for that reader.
- Lead with what it does, in the product's own nouns.
create_invoice,Postgres branch,vector index— those nouns are what appear in a user's request. - Then when to use it, as the phrasings a user actually types. Trigger words last, where a truncation costs least.
- Budget: 1,536 characters for description plus any
when_to_use. Past that the tail is invisible to the model. - Declare
allowed-toolsas the minimum the job needs. A skill that reads a schema and writes a client needsRead Grep Glob Bash Write— it does not need everything.
4. Write the body as a procedure
The reader is an agent mid-task, not a prospect. Open with the first step.
| Include | Leave out |
|---|---|
| The exact call sequence, in order | Marketing copy, positioning, feature lists |
| Real parameter names and enum values | "Powerful", "seamless", "simply" |
| The constraint that breaks naive code | Anything the agent can read from the schema itself |
| Error handling for the errors this product actually returns | Generic advice about try/catch |
| A verified working example | An example nobody ran |
Two rules the draft must satisfy:
- Under ~200 lines. Detail goes to
references/*.md, loaded only when needed. That progressive disclosure is the entire advantage of a skill over a pasted document. - No invented capability. Every method, field, and parameter traces to something found in step 1. Mark anything uncertain and leave it out of the draft.
5. Package for both channels
Two install paths exist, and they resolve different directories. Draft for both:
skill-draft/<name>/
├── SKILL.md the skill itself
├── references/ detail, loaded on demand
├── README.md install lines, above the fold
└── .claude-plugin/
└── marketplace.json only if publishing as a plugin marketplace
| Channel | Install | Lands in |
|---|---|---|
| Claude Code plugin | /plugin marketplace add <org>/<repo> then /plugin install … |
The plugin's own namespace |
| Cross-agent CLI | npx skills add <org>/<repo> |
~/.agents/skills/ — 70+ agents |
| Manual | Copy the directory | ~/.claude/skills/ or .claude/skills/ |
The two CLI paths differ — ~/.agents/skills/ for the skills CLI, ~/.claude/skills/ for
Claude Code. Document both in the README; a skill that installs into a directory the user's
agent never reads looks broken and gets uninstalled.
6. Self-test before handing over
A skill that never loads is worth nothing, and the common failure is a description that does not match how people ask.
- Write five phrasings a real user would type for this job. Include one that names no product term.
- For each, judge whether the description would cause this skill to load. Report the ones that would not.
- Follow the procedure literally against the real surface. Every call must exist. If a step cannot be followed, the step is wrong, not the reader.
- Check the budget: description length, body line count,
allowed-toolsminimality.
Report the results honestly, including phrasings that fail. Then verify the example with
/agentrel:snippet-verify — an official skill shipping a sample that does not run is a
self-inflicted wound.
7. Write the report
Print what was written and what needs a human decision:
SKILL FORGE
Job send an invoice
Surface read openapi.yaml @ v2.4.1 · 41 operations · 6 error types
Written skill-draft/acme-invoicing/
SKILL.md 168 lines
references/errors.md 74 lines
README.md 22 lines
Description domain nouns first · 612 / 1536 chars
Trigger test 4 of 5 phrasings load
Example unverified — run /agentrel:snippet-verify
Needs a human claim on retry semantics not found in the surface
publish decision: plugin marketplace, skills CLI, or both
Drafts → ./skill-draft/acme-invoicing/
End with the one thing a maintainer must decide before publishing. One sentence.
Notes
- Never overwrite. Everything lands in a fresh
./skill-draft/directory; an existing directory gets a numbered sibling. Nothing in the product's own tree is touched. - Drafts, not releases. This skill does not publish, tag, push, or register anything. A human reviews and ships.
- No invented surface. Uncertain claims are listed under "needs a human", never written into the draft as fact.
- Version-anchored. The draft records which release it describes, so drift can be found later instead of discovered by a user.
- No telemetry. Nothing leaves the machine except fetches of the surface you named.