"Claude wrote something that's heading in the wrong direction, so I'm starting over" — if you've burned tokens on this loop, you know the pain. For a while I worked in the "ship something rough, then fix it" style, and for small features that's fine. The moment a task had more than two moving parts, that approach stopped paying for itself.
The thing that changed my workflow was Plan Mode. Read as a feature description it sounds modest: "a mode that shows you its plan before executing." In practice, treating it as an independent design phase cut my rework cycles noticeably. This post is about what that looks like in real work — when to switch into Plan Mode, the prompt pattern that produces plans worth reading, and the traps I kept walking into.
What Plan Mode Actually Is
Plan Mode is a state where Claude Code proposes what it is about to do and waits for approval before touching anything. You enter it by pressing Shift + Tab twice until you see ⏸ plan mode in the UI (/exit-plan takes you back out).
The real difference from normal mode is not the approval step — it's that Plan Mode cannot write files or run destructive commands. Only read-only investigation and Claude's internal reasoning happen. That constraint is what makes it useful as a standalone design phase: you get to argue about structure without any chance of Claude silently editing half your codebase mid-conversation.
Three Moments Where I Reach for Plan Mode
I switch into Plan Mode in roughly three situations.
First, kicking off a new feature. When a feature touches files I haven't seen in a while, jumping straight into src/ almost guarantees I'll change my mind about where the new logic belongs. Getting Claude to propose a file layout first — "use this existing module, add this new file, put tests here" — almost eliminates the "this should have been a different module" realization at PR time.
Second, before any refactor. Refactors have a lot to agree on up front: which tests must stay green, what the migration order is, how much backward compatibility we maintain. Plan Mode makes it safe to walk through this — "list the affected files," "propose the migration order," "point out anything that looks risky" — without Claude getting half-way through and leaving a broken tree.
Third, debugging when there are multiple plausible causes. The failure mode I want to avoid is Claude latching onto one theory, writing a fix, and never mentioning the other two possibilities. Asking in Plan Mode — "investigate these three hypotheses and tell me which is most likely" — forces a side-by-side evaluation instead of a one-shot guess.
A Prompt Template That Actually Produces Useful Plans
Entering Plan Mode and saying "please plan this out" gets you a bulleted TODO list that isn't much more useful than no plan at all. The structure I've settled on asks for four things explicitly:
# Plan Mode request template
## Goal
(1–2 sentences, written as user-visible acceptance criteria)
## Constraints
- Don't break existing type definitions
- Only propose dependency additions if they require package.json changes
- Tests go in <existing test location>
## Things to investigate
- How does the existing <similar feature> work? (list files worth reading)
- Blast radius — which files should change, which must not
## What I want back
1. Implementation approach (≤100 characters)
2. List of files to modify and the role of each
3. Test plan
4. Risks and trade-offs (at least one)The load-bearing part is the last line: "at least one trade-off." Without that, Claude will almost always report that everything looks clean and the plan is safe to execute. Forcing a trade-off surfaces the kind of design smell you actually want to catch before writing code — "this couples two layers that were separate," "this requires a schema migration I hadn't mentioned," and so on.
Three Checks Before I Approve a Plan
Before hitting approve, I scan the plan for three things.
Are there files in the change list that should really be read-only? Plan Mode can blur the line between "read to understand" and "modify." Files that only need to be referenced sometimes end up in the modification list, which later turns into unnecessary diff noise in the PR.
Is the test plan specific? "We'll run the existing tests" is a warning sign. A plan that doesn't say which test file gets which new case almost always produces a post-implementation scramble to add tests that don't quite fit the existing structure.
Are breaking changes called out explicitly? Changes that affect other developers — API signature shifts, new environment variables, migrations — need to be named in the plan. If I don't see that section, I ask for it before approving rather than after.
Traps I Kept Falling Into
When I started using Plan Mode seriously, three things tripped me up.
Plans that are too long to read. Being enthusiastic about the mode, I let Claude produce multi-thousand-character plans. In practice anything over roughly 1000 characters stops being useful — the reader (you) stops reading carefully. That's why the template caps the implementation approach at 100 characters. For genuinely large changes, split the work into phases and run Plan Mode more than once.
Over-investigating and polluting the implementation context. If you have Claude read 30 files during planning, all of that stays in context when you flip back to implementation mode. It sounds like that's good, but the "what I'm currently editing" context — which is what drives accuracy in the next few turns — gets crowded out. Investigate only the files whose content genuinely affects a decision. The long-session context integrity piece talks about this drift; Plan Mode over-use is one of the ways it happens.
Mixing in new topics right after approval. Right after approving a plan, it's tempting to add "while you're at it, also fix X." Claude now has to decide whether to treat it as outside-plan work or to re-plan. Treating the plan as a frozen scope — and running a fresh Plan Mode for any add-on — ends up being faster than either alternative.
Plan Mode vs. Permission Modes
Plan Mode and Claude Code's permission modes (auto / ask / plan) get confused, but they do different jobs. Permission modes control which tool calls require confirmation. Plan Mode is specifically about agreeing on the design before implementation starts. How to combine them in real projects is covered in the permission modes production guide.
My rough rule: if the design is still fuzzy, start in Plan Mode. If the design is settled and you just want fewer interruptions during execution, lean on auto permissions instead.
Once you approve a plan, the approved context carries forward into the implementation session. For long-running implementations where you may come back later, the session-naming practice from the session management guide makes it much easier to reconstruct what the agreed plan was.
A Worked Example: Adding a Rate Limiter
To make this concrete, here is a short example of what a Plan Mode exchange looks like in practice. Suppose I want to add a simple per-user rate limiter to an existing Next.js API route. My request in Plan Mode might be:
## Goal
Reject calls to /api/feedback if a single user ID submits more than 5 times per minute. Return 429 with a Retry-After header.
## Constraints
- No new dependencies unless absolutely required
- Use the existing KV binding already available in the route handler
- Tests go in tests/api/feedback.test.ts
## Things to investigate
- How does /api/feedback currently identify the user?
- Is there an existing rate-limit utility I missed?
## What I want back
1. Implementation approach (≤100 chars)
2. Files to modify and the role of each
3. Test plan
4. At least one trade-offA good plan might come back looking like this:
Approach: fixed 60s window counter in KV keyed by user ID, read-modify-write in the handler.
Files:
- src/app/api/feedback/route.ts — add limiter check before main handler logic
- src/lib/rate-limit.ts (new) — encapsulates the KV key format and TTL math
- tests/api/feedback.test.ts — add three cases: under limit, at limit, over limit
Test plan:
- Stub the KV binding in the test harness (same pattern as tests/api/auth.test.ts)
- Verify Retry-After header matches window remaining
Trade-off:
- Fixed window lets a user burst 10 requests across the boundary (5 at :59, 5 at :00).
A sliding window would fix this but requires tracking individual timestamps and is
not worth the complexity for a feedback endpoint. Flag for revisit if abuse is observed.The trade-off note is the most valuable line. It names a known imperfection of the chosen approach and explicitly decides not to fix it. That one line protects you from a reviewer later asking "why did you use a fixed window?" and getting a confused silence.
From here, approving the plan is safe. Claude now knows the file layout, the test target, and the exact limitation you are accepting. Implementation goes fast because every design question has a pre-committed answer.
What to Try Next
There's a real gap between knowing Plan Mode exists and getting value out of it. The fastest way to close that gap is to use it on your next PR before writing a single line of code — paste the template above, push back on the plan you get, and only then flip out of Plan Mode. The difference between that run and the "start coding immediately" baseline is the clearest before/after comparison you can give yourself.