Spec-driven development skills for Claude Code, Cursor, Codex, and Antigravity. By Fernando Herrera.
$ npx -y skills add klerith/fernando-skills --agent claude-code
npx skills@latest add Klerith/fernando-skills
| Skill | Description | Argument |
|---|---|---|
/spec | Designs the feature document by asking clarifying questions | — |
/spec-impl | Validates the spec is approved and implements step by step | <NN-slug> |
Spec-driven design is an approach where the spec is the main work artifact, not the code. The code is the consequence.
It sounds obvious. The difference from the classic "document before coding" is that in spec-driven the spec is not optional or decorative: it's the contract that guides execution, it's versioned in git, and it's kept alive. If the code diverges from the spec, one of the two is wrong.
Each spec captures the decisions of a single feature. Specs live in specs/ as .md files numbered sequentially, and they form the project's design decision log.
When you work with an LLM like Claude Code, there's a very concrete phenomenon: if you ask it "build me an Arkanoid with power-ups and levels", it's going to improvise. It's going to make 50 implicit design decisions (classes or functions? global or local state? how are entities named?) without you seeing any of them. And each one of those decisions becomes an expensive coupling to revert later.
The problem isn't new — humans improvise too — but with an LLM it's sharper:
The spec solves all three: it makes decisions explicit, it persists across sessions, and it loads once as a reference.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 1. DESCRIBE │→ │ 2. PLAN MODE │→ │ 3. REFINE │
│ the problem │ │ Claude proposes │ │ You give │
│ not the answer │ │ doesn't edit │ │ decisions │
└─────────────────┘ └─────────────────┘ └─────────────────┘
↑ │
│ │
└──────── 2-3 iterations until converged ──┘
│
▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 4. SAVE │→ │ 5. EXECUTE │→ │ 6. REVIEW │
│ specs/NN- │ │ Step by step │ │ Diff per step │
│ feature.md │ │ with pauses │ │ not at the end │
└─────────────────┘ └─────────────────┘ └─────────────────┘
You describe the feature to Claude in terms of the problem, not the solution. If you dictate the solution, Claude just formats it — you lose its ability to propose structure.
You activate plan mode (in plan mode Claude can't write files, only read and propose). Claude responds with a structured document: scope, data model, implementation plan, and acceptance criteria.
You read the plan with resistance and give concrete decisions. "Take X out of scope", "data lives in JSON, not in JS modules", "add a risks section". You iterate 2-3 times.
When the spec is honed, you save it in specs/NN-slug.md with status Draft. You leave the chat, re-read it outside the editor, and only when you're satisfied do you change the status to Approved manually. That change is made by the human, not Claude.
You exit plan mode and ask Claude to implement the spec step by step, stopping after each step in the implementation plan. The pause between steps is what makes the method work.
After each step, you review the diff. If it's good, you continue. If not, you correct in the moment — not at the end with 600 lines mixed together.
Not every document does the job. A useful spec has six parts — if any of them is missing, it's probably not enough to guide execution.
If it doesn't fit in a sentence, the feature is too big. Split it before writing anything else.
The "out of scope" is as important as the "in scope". Without it, the boundaries are blurry and scope creep appears during implementation. Capture the things that were mentioned but decided to postpone.
Concrete structures and names. If you say "the levels module", say src/levels.js. If you say "a key", give the exact string. This section is the one most cited later in other specs and skills.
Numbered sequential steps. Each step must leave the system in a working state. If a step requires more than 30-50 lines of code, split it. The last step is not "test everything" — that's the acceptance criteria.
A verifiable boolean checklist. Each item can be answered yes or no.
What you considered and why you chose what you chose. This is gold three months from now when someone asks "why does persistence use a versioned key?". The answer lives there.
Each decision ideally has a short reason. Decisions without a reason are the first ones questioned later.
This architecture has a cost. Don't apply it to everything.
If you're tempted to open plan mode, you probably need it. > If planning the feature bores you, you probably don't.
Common sense beats the rule — but common sense is trained by the two columns above.
Four usage patterns that distinguish the method working well from the method as decorative bureaucracy:
❌ "Add an array of levels loaded from JSON, a loadLevel() function, and persistence with versioned localStorage."
That's already a spec poorly written by you. Claude is just going to format it.
✅ "I want the game to stop being single-screen. The next feature is: progression through levels with increasing difficulty, and persistence of high scores across sessions."
That second version leaves room for Claude to decide and you to review. That's the nature of the flow.
Plan mode is where you direct. "Take X out", "the format is JSON", "add risks". If you say "I think maybe it would be good to...", Claude is going to leave it as is.
The difference is:
Mid-implementation something occurs to you. The right move is: stop, go back to plan mode, update the spec, exit, continue. Don't improvise on the code.
That separation is what prevents silent scope creep.
npx skills@latest add Klerith/fernando-skills
To uninstall:
npx skills@latest remove Klerith/fernando-skills
git clone https://github.com/Klerith/fernando-skills ~/.fernando-skills
cd ~/your-project
~/.fernando-skills/scripts/install-to-agent.sh <agent>
<agent> can be claude, cursor, codex, or antigravity.
| Agent | What gets written |
|---|---|
claude | Symlinks each skill into .claude/skills/ (project-scoped) |
cursor | Generates .cursor/rules/<name>.mdc files. Invoke with @spec, @spec-impl, etc. |
codex | Adds a ## Skills block to AGENTS.md and copies skill bodies into .codex/skills/ |
antigravity | Copies skill bodies into .antigravity/skills/ |
Cursor and Codex don't natively support Claude Code's
argument-hintordisable-model-invocationfrontmatter. The installer drops those fields and keeps the body — the workflow is the same, only the trigger changes.
# Personal (all your projects)
mkdir -p ~/.claude/skills
cp -r skills/engineering/spec ~/.claude/skills/
cp -r skills/engineering/spec-impl ~/.claude/skills/
# Or per-project (versioned in git)
mkdir -p .claude/skills
cp -r skills/engineering/spec .claude/skills/
cp -r skills/engineering/spec-impl .claude/skills/
For the method to work, you also need to create the specs/ folder at the project root:
mkdir specs
Optionally, add a specs/README.md documenting the convention (see the example in this repo).
fernando-skills is a Claude Code plugin with 2 hand-picked skills, indexed on Flowy in the Writing category. Install it with the command on its page. It includes spec-impl, spec. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it