# Claude Code plan mode: what it really enforces

> Plan mode makes Claude Code read and plan without editing until you approve (Shift+Tab). It blocks the edit tools - but shell commands can still write.

URL: https://bartlomiejkrupa.dev/articles/claude-code-plan-mode/
Published: 2026-07-01
Updated: 2026-10-07
Tags: claude-code, plan-mode, agentic-workflow, permission-modes, context-engineering
Summary: Plan mode makes Claude Code read and plan without editing until you approve (Shift+Tab). It blocks the edit tools - but shell commands can still write.

Plan mode separates exploration from execution: Claude Code reads files and drafts an implementation plan but makes **no edits until you approve it**. Turn it on with `Shift+Tab` mid-session or `claude --permission-mode plan` at startup. Anthropic's recommended loop is explore → plan → implement → commit. But the read-only promise has edges: Claude Code (the harness - the program that runs the agent and executes its tool calls) blocks the edit tools, while shell commands keep running during planning, and the planning instructions themselves are a short injected prompt.

## Definitions

**Plan mode** - a Claude Code permission mode in which the agent reads, searches, and plans but makes no edits to your codebase until you approve the plan.

**Permission mode** - the harness setting that governs which actions Claude may take without asking. Plan mode is one; the default (ask-per-write) and `auto` (a classifier gates writes) are others.

## Enable it

| Method | Command / key | Effect |
| --- | --- | --- |
| Startup flag | `claude --permission-mode plan` | Begin the session read-only |
| Mid-session toggle | `Shift+Tab` | Flip into plan mode on the fly |
| Edit the plan | `Ctrl+G` | Open the plan in your text editor before Claude proceeds |

In plan mode Claude reads files and proposes a plan but touches nothing on disk. When the plan is drafted, `Ctrl+G` opens it in your `$EDITOR` for direct editing before you approve - so you correct the spec, not the diff.

## The workflow: explore → plan → implement → commit

Letting Claude jump straight to code risks solving the wrong problem. Anthropic's recommended four phases separate research from execution:

**1 - Explore (plan mode).** Point Claude at the relevant code and let it read.

```text
read src/auth and explain how we handle sessions and login.
also check how we load secrets from env.
```

**2 - Plan (plan mode).** Ask for a concrete implementation plan, then edit it with `Ctrl+G`.

```text
I want to add Google OAuth. What files change? What's the session
flow? Write a plan.
```

**3 - Implement (default mode).** Exit plan mode and let Claude code against the plan.

```text
implement the OAuth flow from your plan. write tests for the callback
handler, run the suite, and fix any failures.
```

**4 - Commit (default mode).**

```text
commit with a descriptive message and open a PR.
```

Separating the read-heavy explore phase from implementation is the same discipline as [delegating research to a subagent](/notes/subagent-context-isolation): keep exploration out of the window that does the work. For how those reads accumulate in the first place, see [how Claude Code's agentic loop fills your context window](/articles/claude-code-agentic-loop-context).

## When to use it - and when to skip

The rule of thumb: **if you could describe the diff in one sentence, skip the plan.** The garden rule [Plan mode decision tree](/notes/plan-mode-decision-tree) is that table in one place.

| Use plan mode | Skip it |
| --- | --- |
| The approach is uncertain | Fixing a typo or adding a log line |
| The change spans multiple files | Renaming a single variable |
| You're unfamiliar with the code | Scope is clear and the fix is small |

Plan mode is useful but adds overhead. Spend it where the uncertainty is highest, not on one-line diffs.

## What the harness actually enforces

Plan mode *feels* hard-locked to read-only. Today that is half true. Anthropic's [permission modes docs](https://code.claude.com/docs/en/permission-modes#analyze-before-you-edit-with-plan-mode) say Claude Code blocks edits until you approve a plan, and the block sits in the permission layer - v2.1.136 (2026-05-08) fixed a hole where a matching `Edit(...)` allow rule let writes through. Two gaps remain. Shell commands still run while planning: with auto mode available a classifier approves them, and without it anything outside the built-in read-only set prompts you. And in interactive terminal sessions with bypass permissions available, neither the classifier nor a prompt applies to planning commands.

The instruction layer is still a prompt. Armin Ronacher's [reverse-engineering of the harness](https://lucumr.pocoo.org/2025/12/17/what-is-plan-mode/) (2025-12-17) found that plan mode is, in his words, "just a rather short predefined prompt that enters plan mode" - "prompt reinforcement that changes the behavior of the tools and also which tools are available." The agent still edits one file while "read-only": the plan itself.

The injected prompt does not hedge. It tells the model it "MUST NOT make any edits, run any non-readonly tools ... or otherwise make any changes to the system," and that this "supercedes any other instructions you have received." Strong wording is still only wording. A [March 2026 write-up](https://blog.sondera.ai/p/claude-codes-plan-mode-isnt-read) demonstrated the gap concretely by getting Claude to modify a `.zshrc` while plan mode was active - the kind of write a shell command makes without ever touching the edit tool. Their summary is the line worth keeping: writing MUST NOT in all caps is not a load-bearing security boundary.

- **The plan is a file.** It lives as markdown in `~/.claude/plans` by default (the `plansDirectory` setting moves it). While planning, the agent edits exactly that file and nothing else in your tree.
- **The injected prompt has its own four phases** - distinct from the user-facing workflow above: *Initial Understanding* (read code, ask clarifying questions) → *Design* (draft approaches with context) → *Review* (check alignment with the original intent) → *Final Plan* (concise, executable steps with the critical file paths).
- **Exit reads the plan back.** Approving the plan makes the harness read the plan file from disk and start executing against it. Exiting plan mode this way only makes sense for code-implementation tasks - if you were just exploring, there's nothing to execute against, so the exit step has nothing to do.

The practical takeaway: plan mode blocks Claude's **edit tools, not the shell**, and it is not a sandbox. If you need a hard guarantee that nothing is written - an untrusted repo, a destructive tool - reach for OS-level sandboxing or permission rules, not plan mode alone.

### Make it actually read-only

A `PreToolUse` hook makes the edit block hold in every session, including ones with bypass permissions available: deny `Write` and `Edit` whenever the session's permission mode is `plan`, with one exception for the plan file itself. For shell writes, pair it with the sandbox. See [PreToolUse read-only hook](/notes/pre-tool-use-read-only-hook).

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|NotebookEdit",
        "hooks": [{ "type": "command", "command": "~/.claude/hooks/block-plan-writes.sh" }]
      }
    ]
  }
}
```

The script reads the hook payload on stdin and exits with code 2 (blocking the call - exit code 1 is a non-blocking error) when `permission_mode` is `plan` and the target path is outside `~/.claude/plans/`. This costs nothing in capability: the agent never legitimately writes anywhere else while planning, which is exactly why the exception list is one directory long. Anything stronger than a hook - an untrusted repo, an unattended run - is the [sandbox ladder](/articles/claude-code-security-sandboxing-2026), where the boundary is enforced by the kernel rather than by the harness.

## Plan mode vs a DIY markdown handoff

Because the plan is just a markdown file, Ronacher argues you can approximate it without switching modes: iterate on a visible markdown file on disk, asking Claude clarifying questions until the plan is solid.

| Aspect | Plan mode | DIY markdown handoff |
| --- | --- | --- |
| Enforcement | Edit tools blocked until approval; shell commands still run | Normal tools stay live; your discipline gates edits |
| Plan artifact | Markdown in the hidden plans folder; edit via `Ctrl+G` | A visible markdown file you own and version |
| Approval | Built-in approve / reject UI on exit | You read and edit the file yourself |
| Best for | The standard flow - one keystroke, built-in gate | Full transparency and control over the handoff |

The one thing the DIY route can't cheaply replicate is the built-in approval UI on exit. Everything else - the plan, the phased prompt - is reproducible with a file and a good prompt.

## Bottom line

Use plan mode to force a read-only explore-and-plan pass before Claude touches code; it's the cheapest way to avoid building the wrong thing. Just know the block covers the edit tools, not the shell, and the plan is only a markdown file. Plan mode is one lever in the bigger discipline of controlling what enters the window during that explore pass - [context engineering](/notes/context-engineering), which [beats a bigger window](/articles/context-engineering-beats-a-bigger-window). For daily keyboard shortcuts and in-session slash commands, see [Claude Code commands cheatsheet](/articles/claude-code-commands-cheatsheet-2026).

Sources:
- Choose a permission mode — Analyze before you edit with plan mode: https://code.claude.com/docs/en/permission-modes
- Best practices for Claude Code — Explore first, then plan, then code: https://code.claude.com/docs/en/best-practices
- What is plan mode?: https://lucumr.pocoo.org/2025/12/17/what-is-plan-mode/
- Claude Code's plan mode isn't read-only: https://blog.sondera.ai/p/claude-codes-plan-mode-isnt-read
- Hooks reference — PreToolUse and blocking exit codes: https://code.claude.com/docs/en/hooks
- Sandboxing — filesystem and network isolation: https://code.claude.com/docs/en/sandboxing
- Claude Code changelog - 2.1.136: https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md
- Settings reference - plansDirectory: https://code.claude.com/docs/en/settings-reference
