Interactive version
This piece comes with an interactive page: diagrams, scenarios and sample sessions. The link is created fresh on every click.
Quick summary: Use
--deepwhen the scope is wide, add--tddwhen existing behavior must survive, and turn on both only when both risks apply.--deepgives the plan a detailed map for each phase.--tddmakes the agent capture current behavior in tests before refactoring. Small tasks and brand-new code need neither.
Not every task needs the heavy mode. A big refactor rarely breaks on the first line of code. It usually breaks because the plan did not see enough scope, and by the time /ak-cook runs, the missing tests, migrations, or background jobs have already been skipped.
Disclosure: I maintain AgentKit and have an affiliate relationship with it: the AgentKit link in this post is an affiliate link; buying through it gets you 30% off.
Note: the current AgentKit beta (since 3.0.0-beta.35, October 21, 2026) changed skill names from ak:<name> to ak-<name>, and the commands in this post use the new names: Claude Code calls /ak-plan, Codex calls $ak-plan. On an older version, swap ak- back to ak: to get the matching command.
/ak-plan is the planning command in AgentKit (formerly ClaudeKit). Command names follow AgentKit as of October 2026; older ClaudeKit installs use the /ck: prefix for the same commands. I use one running example, extracting billing from a monolith, to show when these two options are worth the cost and when they only slow you down.
Running example: extracting the billing module
Billing is spread across API routes, database models, background jobs, retry logic, invoice status, webhook handlers, and the admin UI. The task sounds simple enough: "extract billing into its own module, keep the old behavior." But once the agent starts running, the real questions surface:
- Which files actually belong in scope: API, jobs, database, UI, or webhooks?
- Which behaviors must stay identical: retry, idempotency (running twice gives the same result), invoice status, payment failure?
- How much of the current behavior is actually under test?
- Does this phase depend implicitly on a migration or a background job?
- If the new code builds but diverges on an edge case, who catches it?
For small tasks, /ak-plan --fast or plain /ak-plan is usually enough. For complex tasks that are not a full major refactor, --hard is usually the better fit. For large tasks, missing context upfront becomes cost at the end: cook has to guess scope again, phase files stay vague, tests get written after the code, and regressions only surface once the refactor is done.
Neither option is a "stronger mode" you switch on to make things better. They address two specific risks: not knowing enough scope and not protecting existing behavior.
| Option | Use when |
|---|---|
--deep | Scope is wide and each phase needs a map |
--tdd | Existing behavior must survive the refactor |
--deep --tdd | Both risks apply |
Mode and flag are different things
Before going further, one distinction worth making: /ak-plan takes two kinds of arguments.
| Type | Example | Effect |
|---|---|---|
| Mode | --fast, --hard, --deep, --parallel, --two | Selects the planning pipeline. One mode per command. |
| Composable flag | --tdd, --no-tasks | An add-on that pairs with any mode. |
--deep is a mode, so it changes the whole planning pipeline. --tdd is a flag, so it keeps whichever mode you chose and adds a tests-first structure to the phase file and the cook step.
The argument hint in the skill definition reads:
argument-hint: "[task] [--fast|--hard|--deep|--parallel|--two] [--tdd|--no-tasks]"The | between modes means pick one. --tdd sits in its own group, so it composes. That is why --deep --tdd is valid and --deep --hard is not.
--deep: when the plan needs a map for each phase
This section covers the problem --deep solves, the steps in its pipeline, and what it adds to each phase file.
The problem --deep solves
Large tasks usually touch many areas of code at once. For the billing module, scope can span:
- API routes: create invoice, retry payment, refund, webhook callback.
- Database: invoice table, payment attempt table, status history.
- Background jobs: retry scheduler, reconciliation job, webhook replay.
- Admin UI: invoice detail, manual retry, refund action.
- Shared contracts: frontend API response, webhook payload, event names.
These tasks need more than a list of steps. They need a map:
| Question | In the billing example |
|---|---|
| Which files are created, modified, or deleted? | Route, service, job, migration, UI action |
| Which tests cover the old behavior? | Retry, idempotency, refund, webhook replay |
| Which phase depends on which? | Migration before service, service before UI |
| Which interfaces need test protection? | API response, webhook payload, job input |
| Which dependency edges are risky? | A job reads the old status while the service has changed the enum |
--deep fits when the cost of a wrong plan is higher than the cost of planning carefully. The mode rule in the skill says:
Major refactor, 5+ areas, architectural debt -> use --deepIf you only touch a few files, --fast or plain /ak-plan is usually enough. If the scope is complex but the architecture is still clear, --hard is a better fit. --deep earns its cost when a wrong plan would mean hours of reworking phases, tests, and ownership.
The --deep pipeline
It starts from broad context and narrows into each phase:
- Researcher pass: two to three passes over the architecture and affected areas.
- Full-scope scout: docs, core modules, existing tests, major dependencies.
- Per-phase scout: each phase gets a file inventory, test gaps, and interfaces to preserve.
- Phase files: the planner feeds the scout data into each phase.
- Red team: catches scope leaks, wrong phase order, and implementation risks.
- Validation: checks that the plan has the commands, dependencies, and success criteria it needs.
- Tasks: creates the task list, unless you pass
--no-tasks. - Cook handoff: prints
/ak-cook {path}/plan.md.
Compared with --hard, which usually scouts once for the whole plan, --deep adds a pass for each phase. It costs more, and in return the phase files are more specific: which files get touched, which tests are missing, which dependencies are risky.
What a phase file gains with --deep
- File inventory table: action (create, modify, delete), rough size, test impact.
- Test scenario matrix: critical, high, and medium paths.
- Dependency map: which other phases this one links to.
- Function and interface checklist: which functions or interfaces need test protection.
This is the main difference. A phase does not just say "refactor billing service." It spells out which files, which tests, which edge cases, and which phase it depends on.
--tdd: when you fear a refactor will break what is running
This section covers the problem --tdd solves, when it pays off, and what it changes in both the plan step and the cook step.
The problem --tdd solves
The default cook flow is familiar: read the plan, implement each task, type-check after each file, then run a separate testing step. That works for greenfield code. For refactoring live code, it is not safe enough.
In the billing example, old behavior might include:
- Retry runs at most 3 times, then moves the invoice to
failed. - A webhook with the same
event_idis applied only once. - A refund cannot run if the invoice is already
voided. - The admin UI still shows the correct status history after the service is extracted.
The happy path may still pass while the bug hides in an edge case. --tdd puts a regression gate in place before the code changes. TDD (test-driven development) here means capturing current behavior before refactoring, rather than writing tests for a new feature.
When --tdd is most valuable
| Situation | Use it? | In the billing example |
|---|---|---|
| Brand-new greenfield code | Usually not | No invoice or retry behavior exists yet to capture |
| Refactoring a module with live users | Yes | Retry, idempotency, and status transitions must hold |
| Switching payment provider while keeping the contract | Yes | Easy to drift on API responses or webhook behavior |
| A 1 to 2 line fix with a known cause | Usually not | For example, fixing a typo in an admin UI label |
| Throwaway prototype | No | A test gate is not worth the cost |
--tdd is most valuable in modules with async patterns, stateful workflows, database transactions, or public API contracts. Billing has all of them: background jobs, status transitions, transaction boundaries, webhook payloads, admin actions.
At plan time
| Section in the phase file | Role |
|---|---|
| Tests before refactor | Write regression coverage before changing code, to record current behavior. |
| Refactor | Describe the code being changed, protected by the tests above. |
| Tests after | Add tests for any new behavior in this phase. |
| Phase gate | A concrete compile and test command that must pass after the refactor. |
A phase that uses --tdd usually reads in this order:
- Write tests that protect current behavior.
- Extract a small dependency seam if the old code is hard to test.
- Refactor the code.
- Run compile and tests again.
Making old code testable is the step people skip. Sometimes legacy code cannot be tested directly: a long function calls the database internally, dependencies cannot be injected, output cannot be isolated. You first extract a small seam that keeps behavior identical but makes the code testable, and only then do the real refactor.
At cook time
When /ak-cook runs with --tdd, the order is:
- Write tests first: record current behavior before changing code.
- Refactor: restructure, extract modules, make old code testable if needed.
- Run the gate: tests that protect the old behavior must still pass along with the compile step.
Put simply, tests written first are the baseline for old behavior. If that baseline fails after the refactor, cook should stop and fix the drift before moving on.
When I wrote this post, I checked it against the ak-plan and ak-cook skill source in a beta build of the Engineer Kit (check your installed version with ak --version). If either skill's workflow changes later, the mode tables in this post may drift.
Why --deep and --tdd often go together
The two options address two different layers of risk. When a task has both, turn on both.
| Risk | What you need | Option |
|---|---|---|
| Not knowing enough scope | Per-phase scout, file inventory, dependency map | --deep |
| Refactor drifts from old behavior | Tests before refactor, regression gate during cook | --tdd |
--deep gives you the map and --tdd gives you the verification layer. A major refactor usually needs both. For example, a request like this:
Extract billing module from the monolith.
Keep current API contract for the frontend.
Preserve existing behavior for retry, idempotency, invoice status.
Touches database schema, background jobs, API routes, admin UI.This task needs --deep because the scope is wide and has many dependencies. It also needs --tdd because retry, idempotency, refunds, and webhooks are all old behavior that has to survive.
With only --deep, the plan may be very clear, but the refactor still lacks a regression gate. With only --tdd, the test flow may be right, but the phase files stay vague: what to test, where, which modules are affected, and which dependencies must come first.
Quick rule: wide task, use
--deep. Old behavior to keep, add--tdd. Both risks, turn on both.
When to run /ak-brainstorm or /ak-scout first
A common mistake is reaching for --deep --tdd while the approach is still unclear. Planning modes do not resolve ambiguity. They only turn an approach you already chose into more concrete steps.
For example, if you have not decided yet:
- Extract a real service, or just modularize inside the monolith?
- Add a new queue, or keep the current background jobs?
- Keep the current invoice status enum, or move to a clearer state machine?
- Rewrite the admin UI flow, or refactor it piece by piece?
In that case, run /ak-brainstorm first to settle the approach, then plan.
There is one more layer: /ak-scout. Think of it as a context-gathering step, not a decision step. Scout fits when you are not sure where the code lives, which modules are involved, or which tests cover current behavior. When the brief is still vague, do not jump straight into planning:
- Scout: find the real code, real tests, real dependencies.
- Brainstorm: choose an approach and its trade-offs before locking the plan.
- Plan: use
--deep --tddonce the approach is clear enough.
/ak-scout "billing retry flow, invoice status, background jobs, admin UI"
/ak-brainstorm "Extract billing module while keeping the current API contract"
/ak-plan --deep --tdd "Refactor billing module per agreed approach..."Once you know the relevant code and the main trade-offs, you can skip the separate /ak-scout pass, since /ak-plan --deep already scouts as part of its pipeline. When the brief is still too broad, scouting first avoids a quiet failure: the agent reasons plausibly while working from the wrong map of the project.
| Situation | Start with |
|---|---|
| Project context unclear, code location unknown | /ak-scout, then /ak-brainstorm |
| You know what and how | /ak-plan directly |
| You know what, not sure how | /ak-brainstorm, then /ak-plan |
| Not sure whether to do it | /ak-brainstorm, decide, then plan or drop it |
Command picker
In short: unclear scope, /ak-scout first; unclear approach, /ak-brainstorm first; major refactor, /ak-plan --deep --tdd. In full:
| Situation | Command |
|---|---|
| Project context unclear | /ak-scout first, then brainstorm or plan |
| Approach uncertain | /ak-brainstorm first |
| Small fix in 1 or 2 files | /ak-plan --fast |
| Medium new feature | /ak-plan (auto mode) |
| Complex feature, unfamiliar domain | /ak-plan --hard |
| 3 or more independent modules in parallel | /ak-plan --parallel |
| Torn between 2 specific approaches | /ak-plan --two |
| Refactor across 5 or more areas, architectural debt | /ak-plan --deep |
| Refactoring live or dogfooded code, fear of regressions | Any mode plus --tdd |
| Major refactor on a codebase with behavior to preserve | /ak-plan --deep --tdd |
The --deep --tdd pair is not one mechanism; it is two different jobs running together. Planning costs more, but cook guesses less about scope and has a clearer regression gate.
Inside: how the two options work
This section goes deeper into how --deep and --tdd affect plan time, cook time, and run cost.
--deep costs more because of researchers and per-phase scouting
| Mode | Researchers | Red team | Validation | Per-phase scout |
|---|---|---|---|---|
--fast | 0 | 0 | 0 | No |
--hard | 2 | Yes | Optional | No |
--deep | 2 to 3 | Yes | Yes | Yes |
--parallel | 2 | Yes | Optional | No |
--two | 2 or more | After selection | After selection | No |
The cost of --deep comes mostly from two to three researchers for high-level architecture analysis, the red-team review, the validation step, and the per-phase re-read. Put simply, each phase is examined on its own before the plan is locked: which files it touches, which phase it depends on, which tests are missing, which edge cases are easy to miss.
Do not misread the word "scout" here. It refers to the reading and checking that has to happen for each phase, not a promise that a separate agent always spawns at runtime. What matters is that --deep forces the plan through several smaller checks instead of looking at scope once from a high level.
--tdd does not create a new agent
--tdd does not change the mode you chose. It is an add-on flag: you still run --fast, --hard, or --deep as usual, with a tests-first structure added. It changes exactly two things:
- The phase file at plan time. A normal phase has an overview, requirements, architecture, related files, implementation steps, success criteria, and a risk assessment. With
--tdd, the phase also gets tests before refactor, tests after refactor, and a phase gate. - Execution order at cook time. Write tests that protect old behavior first, refactor second, then rerun the compile and test gate.
--tdd costs much less than --deep, since it mostly adds structure to the phase file and changes the execution order during cook.
The regression gate needs a concrete command
The cook spec requires the regression gate to be a concrete compile or test command. For a Go project, for example:
Regression Gate: go test ./... && go vet ./...If the phase file only says "run tests to verify," the verification step weakens because cook has no exact command to anchor on. The --tdd flag does not guarantee it guesses the right tooling in every repo. If the project uses its own commands, state them in the task description or the plan file:
Project uses go test ./..., frontend uses npm test, E2E uses Playwright.When the task names the tooling, the plan has a basis for writing the right gate into each phase.
How to run it: a general template
The template below follows the skill source of ak-plan and ak-cook: plan receives the task plus mode and flags, and cook receives the plan path and carries --tdd forward if the plan enabled it.
/ak-plan [mode] [--tdd] "[What needs to happen].
Scope: [modules/files/stack being touched].
Preserve: [API contract, existing behavior, compatibility].
Touches: [database, jobs, routes, UI, shared types].
Tooling: [concrete compile/test command].
Known bugs / out of scope: [if any]."If the plan uses --tdd, pass it to cook as well:
/ak-cook /absolute/path/to/plan.md --tddApplying the template to a few common situations.
--deep for an inventory phase
/ak-plan --deep "Build an inventory plan to prepare extracting billing into its own package.
Scope: API routes, invoice service, payment jobs, admin UI, database schema.
Output must include: file inventory, dependency map, phase ownership, risk list.
Not refactoring live behavior in this round."--hard --tdd for refactoring running code
/ak-plan --hard --tdd "Refactor invoiceStatusService: move transition rules
to a separate file, keep exact behavior for retry, failed, refunded, voided."--deep --tdd for a major refactor with behavior to preserve
/ak-plan --deep --tdd "Extract billing module from the monolith.
Keep API contract for frontend, preserve retry/idempotency/refund/webhook behavior.
Touches: database schema, payment jobs, API routes, admin UI. Project uses
go test ./..., frontend uses npm test."A good task description usually covers:
- Scope: which files, modules, or stack.
- Constraints: what must not break, what must stay compatible.
- Tooling: test and compile commands, which matter most for
--tdd. - Expected outcome: short but concrete.
Vague input such as "refactor billing" produces a vague plan. Without a concrete anchor, scouting easily returns generic output.
Do this, avoid that
These two groups cover where people stumble most with --deep --tdd: what to do before cook, and the mistakes to avoid.
Do before cook
Keep the worktree clean before planning
If your working directory has uncommitted changes from another task, scouting can mix current code with half-finished work. Before a big plan, commit or stash. Better still, create a separate worktree with /ak-worktree.
Review the phase files before cook
A --deep --tdd plan takes a while to run, so do not cook before rereading plan.md and the phase files it created. Check five questions:
- File inventory: is there any file you do not want the agent to touch?
- Test scenario matrix: does it miss a race condition or an edge case such as a duplicate webhook?
- Phase order: are the phases really independent, or does the migration have to run before the job?
- Regression gate: is it the right tool and the right test subset?
- Known bugs: should they be fixed, or should the old behavior be preserved?
Declare test commands in the task
With --tdd, if the repo uses less common tools such as bun instead of npm, mise instead of asdf, or task instead of make, declare them up front:
Project uses go test ./..., frontend uses npm test, E2E uses Playwright.If you do not, the agent guesses. A wrong command weakens the regression gate.
Run /clear between plan and cook
Planning context for a large task is usually heavy: research output, scout data, red-team feedback. The recommended flow: finish the plan, run /clear, reopen, then run /ak-cook {absolute-path}/plan.md --tdd. Cook rereads the plan file and does not need the old planning context.
Avoid
| Mistake | Why it breaks | Do this instead |
|---|---|---|
Forgetting --tdd on /ak-cook | Cook still reads the tests-before-refactor section but does not enforce tests first, so tests may get written after the code. | Use the cook command the plan suggests at the end. |
Using --deep on small tasks | Below roughly five files, the per-phase scouting is usually wasted. | Use --hard or --fast instead. |
Using --tdd on greenfield code | New code has no behavior to keep, the tests-before-refactor section is nearly empty, and the agent tends to write token tests. | Use --hard and let tests be written in the normal flow. |
| Trusting the phase files blindly | --deep scouts more thoroughly but can still miss hidden dependencies. | Before cooking, ask whether a later phase quietly relies on something an earlier phase has not created yet. |
Letting --tdd lock in an existing bug | If the tests capture an old bug (for example a duplicate webhook creating two payment attempts) as "current behavior," a refactor that accidentally fixes it fails the gate, and the agent may "fix" the code back to the bug. | List known bugs in the task, or split into two plans: fix the bug first, refactor second. |
Trying to combine --deep with --parallel | Both are modes, so they do not compose. | For parallel agents, use --parallel --tdd with very clear ownership and test scope; if unsure, drop --parallel and keep --deep --tdd. |
In short
--deep --tdd is not for every task. It is for tasks with two signs:
- The scope is large enough that a normal plan is likely to miss the map.
- The current code has behavior that must survive the refactor.
--deep makes planning slower and in return gives clearer phase files: file inventory, test gaps, dependency map, function and interface checklist. --tdd makes cook slower and in return gives the refactor a regression gate: write tests first, refactor, then verify.
If you are in a PM, founder, or product role, you only need to know these two options exist. When the team is about to refactor a large module like billing, ask whether the plan has per-phase scouting and a regression gate.
If you are a developer, try it on your next large task. It may feel slower the first time. But once a test written up front catches one hidden regression, the extra cost becomes much easier to accept.
One last note: --tdd works with any mode in principle, but pairing it with --fast is usually not worth it, since you already chose to move fast.
If you are new to AgentKit, read the AgentKit beginner's guide for Claude Code. To compare ak-plan with Plan mode in Oh-my-pi (OMP), see OMP Plan mode vs AgentKit ak-plan.
Use this piece in your agent
Get an API keyCopy the text below and paste it into Claude Code, Codex or whichever agent you use. The agent reads the piece and checks it against the repo you have open.
Read "When to turn on --deep and --tdd for /ak-plan" on modernEngineer and apply it to this repo.
1. Call the content_get tool of the modernengineer MCP server with locale "en", slug "ck-plan-deep-tdd-when-to-use". If MCP is not connected or access is refused, read the page https://modernengineer.dev/en/library/ck-plan-deep-tdd-when-to-use instead.
2. Summarize the main steps of the piece and point out which apply to this repo.
3. Propose concrete changes and ask me before editing any file.Connect MCP in Claude Code (once)
claude mcp add --transport http modernengineer \
https://api.modernengineer.dev/mcp \
--header "Authorization: Bearer <API key>"This piece is open to everyone: without MCP, the agent can still read it straight from the link.
- Version
- v1.0.0
- Updated
- 22/05/2026
- Licence
- All rights reserved
- Slug
- ck-plan-deep-tdd-when-to-use


