Between "understand" and "change" stands a separate phase, and mixing them is a costly mistake. Plan mode is needed precisely when a bug crosses several modules and the cost of a wrong patch is higher than the cost of a short exploration. In such tasks you build a map first and only then make the decision. You enter the mode with the /plan command or pass an inline objective; the result is a plan you approve before a single file is touched.
The point of plan mode is to separate exploration from implementation, not to hide implementation under another name. In this mode the agent reads files and traces the real entry points, callers and tests but does not edit sources. It is a technical guarantee that the understanding phase will not quietly turn into edits. But the guarantee does not remove the need for a clear task: the mode limits actions, it does not replace the framing of the goal and boundaries.
A good plan is recognizable by its specifics, not by general verbs. It has not "update the service, add a test, check" but concrete files and symbols to be changed, dependencies between steps, a test signal, the question of data migration and rollback, and separately the unknowns requiring your decision. A plan of three general phrases gives no point of control: it cannot be judged by what exactly will happen, and therefore cannot be objected to in time.
It helps to see once the wording that forces a plan to be concrete. Below is a request to design a migration of the auth middleware: first trace the real entry points, callers and tests, do not edit files, and in the plan state the order, affected contracts, rollback and the verification of each stage. You return to this form when the plan came out general: it externalizes the assumptions and turns a sketch into a checkable sequence of steps.
The most valuable thing in a plan is the externalized assumptions. It is they that show where the plan stands on a guess rather than on read code, and where you may need to intervene before implementation, not after. When the agent explicitly lists what it assumes but has not yet confirmed, you see the weak spots in advance. A hidden assumption, on the contrary, surfaces already in the finished diff - and there it is both more expensive and riskier to fix.
Not every task deserves a plan, and this matters. For a one-line typo fix with an obvious test a complex plan adds only ceremony: time goes into formalizing what is already clear. Planning is applied where discovery can change the decision itself - where the result of the exploration may show that the original idea was wrong. Using a heavy plan on a trivial task is as unwise as going without a plan on a risky migration.
Accepting a plan is a point of directional control, and it is passed consciously. Before moving to writing you check the git state; if another agent works in parallel, you take a separate worktree. Then you leave plan mode, approve the plan and explicitly restate the boundaries: which steps to implement, what not to do, where to stop to show the diff. Restating boundaries at approval is cheaper than rolling back extra changes already made - it is discipline, not an extra ritual.
The typical failures of this phase are predictable. Letting the agent immediately edit poorly understood code instead of exploring. Approving a plan of general verbs with no files, dependencies and checks. Hiding in the implementation an assumption that was worth externalizing. And spending a heavy plan on a trivial edit. A map and a concrete plan first, then approval with boundaries - and the phase between "understand" and "change" stops being the place where beautiful but wrong solutions are born.
/plan Design a migration of the auth middleware.
First trace the real entry points, callers and tests.
Do not edit files. In the plan state the order, affected contracts,
rollback and the verification of each stage.
Separately list the assumptions not yet confirmed by the code.