# Plan mode | Claude for Real Work

> When stopping to plan pays for itself and when it is ceremony. The same task run both ways, with the diffs side by side.

Source: https://karakabakov.com/courses/claude-for-real-work/plan-mode/

---

[&larr; Claude for Real Work](https://karakabakov.com/courses/claude-for-real-work/)

# Plan mode

Lesson 14 of 28 · 11 min · Updated August 21, 2026

Plan mode is the one where Claude can read your files and run commands to explore, but cannot change anything. It researches, then writes you a plan, and edits stay blocked until you approve it.

That is a small mechanical difference and a large practical one. In the normal loop you review a change. In plan mode you review an intention, before any code exists to be attached to it. Intentions are much cheaper to argue with.

You get in three ways: `Shift+Tab` until the indicator says plan, `/plan` in front of a single prompt, or from the start:

```
claude --permission-mode plan
```

`Shift+Tab` again leaves without approving anything.

## One test, done twice

Stockroom has one failing test left:

```
 FAIL  test/util.test.ts > dates > gives the day a local timestamp falls on
AssertionError: expected '2026-03-03' to be '2026-03-04'
```

`dayKey("2026-03-04T09:12:00+13:00")` returns `2026-03-03`. Nine in the morning in Auckland is the previous evening in UTC, `dayKey` formats in UTC, and the day comes out wrong. The tests pin `TZ` to `Pacific/Auckland` in `vitest.config.ts`, so this fails the same way on everyone’s machine.

**First, without a plan.** In a normal session, ask for the fix. You will probably get a change to `dayKey`, and there is a good chance you also get changes to `startOfDay` and `endOfDay`, because they sit directly underneath it in the same file and they use local time while `dayKey` uses UTC. That inconsistency is right there on the screen and it looks exactly like part of the bug.

**Now the same thing in plan mode.** Reset first:

```
git checkout -- src/util/dates.ts
```

Then, in plan mode:

```
The test "gives the day a local timestamp falls on" in test/util.test.ts fails.
Work out what to change in src/util/dates.ts. Check who calls each function in that
file before you decide.
```

The plan should tell you something the other run did not: `startOfDay` and `endOfDay` are exported and called by nothing. Not by `src`, not by `test`.

```
grep -rn "startOfDay\|endOfDay" src/ test/
```

```
src/util/dates.ts:15:export function startOfDay(iso: string): Date {
src/util/dates.ts:22:export function endOfDay(iso: string): Date {
```

Two definitions and no callers. So the fix is one function, not three, and the inconsistency that made the bug look bigger is between the live code and two pieces of dead code.

That is what the plan bought you: the same fix, two functions’ worth of change you now know not to make, and the discovery that there is dead code in that file.

## Reading a plan

When the plan is ready you get three choices:

- **Yes, and use auto mode** - approve, and let the classifier take over the prompts. If auto mode is not available to your account this reads **Yes, auto-accept edits** instead.
- **Yes, manually approve edits** - approve, and go back to seeing each change. This is the one to use while you are learning.
- **No, keep planning** - stay in plan mode and say what is wrong.

Approving exits plan mode, so the session starts editing straight away in whichever mode you picked. To plan again, cycle back with `Shift+Tab`.

`Ctrl+G` opens the plan in your editor. Use it when the plan is nearly right: deleting the step you do not want is faster and more precise than three rounds of explaining which step you meant.

What to look for in a plan, in order:

- **The file list.** This is the highest-value line in the whole thing. If it names a file you did not expect, find out why now. If it is missing a file you know is involved, the research did not go deep enough and the plan is guessing.
- **The order.** A plan that changes the callers before the thing they call is a plan that cannot be stopped half way.
- **What it says it will not do.** A plan with no boundaries usually acquires some while it runs.
- **The size.** Fourteen steps for a two-file change means it has planned the work of understanding the code as well as the work of changing it, and you are about to approve both.

## When is planning ceremony?

Not often enough is a real failure mode, and too often is a real failure mode, and the second one is the one nobody warns you about.

Plan first when the change touches more than about three files, when you cannot yet name every file it should touch, when the naive fix is probably wrong, or when you are working in code you do not know. Those are the cases where a wrong direction costs a review instead of a sentence.

Skip it for a one-line fix, for anything you would happily revert with `git checkout --`, for exploratory changes you are going to throw away anyway, and for anything where you already know the exact diff you want. Planning a one-line change costs you a round trip and gives you a paragraph describing a line.

The tell that you are over-planning: you are approving plans without reading them. A plan you skim is worse than no plan, because it feels like review.

If you want it always on for a project, put it in `.claude/settings.json`:

```
{
  "permissions": {
    "defaultMode": "plan"
  }
}
```

Lesson 18 is about that file properly.

> One thing worth knowing before it surprises you: plan mode does not mean nothing runs. Claude runs commands to explore, and if auto mode is available to your account the classifier approves those commands rather than prompting you. Reads and greps, mostly. But “cannot edit my files” and “will not execute anything” are different promises, and plan mode only makes the first one.

## Your turn

`src/reports/index.ts` is 335 lines and seven reports. Split it, in plan mode.

The rule that makes this checkable: nothing outside `src/reports/` may change. The CLI, the server and the tests all import from `src/reports/index.ts`, and they should carry on importing from there afterwards.

```
Split src/reports/index.ts into one file per report, in src/reports/. Keep index.ts as
a barrel that re-exports everything, so src/cli/main.ts, src/server/main.ts and
test/reports.test.ts do not have to change. Find every importer before you plan.
```

Read the plan before approving it. Specifically: does it list all three importers? Does it say index.ts stays? If either is missing, choose **No, keep planning** and say so.

> **Check:** `npm test` reports `Tests 86 passed (86)`, `npx tsc --noEmit` prints nothing, `wc -l src/reports/index.ts` is under 40, and `git status --short` shows changes only under `src/reports/`. If `src/cli/main.ts` is in that list, the barrel is not doing its job.

This is the exercise in this course most likely to leave you somewhere confusing, because it moves code between eight files. If the tests will not go green and you have lost the thread, `git reset --hard after-lesson-12` puts you back at the start of it. Compare with `git diff after-lesson-12 after-lesson-14` once you have finished, and see how somebody else split the same file.

Then commit it, the way lesson 12 asked:

```
git add -A && git commit -m "Split the reports module behind a barrel"
```

## Recap

Plan mode reads and explores but cannot edit until you approve a plan. `Shift+Tab` or `/plan` gets you in, `Shift+Tab` gets you out, `Ctrl+G` edits the plan directly.

The value is finding out what a change touches before anything is touched, which is why the file list is the part of a plan worth reading closely.

Plan for multi-file work and unfamiliar code. Do not plan a one-line fix. And if you are approving plans without reading them, you have stopped planning and started performing it.

Next: the file that tells Claude what it needs to know about your project before you have to say it again.

[&larr; Previous

## Reading before writing](https://karakabakov.com/courses/claude-for-real-work/reading-before-writing/) [Next &rarr;

## CLAUDE.md](https://karakabakov.com/courses/claude-for-real-work/claude-md/)

[&larr; All lessons](https://karakabakov.com/courses/claude-for-real-work/) [Next lesson &rarr;](https://karakabakov.com/courses/claude-for-real-work/claude-md/)
