tdd-loop
Skill5 starsChanged 15 days agoMITView on GitHub
Runs strict test-driven development one behaviour at a time. Picks the next smallest behaviour from the spec or task list, writes one failing test, makes the smallest change that passes it, then refactors with the tests green. A guard script records each step and refuses the usual shortcuts. It rejects a red step that fails for the wrong reason (syntax, import or compile error, missing function, no tests ran) and code written before any failing test. It also rejects a test that was edited, deleted, skipped or focused with .only to reach green. Works with pytest, unittest, Jest, Vitest, go test, cargo test, RSpec, Maven and Gradle. Use when the user asks to do TDD, work test-first, write the test first, follow red green refactor, build a feature test-driven from a spec or user story, or stop the agent from changing tests to make them pass.
9 other projects use a version of this.
Adopted by
Most recently taken up by
- OrionArchitekton/orion-skillstheir own version, first seen Nov 2, 2026
- michaelalber/ai-toolkittheir own version, first seen Nov 1, 2026
- daniel-kindl/dkstacktheir own version, first seen Nov 1, 2026
- sbradl/claude-skillstheir own version, first seen Oct 15, 2026
- dagarre00/claude-code-templatetheir own version, first seen Oct 15, 2026
- qyndex/claude-inittheir own version, first seen Oct 13, 2026
Other versions9 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 9
- khuynh22/agent-dev-team★ 9same name
- ramboz/jig★ 7same name
- michaelalber/ai-toolkit★ 3same name
- OrionArchitekton/orion-skills★ 2same name
- qyndex/claude-init★ 2same name
- dagarre00/claude-code-template★ 1same name
- daniel-kindl/dkstack★ 1same name
- itsmuskanagarwal/claude-pack★ 0same name
- sbradl/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository56 other files it gives its agents.
- docs/llms.txtllms.txt
- a11y-fixerSkill
- ad-copy-generatorSkill
- agent-guardrailsSkill
- agent-memory-keeperSkill
- ai-slop-detectorSkill
- api-to-sdkSkill
- app-store-optimizerSkill
- architecture-doctorSkill
- brand-voice-guideSkill
- bug-detectiveSkill
- changelog-from-gitSkill
- codebase-explainerSkill
- codebase-time-machineSkill
- commit-craftSkill
- competitor-spySkill
- content-repurposerSkill
- cost-cutterSkill
- demo-recorderSkill
- dependency-doctorSkill
- dockerize-anythingSkill
- durable-agent-workflowsSkill
- e2e-flow-testerSkill
- email-campaign-writerSkill
- env-secrets-guardSkill
- gh-actions-auditorSkill
- hook-generatorSkill
- incident-commanderSkill
- influencer-outreachSkill
- instagram-growth-managerSkill
- landing-page-roasterSkill
- launch-post-writerSkill
- meeting-notes-to-ticketsSkill
- merge-conflict-resolverSkill
- migration-wizardSkill
- plan-grillerSkill
- prompt-injection-scannerSkill
- pr-reviewer-proSkill
- readme-glow-upSkill
- roast-my-githubSkill
- screenshot-to-componentSkill
- seo-blog-writerSkill
- skill-creator-proSkill
- skill-finderSkill
- skills-doctorSkill
- social-analytics-reporterSkill
- social-media-calendarSkill
- social-media-managerSkill
- sql-optimizerSkill
- startup-idea-validatorSkill
- terse-modeSkill
- test-gap-hunterSkill
- tiktok-viral-creatorSkill
- ui-tasteSkill
- youtube-script-writerSkill
- youtube-seo-optimizerSkill
The file
We split this skill into the rules it gives an agent
7 rules. 0 are common, 3 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 9 edited versions we read keep these.
3
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 59
Remove duplication, rename, extract, and simplify the test code as well as the production code.
- Very specific: line 69
Commit after each refactor if the user wants a commit per cycle.
- Very specific: line 75
After each cycle, give one line: behaviour, test name, red reason (assertion), green, refactor done or skipped, commit.
- Distinctive: line 80
Write several tests before making any of them pass.
- Distinctive: line 84
Add behaviour during refactor, or refactor while red.
- Very specific: line 85
Run --allow-test-change or --allow-error without telling the user the reason.
- Very specific: line 86
Delete .tdd/ to get around a failed check.
“Common” is measured: kept by at least 6 in 10 of the 9 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
TDD Loop
Build one behaviour at a time: a failing test, the least code that passes it, then a cleanup with the tests green. The guard script makes each step checkable, so "I wrote the test first" is a recorded fact rather than a claim.
0. Set up once
python3 scripts/tdd_guard.py detect # suggests the test command from project filesPick a command that runs once and exits (npx vitest run, not vitest in watch mode). Prefer one that runs the current test file or test, so cycles stay fast, and run the whole suite before each commit. The guard keeps its state in .tdd/ at the project root and writes a .tdd/.gitignore so git ignores it. Add .tdd/ to the project's .gitignore too if the user wants it listed there.
Run one test:
| Runner | Command |
| pytest | python3 -m pytest -q tests/test_slug.py::test_lowercases |
| unittest | python3 -m unittest tests.test_slug.SlugTest.test_lowercases |
| Vitest / Jest | npx vitest run src/slug.test.ts -t "lowercases" / npx jest src/slug.test.ts -t "lowercases" |
| go test | go test ./slug -run '^TestLowercases$' |
| cargo | cargo test lowercases |
| Maven | mvn -Dtest=SlugTest#lowercases test |
1. Make a behaviour list
From the spec, issue or user story, write a short list of behaviours, each one observable from outside: "slugify('Hello World') returns hello-world", "a cart with an expired code is charged full price". Order them so each builds on the last, simplest and most central first. Show the list to the user and keep it updated in the conversation.
Slice vertically. One behaviour goes through every layer it needs (route, service, storage) in a single cycle. Don't write all the models first, then all the services.
2. Red: one failing test
Write exactly one test for the next behaviour. Test through the public interface (the function, the endpoint, the CLI), and assert on results the caller can see, not on private helpers or which internal methods were called. If the code doesn't exist yet, add a stub that compiles and returns a placeholder, so the test fails on its assertion rather than on an import.
python3 scripts/tdd_guard.py red --test "python3 -m pytest -q tests/test_slug.py"
python3 scripts/tdd_guard.py red --test "npx vitest run src/slug.test.ts" --files src/slug.test.ts
python3 scripts/tdd_guard.py red # later cycles reuse the recorded commandred passes only when the command fails on an assertion. It refuses if the tests pass already, if the failure is a syntax, import, compile or collection error, a missing function, a missing command, a timeout, or if no tests ran. It records SHA-256 snapshots of the test files: --files, plus every test file git status shows as changed. Without --files it needs at least one test file that is new or changed since the last cycle. It warns when more than one new test appeared, when the new test's name isn't in the failure output, and when source files were already changed. If the error really is the behaviour under test, pass --allow-error "reason", which is recorded.
3. Green: the smallest change that passes
Change only production code. Hard-coding the expected value is fine when it is the simplest thing that passes. The next test will force the general version.
python3 scripts/tdd_guard.py greengreen re-runs the recorded command and passes only if it exits 0 with tests run and no test file changed since red. A changed or deleted test file, or an added skip or focus marker (@pytest.mark.skip, @unittest.skip, it.skip, xit, describe.only, t.Skip(), #[ignore], @Disabled), fails the check and prints the diff. This covers older test files too. If the test itself was wrong, revert it and run red again, or tell the user why and run green --allow-test-change "reason".
4. Refactor with the tests green
Remove duplication, rename, extract, and simplify the test code as well as the production code. Keep the behaviour the same and re-run after each small step.
python3 scripts/tdd_guard.py refactorIt passes when the tests pass and no test file lost tests or assertions, gained a skip marker or was deleted. It lists the test files that changed. If a test was added, write it in the next red cycle instead.
5. Commit and repeat
Commit after each refactor if the user wants a commit per cycle; otherwise keep going. Tick the behaviour off the list and return to step 2. python3 scripts/tdd_guard.py status shows the phase, the guarded files and the cycle count.
Exit codes for every command: 0 check passed, 1 check failed (the reason is printed), 2 usage or state error, such as green with no recorded red. Add --json for machine-readable output and --dir to point at the project root.
Report
After each cycle, give one line: behaviour, test name, red reason (assertion), green, refactor done or skipped, commit. At the end, list the behaviours done and the ones left, plus any --allow-* overrides and why they were needed.
What not to do
- Skip red, or write the implementation and then a test that passes on the first run.
- Write several tests before making any of them pass.
- Change, loosen, delete,
.skip,xitor.onlya test to get to green. - Mock everything. Mock only what is slow or outside your control (network, clock, payment provider), and use real objects for the rest.
- Assert on implementation details (private methods, call counts on internal collaborators) that break on every refactor.
- Add behaviour during refactor, or refactor while red.
- Run
--allow-test-changeor--allow-errorwithout telling the user the reason. - Delete
.tdd/to get around a failed check. Fix the cause, or ask the user.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

