Writing Skills
How to create Agent Skills for pair, directory structure, SKILL.md anatomy, composition, the effectiveness standard, and testing.
Agent Skills are structured instructions that AI coding assistants discover and execute. They follow the Agent Skills open standard, supported by Claude Code, Cursor, VS Code Copilot, and OpenAI Codex.
This guide has two parts: the mechanics of a pair skill (structure, anatomy, composition), and the effectiveness standard, what makes a skill trigger reliably and execute predictably. The goal isn't identical output: it's an agent that runs through identical steps on every invocation; everything in the standard below is aimed at protecting that repeatability.
Skill types
| Type | Count | Purpose |
|---|---|---|
| Process | 9 | Lifecycle phases, orchestrate capability skills (e.g., /implement, /review) |
| Capability | 24 | Atomic units, perform a single focused operation (e.g., /verify-quality, /record-decision) |
Process skills compose capability skills. Capability skills are independently invocable.
Directory structure
Skills live in the Knowledge Base dataset and get distributed to AI tool directories on install:
Each skill lives in its own directory named <type>-<name> (e.g., pair-process-implement, pair-capability-record-decision).
SKILL.md anatomy
Every skill is a single SKILL.md file with YAML frontmatter and markdown content:
Frontmatter fields
| Field | Required | Description |
|---|---|---|
name | Yes | Skill identifier, matches directory name |
description | Yes | Trigger-oriented description (used by AI tools for discovery, see Description = trigger) |
Frontmatter is bound by hard constraints: size limits and portability rules.
Composition model
Process skills orchestrate capability skills through a compose relationship:
Key composition rules:
- Required compositions: The skill halts if the composed skill is not installed.
- Optional compositions: The skill warns and continues if the composed skill is not installed (graceful degradation).
- Arguments: Composed skills receive arguments (e.g.,
$scope,$type) from the parent skill.
Algorithm conventions
Skills use a consistent step pattern:
- Check: Evaluate a precondition.
- Skip: If the condition is already met, skip to the next step.
- Act: Perform the action.
- Verify: Confirm the result before proceeding.
This pattern ensures idempotency: re-running a skill skips already-completed steps.
HALT conditions
Skills define explicit HALT conditions, situations where the skill stops and waits for developer input rather than proceeding with incomplete information.
Setup skills: guided vs quick
A skill or CLI command that collects inputs to produce or configure something (package metadata, an adoption decision, a scaffolded project) exposes the same two-mode duality, guided (asks one input at a time, each pre-filled with a sensible default) and quick (accepts KB-sensible defaults in one shot, for CI, scripting, and experienced users).
Neither mode is universally the default: each adopter declares its own (a human-facing setup skill leans guided, a scripting-first CLI command leans quick), and an explicit signal selects the non-default mode. Guided always needs a TTY: a non-interactive environment can never run it, so the command fails clearly or falls back to quick, never hangs.
The two shipped precedents declare opposite defaults: pair-cli package defaults to quick with --interactive as the guided opt-in, while the assess-* family defaults to guided (Path C) with a $choice override as the quick opt-in.
Both modes read the same resolved defaults through one precedence cascade (explicit argument/flag > project state > saved/inferred preferences > hardcoded) the mode only decides whether each value is confirmed or taken as-is. This is the pair-cli package command's --interactive flag + resolveDefaults() cascade (both the quick and guided paths resolve it), and the assess-* family's resolution cascade (Path A override = quick, Path C = guided).
Adopt the convention directly rather than re-designing the duality: the full mechanics, precedents, and edge cases live in the KB reference .pair/knowledge/guidelines/technical-standards/ai-development/skill-conventions/guided-quick-setup.md.
The effectiveness standard
Conformance to the anatomy above makes a skill valid; it does not make it effective. This standard is the authoring bar for every new skill and the review checklist for every edit (recorded as ADR-010). Each principle ends with a How to check test you can run against the skill text alone.
1. Description = trigger
The frontmatter description carries a dual burden: it identifies the skill's purpose, and it enumerates the trigger branches: the distinct situations that should cause an agent to load it. Rules:
- A branch earns exactly one trigger. Two clauses naming the same situation in different words still describe one branch, "evaluates the tech stack … use when choosing technologies" is a single trigger stated twice, not two. Merge such pairs down to the one branch they actually cover.
- Reach clause for composed capabilities. A capability that fires mostly through composition by other skills carries a lean reach clause ("Composed by
/refine-storyand/plan-tasks; invoke directly when …") instead of a prompt-trigger list. - Body identity stays in the body. Algorithm detail, step structure, and output format belong below the frontmatter. Since every session reloads the description on every turn, its token cost compounds, which is exactly why it deserves the most aggressive trimming of anything in the file.
How to check: map every description clause to a distinct trigger branch; two clauses on one branch collapse into one. Any clause that only matters after the skill is loaded moves to the body.
2. Information hierarchy
Content in a skill sits at different depths, ranked by how soon after invocation it actually gets used:
- Steps: the sequence of actions written directly into
SKILL.md; this is the top tier, read first and acted on immediately. - In-file reference: definitions, rules, and tables that stay in
SKILL.mdbut are only looked up when a step actually calls for them. - Disclosed reference: a same-directory
.mdfile, folded in through a context pointer. How it's phrased is what decides whether it actually gets pulled in: the destination it names has no bearing on that.
Progressive disclosure (pushing reference material down into a sibling file) keeps the top of that stack readable: when reference piles up around the steps, whether the executor actually reads and follows them each time stops being a sure thing. Deciding what to disclose comes down to branching, how many paths actually reach the material. Material every run touches belongs inline; once only a fraction of runs ever reach it, that fraction marks the cut point for a pointer. Rewrite the pointer's wording first when it fails to surface must-have material: that's the cheap, local fix; only fold the content back into the main file if repeated rewording still doesn't make it stick.
How to check: for each block ask "does every run need this before acting?", yes: keep it with the steps; on demand: in-file reference; only some branches: sibling file behind a sharply worded pointer.
3. Completion criteria
Every step's Verify beat needs two properties. First, it must be checkable: given the current state of things, either the step obviously happened or it obviously didn't, with no judgment call needed in between.
Second, where thoroughness actually matters, it must be exhaustive, say "every AC has a mapped task" rather than something as loose as "coverage looks reasonable."
A criterion like "internally consistent" or "guidelines loaded" passes almost automatically, which opens the door to premature completion: the step gets marked finished because finishing became the goal, not because the underlying work actually got done.
Where a human, not the executor, is the real judge, say so explicitly with an approval gate instead of dressing up a soft self-assessment as a check.
How to check: for each Verify beat, ask "could two executors disagree on whether this is satisfied?" If yes, rewrite it as an observable condition or an explicit approval gate.
4. Pruning discipline
Four tests keep a skill lean, run on every edit, pruning by discipline, not by periodic slimming passes:
- One home per meaning: pick a single authoritative spot for each meaning and have everything else point back to it, so changing the behavior means editing exactly one place. A convention shared across many skills belongs in one KB reference, with each skill holding only its own delta. Two up-to-date copies are still a bug: the next edit desynchronizes them.
- Relevance, per line: if you deleted this line, would the skill actually lose something it depends on?
- No-op, per sentence: pull the sentence out and ask whether the model's behavior would change at all; if it wouldn't, the sentence wasn't doing any work. When a sentence fails that test, remove it in full, reworking a no-op only leaves behind a shorter no-op.
- Sediment: a skill only ever grows by default, because appending a new rule feels low-risk while deleting an old one feels like it might break something for someone. Nobody schedules a pass to remove what's no longer true, so it doesn't happen on its own. Make removal part of the edit you're already making, not a separate pass you'll get to later.
How to check: run relevance + no-op on every section you touch, and search the corpus for the meaning you're about to add: if it already lives somewhere, point to it instead of restating it.
5. Leading words
Certain words already carry a fully-formed behavior from what the model saw during pretraining (idempotent, scope, gate, halt, delta) call these leading words: naming one does the work a full explanation would otherwise need, because the model brings its own sense of what halt means without the sentence spelling it out. Where you place one changes what it stabilizes: inside a step it keeps the executor's action the same on every run; inside the description it keeps invocation itself consistent, especially when that same word also turns up in the user's prompts and the project's docs.
How to check: scan the file for every sentence circling the same single quality; either they collapse into one recurring leading word, or there's a reason no pretrained word already covers it. Take an example like "be thorough": it doesn't out-pull what the model does by default, so it earns nothing and should be swapped for a sharper word rather than padded with extra prose.
6. Positive phrasing
State the target behavior. Naming the behavior you don't want puts exactly that behavior on the page, and the page is what the executor reads from next, "never skip the verify step" leaves skip the verify step as the most recent phrase in view, competing with the instruction meant to prevent it. Reach for a prohibition only when there is no positive behavior that closes the same gap (a true hard guardrail) and even then, write the positive target next to it so the executor has somewhere else to look.
How to check: for every "never"/"don't", attempt the positive rewrite (e.g. swap "never merge without a green quality gate" for "merge only once the quality gate reports green"). Keep the negation only where the rewrite loses the guardrail, and confirm the positive target sits beside it.
7. Co-location
Group a concept's definition, its rules, and its exceptions under the one heading that governs the step they apply to, rather than letting them settle wherever they were written. A load-bearing rule buried in a Notes section hundreds of lines from the step it constrains makes whether the executor notices it a toss-up between runs, not a certainty. Co-location is not the same failure as duplication (duplication says the same thing twice in two places; poor co-location says one thing once, but scattered as fragments throughout the document) no single pass through it gives the whole picture.
How to check: for each load-bearing concept, search the skill: if its rules appear under more than one heading (other than a context pointer), regroup them under the concept's own heading.
8. Constraints
Hard mechanics on top of the principles:
- Size limits: the spec caps
nameat 64 chars anddescriptionat 1024 chars separately; Pair adopts a stricter combined ≤1024 bound for both together. - Portability: the agentskills.io spec's top-level frontmatter fields are
nameanddescription(required) pluslicense,compatibility,metadata, andallowed-tools(optional); the spec's own exampleversion/authorkeys live undermetadata:, not top-level. Pair skills carryversion/authorat top level instead: a tolerated Pair extension beyond the spec's optional fields, kept there for provenance tracking (who authored/last bumped a skill) until a future skill-corpus pass considers moving them undermetadata:. Assistant-specific fields (e.g.,disable-model-invocation) stay out of the dataset regardless: a skill must install identically on Claude Code, Cursor, VS Code Copilot, and Codex. - Mirror sync: the dataset copy (
packages/knowledge-hub/dataset/.skills/) and the installed mirror (.claude/skills/) change in the same commit, always. versionbumps track observable behaviour, not edits: minor (0.5.0 → 0.6.0) when a skill gains or changes something a caller can observe: a new argument, a new mode/execution depth, a new or removed phase, a changed HALT condition. Patch (0.6.0 → 0.6.1) for a behaviour-preserving correction to the algorithm's wording. No bump for prose, formatting, link, or documentation-only edits, which is why a clarity pass across many skills leaves their versions alone. Same value in both copies: the mirror transform rewritesname/description, neverversion.
How to check: character-count name and description against the combined bound; diff the frontmatter's fields against the spec's top-level list plus the tolerated version/author extension, anything else is a portability violation; confirm the commit touches both copies; if the diff adds an argument, a mode, or a phase, confirm version moved.
9. Evaluation
A description rewrite is a hypothesis; the eval is the experiment. Maintain a should-trigger / should-not-trigger prompt set per skill family: prompts that must load the skill, and near-miss prompts that must not. Run it in fresh sessions, triggering is a cold-start behavior, so conversation history invalidates the result. When rewriting a description, run the set against both the old and the new description and record the before/after results; a regression reverts the rewrite, and you iterate on the description, not on the eval.
How to check: before/after results are recorded for every rewritten description; each skill family has prompts on both sides of the trigger boundary.
Review checklist
One line per principle: use it when authoring or reviewing any skill change:
- Every description clause maps to a distinct trigger branch (or a lean reach clause for composed capabilities); no body identity in the description
- Steps lead; in-file reference only where most runs need it; branch-specific material disclosed behind a sharply worded pointer
- Every Verify beat leaves no room for a judgment call, and is exhaustive where thoroughness matters
- No meaning duplicated (in-skill or cross-skill); every touched line passes relevance, every sentence clears the no-op check
- Recurring concepts anchored by leading words, not restated prose
- Prohibitions only as hard guardrails, each paired with its positive target
- Each concept's rules co-located under one heading, adjacent to the step they govern
-
name≤ 64 /description≤ 1024 chars separately (spec), and both together ≤ 1024 (Pair's stricter bound); frontmatter limited to spec fields + the toleratedversion/authorextension (no assistant-specific fields); dataset + mirror in the same commit -
versionbumped iff observable behaviour changed (new argument/mode/phase → minor; wording-only → no bump), identical in both copies - Description rewrites carry before/after trigger-eval evidence
Writing a new skill
1. Choose the skill type
- Process if it orchestrates multiple steps across the development lifecycle.
- Capability if it performs a single, focused operation.
2. Create the directory
3. Write the SKILL.md
Follow the anatomy above and hold the draft to the effectiveness standard. Key principles:
- Be explicit: AI agents follow instructions literally. Ambiguity leads to incorrect behavior.
- Use the Check/Skip/Act/Verify pattern: Ensures idempotency.
- Define HALT conditions: Better to stop and ask than to proceed incorrectly.
- Document composition: List all composed skills with required/optional status.
- Include graceful degradation: What happens when optional dependencies are missing.
- Pass the review checklist: Every box above, before opening the PR.
4. Update the skills guide
Add your skill to packages/knowledge-hub/dataset/.pair/knowledge/skills-guide.md in the appropriate section (Process or Capability).
5. Test the skill
- Install the KB locally: run
pair-cli installor copy the SKILL.md to.claude/skills/<skill-name>/. - Run the trigger eval: should-trigger and should-not-trigger prompts in fresh sessions (see Evaluation).
- Invoke the skill via the slash command (e.g.,
/pair-capability-example). - Verify the skill follows its algorithm correctly.
- Test idempotency: re-invoke and confirm it skips completed steps.
- Test graceful degradation: remove optional composed skills and verify the warning behavior.
Naming conventions
| Convention | Example |
|---|---|
| Process skills | pair-process-<name> (e.g., pair-process-implement) |
| Capability skills | pair-capability-<name> (e.g., pair-capability-verify-quality) |
| Verification skills | pair-capability-verify-<aspect>, conformance pass/fail (e.g., pair-capability-verify-quality) |
| Assessment skills | pair-capability-assess-<topic>, evaluate options + propose an adoption choice (e.g., pair-capability-assess-stack) |
| Analysis skills | pair-capability-analyze-<topic>, analyze + report only, never blocks (e.g., pair-capability-analyze-debt) |
Three distinct verbs, kept separate, don't overload one across branches: verify-* = conformance pass/fail; assess-* = evaluate options and PROPOSE an adoption decision; analyze-* = analyze and REPORT only (no decision, never blocks). Recorded as ADL 2026-07-13-skill-naming-verb-taxonomy.md.
Resources
- Agent Skills specification: The open standard, including frontmatter fields and size limits.
writing-great-skills: The reference model behind the effectiveness standard (predictability, information hierarchy, leading words, pruning).- Skills Catalog: Full list of all 51 pair skills.
- Skills concept: How skills fit into the pair ecosystem.