CoreMesh

How to Use Claude Code Plan Mode (With Headless Examples)

What Claude Code plan mode does, how to enter it with Shift+Tab or --permission-mode plan, how to run it headless with -p, and what to check when Shift+Tab fails.

How to Use Claude Code Plan Mode (With Headless Examples)

Plan mode is the Claude Code permission mode where Claude can read your code and propose changes but can't make them. It opens files, searches, and writes a plan. Nothing touches disk until you approve. The common workflows page describes it as the mode for changes you want to review before they touch disk, and the status bar shows ⏸ plan mode on while it's active.

There are two ways in. Mid-session, press Shift+Tab until the status bar shows ⏸ plan mode on. From the shell, start with claude --permission-mode plan. The same flag works with -p, so a script or CI job can produce a plan with claude -p --permission-mode plan "your task". The rest of this page covers each route, how plan mode compares to auto mode, how to shape the plan with system prompt flags, and what to check when Shift+Tab does nothing.

What plan mode does#

Plan mode splits a change into two phases: understand and propose, then edit. In the first phase Claude behaves like a reviewer with read access. It opens files, traces how components fit together, and writes a plan. In the second phase, after you approve, it carries the plan out.

Three behaviors are documented as of October 18, 2026:

  • No edits before approval. The common workflows page states that Claude reads files and proposes a plan but makes no edits until you approve.
  • A visible indicator. The status bar shows ⏸ plan mode on. If you don't see that text, you're not in plan mode, whatever you pressed.
  • An approval step with an editable plan. The permission modes page covers the approval flow and editing the plan in your text editor. The Claude Code changelog entry for 2.1.301 calls this surface the plan approval card and notes that plans render there as Markdown, tables included.

Plan mode isn't a separate model and isn't a separate prompt. It's a permission mode. The same session, with the same model and the same CLAUDE.md, is just not allowed to write yet. That answers the "plan model" searches: there's no planning model to pick. The model that would implement the change is the one that plans it.

How to enter plan mode interactively#

The shortcut is Shift+Tab. It cycles through permission modes, so press it until the status bar reads ⏸ plan mode on. Watch the status bar rather than counting presses. If you overshoot, keep cycling.

To exit plan mode, press Shift+Tab again until the ⏸ plan mode on text is gone. Approving a plan is the other exit. Once you accept it, Claude proceeds with the edits.

If you know before you start that the task needs a plan, skip the shortcut and launch in plan mode:

bash
cd /path/to/project
claude --permission-mode plan

Then type the task as you normally would. A good prompt in plan mode states the goal, the constraints, and what done looks like:

text
Add retry with exponential backoff to the HTTP client in src/http/client.ts.
Keep the exported function signatures unchanged. Tell me which tests you'd add.

Claude reads, proposes, and waits. You read the plan, edit it in your text editor if you want, and approve. If the plan is wrong, say what's wrong in the next message and Claude revises it while still in plan mode.

How to start plan mode headless with --permission-mode plan#

Headless runs use -p. Add --permission-mode plan and pass the task as the last argument:

bash
claude -p --permission-mode plan "Plan how to add retry with backoff to src/http/client.ts without changing its exported API" > plan.md

Nobody is at the keyboard in a -p run, so there's no approval step. The output is the plan, and the run ends. That's the useful property: a headless plan run can read the repository and reason about it, but plan mode makes no edits until approval, and approval never comes.

Keep the implement step as a separate run that someone starts after reading plan.md, in whatever permission mode your team allows for edits. The post on running Claude Code headless on a server covers the -p side in detail, and permission rules you can copy and test covers the allow rules for that second run.

Shell quoting is where these commands break. The task string and any appended rules are single arguments, so build the argument list in code and quote it once:

javascript
// Build a headless plan-mode command as an argv array, then as a bash line.
const task = 'Plan how to add retry with backoff to src/http/client.ts. Do not change its exported API.';
const rules = 'Output a numbered plan. For each step, name the file and the test that proves it works.';

const argv = ['claude', '-p', '--permission-mode', 'plan', '--append-system-prompt', rules, task];

const sq = (s) => "'" + s.split("'").join("'\\''") + "'";

console.log('argv entries:', argv.length);
console.log(JSON.stringify(argv, null, 2));
console.log('\nbash:');
console.log(argv.map((a) => (/^[A-Za-z0-9_./=-]+$/.test(a) ? a : sq(a))).join(' '));

Plan mode vs auto mode and the edit-allowing modes#

People compare plan mode with auto mode, accept edits, and edit mode. The underlying question is the same each time: who decides that a tool call may run, and when.

Mode Who decides whether a tool call runs Edits before you've reviewed a plan
Plan mode You, by approving the plan No
Auto mode A classifier, per tool call Yes, when the classifier allows the call

Auto mode is the opposite end of the range. According to the changelog for 2.1.278, auto mode for Claude API and Enterprise users, and on Bedrock, Vertex, Foundry and gateways, defaults to a server-side classifier that doesn't charge for classifier overhead, and CLAUDE_CODE_AUTO_MODE_SERVER=0 opts out on Bedrock, Vertex, Foundry and gateways. The /status command shows an Auto mode server row telling you where the classifier runs. Since 2.1.301, OpenTelemetry tool_decision events carry permission_mode and classifier_verdict, so you can tell classifier decisions apart from permission rules in your logs. If you're setting that up, see how to set the auto mode model and fix headless sessions.

Searches for plan mode vs accept edits, or plan mode vs edit mode, come down to approving the approach versus approving each change. Plan mode approves the approach once, up front. The modes that let edits through handle approval per change, or not at all. The permission modes page is the reference for their exact names and behavior, and I'd read it before relying on any of them in automation.

The practical rule: plan mode when you don't yet trust the approach, auto mode when you trust the approach and want the task to run long without you, and the modes in between when you want to watch each diff.

Shaping the plan with system prompt flags#

The CLI reference lists no plan-specific prompt flag. What it does list are five system prompt flags, and they all work in both interactive and non-interactive modes, so they combine with --permission-mode plan.

Flag Behavior
--system-prompt Replaces the entire default prompt
--system-prompt-file Replaces it with a file's contents
--append-system-prompt Appends to the default prompt
--append-system-prompt-file Appends a file's contents
--system-prompt-snapshot on (default) reuses the recorded prompt; off rebuilds it every request

For plans, use an append flag. Appending keeps Claude's default tool guidance, safety instructions, and coding conventions and adds your plan format on top. Replacing drops all of that, which is only sensible for a non-coding agent in a pipeline nobody watches.

A plan-format file you can keep in the repo:

text
Write the plan as a numbered list.
Each step names one file and the test that proves the step works.
List risks and open questions at the end under their own heading.

And the command:

bash
claude --permission-mode plan --append-system-prompt-file ./plan-rules.md

Two details from the CLI reference matter here, as of October 18, 2026. With Claude Code v2.1.283 or later, you can pass --append-system-prompt-file together with --append-system-prompt, and Claude Code uses both, with the file's contents first regardless of flag order. And by default the system prompt is built once on a conversation's first request and recorded. If you resume with --continue and different prompt text, the new text only takes effect after the conversation is compacted or in a new conversation. While you iterate on plan wording across --continue runs, pass --system-prompt-snapshot off so the prompt rebuilds every request.

When to use plan mode before edits#

Plan mode costs a round of reading and writing before any code changes, so it's not for every task. I'd use it when:

  • The change spans several files. A refactor that touches a public API, a schema, or auth is exactly the case the common workflows page describes: you want to see the approach before it touches disk.
  • You're new to the codebase. The common workflows page suggests starting with broad questions like an overview of the codebase, then narrowing. Plan mode is the natural next step after that: ask for the plan once you understand the shape of things.
  • The task statement is ambiguous. A plan surfaces the interpretation Claude picked. Correcting a plan is cheaper than reverting edits.
  • Someone else will review the work. A plan written to a file is a review artifact. It documents intent before the diff exists.

Skip it for one-line fixes, test additions in a file with established patterns, or documentation touch-ups. The planning round adds tokens, and the post on why Claude Code uses so many tokens explains where they go.

Once you have a plan, turn it into a checklist you can tick off during review. A few lines of Python handle the usual numbered-list format:

python
import re

plan = """# Plan: add retry with backoff

1. Add a retry() helper in src/http/retry.ts with jittered exponential backoff.
2. Call it from request() in src/http/client.ts and keep the exported signature.
3. Add tests in src/http/__tests__/retry.test.ts for 429 and 503 responses.
4. Document the HTTP_MAX_RETRIES setting in docs/http.md.

## Risks
- Backoff timing could slow existing tests that stub failures.
"""

steps = re.findall(r"^\s*\d+\.\s+(.*)$", plan, flags=re.M)
files = sorted(set(re.findall(r"\b[\w./-]+\.(?:ts|tsx|js|py|md)\b", plan)))

print("Review checklist")
for i, step in enumerate(steps, 1):
    print(f"[ ] {i}. {step}")

print("\nFiles the plan touches:")
for f in files:
    print(f"  - {f}")

Plan mode not working: Shift+Tab and other gotchas#

Shift+Tab does nothing. First, look at the status bar. The shortcut cycles modes, so a single press may have landed on a different mode. Press again until you see ⏸ plan mode on. If the status bar never changes, your terminal or multiplexer is probably consuming the key combination before Claude Code sees it. The reliable workaround is to quit and relaunch with claude --permission-mode plan, which doesn't depend on the key reaching the app.

Claude "won't edit anything." That's plan mode working. Approve the plan, or cycle out of plan mode with Shift+Tab. Check the status bar before assuming something is broken.

A headless run produced a plan but no changes. Same cause. There's no approval in a -p run, so a plan-mode run ends after the plan. Start a second run for the implementation.

New prompt rules aren't showing up in the plan. If you resumed with --continue or --resume, the conversation keeps the system prompt recorded on its first request until compaction. Start a new conversation, or pass --system-prompt-snapshot off. Note that outside cloud sessions, bare mode (--bare or CLAUDE_CODE_SIMPLE=1) leaves recording off unless you pass --system-prompt-snapshot on.

Windows. The common workflows page gives one command for every platform and lists no Windows-specific steps. Use the same flag in PowerShell. If the shortcut misbehaves there, the flag is again the dependable route.

Desktop app. The pages linked here describe the terminal: the Shift+Tab shortcut and the --permission-mode plan flag. They don't list a separate desktop app shortcut for plan mode yet.

Confusing it with auto mode. Plan mode is announced in the status bar. Auto mode's classifier location shows in /status under Auto mode server. If you see classifier decisions in your logs, you're not in plan mode.

Hooks still fire. Plan mode controls what Claude is allowed to do, not what your hooks do. If you have hooks that assume edits are happening, they'll run against a session that makes none. See how Claude Code hooks work if you need to gate them.

Quick reference#

Task What to do
Enter plan mode mid-session Press Shift+Tab until the status bar shows ⏸ plan mode on
Exit plan mode Press Shift+Tab again until that text is gone, or approve the plan
Start in plan mode claude --permission-mode plan
Plan headless claude -p --permission-mode plan "task" > plan.md
Add plan format rules --append-system-prompt "..." or --append-system-prompt-file ./plan-rules.md
Rebuild the prompt on every request --system-prompt-snapshot off
Check where auto mode's classifier runs /status, row Auto mode server

Before you rely on plan mode for a real change:

  • Confirm ⏸ plan mode on is in the status bar.
  • State the goal, the constraints, and what done means in the first message.
  • Read the whole plan, and edit it in your text editor if a step is wrong.
  • For headless use, write the plan to a file and run the implementation as a separate step.
  • If you changed prompt flags on a resumed conversation, remember they apply only after compaction unless snapshotting is off.

Quick answers

How do I enter Claude Code plan mode?

Press Shift+Tab during a session until the status bar shows ⏸ plan mode on, or launch with claude --permission-mode plan. The flag also works with -p for headless runs.

How do I exit plan mode?

Press Shift+Tab again until the ⏸ plan mode on indicator disappears, or approve the plan, after which Claude goes ahead with the edits.

What's the difference between plan mode and auto mode?

In plan mode Claude makes no edits until you approve its plan. In auto mode a classifier decides per tool call whether it runs, and as of the 2.1.278 changelog that classifier runs server-side by default for Claude API and Enterprise users.

Why is Shift+Tab not switching to plan mode?

The shortcut cycles through modes, so keep pressing until the status bar shows ⏸ plan mode on. If the status bar never changes, your terminal is likely intercepting the key, and starting with claude --permission-mode plan avoids the problem.

Is there a special plan mode system prompt or plan model?

No. Plan mode is a permission mode, not a different model or prompt. To shape the plan's format, pass --append-system-prompt or --append-system-prompt-file alongside --permission-mode plan.

Did this solve it?

One tap. No account.

Saved you an hour? Send a tip.

USDC or ETH on Base, Ethereum, Arbitrum and more. Keeps the notes free and the examples running.

Base

Network

0xc783bc5c3fa14cEC3f09A22284bC91C5AF0d59e1
Open in wallet · 5 USDC

On a computer? Scan the code with your phone wallet, or copy the address.

Pick the network your wallet or exchange uses. USDC works on all six; ETH on Base, Ethereum, Arbitrum and Optimism. Don't send on Tron or Solana: this address doesn't exist there. Tips are optional and unlock nothing; every guide stays free.

Discussion

Start the discussion

Indra Wijaya

Builds and runs AI agents, bots and content pipelines, and writes down what works and what broke.

About · Email · RSS

Keep reading

New notes, no spam.

One post at a time, only when there's something worth reading. Follow in any feed reader.

Subscribe via RSS