This is the third post in my Claude Code Tools Deep Dive series. The first two unpacked AskUserQuestion and EnterPlanMode—the first two stages of the decision pipeline: clarify, then expand. This post covers the final stage: submit the plan for user approval.
Before reading this post, it may help to read the series prelude on how Claude Code's tool mechanism works. This article follows the same four-layer framework introduced there.
ExitPlanMode
On the surface, ExitPlanMode may be the least conspicuous of Claude Code's three interaction tools. It has none of AskUserQuestion's option cards and none of EnterPlanMode's dramatic mode switch. It does exactly one thing: trigger an approve-or-reject confirmation.
But that restraint—doing almost nothing—is precisely what closes the three-tool workflow.
What It Does
ExitPlanMode is Claude Code's built-in “leave planning mode and request approval” tool. Its responsibility fits in one sentence: after Claude has written a complete plan in plan mode, it calls this tool so the user can review the entire plan and decide whether to approve execution, request revisions, or reject the direction.
It solves the core problem of obtaining explicit user approval when the AI moves from planning back to implementation:
- Make the proposal visible — the UI displays the complete plan file instead of letting it disappear inside a chat message.
- Require an explicit decision — the user must approve or reject; Claude cannot continue by default or jump the gun.
- Switch back to implementation in one action — after approval, Claude automatically returns to the default mode where Edit and Write are available.
- Preserve a feedback channel — the user can reject the current version and ask for changes instead of choosing between “accept everything” and “throw everything away.”
A Concrete Example
Scenario: continuing the authentication refactor from the EnterPlanMode post. The user asked Claude to replace JWT with session cookies. Claude entered plan mode, explored the codebase, clarified that only the web flow should change and that Redis should hold session state, then wrote the plan file. It is now ready to implement.
One question remains: how does Claude tell the user that the plan is complete and implementation can begin?
The Anti-Pattern: Life Without ExitPlanMode
Claude could only say something like this in chat:
“I've finished the plan. It looks roughly like this... [several hundred words] ... May I start?”
That creates several problems:
- The plan gets buried in the conversation — hundreds of words mix with exploration logs and clarification messages, making the proposal difficult to review.
- There is no explicit approval action — “OK,” “sure,” “go ahead,” and “👍” may all mean approval, but their semantics are not identical.
-
Claude must interpret approval language — a reply such as “Looks good, but can we add a
device_idfield to the sessions table?” is half approval and half revision request. Should Claude implement or revise the plan? - The mode transition has no boundary — Claude can gradually slide from planning into implementation and start writing code before the user realizes the transition occurred.
- Rejection is expensive — if the proposal is wrong, the user must type an explanation instead of using a first-class “reject and explain” channel.
The deepest problem appears if Claude tries to solve this with AskUserQuestion by asking, “Is the plan OK?” As the previous post explained, the user cannot see the full plan before ExitPlanMode presents it. Asking for approval before showing the document is asking the user to vote in a vacuum.
How ExitPlanMode Fixes It
After finishing the plan file, Claude calls ExitPlanMode. The call takes no meaningful arguments—more on that below. The UI then handles three steps.
Step 1: Display the Complete Plan
The interface reads the file at the path maintained by plan mode and renders it as a separate, structured, scrollable proposal. The user sees a formal plan—scope, affected files, migration steps, risks, and rollback—not a paragraph floating through chat.
Step 2: Provide Explicit Response Paths
- ✅ Approve — return Claude to default mode and execute the plan.
- ✏️ Request changes — give feedback and keep Claude in plan mode so it can revise the proposal.
- ❌ Reject — stop and change direction.
Step 3: Make the Transition Atomic
The moment the user approves, the runtime performs several actions together:
- Edit, Write, and NotebookEdit become available again.
- CWD-dependent caches are refreshed.
- Claude receives an explicit “user approved” signal and begins implementation.
There is no semantic ambiguity, no gradual slide, and no opportunity for Claude to jump the gun.
Side-by-Side Comparison
| Anti-pattern pain | ExitPlanMode's solution |
|---|---|
| The plan gets buried in chat | The UI independently renders the complete plan file |
| No explicit approval action | The user must choose approve, revise, or reject |
| Claude must interpret agreement | The result is a structured state, not ambiguous natural language |
| The mode transition has no boundary | Approval atomically changes the tool allowlist |
| Rejection is expensive | Revision is a first-class path rather than an improvised reply |
When to Fire It
The tool description gives a very strict rule: use ExitPlanMode only when Claude is in plan mode, has finished writing the plan file, and is ready for user approval.
The One Valid Situation
- Claude is in plan mode and the plan file is complete.
Situations That Do Not Qualify
- Pure research — a task such as “search for and understand the Vim mode implementation” does not need ExitPlanMode because no implementation plan is being submitted.
- An unfinished plan — do not submit a partial proposal for approval. Finish it first.
- A general-purpose permission question — do not use this tool as a fancy “May I continue?” prompt. If a real implementation fork needs clarification, use AskUserQuestion to ask about that fork rather than asking a meta-question.
A useful dividing line is: only a citable plan deserves ExitPlanMode. If the proposal is not yet a readable, reviewable, refutable document, keep exploring in plan mode instead of rushing to exit.
Technical Design
1. Naming
ExitPlanMode
The name is perfectly dual to EnterPlanMode. The Enter/Exit pair signals a stateful operation with a beginning and an end, following familiar pairs such as opening/closing a file descriptor or acquiring/releasing a lock. The semantics need almost no explanation.
Names such as SubmitPlan or RequestApproval would shift attention toward submitting data or requesting permission. They would weaken the tool's core meaning as a signal that ends a mode.
2. Tool-Level Description
ExitPlanMode's description focuses on three things: when to use it, why the plan content is not an argument, and why AskUserQuestion must not be used for the same meta-question.
Strict Applicability Boundary
Use this tool when you are in plan mode and have finished writing your plan to the plan file and are ready for user approval.
Three conditions are stacked together: Claude is in plan mode, the plan file is complete, and the proposal is ready for approval. If any one is false, the tool should not be called.
Transparent Parameter Mechanism
This tool does NOT take the plan content as a parameter - it will read the plan from the file you wrote
The instruction tells Claude not to copy the plan into the tool call. The UI reads the file directly. This saves tokens and, more importantly, guarantees that the plan the UI displays is the same plan stored in the file.
Approval as an Implied Signal
This tool simply signals that you're done planning and ready for the user to review and approve
The key word is signals. The tool itself does not render the document or decide whether it was approved. It only emits an event. The runtime handles rendering, user input, and the state transition.
The tool call is therefore the lightest possible signal emitter—a distinctly Unix-like design.
Boundary with Research Tasks
IMPORTANT: Only use this tool when the task requires planning the implementation steps of a task that requires writing code. For research tasks where you're gathering information, searching files, reading files or in general trying to understand the codebase - do NOT use this tool.
This mirrors the boundary described for EnterPlanMode: plan mode exists for planning implementation, not for understanding an existing codebase as an end in itself. A pure investigation belongs in a research workflow rather than an implementation-approval workflow.
The Forbidden Meta-Question
Important: Do NOT use AskUserQuestion to ask “Is this plan okay?” or “Should I proceed?” - that's exactly what THIS tool does. ExitPlanMode inherently requests user approval of your plan.
This is especially elegant. It does not merely say “use ExitPlanMode instead of AskUserQuestion.” It identifies the two actions as semantically equivalent and declares that ExitPlanMode is the correct representation of that intent.
The earlier posts noted this anti-pattern. Here, the tool description bans it at the source.
Clarification Before Approval
One official example says:
Initial task: “Add a new feature to handle user authentication” - If unsure about auth method (OAuth, JWT, etc.), use AskUserQuestion first, then use exit plan mode tool after clarifying the approach.
This establishes the ordering between AskUserQuestion and ExitPlanMode while planning: clarify concrete forks first, then request approval for the complete proposal. Do not clarify and approve at the same time. Let the process converge linearly.
3. Field-Level Descriptions
Effectively none.
There is an allowedPrompts field, but it is marked deprecated: “Deprecated: no longer used.” In practice, the tool accepts no useful input.
That historical trace is interesting. Judging by the field name, an earlier version may have allowed Claude to declare a set of operation types that would become automatically permitted after approval—for example, run tests or install dependencies. Its deprecation suggests that the design moved toward a more conservative separation: approving the plan and granting additional permissions are different decisions.
In other words, it hints at an evolution from “approval implies authorization” toward “approval is approval; authorization is authorization.”
4. Schema Validation Rules
Effectively none.
Like EnterPlanMode, the input schema has no active constraints. Calling the tool is itself the intent to submit the plan; there is no data Claude needs to pass.
The empty schema leaves four responsibilities to the runtime:
- Make the tool available only in plan mode.
- Read and render the plan using the file path stored in the plan-mode state.
- Block until the user explicitly responds; there is no automatic continuation.
- On approval, atomically restore the tool allowlist, refresh caches, and send Claude the approval signal.
None of that requires an argument. This echoes EnterPlanMode's empty-schema design: permissions and state belong to the runtime; Claude only emits a signal.
Division of Responsibility with Neighboring Tools
ExitPlanMode is the final stage of the decision pipeline:
User: “Refactor auth and replace JWT with sessions.”
↓
Claude: Several forks need clarification.
↓
AskUserQuestion: clarify web-only scope and Redis session storage
↓
Claude: Let me develop a plan first.
↓
EnterPlanMode: user approves entry
├─ Explore with Grep / Read / Glob
├─ Clarify sub-decisions with AskUserQuestion as needed
└─ Write the plan file
↓
ExitPlanMode: user sees the complete plan
├─ Approve → return to default mode and execute
├─ Request changes → revise in plan mode, then call ExitPlanMode again
└─ Reject → stop or change direction
Each of the three tools has exactly one job. Together, they create a complete collaborative alignment loop:
- AskUserQuestion — clarify: “A or B?” A single-point decision.
- EnterPlanMode — expand: explore read-only and turn the approach into a document.
- ExitPlanMode — commit: let the user approve, revise, or reject the entire proposal.
Takeaway
ExitPlanMode's elegance is not simply that it “lets the user approve the plan.” It comes from how closely its signals mirror EnterPlanMode: dual naming, behavior concentrated in the tool description, and effectively empty field and schema layers.
If AskUserQuestion lets the user choose, and EnterPlanMode opens a protected planning state, then ExitPlanMode is the humblest part of the system: it does nothing but emit a signal. Yet that signal gives the workflow an endpoint and gives collaboration a ceremonial moment of commitment.
The three-tool pipeline is now complete:
Claude Code decomposes AI–human collaboration into three composable, orchestratable, predictable interaction primitives: clarify, expand, commit. Each primitive is deliberately restrained—it does one small thing—but together they can express a complete collaborative workflow.
The next post will move from collaborative alignment to code exploration with Grep + Glob, examining how information-retrieval tools encode what to search, how to search, and how much to return.
Top comments (0)