tdd-gate — Claude Code hook: tests before production code
The hook blocks edits to production files until a matching test exists. Useful if you want the agent to keep the TDD order.
npx claude-code-templates@latest --hook quality-gates/tdd-gateWhat tdd-gate does
tdd-gate runs on PreToolUse and intercepts Edit, MultiEdit and Write. Before a file with a .cs, .py, .ts, .go, .rs, .rb, .php, .java, .kt, .swift or .dart extension gets touched, the script looks for a test file named like MyClassTest.ext, my-class.test.ext, my_class_test.ext or test_my_class.ext. No test found, no edit.
Config files, migrations, DTOs, infrastructure files and the tests themselves are skipped. So the hook won't stop you from editing settings.json or a schema, but it will stop you from adding a method to a service with no test beside it. All the logic lives in tdd-gate.sh, dropped into .claude/hooks/ and called through $CLAUDE_PROJECT_DIR.
Install with npx claude-code-templates@latest --hook quality-gates/tdd-gate; the hook entry lands in .claude/settings.json. The script needs bash on the machine. The author points to the Spec-Driven Development methodology from pm-workspace.
What it helps with
- make the agent write a test before the implementation
- catch a service edit that has no coverage
- stop a new method from landing without a test
- keep the test-first order on a fresh feature
Example prompts for the agent
- Add a discount calculation method to OrderService — test first, then the code
- Write a test for this case, then touch the implementation
- Why is this edit blocked? Check whether a test file exists for this module
How to install tdd-gate
1claude-code-templates
npx claude-code-templates@latest --hook quality-gates/tdd-gate2Manually: put the files in place
.claude/settings.jsonThe hooks block: event (PreToolUse, PostToolUse, Stop…) → command. Personal ones go to ~/.claude/settings.json
Step by step, with commands for each platform: Claude Code hooks: what they are, where to configure them, how to block a risky command
Questions about tdd-gate
How do I install tdd-gate in Claude?
Run npx claude-code-templates@latest --hook quality-gates/tdd-gate. It copies tdd-gate.sh into .claude/hooks/ and adds the hook to .claude/settings.json.
What does tdd-gate do?
It blocks Edit, MultiEdit and Write on production files unless a test with a matching name exists. Configs, migrations, DTOs and test files pass through.
Which test file names does the hook recognise?
MyClassTest.ext, my-class.test.ext, my_class_test.ext and test_my_class.ext. A file named differently won't satisfy the gate.
Source text
tdd-gate.json · MIT
{
"description": "Test-Driven Development enforcement hook. Blocks editing production code files (.cs, .py, .ts, .go, .rs, .rb, .php, .java, .kt, .swift, .dart) unless a corresponding test file exists. Forces the TDD workflow: write tests first, then implement. Automatically skips config files, migrations, DTOs, test files themselves, and infrastructure files. Looks for test files with common naming patterns (MyClassTest.ext, my-class.test.ext, my_class_test.ext, test_my_class.ext). Inspired by pm-workspace's Spec-Driven Development methodology.",
"supportingFiles": [
{
"source": "tdd-gate.sh",
"destination": ".claude/hooks/tdd-gate.sh",
"executable": true
}
],
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/tdd-gate.sh"
}
]
},
{
"matcher": "MultiEdit",
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/tdd-gate.sh"
}
]
},
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/tdd-gate.sh"
}
]
}
]
}
}
© davila7 · MIT · davila7/claude-code-templates