tdd-loop
Drive the red-green-refactor loop for any non-trivial code change.
Skill by ramboz
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/ramboz-tdd-loop
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: testing, writing
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Python package
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/tdd-loop
What's inside
- Skill name
tdd-loop- Description
- Drive the red-green-refactor loop for any non-trivial code change. Auto-detect the project's test runner (pytest / vitest / jest / node --test), invoke it via the `tdd.py` helper, and act on the normalized exit code. Use when you write a test, TDD this feature, let me test-drive a behaviour, are about to implement [feature], want to run my tests, ask is my coverage complete, or ask are tests green. Do not use for one-off exploratory scripts, throwaway spikes, or pure-documentation edits that touch no executable code.
- License
- MIT
- Instructions
- 194 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Files (3)
- SKILL.md
- quality.py
- tdd.py
SKILL.md (first lines)
> Spec 006 promoted this skill from a dangling auto-install reference to an
> active skill. The deterministic runner detection + subprocess invocation
> live in `tdd.py`; this SKILL.md drives the judgment layer.
## What this skill does
Codifies the red-green-refactor loop that the `implementer` subagent
(`agents/implementer.md`) already encodes as "non-negotiable TDD discipline."
The skill:
- Detects the project's test runner from filesystem signals (one of `pytest`,
`vitest`, `jest`, or Node's built-in `node --test`).
- Invokes the runner as a subprocess against a target, a focused
`--test-path`, or a single `--test` selector.
- Streams the runner's stdout/stderr through to the caller — you see real
output, not a swallowed summary.
- Normalizes the runner's native exit code so callers can branch
deterministically:
- `0` — all green
- `1` — at least one red test (runner started but reported failure)
- `2` — could not detect a runner, OR the runner binary is missing
## The red-green-refactor loop
1. **Red.** Write a failing test for one acceptance criterion (or one
well-bounded behaviour). Run `tdd.py run <target>` and confirm the new
test is the *only* new failure — exit 1.
2. **Green.** Write the minimum implementation that makes the test pass.
Run `tdd.py run <target>` again; expect exit 0.
3. **Refactor.** Clean up only after green. Re-run after each meaningful
refactor; exit 0 must hold.
Stay in this loop one AC at a time. Do not write three tests and then three
implementations — the loop's value is the tight feedback cycle.
### When a test you did NOT just write goes red
The Green step above is about the *new* failing test you wrote for this AC —
making it pass is the work. A **pre-existing** test going red is the opposite
signal: it is a guard reporting that your change touched something load-bearing.
The reflex to "make it green" is wrong here, and an agent is very good at
satisfying it — deleting the assertion, loosening the expectation, or marking
the test skipped all turn the light green while removing the protection.
So: **when a test you did not just write fails, do not fix the test — first
suspect that your change broke what the test guards.** Only after you have ruled
that out (the test encodes an intent that has genuinely, deliberately changed)
may you touch the test, and then update its assertion *and its rationale*
together so the next reader sees why. Never weaken, skip, `xfail`, or quarantine
a pre-existing test to reach green. (This mirrors the standing rule for driving
a PR to green — a red guard is work now, not an obstacle to route around.)
## Helper invocations
Two subcommands cover the loop: `tdd.py detect` figures out which runner the
project uses, and `tdd.py run` invokes it.
### Detect the runner
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/tdd-loop/tdd.py" detect [target]
```
- `target` defaults to `.` when omitted.
- Stdout: `pytest`, `vitest`, `jest`, or `node` (one line).
- Exit 2 with stderr `no test runner detected at <target>` if no signal matches.
Signals checked (priority order — first hit wins):
- **pytest** — `pytest.ini` OR `conftest.py` OR `[tool.pytest` in
`pyproject.toml` OR a `test_*.py` / `*_test.py` file at root or in any
direct subdirectory.
- **vitest** — `vitest.config.{ts,js,mjs}` OR `vitest` in `package.json`'s
`dependencies` / `devDependencies`.
- **jest** — `jest.config.{ts,js,json}` OR `jest` in `package.json`'s
`dependencies` / `devDependencies`.
- **node** — `package.json` `scripts.test` invokes `node --test`, OR a shallow
JS/TS file imports from `node:test`.
When multiple runners are detected, priority is
**pytest > vitest > jest > node**.
### Run the suite
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/tdd-loop/tdd.py" run [target] [--test-path PATH]
python3 "${CLAUDE_PLUGIN_ROOT}/skills/tdd-loop/tdd.py" run [target] [--test SELECTOR]
```
- Auto-detects the runner via the same logic as `detect`.
- Default commands:
- pytest → `python3 -m pytest <path>`
- vitest → `npx vitest run <path>` (note the `run` — keeps watch mode off)
- jest → `npx jest <path>`
- node → `node --test` for the full suite; `node --test <path>` with
`--test-path`
- Output streams through to the caller's terminal.
- Exit code is normalized (0 / 1 / 2) per the table above.
Use `--test-path` when you want to run a focused subset (e.g. a single
test file) while still letting the helper detect which runner to invoke.
Use `--test` when you want one named test: pytest selectors are passed as
node ids (`path::test_name`), vitest/jest selectors map to file plus `-t`,
and node selectors map to file plus `--test-name-pattern` when shaped as
`path::test name`.
## When NOT to use
- **One-off scripts** or **REPL exploration** — TDD overhead isn't worth it
for code that won't survive the session.
- **Exploratory spikes.** Spikes are research artifacts; they answer "what
shape should this take?" — tests come *after* the spike has settled the
shape.
- **Pure-documentation edits** that touch no executable code.
- **Auto-generated code** (codegen output, vendored deps). Test the
generator, not the generated artifact.
## Sibling helper: `quality.py` (test-quality snapshot)From ramboz/jig, MIT.
More from ramboz/jig
- 0.624score
adr-workflow
ramboz
Scaffold, accept, index, and link Architectural Decision Records (ADRs).
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
analyze
ramboz
Cross-artifact consistency report for jig specs — a non-destructive six-category audit at CRITICAL/HIGH/MEDIUM/LOW severity, covering duplication, ambiguity…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
arch-review
ramboz
Team baseline for architecture, design-doc, and RFC review — produces summary, strengths, concerns, and open questions.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
bug-fix
ramboz
Drive the teeth-gated lifecycle for reported defects: diagnose root cause, prove it, and prevent regression through REPORTED → DIAGNOSING → ROOT_CAUSED →…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
clarify
ramboz
Lightweight spec clarification scan for jig projects — a six-category ambiguity audit that asks up to five prioritized questions and appends them to the…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
code-health
ramboz
Run a static-analysis pass on a project — detect the ecosystem (Python or Node), drive its linter (ruff / eslint, plus advisory pyright/complexity/ prettier…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
contracts
ramboz
Team baseline for external-interface contract artifacts: OpenAPI, JSON Schema, AsyncAPI, .proto, and GraphQL SDL, with spectral, ajv, buf, and…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
explain
ramboz
Explain jig vocabulary and artifacts in plain language.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
orient
ramboz
Orient a spec-driven jig/servo/shaper repository with a read-only, project-wide briefing: start from the `workflow.py orient` headline, then survey open pull…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
pr-review
ramboz
Team baseline for PR and code review — produces scope, blockers, nits, and strengths.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
reframe
ramboz
Re-baseline a jig corpus onto a moved load-bearing reference by drafting a keystone ADR and an affected-artifact disposition manifest.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
security-review
ramboz
Team baseline for security review — a best-effort heuristic security pass over a diff or change-set.
SkillAFreshness: A★ 7Claude Code +9
Signals
- Stars
- 7
- Forks
- 1
- Open issues
- 10
- Last commit (this folder)
- Aug 31, 2026 (1 month ago)
- Last release
- Oct 5, 2026 (24 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/ramboz/jig
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from ramboz
- 0.624score
analyze
ramboz
Cross-artifact consistency report for jig specs — a non-destructive six-category audit at CRITICAL/HIGH/MEDIUM/LOW severity, covering duplication, ambiguity…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
arch-review
ramboz
Team baseline for architecture, design-doc, and RFC review — produces summary, strengths, concerns, and open questions.
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
bug-fix
ramboz
Drive the teeth-gated lifecycle for reported defects: diagnose root cause, prove it, and prevent regression through REPORTED → DIAGNOSING → ROOT_CAUSED →…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
clarify
ramboz
Lightweight spec clarification scan for jig projects — a six-category ambiguity audit that asks up to five prioritized questions and appends them to the…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
code-health
ramboz
Run a static-analysis pass on a project — detect the ecosystem (Python or Node), drive its linter (ruff / eslint, plus advisory pyright/complexity/ prettier…
SkillAFreshness: A★ 7Claude Code +9 - 0.624score
adr-workflow
ramboz
Scaffold, accept, index, and link Architectural Decision Records (ADRs).
SkillAFreshness: A★ 7Claude Code +9
Cite this page
tdd-loop skill. Agent Mart. https://agentmart.dev/skills/ramboz-tdd-loop (last updated 2026-10-24)