Skip to main content
Plan mode lets you review and refine the agent’s approach before any code changes happen. Instead of diving straight into implementation, the agent writes a plan to a file, proposes it for your review, and waits for approval.

How It Works

  1. Toggle to Plan Mode: Press Cmd+Shift+M (Mac) or Ctrl+Shift+M (Windows/Linux), or use the mode switcher in the UI.
  2. Agent Writes Plan: In plan mode, all file edit tools (file_edit_*) are restricted to only modify the plan file. The agent can still read any file in the workspace to gather context.
  3. Propose for Review: When ready, the agent calls propose_plan to present the plan in the chat UI with rendered markdown.
  4. Edit Externally: Click the Edit button on the latest plan to open it in your preferred editor (nvim, VS Code, etc.). Your changes are automatically detected.
  5. Iterate or Execute: Provide feedback in chat, or switch to Exec mode (Cmd+Shift+M) to implement the plan.

External Edit Detection

When you edit the plan file externally and send a message, Xum automatically detects the changes and informs the agent with a diff. This uses a timestamp-based polling approach:
  1. State Tracking: When propose_plan runs, it records the plan file’s content and modification time.
  2. Change Detection: Before each LLM query, Xum checks if the file’s mtime has changed.
  3. Diff Injection: If modified, Xum computes a diff and injects it into the context so the agent sees exactly what changed.
This means you can make edits in your preferred editor, return to Xum, send a message, and the agent will incorporate your changes.

Plan File Location

Plans are stored in a dedicated directory under your Xum home:
Notes:
  • <workspace-name> includes the random suffix (e.g. feature-x7k2), so it’s globally unique with high probability.

SSH and Coder workspaces

Plans of SSH and Coder workspaces live on the remote host, in a tree of their own for each Xum installation:
  • <installation-id> is a random ID that Xum creates on first use in the installation_id file of its data root (~/.xum by default). Two Xum installations that use one host (two machines, or two data roots on one machine) get separate trees, so a clear or delete in one never removes the other’s plan.
  • <project-id> is the same ID that names the project’s remote checkout under srcBaseDir.
  • One data root holds each installation ID. If you move a data root and stop using the old one, it keeps its ID and its remote plans. If both the original and a copy stay usable, the copy must get a new ID before it opens an SSH or Coder workspace, even if the two never run at the same time. Xum does not detect copies. Two roots with one ID share one tree, so one root can delete a plan that the other still shows, and an older plan can come back after a clear. See Give a copied data root its own ID.
  • If the installation_id file is unreadable or is not a UUID, Xum refuses to read, write or delete remote plans until you restore the file from a backup or delete it. A deleted file gets a new ID, and plans under the old ID stay on the host unused.
Older builds kept SSH plans in files that every installation on the host shared. Xum moves a workspace created before the upgrade to the new tree once, on its first plan access:
  • If the workspace has a plan at ~/.mux/plans/<workspace-id>.md, Xum copies it into the new tree. That file belongs to this workspace only.
  • Xum does not import ~/.mux/plans/<project>/<workspace-name>.md automatically, because another installation can own that file. If that is the only old plan, a notice above the chat input shows its path with an Import plan button. The command palette has the same action, Import plan from an older Xum. Importing copies the file into the new tree. It never replaces a plan that is already there. Until you import that plan or write a new one, Xum refuses to rename the workspace, because the old file is named after the workspace.
  • Xum never moves, edits or deletes either old file.
After the move, Xum uses only the new tree. If the plan there is missing later (for example after you delete the installation_id file), Xum shows no plan. It does not go back to the old files. If you downgrade, the older build reads only the old paths. It shows the plan from before the upgrade, or no plan, not the newer copy. To keep the newer plan, copy it on the host from the installation-<installation-id> tree to ~/.mux/plans/<project>/<workspace-name>.md before you downgrade. Edits that the older build makes there are not imported when you upgrade again. If you rename the workspace while you run the older build, the upgraded build looks for the plan under the new name: rename <workspace-name>.md in the installation-<installation-id> tree on the host to match.

Give a copied data root its own ID

Do this on the copy. The original keeps its ID. These steps copy plans and never move, replace or delete a file on the host.
  1. Stop Xum on the copy.
  2. Read the old ID: cat <copy-root>/installation_id.
  3. Write a new ID in lowercase, because Xum uses the lowercase form in paths: uuidgen | tr 'A-Z' 'a-z' > <copy-root>/installation_id. If uuidgen is missing, use python3 -c 'import uuid; print(uuid.uuid4())' > <copy-root>/installation_id instead.
  4. On every SSH or Coder host that the copy uses, copy the old tree to the new one. The command does nothing if there is no old tree, or if the new tree already exists, so it never replaces a file:
  5. Start Xum on the copy.
Step 4 matters for workspaces that already moved to the new tree (their remotePlanMigrated field in config.json is true). Without it, the copy shows no plan for them, because Xum does not go back to other files. Workspaces that did not move yet move on their first plan access in the copy, as described above. If step 4 already put a plan for such a workspace into the new tree, the move keeps that plan. After these steps, each root has its own tree, and a clear in one leaves the other’s plan unchanged. The steps do not undo changes that the two roots made to each other’s plans while they shared one ID.

ask_user_question (Plan Mode Only)

In plan mode, the agent may call ask_user_question to ask up to 4 structured multiple-choice questions when it needs clarification before finalizing a plan. What you’ll see:
  • An inline “tool call card” in the chat with a small form (single-select or multi-select).
  • An always-available Other option for free-form answers.
How to respond:
  • Recommended: answer in the form and click Submit answers.
  • Optional: you can also just type a normal chat message. This will cancel the pending ask_user_question tool call and your message will be sent as a regular chat message.
Availability:
  • ask_user_question is only registered for the agent in Plan Mode.
  • In Exec Mode, the agent cannot call ask_user_question.

UI Features

The propose_plan tool call in chat includes:
  • Rendered Markdown: View the plan with proper formatting.
  • Edit Button: Opens the plan file in your external editor (latest plan only).
  • Copy Button: Copy plan content to clipboard.
  • Show Text/Markdown Toggle: Switch between rendered and raw views.
  • Start Here: Replace chat history with this plan as context (useful for long sessions).

Customizing Plan Mode Behavior

Use scoped Mode: instructions to customize how the agent behaves in plan mode. Add the following to .xum/AGENTS.md (or ~/.xum/AGENTS.md):

CLI Usage

Plan mode is also available via the CLI:
See CLI documentation for more options.