tdd

tdd is a command for Claude Code from juanmhidalgo/claude-plugins. It costs 35 tokens per session (10,390 once invoked), scanned A, original, MIT.

A command for implementing a feature or bug fix with a test-first workflow. It can use an existing feature plan or ask for a clear specification before proceeding.

In plain words
What is it for?
Use it to select or resolve a feature plan, explore the relevant code, and run bounded TDD work for the change.
Why use it?
It makes the requirements and test plan explicit before coding and stops when the repository or specification is not ready.

Command for Claude Code

Written for Claude Code: allowed-tools in frontmatter. Also seen: mentions subagents; names the AskUserQuestion tool; mentions Claude Code.

Runs only inside its plugin — its command needs a path that Claude Code sets for a plugin’s own hooks and for nothing else. Install the plugin, not this.

Part of the feature-dev plugin — 2 skills, 7 commands, 13 agents shipped together

Good fit Use it to select or resolve a feature plan, explore the relevant code, and run bounded TDD work for the change.

Compare 6 commands from other repositories ↓
Install

Getting it into your agent

This one installs as part of its plugin. Adding the marketplace and installing the plugin brings it with everything else the plugin ships.

Claude Code
/plugin marketplace add juanmhidalgo/claude-plugins
Claude Code
/plugin install feature-dev

Made for: Claude Code.

Or install feature-dev, the plugin that ships this one along with the rest of its 2 skills, 7 commands, 13 agents.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for tdd

README.md
[![agentmods](https://agentmods.dev/badge/commands/juanmhidalgo/claude-plugins/tdd/github.svg)](https://agentmods.dev/commands/juanmhidalgo/claude-plugins/tdd)
Your own site
<a href="https://agentmods.dev/commands/juanmhidalgo/claude-plugins/tdd"><img src="https://agentmods.dev/badge/commands/juanmhidalgo/claude-plugins/tdd/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for tdd

Your own site · 80×15
<a href="https://agentmods.dev/commands/juanmhidalgo/claude-plugins/tdd"><img src="https://agentmods.dev/badge/commands/juanmhidalgo/claude-plugins/tdd.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 35 Only the description is in the session, so the agent can decide to use it. The body loads when it is invoked.
When invoked 10,390 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00035 $0.10390
Opus 5.5 $0.00014 $0.04156
Sonnet 5.5 $0.00007 $0.02078
Haiku 4.5 $0.00003 $0.01039

Measured 2d ago against content hash 7b4b08545809, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

tdd scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

feature-dev/commands/tdd.md · 402 lines

How it starts

The opening of the file, as written. The whole thing — 402 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Context

  • Repository: !git remote get-url origin
  • Current branch: !git branch --show-current
  • Working tree clean: !git status --short
  • Feature spec: $ARGUMENTS
  • Feature store: each feature lives in .feature-dev/features/<slug>/, managed by ${CLAUDE_PLUGIN_ROOT}/scripts/features.py (every call below passes --root <repo root>). Run progress is recorded there with step, never by editing a file. Layout: artifact-locations.md.

Phase 0: Resolve Spec and Validate

First, strip flags from $ARGUMENTS. --coordinator <session-name> names a live Claude Code session acting as this feature's coordinator (Phase 3 routes cross-repo questions to it). Remove the flag and its value before anything else reads $ARGUMENTS — what remains is the feature spec, and it may now be empty, which is the normal auto-discovery path. Record the name. Do not resolve or validate it yet; a coordinator that turns out to be unreachable must not block a run that is otherwise fine. Strip --pane / --no-pane too, and run ${CLAUDE_PLUGIN_ROOT}/scripts/herdr-pane.sh status once: it prints inside or outside (Herdr), and the checkpoint line below depends on it.

--pane hands the run to a fresh session. The run moves to a sibling Herdr pane in handoff mode (${CLAUDE_PLUGIN_ROOT}/references/herdr-pane.md) and this session stops: the pane gets a full context budget instead of inheriting this one. Resolve the argument to a PLAN-*.md or SPEC-*.md path first (step 1 below), then send /feature-dev:tdd <path> [--coordinator <name>] --no-pane with agent name tdd-<slug>. Phase 1b's resume re-verifies any steps already done, so handing off mid-run loses nothing. Do not run any step here after the handoff: two runs on one checkout race. Outside Herdr, say so and run here.

  1. Resolve the feature spec:
    • If $ARGUMENTS is the path of an existing PLAN-*.md → read it and use it exactly as a single auto-discovered plan below (the closing lines of /feature-dev:explore-plan and /feature-dev:plan-review print this form). Its feature slug is its folder name under .feature-dev/features/; refuse any other path (a root PLAN-*.md, or the layout older than 2.0.0) in one line and name .feature-dev/features/<slug>/ as the only place plans live.
    • If $ARGUMENTS is the path of an existing SPEC-*.md → the feature slug is its folder name under .feature-dev/features/ (refuse any other path the same way). Read its feature: frontmatter value and use it as the spec; the spec path is the source spec. Then read the feature's entry from ${CLAUDE_PLUGIN_ROOT}/scripts/features.py list --json --root <repo root>:
      • If its status is implemented, say so and ask before continuing.
      • If the spec is still draft: ask once with AskUserQuestion "This spec is still a draft. Mark it approved and implement it?" (options: approve and continue / stop). Yes → run ${CLAUDE_PLUGIN_ROOT}/scripts/features.py approve <slug> --root <repo root> and continue. No → STOP and point the user to /feature-dev:review <spec path> to approve it first. Never implement from a draft.
      • If the feature already has a PLAN artifact in its entry, use that plan as the pre-selected plan (as for a PLAN-*.md argument) — a spec with a plan is not a no-plan run.
      • Otherwise there is no plan: skip the plan search in Phase 1 and take the no-plan path. This is the small-feature fallback /feature-dev:spec mentions; the spec's ACs (or its Tasks) are the reviewed anchor, the decisions go to its Decisions Log, and Phase 6 closes it. Record the run in the feature store before the first step: with the spec approved, run ${CLAUDE_PLUGIN_ROOT}/scripts/features.py plan <slug> --steps <number of ACs> --from-spec --root <repo root> (one step per AC, matching the criteria Phase 2 derives). A refusal (refused: …) names the state and the valid events; report it instead of editing feature.json.
    • If $ARGUMENTS is #N, owner/repo#N, or an issue URL → resolve it per issue-store.md's Argument parsing, then run issue-store.md's Import algorithm against it, start to finish. Do not restate Import's steps here — follow the reference; its own step 3 is where a closed issue asks before continuing, the same shape as this command's implemented check above. A failed gh preflight, or a failed gh issue view call, stops here and names the issue that could not be read. On success, continue as if $ARGUMENTS had been the resulting SPEC-<slug>.md path (the SPEC-*.md bullet above applies).
    • If $ARGUMENTS is anything else → use it as the feature spec. There is no feature in the store, so the run records no state. Continue to step 2.
    • If $ARGUMENTS is empty → run ${CLAUDE_PLUGIN_ROOT}/scripts/features.py list --json --root <repo root> (a missing .feature-dev/features/ is an empty list) and keep the features whose status is planned, running or halted and that have a PLAN artifact, plus the running or halted features with only a SPEC artifact (a run straight from the spec; for these the SPEC path stands in for the plan path below, and the run continues as for a SPEC-*.md argument):
      • 0 plans found → STOP and ask the user for a feature description.
      • 1 plan found → read its PLAN (path from artifacts), extract the feature: value from the spec when the feature has one (else the plan's title), and use that as the spec. Record the plan path as the pre-selected plan for Phase 1. Inform the user: "Auto-selected plan: <plan path> (feature: , )".
      • 2+ plans found → use AskUserQuestion to let the user pick one (label = feature name or slug, description = <slug> — <status>). The chosen feature's plan path is the pre-selected plan for Phase 1.
  2. Check the working tree. Use the Working tree clean field from the Context section above — it was captured before Phase 0 ran, so an issue import in step 1 (which writes a new, untracked SPEC-<slug>.md when no local copy exists) never trips this check on its own output.
    • Clean → proceed normally. If the resolved feature is halted, still go to Phase 1b: Resume after Phase 1: it records the restart, and step done is refused until it does.
    • Dirty → this may be a halted run, not stray edits. Take the feature's status and plan.completed from list --json (a run with no feature in the store cannot be a resumable run: apply the stop below). If status is running or halted (a halt at step 1 leaves plan.completed empty and is still this command's work), the dirty tree is this command's own unfinished work → go to Phase 1b: Resume after Phase 1.
    • Dirty with no running or halted feature → STOP and ask the user to commit or stash.

Read the full file on GitHub · 402 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 2d ago Changed · +8 lines 7b4b08545809
  2. 10d ago Changed · +5 lines ab574341a99f
  3. 14d ago Changed · +3 lines 1c9589bd2089
  4. 18d ago Changed · +12 lines 038a00b077d7
  5. 19d ago Changed · +50 lines 8609f3f21bef
  6. 23d ago Changed · -4 lines 97b969aafa6c
  7. 1mo ago Changed · +50 lines 5c9d77ec9ca7
  8. 1mo ago Changed · +25 lines 425ef2537418
  9. 1mo ago Changed · +69 lines 6b6eb1a4a30d
  10. 1mo ago First seen · 184 lines · 35 tokens per session scan A 710b1e85fbb0

Subscribe to this mod's changes

tdd is a command published in the GitHub repository juanmhidalgo/claude-plugins (8 stars, last pushed 2d ago), licensed MIT. It adds 35 tokens to every session and 10,390 once invoked, about $0.0001 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-03.