A spec is a codebase without the code. specify is a spec-driven CLI + AI
skill: reverse-engineer behavioral specs from code, scaffold code from specs,
and verify code still matches its spec — so an update never silently breaks
behavior. From a complete spec you could rebuild the project and get the same
functionality.
npx @docsbook/specify install # adds the skill + /specify to Claude Code, Cursor, or CodexThat's it. Now talk to your AI tool in plain language. Once a specs/ directory
exists, specify works under the hood on its own — you never run a command or
say "update the spec".
You: "Add team invites with role-based access."
AI: (silently, before touching code)
1. reads the spec for the area you're changing
2. ⚠️ "The auth spec says viewers can't see billing — should an invited
admin? The spec is silent on invite expiry. Confirm before I build."
3. implements it, honoring every invariant the spec locked in
4. updates specs/ in the same change so the spec never lags the code
You asked for a feature. The AI consulted the spec, reflected and asked the right questions first, built it without breaking a stated behavior, and kept the spec in sync — all without you mentioning specs once.
| You have… | Just say to your AI tool |
|---|---|
| A project, no specs yet | “Generate specs for this project.” → it graphs your code, clusters it into behaviors, writes one code-free spec per subsystem into specs/. From then on, the loop above runs automatically. |
| Only an idea, no code yet | “I want to build a URL shortener with click analytics.” → it writes the spec first, asks what's ambiguous, then “build it” generates code from the agreed spec. |
Why spec-first is cheaper: the spec is a codebase without the code — write it once, and every future change is checked against it instead of discovered in production. The AI reflecting against a spec before coding catches the broken contract while it's still a question, not a bug.
A spec lands as plain markdown you can read and edit:
specs/analytics/
README.md # what the subsystem does + links to aspects
failed-searches.md # one file per behavioral aspect
page-journeys.md
The CLI that powers all of this is documented below — but for day-to-day use, you never need it.
Everything above runs out of the box. Two integrations are opt-in upgrades — you choose if and when the extra accuracy is worth a one-time setup step.
| Capability | ✅ Zero setup (default) | ⚡ With the booster |
|---|---|---|
Match spec ↔ code (reverse, verify) |
codescan — scans your source for declared symbols directly. No install, no build, works offline. | graphify — a parser-built code graph: deduped symbols, call-graph clustering. Tighter clusters, usually higher coverage. Run graphify ./src once. |
| Search a large spec | markdown-lsp full-text / fuzzy — instant, no API key: markdown-lsp search-text ./specs "quota". |
markdown-lsp semantic-search — embedding-backed meaning search (finds "rate limit" from "too many requests"). One index step + an API key. |
How the choice surfaces in practice:
# default — no graphify needed, runs anywhere
specify verify ./specs/billing
# → { "mode": "codescan", "covered": 7, "total_triggers": 7, ... }
# booster — if a graphify graph exists, specify uses it automatically
graphify ./src && specify verify ./specs/billing
# → { "mode": "graphify", ... } ← tighter symbols, the hint tells you when it helpsYou never get blocked waiting on setup: specify picks the best surface that's
available and tells you (mode + hint) when a booster would improve the
result. Add graphify or embeddings only when you want the extra precision.
A spec is a folder of markdown describing what a system does — its behaviors, invariants, edge cases — with no file paths, function names, types, or imports. It is the contract that stops the next change from breaking behavior.
The bar is rebuildability: a complete spec captures enough behavior that someone could reconstruct the project from the spec alone and get the same functionality. That means the business rules too — plan/tier gating, pricing, limits, permissions — not just the structure. When generating a spec from code, specify reads the file bodies, not just symbol names, precisely so these rules (which live inside functions) don't get dropped. If a rule isn't in the spec, it doesn't exist for whoever rebuilds from it.
my-module/
README.md # frontmatter `triggers:` + behavior overview, links to aspects
caching.md # one file per behavioral aspect (nestable)
quota.md
Every file carries a frontmatter triggers: array — the phrases a developer or
AI would use to ask about that behavior. Triggers are the lookup key (for
search and for verify coverage). A file's body is either a direct behavior
description, or links to nested files — each link is a key trigger → file
pair, the same shape as a knowledge base.
---
triggers:
- "translation cache"
- "cache hit"
- "cache miss"
---
# Caching Behavior
A translation is uniquely identified by source content + target language. …Rule: no code in the spec. No paths, signatures, types, imports — each
heading is a behavioral claim. See examples/translation-behavior/
for a real, validated spec.
For day-to-day use you don't need this — the installed skill drives the CLI for you (see Quick Start). This section is for understanding the machinery, scripting, or CI.
The CLI does the deterministic half (validate structure, build the trigger↔code coverage map). The generative steps are AI tasks your agent performs, reasoning over the CLI's JSON dossier.
Only have an idea? It's cheaper to write the spec first, then generate the code from it. No code required.
npx @docsbook/specify new "AI-powered habit tracker with streaks and reminders"Scaffolds a valid, code-free spec skeleton. The agent then expands the idea into
behavioral claims — splitting concerns into aspect files, filling triggers:,
stating invariants and edge cases — without naming any stack or framework
(that's the build step's job). Then validate, then build.
graphify ./src # → graphify-out/graph.json (graphify skill)
npx @docsbook/specify reverse ./src --graph ./graphify-out/graph.jsonThe CLI clusters code symbols by graphify community and hands the agent the clusters; the agent writes one code-free spec file per cluster.
npx @docsbook/specify build ./specs/my-featureReturns triggers + a code-plan skeleton. The agent implements every behavioral claim, honoring every invariant — and invents nothing the spec omits.
npx @docsbook/specify verify ./specs/my-feature --graph ./graphify-out/graph.jsonReturns a coverage map: every trigger lexically matched against graphify
code-graph nodes. uncovered triggers are the drift signal — a behavior the
spec promises with no matching code (or spec text too vague to match). The spec
stays code-free; all code references live in this output, never in the spec.
npx @docsbook/specify reflectPrints the standing guide for changing code under a spec: find the triggers your change touches, treat them as the contract, update the spec in the same change if observable behavior shifts.
| Tool | What it buys you |
|---|---|
| graphify | A knowledge graph of the code. reverse clusters it into spec files; verify matches triggers to its symbol nodes — so the spec carries zero code references and conformance stays cheap. |
| markdown-lsp | Search a large spec without reading whole files into context: markdown-lsp search-text ./specs "quota", search-symbols, links-from. Optional index + semantic-search for embedding-backed lookup. |
# search a spec cheaply instead of reading every file
npx markdown-lsp search-text ./specs/my-feature "quota exceeded"
npx markdown-lsp links-from ./specs/my-feature README.md| Command | Kind | Description |
|---|---|---|
specify new "<idea>" [--dir <p>] |
scaffold | Create a brand-new spec from an idea — no code yet (greenfield) |
specify install [dir] |
setup | Install the skill + /specify command into Claude / Cursor / Codex |
specify spec validate <dir> |
deterministic | Lint spec structure — triggers present, links resolve, no code leaks |
specify verify <spec> [--graph <p>] [--threshold <n>] |
deterministic | Coverage map: triggers ↔ graphify code-graph nodes |
specify reverse <code-dir> [--graph <p>] |
dossier → AI | Clustered code symbols to turn into spec files |
specify build <spec-dir> |
dossier → AI | Triggers + code plan to scaffold from |
specify reflect |
guide | Spec-driven coding guide |
All commands print JSON to stdout.
npx @docsbook/specify install # detects Claude / Cursor / Copilot / Codex- Claude Code →
.claude/skills/specify/+.claude/commands/specify.md(use/specify) - Cursor →
.cursor/rules/specify.mdc - Copilot / Codex → appended to
copilot-instructions.md/AGENTS.md
MIT © Dan Bondarev