
Spec Tests First
- Updated May 29, 2026
- Akhiranandha/custom-claude-plugins
Chains six phases from spec through ship with AC-IDs, per-AC test writing, and dedicated review and fix steps. Supports 12 test layout profiles, monorepos, and zero external plugin dependencies.
Key points
- Per-AC red-green-refactor loop
- Built-in parallel security and quality review
Spec Tests First by the numbers
- Data as of Jul 9, 2026 (Skillselion catalog sync)
/plugin marketplace add Akhiranandha/custom-claude-plugins/plugin install spec-tests-first@akhira-pluginsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Last updated | May 29, 2026 |
|---|---|
| Repository | Akhiranandha/custom-claude-plugins ↗ |
What it does
Run TDD-first spec-driven cycles with per-acceptance-criterion red-green-refactor and code review phases.
README.md
spec-tests-first — Spec-Driven Development for Claude Code (v2.2.1)
A Claude Code plugin that runs a Spec-Driven Development cycle in six phases (spec → build → review → fix → validate → ship), each a self-contained skill, plus /spec-tests-first:init (pre-cycle setup for existing repos), /spec-tests-first:update (iteration handler), /spec-tests-first:run (orchestrator), a read-only /spec-tests-first:status slash command, and a /spec-tests-first:tests deprecation shim. Four subagents power the cycle: test-runner (Haiku) for test execution and three reviewers (code-quality-reviewer, security-reviewer, code-reporter, all Sonnet) for the in-cycle code-review phase. The plugin is fully self-contained — zero external plugin dependencies.
Quick start
# 1. Install
/plugin marketplace add Akhiranandha/custom-claude-plugins
/plugin install spec-tests-first@akhira-plugins
# 2. Run the whole cycle for a feature (recommended entry point)
/spec-tests-first:run my-feature
/spec-tests-first:run is the orchestrator — it chains all six phases with a checkpoint between each and offers to run /spec-tests-first:init first if the repo isn't set up for SDD yet. Start here unless you want to drive phases manually.
Prefer manual control? Run the phases yourself in order:
/spec-tests-first:init <project> # optional — adopt SDD on an existing repo
/spec-tests-first:spec my-feature # then build → review → fix → validate → ship
Each phase prints a Next: … pointer when it finishes, so you always know the next command.
Requirements: git (required), gh authenticated (only for /spec-tests-first:ship when a remote is configured), and your project's test runner on PATH. No external Claude Code plugins needed.
The cycle
/spec-tests-first:init <project> → Phase 0 (optional): Bring a repo into SDD — fresh / existing-codebase / migrate-flat-specs
/spec-tests-first:spec <feature> → Phase 1: Write spec interactively (8-section template, monorepo-aware, scope check, user-approval gate)
/spec-tests-first:build <feature> → Phase 2: Per-AC red-green-refactor — resolve profile, scaffold, iterate ACs
/spec-tests-first:review <feature> → Phase 3: code-quality + security reviewers in parallel → timestamped report
/spec-tests-first:fix <feature> → Phase 4: Walk findings one-by-one, revert-on-regression, mutate report in place
/spec-tests-first:validate <feature> → Phase 5: Walk VS-N steps (auto + manual checklist)
/spec-tests-first:ship <feature> → Phase 6: Inline commit/push/PR/merge — SDD-aware messages
/spec-tests-first:update <feature> → Iteration: amend spec; only changed ACs re-iterate via RGR in /spec-tests-first:build
/spec-tests-first:run <feature> → Orchestrator: chains the 6 phases (offers /spec-tests-first:init at start if needed)
/spec-tests-first:status [<feature>] → Read-only progress + findings rollup (aggregate or per-AC drill-down)
/spec-tests-first:status is a slash command, not a skill — it never writes files, never invokes other phases, never proposes next actions. Use it to check progress at any point without disturbing the cycle. With no argument it scans every docs/specs/*/spec-status.md and prints one row per spec; with a feature name it drills into that spec and prints one row per AC-ID plus a Latest-review summary block.
Spec file convention
All specs live at docs/specs/<feature>/spec.md in the target project (not the plugin). Each spec folder accumulates:
spec.md— the spec itself (8 sections: Goal, Requirements, Acceptance Criteria with AC-IDs, User stories, Technical details, Out of scope, Edge cases / open questions, Validation steps with VS-IDs).spec.md.prev— snapshot from the last/spec-tests-first:update(used for diff).spec-status.md— live status per AC-ID (pass/fail/blocked/stale/not-started/removed/in-progress), plus a top-of-fileLatest review: <path>pointer.
The project has one shared docs/codebase-map.md — a project-wide table of source files with one-line role descriptions, append/merge-updated by /spec-tests-first:build after each spec.
Review reports are written to ./reports/code-review_<feature>_<YYYY-MM-DD_HHMMSS>.md in the target project; /spec-tests-first:fix mutates the per-finding Status: field in place and appends a ## Fix log table.
Test commands + test layout (project convention — CLAUDE.md)
Two project-wide config sections in the target project's CLAUDE.md:
## Test commands
| name | command | default |
|------|----------------------|---------|
| unit | `python -m pytest` | yes |
| e2e | `playwright test` | no |
## Test layout
profile: python-pytest
tests_root: tests/<feature>/
files: test_<cluster>.py
fixtures: tests/<feature>/conftest.py
feature_anchor: directory
/spec-tests-first:build reads both. If either section is missing, it auto-detects from project manifests (pyproject.toml, package.json, pom.xml, etc.), confirms with the user via AskUserQuestion, and writes the section. Subsequent phases read without re-prompting.
Built-in test layout profiles
| Profile | tests_root | files | feature_anchor |
|---|---|---|---|
python-pytest |
tests/<feature>/ |
test_<cluster>.py |
directory |
python-unittest |
tests/<feature>/ |
test_<cluster>.py |
directory |
js-jest |
tests/<feature>/ |
<cluster>.test.ts |
directory |
js-vitest |
tests/<feature>/ |
<cluster>.test.ts |
directory |
react-jest-rtl |
src/features/<feature>/__tests__/ |
<Component>.test.tsx |
directory |
angular-jasmine |
co-located with source | <thing>.spec.ts |
co-located |
spring-boot-junit5 |
src/test/java/<pkg>/<feature>/ |
<Cluster>Test.java |
directory |
go |
same dir as source | <source>_test.go |
co-located |
rust |
tests/<feature>/ (integration); #[cfg(test)] for unit |
<cluster>.rs |
directory |
dotnet-xunit |
<Project>.Tests/<Feature>/ |
<Cluster>Tests.cs |
directory |
ruby-rspec |
spec/<feature>/ |
<cluster>_spec.rb |
directory |
phpunit |
tests/<feature>/ |
<Cluster>Test.php |
directory |
custom |
user-supplied | user-supplied | user-supplied |
For unknown stacks, /spec-tests-first:build prompts the user inline for the four fields (tests_root, files, fixtures, feature_anchor) and saves as profile: custom. No plugin update needed.
Per-stack test-writing patterns (fixtures, assertion styles, anti-patterns) for every profile live in skills/build/references/test-writing-patterns.md, which /spec-tests-first:build reads during the RED step.
Monorepo support
When /spec-tests-first:spec detects multiple stack manifests in subdirectories (e.g. frontend/package.json + backend/pom.xml), it asks whether to configure multi-service. On yes:
## Test commands
### service: frontend
| name | command | default |
|------|------------|---------|
| unit | `npm test` | yes |
### service: backend
| name | command | default |
|------|------------|---------|
| unit | `mvn test` | yes |
## Test layout
### service: frontend
profile: react-jest-rtl
tests_root: frontend/src/features/<feature>/__tests__/
...
### service: backend
profile: spring-boot-junit5
tests_root: backend/src/test/java/com/example/<feature>/
...
Specs add a Services: line and per-service AC subsections:
# Spec: login-flow
Services: backend, frontend
## 3. Acceptance Criteria
### Backend (service: backend)
- AC-1.1: POST /api/login returns 200 with JWT on valid credentials.
- AC-1.2: POST /api/login returns 401 with `{"error":"invalid credentials"}` on bad password.
### Frontend (service: frontend)
- AC-2.1: LoginForm submits credentials and stores the returned JWT in localStorage.
- AC-2.2: On 401 response, LoginForm shows the inline error "Invalid credentials".
/spec-tests-first:build reads each AC's enclosing subsection header, looks up that service's profile + test command, and writes the test in the right tests_root. Cross-service ACs run sequentially.
Single-service repos omit the per-service subheadings — the format degrades to today's single-block layout. No breakage.
Dependencies
External plugins
None. STF v2 is fully self-contained.
System binaries
git— required by/spec-tests-first:build(stash, branch, end-of-build commit),/spec-tests-first:fix(per-fix atomic commits, revert-on-regression), and/spec-tests-first:ship(commit, push, remote detection).gh(GitHub CLI), authenticated — required by/spec-tests-first:shiponly when a remote is configured (push, PR, merge).- Project test runners — resolved from
CLAUDE.md ## Test commands(single-service or multi-service). The plugin itself is language-agnostic.
Subagents
test-runner(Haiku 4.5, Bash-only) — Runs the resolved test command, parses output, returns a strict JSON summary keyed by AC-ID (passed/failed/errored/missing_ac_ids/exit_code/stdout_tail). Invoked by/spec-tests-first:build's RED, GREEN, REFACTOR, and REGRESSION-CHECK steps per AC, by/spec-tests-first:review's pre-flight test check, and by/spec-tests-first:fix's per-fix regression check. Read-only — never writes files; the parent skill ownsspec-status.md. Users do not invoke it directly.code-quality-reviewer(Sonnet, Read+Grep+Glob+Bash) — SonarQube-style review across 10 dimensions (cyclomatic complexity, function/file length, duplication, naming, dead code, magic numbers, deep nesting, error handling, inconsistent patterns, test coverage gaps). Language-aware idiom checks. Runseslint/tsc/ruff/golangci-lint/ etc. in check-only mode if present. Read-only.security-reviewer(Sonnet, Read+Grep+Glob+Bash) — OWASP Top 10 (2021) review (injection, XSS, CSRF, SSRF, XXE, path traversal, auth/authz, crypto, secrets, configuration, input handling). CWE + OWASP refs per finding. Runsgitleaks,semgrep,bandit,npm audit,govulncheck,trivy, etc. when present. Read-only.code-reporter(Sonnet, Read+Write+Bash) — Aggregates the two reviewer outputs into one timestamped Markdown report under./reports/. Performs no analysis of its own — faithful aggregation only. Emits stable finding IDs (SEC-NNN,QUA-NNN) and initializesStatus: pendingper finding so/spec-tests-first:fixcan mutate them in place. Only writes the report file; no other writes.
Key design decisions
- Per-AC red-green-refactor. Tests are written one at a time inside
/spec-tests-first:build. Every test is verified failing viatest-runnerbefore any production code is written (the Iron Law: no production code without a failing test first). Every fix is verified green before moving on. Then the full feature suite runs as a regression check — a passing AC test that breaks a prior AC reverts the implementation. The RGR loop loadssuperpowers:test-driven-developmentfor its discipline layer. - Cap = 3 attempts per AC, not feature-wide. Each AC fails fast and gets individual attention. No silent retries past cap.
- Two-stage code review per feature.
/spec-tests-first:reviewruns the two reviewer agents in parallel, writes a report./spec-tests-first:fixwalks findings one-by-one with revert-on-regression and atomic commit per fix. The Critical gate (nopendingordeferredCritical findings) is enforced at both/spec-tests-first:fixexit and/spec-tests-first:shippre-check. - Stable finding IDs. The reporter emits
SEC-001,QUA-014, etc. so/spec-tests-first:fixcan address findings by ID across multiple sessions.Status:lines are parser-stable and mutated in place; the original report body stays verbatim. - Atomic commits per successful fix. Clean git history, cheap revert, easy audit.
/spec-tests-first:buildcommits the whole feature once at the end;/spec-tests-first:fixadds incremental commits on top;/spec-tests-first:shiptypically has nothing left to commit (only edits made after the last fix). - Stack-aware test layout via profiles. 12 built-in profiles cover ~95% of real-world stacks. Unknown stacks fall back to a
customprofile saved toCLAUDE.md. Co-located profiles (Angular, Go) skip directory scaffolding; AC-ID embedding in test names makes/spec-tests-first:update's "find tests for changed ACs" work for them via grep. - Multi-service awareness. Specs can target multiple services in a monorepo. Each AC carries a service tag (via subsection header).
/spec-tests-first:buildresolves per-AC service → profile + test command./spec-tests-first:reviewand/spec-tests-first:fixsee the cross-service diff naturally. - Spec.md as the contract. Section 3 ACs are binary and testable; every error-path AC names a discriminating signal (stderr substring, exception class, status code). Vague error contracts produce false-pass tests; the spec phase enforces this.
/spec-tests-first:runis the orchestrator with explicit checkpoints between every phase. Resumable — re-invoking detects existing artifacts (spec, status, review report, fix log, validation block) and offers to skip already-done phases./spec-tests-first:statusis read-only. Never modifies files; never invokes other phases. Aggregate view gains aCritical Outstandingcolumn in v2 so blocked specs surface at a glance.- Backward compatible with v1 artifacts. Existing
spec.mdandspec-status.mdfiles keep working. TheLatest review:field is added the first time/spec-tests-first:reviewruns. The/spec-tests-first:testscommand stays valid as a deprecation shim that redirects users to/spec-tests-first:build.
Changelog
v2.2.1 (over v2.2)
Documentation / wording patch — no behavioral changes. 13 audit findings addressed:
- Wording fixes:
/spec-tests-first:shipPhase 6 status update now explicitly says "after pre-checks, before Step 1" instead of the misleading "before doing anything else"./spec-tests-first:fixStep 6 sub-labels (6a/6b) flattened into parent prose for cleaner navigation.
- Backward-compat gap:
/spec-tests-first:buildStep 5c now explicitly handles v1spec-status.mdfiles that lack a## Phase progresstable — inserts the full 6-row table and backfills Phase 1 = done.
/spec-tests-first:runpolish:- Resumability table now includes an "Init" row so an already-initialized project doesn't trigger the Phase 0 prompt every time.
/spec-tests-first:fixpolish:- The
--report <path>flag advertised inargument-hintnow has explicit parsing instructions in Pre-check 2.
- The
- README polish:
- Opening blurb now accurately lists all 10 skills (was claiming "six").
- Title bumped to
(v2.2.1)to matchplugin.json.
- Agent descriptions:
code-quality-reviewer,security-reviewer,code-reportereach gain a one-line note that/spec-tests-first:reviewis the canonical entry point inside this plugin.
/spec-tests-first:initpolish:- Case A.2 gitignore inlined with explicit "language-agnostic vs
/spec-tests-first:build's language-specific" note (no more brittle cross-skill reference).
- Case A.2 gitignore inlined with explicit "language-agnostic vs
plugin.jsonkeywords:- Dropped redundant
migrationkeyword (covered byinit).
- Dropped redundant
v2.2 (over v2.1)
- New
/spec-tests-first:initpre-cycle skill. STF can now be adopted on existing repos, not just greenfield. Auto-detects three cases:- Case A — fresh repo, fresh project. Near-no-op: scaffolds CLAUDE.md sections + empty codebase-map.md.
- Case B — existing codebase, no specs yet. Resolves test profile(s) per service for monorepos, seeds
docs/codebase-map.mdfrom source using per-profile glob patterns (12 built-in profiles + custom). - Case C — existing repo with flat
docs/specs/*.mdfiles. Migrates into v2 subdirectory layout. Converts US-N IDs → AC-N.M (happy-path stories deterministic; error-path ACs flagged withTODO(needs discriminating signal)placeholders). Scaffolds per-featurespec-status.mdwith the v2.1## Phase progresstable. Runs a two-signal implementation scan (source files + test files) and proposes Phase 2 status per feature in a single batch confirmation.
/spec-tests-first:runintegration. The orchestrator detects un-initialized projects and offers to run/spec-tests-first:initbefore Phase 1.- Strict idempotency.
/spec-tests-first:initis safe to re-run; never overwrites existing specs, spec-status, or non-empty codebase-map files.
v2.1 (over v2)
- Per-phase status tracking.
spec-status.mdnow has a## Phase progresstable at the top — every phase skill updates its own row (pending→in-progress→done/fail/blocked)./spec-tests-first:statusaggregate view shows current phase per spec at a glance. - Explicit user-approval gate after
/spec-tests-first:spec. The spec phase ends with an AskUserQuestion — Approve / Edit / Cancel. Only on Approve does Phase 1 =done, and/spec-tests-first:buildrefuses to run against an unapproved spec. - Scope check in
/spec-tests-first:spec(Step 1.5). Detects oversized requests (multiple independent features mashed into one) and prompts to split into separate sequential specs vs. combine. Prevention beats post-build refactor. - Superpowers-style flow on every skill. Announce-at-start lines, Iron Law callouts near the top, Red Flags + Common Rationalizations tables for the high-temptation skills (
/spec-tests-first:build,/spec-tests-first:fix).
v2 (over v1)
| v1 | v2 |
|---|---|
| 5 phases: spec → tests → build → validate → ship | 6 phases: spec → build → review → fix → validate → ship |
/spec-tests-first:tests generated ALL tests upfront, then /spec-tests-first:build implemented |
/spec-tests-first:tests is a deprecation shim; /spec-tests-first:build writes tests per-AC inside the red-green-refactor loop |
| Test-fix loop capped at 3 attempts across the whole feature | Cap = 3 attempts per AC (faster failure isolation) |
Inline pre-commit review hand-rolled inside /spec-tests-first:ship |
Dedicated /spec-tests-first:review phase using the two reviewer agents |
PR-level review via external code-review plugin |
Same reviewers run pre-commit in /spec-tests-first:review; no external plugin needed |
Commit/PR via external commit-commands plugin |
Inlined in /spec-tests-first:ship with SDD-aware commit message + PR body |
Python-flavored tests/<feature>/ assumed |
12 built-in stack profiles + custom for unknown stacks; multi-service-aware |
External dependencies: commit-commands + code-review |
None — fully self-contained |