/tdd-workflow is not a built-in Claude Code command. There is no shipped TDD command and no built-in TDD flags. This entry is a custom slash command recipe: you save a Markdown prompt file in your repo and Claude Code exposes it as /tdd-workflow. It works by injecting a fixed red-green-refactor prompt into the session, then letting Claude drive your existing test runner.
Custom commands are documented here: https://code.claude.com/docs/en/slash-commands
How custom commands work
- A file at
.claude/commands/<name>.md (project scope, checked into the repo) or ~/.claude/commands/<name>.md (personal scope) becomes the slash command /<name>. The command name is the file name without the .md extension.
- The Markdown body is the prompt that gets sent to Claude when you invoke the command.
- Optional YAML frontmatter controls behavior. Documented fields include
description, argument-hint, arguments, allowed-tools, disallowed-tools, disable-model-invocation, model, and shell.
- Arguments are substituted into the body:
$ARGUMENTS expands to everything you typed after the command; $1/$2 (shorthand for $ARGUMENTS[1]/$ARGUMENTS[2], 0-based) access positional arguments; named placeholders like $feature work when you declare them in the arguments frontmatter.
- The body can run shell commands at expansion time with
!`command` and reference files with @path/to/file.
Note: As of the current docs, custom commands have been merged into skills. A file at .claude/commands/tdd-workflow.md and a skill at .claude/skills/tdd-workflow/SKILL.md both create /tdd-workflow and behave the same way; existing .claude/commands/ files keep working. Use the skill form if you want supporting files or automatic invocation.
Create the command
Save this as .claude/commands/tdd-workflow.md:
---
description: Drive a red-green-refactor TDD loop for the requested change
argument-hint: [feature description]
allowed-tools: Read, Edit, Write
disable-model-invocation: true
---
Follow strict test-driven development for: $ARGUMENTS
1. RED — Before writing any implementation, add focused failing tests that
describe only the requested behavior. Run the project's test command and
show me the failing output. Do not implement yet.
2. GREEN — Write the minimum implementation needed to make those tests pass.
Re-run the tests and show that they pass. Do not add behavior the tests
do not require.
3. REFACTOR — Clean up names and structure while keeping the tests green.
Re-run the tests after refactoring.
Use the test framework already configured in this project. First inspect the
project's test scripts or documented test command with me, then run only the
exact command I approve. Stop and ask me before changing test configuration,
adding new dependencies, or running a different command.
disable-model-invocation: true keeps Claude from triggering the loop on its own; you invoke it deliberately. The base recipe intentionally does not pre-approve Bash test commands. Let Claude Code prompt you on the first run, review the exact command and project script it will execute, and only then approve or narrow the command to your actual runner (Jest, Vitest, pytest, go test, etc.).
Invoke it
/tdd-workflow add a slugify() helper that strips punctuation and lowercases
Everything after the command name becomes $ARGUMENTS. Claude then walks the red-green-refactor steps from the prompt, using whatever test framework your project already has.
If you want positional arguments instead, declare them in frontmatter:
---
description: TDD a change in a specific module
argument-hint: [module] [behavior]
arguments: [module, behavior]
---
TDD the behavior "$behavior" in the module `$module`, red-green-refactor.
Then /tdd-workflow auth "rejects expired tokens" maps $module to auth and $behavior to rejects expired tokens (quote multi-word values).
When to use it
- You want to enforce test-first discipline in agent-assisted work, so the tests pin down scope before implementation.
- You repeatedly paste the same "write failing tests, then implement, then refactor" instructions and want a one-keystroke entry point.
- You want the loop checked into the repo so the whole team shares the same TDD prompt (project-scope
.claude/commands/).
Honest limitations
- This is just a saved prompt. It does not add new flags to Claude Code, does not enforce coverage thresholds, and cannot guarantee Claude writes tests first — it strongly steers the model, but the model still drives.
- Coverage numbers, watch mode, and auto-commit are features of your test runner and git, not of this command. Wire them in only after reviewing the exact commands and risks; avoid broad wildcard
allowed-tools entries for repository-controlled scripts.
- Behavior depends on your installed test framework and scripts; the command does not install or configure tooling.
Customizing the loop
- After reviewing your project's scripts, optionally add a narrowly scoped, exact test command to
allowed-tools and the prompt to match your stack.
- Add a final step that runs your linter/formatter if you want those gated too.
- For E2E or integration variants, create sibling files like
.claude/commands/tdd-e2e.md with a prompt tailored to that layer, rather than relying on flags.