Plan mode is cheap; rolling back a bad diff is not. Use it when scope is unclear, when more than one file is involved, or when you cannot predict the diff in advance. Skip it for one-line fixes.
How to trigger it
Inside a session: press Shift+Tab until the input box shows “plan mode.” From the default starting mode the cycle is default to acceptEdits to plan; if you have other modes enabled the cycle may include them. While in plan mode Claude reads files without prompting, can still run shell commands (subject to the same permission prompts as default mode), and proposes a plan instead of editing source. Edits, Writes, and MultiEdits wait for your approval before anything lands on disk.
On launch:
claude --permission-mode plan
Without the CLI mode at all: plain English works almost as well:
Do not edit any files yet. Read
src/middleware/auth.tsandtests/auth.spec.ts. Write a plan that lists every file you would change, what you would change in it, and the test command you would run to verify. I will approve before you touch anything.
The English version is what you would write anyway in a tightly scoped prompt. Plan mode is the harness-enforced version, so Claude cannot accidentally edit a file mid-thought because of a context-window slip.
What a good plan must contain
Any plan worth approving has four parts. Withhold approval until all four are present.
- What it understood. One sentence summarizing the actual problem in its own words. This catches a misread in five seconds.
- The exact files it will touch. Path-by-path, with a one-line note per file. A plan that says “update the auth code” without listing files is a plan that will refactor your test suite.
- The explicit out-of-scope list. “I will not touch X, Y, Z.” Forces Claude to commit to bounded scope and gives you a redirection target if the answer is wrong.
- The verification command. Which test, build, or grep proves the change works. “I will run
pnpm test auth.spec.ts” beats “I will write a test.”
If a part is missing, push back:
Add an out-of-scope list. Specifically, do not change anything in
src/storage/or any test other than the one I named.
What a bad plan looks like
A bad plan is short, confident, and vague. It usually reads like this:
I will update the auth middleware to fix the timezone bug. I will adjust the helper functions and update the relevant tests. After that I will run the test suite to verify.
It looks fine. It is exactly the plan that, an hour later, has rewritten three files you did not expect, deleted a memo helper you actually needed, and “updated the relevant tests” by editing four files in tests/ that have nothing to do with your bug.
Cost of approving this plan: the diff is large, you cannot tell in review what was deliberate vs collateral, and the rollback is git reset --hard because you cannot pick out the parts to keep.
The same plan made specific:
- I understood the bug as:
formatTime()insrc/lib/time.tsreturns UTC instead of the user’s timezone when the user is in PST.- I will edit
src/lib/time.tsto callIntl.DateTimeFormatwith the user’s tz, and I will edittests/time.spec.tsto add a PST case.- Out of scope: every other file. Not touching
src/middleware/auth.tseven though it importsformatTime, because the bug is in the formatter, not the middleware.- I will run
pnpm test src/lib/time.tsand confirm both existing tests pass plus the new PST case.
Same model, same problem, four times the information density. Approve this and you can review the diff in 30 seconds.
Footguns
Approving a plan you skimmed is worse than skipping plan mode. Plan mode trains a habit: read carefully, then approve. The day you start rubber-stamping plans because they “look fine,” you are paying the plan-mode latency tax for no benefit. If you cannot tell from the plan whether it will touch files you did not want touched, push back instead of approving.
Plan mode does not vet the commands inside the plan. A plan can include “I will run npm install some-package to add a dependency” or “I will run rm -rf .cache”. Once you approve, those commands run in the execution phase under whatever permission mode you fall back to. Read the plan’s commands as carefully as the file changes. The protection is the human approval, not the mode boundary.
Mid-plan redirects beat post-edit fixes. When the plan is wrong, do not approve and then complain in the next turn. Press Esc to interrupt, point at the specific line that is wrong, and ask for a revision. A redirected plan is a 30-second turnaround; a redirected diff is git reset and a fresh session.
Long sessions accumulate stale plans. Plan-then-build works once per task. After you ship the auth fix, run /clear before starting the next task. Plans from earlier in the session leak into later context as “we already agreed to…” even though you ended that work three tasks ago. That is how surprise refactors enter the codebase.
When NOT to use plan mode
- One-line edits. “Rename
getUserDatatofetchUser” or “add aconsole.loghere” do not need a plan. The diff and the prompt are the same length. - You already wrote the plan in the prompt. If your prompt says “edit
foo.tsline 42 from X to Y”, you have done the planning. Plan mode adds a turn for no information. - Mechanical refactors with a clear pattern. “Replace every
useStatewithuseReducerin this file” is mechanical. Plan mode wastes a turn restating what you said. - You are exploring, not building. “What does this function do?” and “where is
parseDatedefined?” are read-only by nature. Plan mode adds friction without changing behavior. - Single-file diff in a file you wrote yesterday. You already know the code; the planning round adds latency without surfacing anything you do not already see.