| 1 | # Modes and Permission Postures |
| 2 | |
| 3 | codewhale has three related concepts: |
| 4 | |
| 5 | - **TUI mode**: what kind of visible interaction you're in (Plan/Act/Operate). |
| 6 | - **Permission posture**: how aggressively the UI asks before executing tools. |
| 7 | - **Workflow overlay**: optional long-running orchestration that can |
| 8 | run on top of any TUI mode when a task needs many coordinated workers. |
| 9 | |
| 10 | Model selection is separate. `--model auto` and `/model auto` route each turn to |
| 11 | a concrete model and thinking level; they are not TUI modes and are not part of |
| 12 | the `Tab` cycle. |
| 13 | |
| 14 | Workflow is also separate from the mode itself. It is the visible ordered |
| 15 | orchestration layer for repeatable workflows and Fleet workers. High fan-out |
| 16 | routes through durable Fleet-backed workers instead of prompt-only sub-agent |
| 17 | fanout. The active mode |
| 18 | still controls permissions; Workflow controls whether a large task is planned |
| 19 | into a resumable workflow with its own progress view. |
| 20 | |
| 21 | ## TUI Modes |
| 22 | |
| 23 | Press `Tab` to complete composer menus or cycle through the visible modes |
| 24 | when the composer is empty: **Plan → Act → Operate → Plan**. `Tab` never sends |
| 25 | or queues composer text; use `Enter` to send or queue it. |
| 26 | Press `Shift+Tab` to cycle permission posture (Ask → Auto-Review → Full Access). |
| 27 | Press `Ctrl+T` to cycle reasoning effort. |
| 28 | Run `/mode` to open the mode picker, or switch directly with `/mode act`, |
| 29 | `/mode plan`, or `/mode operate`. |
| 30 | |
| 31 | - **Plan**: design-first prompting. Read-only investigation tools stay available; shell and patch execution stay off. Use this when you want to think out loud and produce a plan to hand to a human (yourself later, or a reviewer). |
| 32 | - **Act** (Agent): multi-step tool use. In interactive TUI sessions, the canonical `Bash` tool is available by default and approval prompts gate each call. Set top-level `allow_shell = false` to hide it for a workspace/profile. The canonical `File`, `Git`, and `Run` action tools cover structured workspace work. |
| 33 | - **Operate**: multitask conductor posture. Send ordinary messages and use the same direct tools, shell configuration, sandbox, permission posture, ask-rules, and repository protections as Act. The parent session is the **operator**: dispatching background workers is the **default** way real multi-step or independent work happens (no special multitask command). Handle small or tightly coupled tasks in the parent; for everything else, set a goal when work spans streams, start background `agent` workers early, treat queued follow-ups as new tasks, and keep the parent free for steers and synthesis. **Dispatch is not completion** — every write-capable child must return verification evidence (verifier child, `run_verifiers`, or structured PASS/FAIL with real commands). Prefer direct workers for independent streams; use Workflow when order, phases, gates, shared budgets, or deterministic fan-in matter (starter recipes under `workflows/operate_*.workflow.js`: staged-fix, read-audit, parallel-scout, best-of-n). Best-of-N (skill + starter workflow) runs N worktree implementers then a reviewer; apply the winner only after PASS. |
| 34 | |
| 35 | **Act** is accepted as an alias for Agent mode. Saved settings still normalize to `agent` for backward compatibility. |
| 36 | |
| 37 | ### Tool availability by mode |
| 38 | |
| 39 | | Tool family | Plan | Act | Operate | |
| 40 | |:---|:---:|:---:|:---:| |
| 41 | | Read-only file, search, and diagnostic tools | yes | yes | yes | |
| 42 | | File write and patch tools | no | yes | yes; same active posture and protections as Act | |
| 43 | | `Bash` (`run`, `wait`, `interact`, `cancel`) | no | approval-gated by default, hidden when `allow_shell = false` | same as Act; delegation is preferred when parallelism or isolation helps | |
| 44 | | Paid or external-service tools | follows permission posture | follows permission posture | follows permission posture | |
| 45 | | Access outside the workspace root | explicit trusted paths only | only through trusted paths or trust mode | same trusted-path/trust policy as Act; Fleet profiles never widen it | |
| 46 | |
| 47 | Operate changes scheduling emphasis, not authority. It neither adds a |
| 48 | mode-specific tool denial nor bypasses the active approval, sandbox, shell, |
| 49 | ask-rule, repository-law, or managed-policy boundary. Plan remains the |
| 50 | mode-specific read-only boundary for shell and write-capable tools. |
| 51 | |
| 52 | ### Operate loop (one screen) |
| 53 | |
| 54 | ```text |
| 55 | User message |
| 56 | → small / chat / one-file? → parent does it (Act-equivalent tools) |
| 57 | → real / multi-stream work? → goal (if needed) → dispatch background workers |
| 58 | → each write child: implement → VERDICT PASS/FAIL with evidence |
| 59 | → ordered / gated fan-in? → Workflow (operate_* starters) |
| 60 | → high-stakes ambiguous? → best-of-n (N worktrees + reviewer; apply on PASS) |
| 61 | → parent synthesizes receipts; stays free for the next ask |
| 62 | ``` |
| 63 | |
| 64 | Lifecycle claims stay exact: dispatched ≠ settled ≠ verified. |
| 65 | |
| 66 | If a shell tool is missing from the model-visible catalog in Act or Operate, check |
| 67 | for an explicit `allow_shell = false` in the active config/profile or runtime |
| 68 | session. Durable tasks and automation keep conservative omitted-field defaults; |
| 69 | they only receive shell access when their task settings explicitly grant it. |
| 70 | `allow_shell = true` controls shell availability only; direct multiline `Bash` |
| 71 | `run` commands remain blocked by shell safety validation. For heredocs, |
| 72 | embedded scripts, or long manual flows, use single-line commands, write a |
| 73 | script/file first, or use `Bash` with its background, `wait`, and `interact` |
| 74 | actions. |
| 75 | Full Access turns shell access on together with trust mode and auto-approval. |
| 76 | |
| 77 | Action-capable modes can discover the deferred `rlm` family through |
| 78 | `tool_search`; its `open`, `eval`, `configure`, and `close` actions own persistent |
| 79 | RLM sessions. The legacy split `rlm_*` spellings remain replay-only aliases. |
| 80 | Inside an RLM Python REPL, `sub_query_batch` fans out 1-16 cheap parallel child |
| 81 | calls pinned to `deepseek-v4-flash`. |
| 82 | |
| 83 | The fast `deepseek-v4-flash` / thinking-off path is called Fin in the product |
| 84 | language. Fin is a seam for routing, summaries, cheap child calls, and |
| 85 | coordination work; it does not change approval behavior. |
| 86 | |
| 87 | `/goal` sets a session objective with an optional token budget and keeps active |
| 88 | objectives visible as Work context. `/goal pause` stops goal continuation without |
| 89 | changing the objective, `/goal resume` resumes and sends the objective back into |
| 90 | the turn, `/goal complete` marks it done, `/goal blocked` marks it blocked, and |
| 91 | `/goal clear` removes it. Goal state does not change the active TUI mode, |
| 92 | permission posture, or model route. This remains distinct from `--model auto`, which |
| 93 | only controls model and thinking selection. |
| 94 | |
| 95 | Workflow builds on the same separation: a goal can ask the agent to keep |
| 96 | working, while Workflow supplies the repeatable workflow/progress surface for |
| 97 | large fanout. In the UI, a Workflow run should be shown as an overlay on the |
| 98 | main screen, not as another mode beside Plan, Act, and Operate. |
| 99 | |
| 100 | App-server clients can persist a thread-scoped goal with `thread/goal/set`, read |
| 101 | it with `thread/goal/get`, and clear it with `thread/goal/clear`. That persisted |
| 102 | record carries `active`, `paused`, `blocked`, `usage_limited`, `budget_limited`, |
| 103 | or `complete` status plus token/time accounting fields for clients that need |
| 104 | thread resume semantics. |
| 105 | |
| 106 | ## Mode Persistence |
| 107 | |
| 108 | Choosing a mode interactively also sets the mode a fresh session starts in. |
| 109 | Tab/Shift+Tab cycling, the `Alt+A` / `Alt+P` / `Alt+Y` shortcuts, the hotbar's |
| 110 | Plan/Act/Operate actions, and `/mode` all write `default_mode` to |
| 111 | `~/.codewhale/settings.toml`, so switching to Operate survives a restart. The |
| 112 | write happens off the event loop; if it fails, the TUI says so in a warning |
| 113 | toast rather than reverting silently on the next launch. |
| 114 | |
| 115 | Mode, thinking level, and the model picker share one serialized writer, so the |
| 116 | selection you made last is the one on disk — a burst of Tab presses cannot end |
| 117 | up persisting whichever write happened to finish last — and a mode write never |
| 118 | rolls back an unrelated key such as `default_model`. |
| 119 | |
| 120 | Two paths deliberately do **not** rewrite the startup default: restoring a saved |
| 121 | session (which re-installs the mode that session was in) and a mode change |
| 122 | refused because a turn is in flight. The legacy `yolo` entry point installs Act |
| 123 | plus bypass approvals, and `agent` is what it persists — `yolo` is a permission |
| 124 | alias, never a startup mode. |
| 125 | |
| 126 | Re-selecting the mode you are already in is not a no-op. After a restored |
| 127 | session the live mode and `default_mode` routinely disagree, so choosing the |
| 128 | live mode again is how you make it durable; Codewhale confirms with a |
| 129 | "saved as startup default" receipt rather than reporting "already in that mode". |
| 130 | |
| 131 | While a turn is running, every change to the live route is refused — mode, |
| 132 | model, thinking level, and provider — no matter which surface you use. That |
| 133 | now includes the slash surfaces (`/mode`, `/model`, `/set <key> <value>`, |
| 134 | `/config <key> <value>`, `/config preset`), which are reachable mid-turn. Press |
| 135 | Esc to interrupt first. The restart-only `default_mode` key is exempt, because |
| 136 | it does not touch the running turn. |
| 137 | |
| 138 | Codewhale writes `settings.toml` under a lock that spans processes, and replaces |
| 139 | the file atomically, so a second Codewhale instance on the same home directory |
| 140 | cannot lose your selection or read a half-written file. At exit, queued writes |
| 141 | are flushed before the terminal is restored; anything that failed is printed on |
| 142 | the way out instead of disappearing with the alternate screen. |
| 143 | |
| 144 | ## Compatibility Notes |
| 145 | |
| 146 | - Older settings files with `default_mode = "normal"` still load as `agent`; saving rewrites the normalized value. |
| 147 | |
| 148 | ## Escape Key Behavior |
| 149 | |
| 150 | `Esc` is a cancel stack, not a mode switch. |
| 151 | |
| 152 | - Close slash menus or transient UI first. |
| 153 | - Cancel the active request if a turn is running. |
| 154 | - Discard a queued draft if the composer is empty. |
| 155 | - Clear the current input if text is present. |
| 156 | - Otherwise it is a no-op. |
| 157 | |
| 158 | ## Permission Posture |
| 159 | |
| 160 | Permission posture controls tool approval and whether a turn may pause for a |
| 161 | missing user decision. It is one layer of the full |
| 162 | [authorization order](AUTHORIZATION_ORDER.md), not a bypass for tool admission, |
| 163 | repository law, or sandbox enforcement. Cycle it with `Shift+Tab`, or edit it |
| 164 | at runtime: |
| 165 | |
| 166 | ```text |
| 167 | /config |
| 168 | # edit the approval_mode row to: suggest | auto | never |
| 169 | ``` |
| 170 | |
| 171 | Legacy note: `/set approval_mode ...` was retired in favor of `/config`. |
| 172 | |
| 173 | - `suggest` (**Ask**, default): tool approvals may interrupt, and Codewhale asks |
| 174 | when an unresolved user choice materially changes authority, cost, scope, or |
| 175 | outcome. |
| 176 | - `auto` (**Auto-Review**): the fully autonomous posture. It never opens a user |
| 177 | question; the model resolves ambiguity from context, chooses a safe reversible |
| 178 | interpretation, or reports that it cannot proceed safely. Tool safety holds |
| 179 | remain separate from user questions. |
| 180 | - `bypass` (**Full Access**): ordinary tool calls do not show approval prompts, |
| 181 | while deliberate user questions remain available. Non-bypassable safety, |
| 182 | repository-law, and managed-policy holds fail closed as hard blocks instead |
| 183 | of contradicting Full Access with an approval modal. |
| 184 | - `never`: blocks any tool that is not considered safe/read-only; deliberate |
| 185 | user questions remain available. |
| 186 | |
| 187 | The effective posture and its question discipline are projected into every |
| 188 | turn from the same runtime authority that gates tools. A mode/posture change is |
| 189 | therefore visible to the next turn. Untrusted runtime-generated input is |
| 190 | narrowed before metadata is built and cannot invent approval authority. An |
| 191 | explicit Full Access sub-agent handoff preserves the parent's standing posture |
| 192 | so ordinary child work does not begin prompting again. |
| 193 | |
| 194 | ## Small-Screen Status Behavior |
| 195 | |
| 196 | When terminal height is constrained, the status area compacts first so header/chat/composer/footer remain visible: |
| 197 | |
| 198 | - Loading and queued status rows are budgeted by available height. |
| 199 | - Queued previews collapse to compact summaries when full previews do not fit. |
| 200 | - `/queue` workflows remain available; compact status only affects rendering density. |
| 201 | |
| 202 | ## Workspace Boundary and Trust Mode |
| 203 | |
| 204 | By default, file tools are restricted to the `--workspace` directory. Enable trust mode to allow file access outside the workspace: |
| 205 | |
| 206 | ```text |
| 207 | /trust on |
| 208 | ``` |
| 209 | |
| 210 | Bare `/trust` (like `/trust status`) only *reports* the current setting — it |
| 211 | does not enable anything. Use `/trust off` to restrict access again. |
| 212 | |
| 213 | Full Access enables trust mode automatically. |
| 214 | |
| 215 | ## MCP Behavior |
| 216 | |
| 217 | MCP tools are exposed as `mcp_<server>_<tool>` and use the same approval flow as |
| 218 | built-in tools. Read-only MCP helpers may auto-run in Ask and Auto-Review when |
| 219 | policy permits; MCP tools with possible side effects require approval. Full |
| 220 | Access does not bypass hard policy holds. |
| 221 | |
| 222 | See `MCP.md`. |
| 223 | |
| 224 | ## Related CLI Flags |
| 225 | |
| 226 | Run `codewhale --help` for the canonical list. Common flags: |
| 227 | |
| 228 | - `-p, --prompt <TEXT>`: one-shot prompt mode (prints and exits) |
| 229 | - `codewhale exec --auto --output-format stream-json <PROMPT>`: run the tool-backed non-interactive agent and emit one JSON object per line for harnesses and backend wrappers. Exit codes: `0` on success, `1` for genuine task/agent failures, `75` (`EX_TEMPFAIL`) when the turn ended on a retryable infrastructure failure (provider/transport `network`/`timeout` after all in-session retries) so harnesses can tell a retryable infra exit apart from a task failure; the terminal stream `metadata` event's `error_category` carries the same classification |
| 230 | - `codewhale exec --resume <ID|PREFIX> <PROMPT>` / `--session-id <ID|PREFIX>`: continue a saved session non-interactively |
| 231 | - `codewhale exec --continue <PROMPT>`: continue the most recent saved session for this workspace non-interactively |
| 232 | - `codewhale fork <ID|PREFIX>` / `codewhale fork --last`: copy a saved session into a new sibling session; forked sessions retain additive parent-session metadata and show that lineage in session listings |
| 233 | - `--model <MODEL>`: when using the `codewhale` facade, forward a DeepSeek model override to the TUI |
| 234 | - `--workspace <DIR>`: workspace root for file tools |
| 235 | - `-r, --resume <ID|PREFIX|latest>`: resume a saved session |
| 236 | - `-c, --continue`: resume the most recent session in this workspace |
| 237 | - `--max-subagents <N>`: clamp to `1..=128` |
| 238 | - `--mouse-capture` / `--no-mouse-capture`: opt in or out of internal mouse scrolling, transcript selection, right-click context actions, and transcript scrollbar dragging. Mouse capture is enabled by default on non-Windows terminals and on Windows Terminal/ConEmu/Cmder so drag selection copies only transcript text, removes visual wrap-column line breaks from paragraphs, and stays scoped to the transcript pane; hold Shift while dragging or use `--no-mouse-capture` for raw terminal selection. It defaults off on legacy Windows console (CMD without `WT_SESSION` / `ConEmuPID`) and inside JetBrains JediTerm — PyCharm/IDEA/CLion/etc. — where the terminal advertises mouse support but forwards SGR mouse events as raw text (#878, #898). Use `--mouse-capture` to opt in anywhere it's defaulted off. Raw terminal selection may cross the right sidebar and include visual wraps because the terminal, not the TUI, owns the selection. |
| 239 | - `--profile <NAME>`: select config profile |
| 240 | - `--config <PATH>`: config file path |
| 241 | - `-v, --verbose`: verbose logging |
| 242 | |
| 243 | ## Branching and Rollback |
| 244 | |
| 245 | Codewhale has three related but intentionally separate recovery paths: |
| 246 | |
| 247 | - `codewhale fork <ID>` creates a new saved session from an existing saved |
| 248 | conversation and records the source session id. This is the safe way to |
| 249 | explore a different answer path without overwriting the original session. |
| 250 | - Esc-Esc backtrack rewinds the live transcript to a previous user prompt and |
| 251 | restores that prompt into the composer for editing. |
| 252 | - `/restore` and the `revert_turn` tool restore workspace files from side-git |
| 253 | snapshots. `/restore list [N]` lists more snapshot options before choosing a |
| 254 | rollback point. They do not rewrite conversation history. |
| 255 | |
| 256 | A Pi-style in-file tree browser is a larger UI/data-model project. v0.8.40 |
| 257 | ships the bounded fork/backtrack primitives and explicit lineage metadata. |
| 258 |