---
name: mikey:tdd
description: "TDD workflow driven by Given/When/Then specifications. Provide a spec file or folder path for autonomous batch processing, or run without a path for an interactive TDD loop. Implements code using Functional Core / Imperative Shell design principles."
argument-hint: [path] [--plan] [--export]
user-invocable: true
---
| Parameter | Description |
|---|---|
path |
File or folder containing Given/When/Then specs (triggers agent mode) |
--plan |
Show implementation plan only, do not write code |
--export |
Save session report to sdd-report-<timestamp>.md |
Test-Driven Development workflow guided by Given/When/Then specifications and the embedded test philosophy.
Two modes:
- Agent mode (path provided): Reads spec files, extracts scenarios, and implements each via Red-Green-Refactor autonomously with check-ins between scenarios.
- Interactive mode (no path): Prompts the user to describe behaviors one at a time, implementing each through the TDD cycle with user approval.
This skill always applies:
- Red-Green-Refactor TDD cycle for every scenario
- Test philosophy: observable behavior, RITE tests, 5 Questions
- Functional Core / Imperative Shell code design — pure logic separated from I/O
- Minimal implementation — only write code required by the current test
Shared references:
${CLAUDE_PLUGIN_ROOT}/references/code-testability.md— How to structure code for testability${CLAUDE_PLUGIN_ROOT}/references/test-quality.md— What makes tests reliable and valuable${CLAUDE_PLUGIN_ROOT}/references/test-pyramid.md— Which test layer each scenario belongs at
Spec format reference: See Embedded References below.
-
Parse arguments to extract:
- Target path (optional — file or folder of spec files)
--planflag (plan only, do not implement)--exportflag (save report)
-
Detect project conventions by examining project files:
- Language and framework: Look for
package.json,pyproject.toml,Cargo.toml,go.mod,pom.xml,build.gradle,Gemfile,*.csproj, etc. - Test runner: Identify the test command (e.g.,
npm test,pytest,go test,cargo test,mvn test) - Test file patterns: Detect conventions (e.g.,
*_test.go,test_*.py,*.spec.ts,*.test.js,*Test.java) - Directory structure: Identify where tests and source files live
- Existing test style: Read 1-2 existing test files to match conventions (assertion library, naming, structure)
- Language and framework: Look for
-
Display setup summary to the user before proceeding:
Phase 1: Setup - Target: {path or "interactive mode"} - Project: {language}, {test pattern} convention - Flags: {enabled flags or "none"} - Test runner: {detected runner} - Test directory: {path or "TBD"} - Source directory: {path or "TBD"}In interactive mode or when directories can't be determined yet, show what's known and note the rest as "TBD — will determine from first scenario."
-
Route to mode:
- If
pathis provided → Agent Mode (Phase 2A) - If no
path→ Interactive Mode (Phase 2B)
- If
- If path is a file, read it
- If path is a directory, glob for spec files:
**/*.feature,**/*.md,**/*.txt,**/*.spec - Apply the Spec Format from Embedded References below
- Parse Given/When/Then scenarios from the files using those parsing rules
- Group scenarios by feature/file
Display a numbered list of all scenarios extracted:
Parsed {N} scenarios from {source}:
1. {Feature}: {Scenario name}
Given {precondition}
When {action}
Then {outcome}
2. ...
Test location: {detected test dir}
Source location: {detected source dir}
Test runner: {detected runner}
If --plan flag is set: STOP HERE. Output the plan and exit.
If --plan is not set: Ask the user to confirm before proceeding. Use AskUserQuestion:
- "Implement all scenarios"
- "Let me pick specific scenarios"
- "Cancel"
Spawn a tdd-agent with the following context:
- Project context (detected in Phase 1):
- Language/framework
- Test runner command
- Test file pattern
- Source directory
- Test directory
- Existing test style conventions (assertion library, naming, structure)
- Scenarios: The selected scenarios, formatted as numbered Given/When/Then blocks
Wait for agent completion.
After the agent completes:
- Show final test suite results
- If
--export: write report (see Export section)
Before starting the interactive loop, read the shared references (${CLAUDE_PLUGIN_ROOT}/references/code-testability.md, ${CLAUDE_PLUGIN_ROOT}/references/test-quality.md, ${CLAUDE_PLUGIN_ROOT}/references/test-pyramid.md) and apply those principles throughout.
Display:
Interactive TDD mode. Describe a behavior using Given/When/Then:
Example:
Given a list of users
When filtering by active status
Then only active users are returned
(Or just describe what you want the code to do)
Use AskUserQuestion to get the user's input.
- Extract Given/When/Then from the user's input
- If the user provided a plain description instead of GWT, convert it to Given/When/Then format and confirm with the user
- Identify what needs to be tested and where the test/source files should go
- Apply the test philosophy principles
- Write a test that describes the expected behavior:
- Test observable behavior (return values, errors), NOT implementation
- Follow RITE principles
- Answer the 5 Questions
- Match the project's existing test conventions
- Determine the right test layer (see
${CLAUDE_PLUGIN_ROOT}/references/test-pyramid.mdfor full criteria):- Pure logic with no I/O → unit test
- I/O or user-facing behavior → interface test (the default)
- Inter-service data format validation → contract test
- Requires real external services → E2E test
- Run the test suite — show the failure output
- Confirm the test is failing for the right reason
- Write the minimum code to make the test pass
- Apply Functional Core / Imperative Shell (see
${CLAUDE_PLUGIN_ROOT}/references/code-testability.md). If the scenario involves both logic and I/O, write them as separate functions. - Do NOT add code beyond what the test requires
- Run the test suite — show all tests passing
- Discipline check: Verify every branch and guard clause in the new code is exercised by a test. If you added defensive code (null checks, input validation, error guards) that no test exercises, remove it — it violates minimal implementation. Re-run tests if you removed code.
- Classify each function written or modified as Pure, I/O, or Orchestrator (see
${CLAUDE_PLUGIN_ROOT}/references/code-testability.md). Any function that mixes data transformation with I/O is a Violation — extract the pure logic. - Review for:
- Duplication → extract if genuinely duplicated
- Naming clarity → functions and variables express intent
- Test quality → still RITE? Testing behavior, not implementation?
- If changes needed, apply them and re-run tests
- If no refactoring needed, state why briefly
After completing the cycle, ask the user:
Use AskUserQuestion:
- "Describe the next behavior"
- "Done — finish session"
If "next behavior": return to Step 1. If "done": proceed to Post-Completion.
- Run the full test suite and show output
- Summarize the session:
- Scenarios implemented
- Tests written (categorized: unit / unit mocked / interface)
- Pure functions created, I/O shells, orchestrators
- If
--export: write report (see Export section)
When --export is set, write a session report to sdd-report-<timestamp>.md using date +%Y%m%d-%H%M%S for the timestamp. Include:
# Spec-Driven Development Report
## Session Summary
- Mode: {Agent|Interactive}
- Scenarios implemented: {count}
- Total tests: {count} (unit: {N}, unit mocked: {N}, interface: {N})
## Scenarios
### {Scenario name}
- **Spec**: Given {X}, When {Y}, Then {Z}
- **Test**: {test file}:{line}
- **Implementation**: {source file}:{line}
- **Design**: {pure function | I/O shell | orchestrator}
## Code Design
- Pure functions created: {list with file:line}
- I/O shells: {list with file:line}
- Orchestrators: {list with file:line}
## Verification
{test suite output summary}The shared references define these principles in full. They are not optional:
- Functional Core / Imperative Shell — Always separate pure logic from I/O (
${CLAUDE_PLUGIN_ROOT}/references/code-testability.md) - Test layer placement — Interface tests are the default for I/O; unit tests for pure functions only (
${CLAUDE_PLUGIN_ROOT}/references/test-pyramid.md) - Test quality — RITE tests, observable behavior, never mock pure functions (
${CLAUDE_PLUGIN_ROOT}/references/test-quality.md) - Minimal implementation — Only write code the current test demands. Do not anticipate future scenarios.
If the spec is ambiguous:
- In agent mode: make a reasonable interpretation, note the assumption, continue
- In interactive mode: ask the user to clarify before writing the test
If the test fails unexpectedly during GREEN:
- Debug the failure
- Fix the implementation (not the test — the test defines the desired behavior)
- If the test itself was wrong, explain why and ask the user before changing it
Never:
- Skip a failing test
- Write implementation before the test
- Add features not described in the current scenario
- Mock pure functions
- Fabricate test results — always run the actual test command and show output
- Read and apply the shared references from
${CLAUDE_PLUGIN_ROOT}/references/(code-testability.md, test-quality.md, test-pyramid.md) before any analysis or implementation - Apply the Spec Format from Embedded References when parsing spec files
- The TDD cycle is strict: RED (failing test) → GREEN (minimal pass) → REFACTOR. Never skip steps.
- Code design (functional core / imperative shell) is applied during GREEN and REFACTOR, not as a separate phase
- Match the project's existing conventions for test location, naming, assertion style, and file organization
See ${CLAUDE_PLUGIN_ROOT}/skills/tdd/references/spec-format.md for accepted formats, parsing rules, and examples.