| 1 | # Reasonix Guide |
| 2 | |
| 3 | Provider model capability metadata is documented in |
| 4 | [`MODEL_CAPABILITIES.md`](./MODEL_CAPABILITIES.md). |
| 5 | |
| 6 | <a href="../README.md">README</a> |
| 7 | · |
| 8 | <a href="./GUIDE.zh-CN.md">简体中文</a> |
| 9 | · |
| 10 | <a href="./SPEC.md">Spec</a> |
| 11 | |
| 12 | > Day-to-day configuration and usage. For the engineering contract and internals |
| 13 | > (data types, registries, package layout, roadmap), see the **[Spec](./SPEC.md)**. |
| 14 | |
| 15 | ## Contents |
| 16 | |
| 17 | - [Configuration](#configuration) |
| 18 | - [Billing and display currency](./BILLING.md) |
| 19 | - [CLI reference](./CLI.md) |
| 20 | - [Environment variables](#environment-variables) |
| 21 | - [Web frontend](#web-frontend) |
| 22 | - [Configuration paths](./CONFIG_PATHS.md) |
| 23 | - [Reasoning language](./REASONING_LANGUAGE.md) |
| 24 | - [Task contracts and pause policy](./TASK_CONTRACT.md) |
| 25 | - [Custom OpenAI-compatible providers](#custom-openai-compatible-providers) |
| 26 | - [Desktop hooks](#desktop-hooks) |
| 27 | - [Keyboard shortcuts](#keyboard-shortcuts) |
| 28 | - [Permissions & sandbox](#permissions--sandbox) |
| 29 | - [File deliverables and the `present` tool](./PRESENT_TOOL.md) |
| 30 | - [Capability diagnostics](#capability-diagnostics) |
| 31 | - [Plugins (MCP)](#plugins-mcp) |
| 32 | - [Slash commands](#slash-commands) |
| 33 | - [Embedded documentation retrieval](#embedded-documentation-retrieval) |
| 34 | - [@ references](#-references) |
| 35 | - [Two-model collaboration](#two-model-collaboration) |
| 36 | |
| 37 | ## Configuration |
| 38 | |
| 39 | Resolution order: **flag > `./reasonix.toml` > the user config file > |
| 40 | built-in defaults**. Starting with **Reasonix v1.8.1**, the user config lives at |
| 41 | `~/.reasonix/config.toml` on macOS/Linux and |
| 42 | `%AppData%\reasonix\config.toml` on Windows; see |
| 43 | [Configuration paths](./CONFIG_PATHS.md) for migration and related data paths. |
| 44 | Fields marked user/global only are not overridden by `./reasonix.toml`. |
| 45 | Provider entries name secrets with `api_key_env`, while the secret values live in |
| 46 | Reasonix's global `<Reasonix home>/.env`, shared by CLI and desktop. Project |
| 47 | `.env`, home `.env`, inherited shell environment variables, legacy credentials, |
| 48 | and the OS keyring are not provider-key runtime fallbacks; legacy credentials are |
| 49 | only migration sources. Project `.env` still feeds workspace-scoped, |
| 50 | non-provider `${VAR}` expansion for MCP/plugin settings without importing |
| 51 | provider keys or Reasonix control variables. See |
| 52 | [Configuration paths](./CONFIG_PATHS.md) for the full `config.toml` and `.env` |
| 53 | structure. |
| 54 | |
| 55 | For the desktop and CLI usage of visible reasoning language, see |
| 56 | [Reasoning language](./REASONING_LANGUAGE.md). |
| 57 | |
| 58 | ```toml |
| 59 | default_model = "deepseek-flash" # executor; set [agent].planner_model to add a planner |
| 60 | # language = "zh" # ui language; empty = auto-detect from $LANG / $REASONIX_LANG |
| 61 | |
| 62 | [ui] |
| 63 | # shortcut_layout = "desktop" # classic|desktop; compatibility setting |
| 64 | # cursor_shape = "bar" # block|underline|bar; CLI/TUI text cursor |
| 65 | show_turn_usage = false # hide per-request token/cost receipts in the TUI; default true |
| 66 | |
| 67 | [agent] |
| 68 | reasoning_language = "auto" # visible reasoning text: auto|zh|en |
| 69 | # plan_mode_read_only_commands = ["gh issue view"] # legacy compatibility only; Plan bash now uses Permissions |
| 70 | # planner_model = "deepseek-pro" # optional low-frequency planner |
| 71 | # subagent_model = "deepseek-pro" # optional default for runAs=subagent skills |
| 72 | # subagent_models = { review = "deepseek-pro", security_review = "deepseek-pro" } |
| 73 | # max_subagent_depth = 2 # nested delegation depth; set 1 for the old single-layer boundary |
| 74 | # max_subagent_concurrency = 6 # session-wide sub-agent concurrency (task/fleet/skills) |
| 75 | # max_parallel_writers = 3 # concurrent writers with non-overlapping write_paths |
| 76 | # compact_ratio = 0.80 # sole auto trigger; presets 0.70 / 0.80 / 0.85 |
| 77 | # max_output_tokens = 0 # auto: official DeepSeek omits the field (server 384K) until the window is tight |
| 78 | # max_output_tokens = 32768 # optional cost cap; still clipped to physical remaining |
| 79 | # max_output_tokens = 65536 # optional cost cap |
| 80 | # max_output_tokens = -1 # force-omit the wire field; compact if the known auto budget no longer fits |
| 81 | # max_output_tokens never changes compact_ratio; 0 is the provider auto value, not "skip local checks" |
| 82 | |
| 83 | [[providers]] |
| 84 | name = "deepseek-flash" |
| 85 | kind = "anthropic" |
| 86 | base_url = "https://api.deepseek.com/anthropic" |
| 87 | model = "deepseek-v4-flash" |
| 88 | api_key_env = "DEEPSEEK_API_KEY" |
| 89 | web_search = true |
| 90 | # also preset: deepseek-pro |
| 91 | |
| 92 | [tools] |
| 93 | enabled = [] # omit/empty = all built-ins |
| 94 | bash_timeout_seconds = 120 # foreground safety cap; set 0 for no tool-local cap |
| 95 | mcp_startup_timeout_seconds = 30 # background initialize + tools/list safety cap |
| 96 | mcp_call_timeout_seconds = 300 # default MCP call safety cap; per-plugin/tool overrides may raise it |
| 97 | |
| 98 | [environment] |
| 99 | enabled = true # inject a stable startup summary of OS, shell, and common tools |
| 100 | offline = false # set true when outbound network access is unavailable; prevents futile retries |
| 101 | # [environment.tools] |
| 102 | # go = "/opt/homebrew/bin/go" # optional explicit trusted path; workspace-local paths are not auto-executed |
| 103 | |
| 104 | [skills] |
| 105 | # paths = ["~/my-skills", "../shared/skills"] # extra custom skill roots |
| 106 | # excluded_paths = ["~/.agents/skills"] # hide convention roots without deleting folders |
| 107 | # disabled_skills = ["review"] # hide skills until /skill enable <name> |
| 108 | |
| 109 | [permissions] |
| 110 | mode = "ask" # writer fallback when no rule matches: ask|allow|deny |
| 111 | deny = ["Bash(rm -rf*)", "Bash(git push*)"] # hard-blocked in every mode |
| 112 | allow = ["Bash(go test:*)"] # never prompted |
| 113 | |
| 114 | [sandbox] |
| 115 | # workspace_root = "" # file-writers confined here; empty = current dir |
| 116 | # allow_write = ["/tmp"] # extra dirs write_file/edit_file/multi_edit/move_file may touch |
| 117 | # forbid_read = ["${HOME}/.ssh"] # paths the agent must not read or list |
| 118 | |
| 119 | [serve] |
| 120 | auth_mode = "none" # none|token|password; use auth before binding beyond localhost |
| 121 | # token = "" # optional fixed token; empty token mode generates one at startup |
| 122 | # password_hash = "" # bcrypt hash generated with reasonix serve --hash-password --password '...' |
| 123 | # behind_proxy = false # true only behind a trusted reverse proxy |
| 124 | |
| 125 | [[plugins]] |
| 126 | name = "example" |
| 127 | command = "reasonix-plugin-example" |
| 128 | startup_timeout_seconds = 60 # optional initialize + tools/list cap |
| 129 | call_timeout_seconds = 600 # optional per-server MCP call timeout |
| 130 | tool_timeout_seconds = { "generate_video" = 1800 } # optional raw MCP tool names |
| 131 | ``` |
| 132 | |
| 133 | For the full schema and every field's contract, see [`SPEC.md` §5](./SPEC.md#5-configuration-toml). |
| 134 | |
| 135 | Installed and project-configured MCP servers need no per-tool trust |
| 136 | list. The dedicated two-model Planner may use every non-destructive MCP tool, |
| 137 | even when the server omits `readOnlyHint`; strict read-only sub-agents still |
| 138 | require `readOnlyHint: true` and no `destructiveHint`. |
| 139 | |
| 140 | `[agent].plan_mode_read_only_commands` is also retained for config round trips, |
| 141 | but the main Plan workflow no longer has a separate bash allowlist or trust |
| 142 | prompt. Bash classification and approval use the same Permissions rules in Plan |
| 143 | and Standard mode; the Sandbox remains the filesystem, process, and network |
| 144 | boundary. Dedicated planner and read-only subagent runners keep their own strict |
| 145 | read-only tool registry and foreground-command classifier. |
| 146 | |
| 147 | ### Environment variables |
| 148 | |
| 149 | Most day-to-day settings belong in `config.toml` or the global Reasonix `.env` |
| 150 | described above. The variables below are process-level advanced switches; set |
| 151 | them before launching Reasonix. Project `.env` files are not a runtime source for |
| 152 | Reasonix control variables. |
| 153 | |
| 154 | ### CLI telemetry |
| 155 | |
| 156 | The CLI can send a once-per-day anonymous active-install ping and bounded, |
| 157 | content-free event counters to `https://crash.reasonix.io`. Configure the |
| 158 | user-global policy with: |
| 159 | |
| 160 | ```bash |
| 161 | reasonix config telemetry # print the effective mode |
| 162 | reasonix config telemetry auto # default: local interactive TTY only |
| 163 | reasonix config telemetry on # also allow local headless `reasonix run` |
| 164 | reasonix config telemetry off # disable and delete pending counter files |
| 165 | ``` |
| 166 | |
| 167 | On the first eligible release-build interactive session, Reasonix explains the |
| 168 | exact data boundary and asks once before any telemetry request. The prompt is |
| 169 | `[Y/n]`: pressing Enter, `y`, or `yes` stores `auto`; `n` or `no` stores `off` |
| 170 | and deletes pending counters. After the choice is saved, enabled reporting is |
| 171 | silent and the prompt is not shown again. If the preference cannot be saved, |
| 172 | nothing is uploaded. |
| 173 | |
| 174 | Reporting is always disabled in CI, development builds, and when |
| 175 | `DO_NOT_TRACK` is set or `REASONIX_TELEMETRY=0`. Under `auto`, redirected/piped |
| 176 | or otherwise non-interactive sessions do not report. When no choice has been |
| 177 | saved yet, these ineligible sessions neither prompt nor report. Network failures |
| 178 | after consent are silent and never change stdout, stderr, or the process exit |
| 179 | code; unsent counters stay in a bounded local queue for a later invocation. |
| 180 | |
| 181 | The ping contains a dedicated random 128-bit CLI install ID, CLI version, OS, |
| 182 | architecture, and the `cli` surface marker. Counter batches use that same ID for |
| 183 | daily active-install deduplication and contain only fixed buckets such as CLI |
| 184 | surface, permission/session mode, turn latency, finish reason, cache-hit |
| 185 | range, generic Provider/tool error class, compaction, recovery counters, and |
| 186 | normalized UI language. This ID is separate from the desktop install ID and is |
| 187 | not an account, hardware, repository, or session identifier. |
| 188 | |
| 189 | Reasonix never uploads prompts, answers, reasoning, tool names/arguments/output, |
| 190 | paths, repositories/branches, session IDs, exact token or cost values, |
| 191 | Provider/model names, base URLs, or environment variables. |
| 192 | |
| 193 | ### CLI crash reports |
| 194 | |
| 195 | An unhandled Go panic that reaches the CLI entrypoint is saved locally as a sanitized report under |
| 196 | `<Reasonix home>/cli-crash-reports`. Reasonix keeps at most 10 files with owner-only |
| 197 | permissions. The panic value is never serialized. Absolute source paths become |
| 198 | `<path>/<file>.go:<line>`, function arguments are removed, and the same secret, |
| 199 | token, email, and long-identifier scrubbers run both when saving and immediately |
| 200 | before sending. |
| 201 | |
| 202 | Crash reports are never uploaded automatically. Review and manage them with: |
| 203 | |
| 204 | ```bash |
| 205 | reasonix report # preview newest; prompt before sending on a TTY |
| 206 | reasonix report list # list local reports |
| 207 | reasonix report show [ID] # preview without sending |
| 208 | reasonix report send [ID] # explicit send; delete locally only after success |
| 209 | reasonix report delete [ID] # delete without sending |
| 210 | ``` |
| 211 | |
| 212 | Piped or redirected `reasonix report` calls only preview and never prompt or |
| 213 | send. The CLI telemetry setting does not auto-send or auto-delete |
| 214 | these separately reviewed reports. Runtime fatal throws, operating-system kills, |
| 215 | and panics in unwrapped background goroutines cannot be recovered by Go and do |
| 216 | not produce this local report. |
| 217 | |
| 218 | ## Web frontend |
| 219 | |
| 220 | For local use, `reasonix web` starts the browser UI and opens it in your default |
| 221 | browser. Inside an interactive CLI session, `/web` snapshots the current session, |
| 222 | restores the terminal, and opens an explicit `/sessions/<id>#token=...` deep link. |
| 223 | Even a never-used session keeps its reserved ID without forcing an empty |
| 224 | transcript onto disk, so the first Web turn continues the same session identity. |
| 225 | |
| 226 | ```bash |
| 227 | cd your-project |
| 228 | reasonix web |
| 229 | ``` |
| 230 | |
| 231 | Use `reasonix web --no-open` when you want to start the foreground Web server |
| 232 | and print its URL without opening a browser tab. The lower-level |
| 233 | `reasonix serve` command starts the same engine without opening a browser by |
| 234 | default. It remains the right entry point for remote development boxes, |
| 235 | supervisors, tunnels, reverse proxies, and shareable authenticated sessions. |
| 236 | |
| 237 | `reasonix web` starts at `127.0.0.1:8787`, automatically tries 8788, 8789, and |
| 238 | so on when a port is busy (up to 100 retries), and defaults to a newly generated |
| 239 | token even when `[serve].auth_mode` is `none`. Each live process registers a |
| 240 | single-writer heartbeat file under `<Reasonix home>/server/instances/`; clean |
| 241 | shutdown removes its own file, while later instances lazily remove records whose |
| 242 | owner process is confirmed dead. Multiple Web instances can therefore share one |
| 243 | Reasonix home without overwriting registry state. The process stays attached to |
| 244 | the terminal; stop it with Ctrl-C. |
| 245 | |
| 246 | An explicit `reasonix web --auth none` disables the default token and should be |
| 247 | used only when the listener is intentionally trusted. `reasonix serve` keeps its |
| 248 | backward-compatible, config-driven `auth_mode = "none"` default on |
| 249 | `127.0.0.1:8787`. If you bind Serve outside loopback, expose it through a tunnel, |
| 250 | or put it behind a reverse proxy, enable authentication before sharing the URL: |
| 251 | |
| 252 | ```bash |
| 253 | reasonix serve --auth token |
| 254 | reasonix serve --addr 0.0.0.0:8787 --auth token |
| 255 | reasonix serve --auth password --password 'temporary-password' |
| 256 | ``` |
| 257 | |
| 258 | Token mode prints a share URL with `#token=...`; the Web page exchanges the |
| 259 | fragment for an HttpOnly cookie before starting API or SSE requests, keeping the |
| 260 | token out of request URLs, browser history, referrers, and access logs. Pass `--token` or set |
| 261 | `[serve].token` to reuse a stable token. Password mode requires either |
| 262 | `--password` at startup or a stored bcrypt hash: |
| 263 | |
| 264 | ```bash |
| 265 | reasonix serve --hash-password --password 'strong-password' |
| 266 | |
| 267 | # <Reasonix home>/config.toml |
| 268 | [serve] |
| 269 | auth_mode = "password" # none|token|password |
| 270 | password_hash = "$2a$12$..." |
| 271 | behind_proxy = true # only behind a trusted reverse proxy |
| 272 | ``` |
| 273 | |
| 274 | The web UI exposes chat, tool approvals, session history, rewind/fork/summarize, |
| 275 | model and reasoning-effort controls, Goal, a live todo panel fed by the |
| 276 | `todo_write` tool, extension status/card/form/notification surfaces, and |
| 277 | provider balance when configured. Extension-hosted providers appear in the |
| 278 | model picker. Serve can keep several sessions active at once: creating or |
| 279 | resuming another session detaches a busy turn instead of cancelling it, and the |
| 280 | session list continues to report that background activity. Run `/reload` while |
| 281 | idle to fail-atomically reload extension sidecars and the runtime generation |
| 282 | without restarting Serve. Use `--model`, `--max-steps`, or `--resume` for |
| 283 | one-off launches; otherwise `serve` uses the user-global `default_model`. |
| 284 | |
| 285 | If the selected Provider has no saved API key, a loopback-bound Serve still |
| 286 | starts and shows a Provider setup page instead of failing before the browser can |
| 287 | connect. After authentication, enter the key there; Reasonix writes it to this |
| 288 | host's global credential file with restricted permissions, rebuilds the active |
| 289 | controller in the same process, and opens the normal UI. The credential-writing |
| 290 | endpoint is disabled for non-loopback listeners. For a remote SSH window, |
| 291 | "this host" means the remote host reached through the SSH tunnel; the key is |
| 292 | not copied from the desktop machine. |
| 293 | |
| 294 | ## Editor integrations over ACP |
| 295 | |
| 296 | `reasonix acp` exposes Reasonix as an ACP v1 stdio agent for editors and other |
| 297 | host clients. The dedicated **[ACP editor integration](./ACP.md)** guide covers |
| 298 | startup, capability negotiation, session lifecycle, independent model/work/ |
| 299 | collaboration/approval controls, client filesystem and terminal capabilities, |
| 300 | MCP servers, permission requests, and the Reasonix mid-turn steering extension. |
| 301 | |
| 302 | ## Remote SSH |
| 303 | |
| 304 | The remote module runs Reasonix on a remote host and reaches it over your own |
| 305 | SSH connection — VS Code Remote-SSH style. It bootstraps a persistent headless |
| 306 | `reasonix serve` on the remote host, forwards a local loopback port to it, and |
| 307 | opens the existing serve web client through that tunnel. The agent, its tools, |
| 308 | and its files all live on the remote host at full fidelity; nothing runs through |
| 309 | a lossy file proxy. V1 supports Linux and macOS remote hosts. |
| 310 | |
| 311 | The dedicated **[Remote sessions](./REMOTE_SESSIONS.md)** guide covers host |
| 312 | configuration (`[remote]` in `config.toml`), SSH-config resolution and import, |
| 313 | the `reasonix remote` CLI, the remote serve bootstrap and its install ladder, |
| 314 | the remote session lifecycle and takeover, the desktop remote workspace, the |
| 315 | `remote` and `local-proxy` credential modes, connection failure semantics, and |
| 316 | troubleshooting. |
| 317 | |
| 318 | ## Custom OpenAI-compatible providers |
| 319 | |
| 320 | In the desktop app, open **Settings -> Model -> Access -> Add model service -> |
| 321 | Custom provider** for proxies, aggregators, or self-hosted services that speak |
| 322 | the OpenAI-compatible chat API or Anthropic-compatible Messages API. |
| 323 | |
| 324 | For common providers, choose **Add model service -> Recommended preset** instead. |
| 325 | New official DeepSeek entries use the Anthropic-compatible Messages endpoint by |
| 326 | default and enable provider-side `web_search`; the same `DEEPSEEK_API_KEY` works |
| 327 | for both protocols. On startup, Reasonix upgrades unmodified legacy |
| 328 | `deepseek-flash` / `deepseek-pro` entries that still use the official endpoint |
| 329 | and standard key/model settings. Customized official Chat Completions entries |
| 330 | stay unchanged and show an **Upgrade protocol** action in Settings. Proxy |
| 331 | endpoints, custom headers, model lists, and capability overrides are never |
| 332 | migrated automatically. Existing |
| 333 | separately named `deepseek-anthropic` entries remain compatible, but that |
| 334 | redundant preset is no longer offered for new access. Reasonix can prefill editable custom-provider entries for Kimi CN, |
| 335 | Kimi Global, |
| 336 | Kimi Coding Plan, MiMo API, MiMo Anthropic, MiMo Token Plan CN/SGP/AMS and their |
| 337 | Anthropic-compatible variants, MiniMax CN/Global API, MiniMax CN/Global |
| 338 | Anthropic, GLM CN, Z.AI Global, GLM/Z.AI Coding Plan OpenAI-compatible and |
| 339 | Anthropic-compatible endpoints, OpenCode Go, OpenCode Go Anthropic, OpenCode Go |
| 340 | DeepSeek Anthropic, OpenCode Go DeepSeek Responses, OpenCode Zen |
| 341 | Anthropic, Qwen/DashScope CN/Global, Qwen Coding Plan CN/Global |
| 342 | OpenAI-compatible and Anthropic-compatible endpoints, StepFun OpenAI-compatible |
| 343 | and Anthropic-compatible endpoints, NovitaAI, GMI Cloud, Vercel AI Gateway, |
| 344 | HuggingFace Router, ModelScope, NVIDIA NIM, KiloCode, and Ollama Cloud. Plan names describe |
| 345 | the access/payment route; they include CN/Global only when the provider exposes |
| 346 | distinct regional endpoints. Kimi Coding Plan is therefore a dedicated plan |
| 347 | endpoint, while Kimi direct API is split into CN and Global. The preset path |
| 348 | usually needs only the provider API key: the key value is stored in Reasonix home |
| 349 | `.env`, while `config.toml` stores the endpoint, model list, key |
| 350 | environment-variable name, context window, model capability metadata, proxy bypass |
| 351 | for China-only endpoints, MiniMax `reasoning_split`, GLM/MiniMax thinking |
| 352 | heuristics, Anthropic-compatible Bearer auth where needed, Ollama Cloud |
| 353 | max-effort support, and OpenCode Go per-model reasoning overrides. Official DeepSeek Anthropic, Responses, and Chat Completions catalogs also |
| 354 | include the multimodal SKUs `deepseek-flash` and `deepseek-v4-flash-vision-exp`. Settings derives image support from |
| 355 | model capability metadata. Each model also has an Image input Auto / On / Off |
| 356 | selector. For an ID-only relay list, unknown means unrecognized, not confirmed |
| 357 | text-only: select On after confirming support with the relay, then save. See the |
| 358 | [image input guide](MODEL_CAPABILITIES.md#set-image-input-for-a-relay-model). |
| 359 | Composer |
| 360 | and `@` user images are sent as official visual input using the three documented |
| 361 | shapes: inline base64 `data:` URLs for local files, `http(s)` image URLs as-is, |
| 362 | and Files API `file-api-` ids (local images over 32 MiB on official DeepSeek are |
| 363 | uploaded automatically). Chat Completions uses `image_url` or `file`, Anthropic |
| 364 | uses `image`+`source.base64|url|file`, and Responses uses `input_image`. |
| 365 | Flash and Pro stay text-only on the wire even when legacy configuration lists them, and tool screenshots |
| 366 | are not forwarded as image parts. The vision SKU uses the Flash rate card. The dedicated |
| 367 | OpenCode Go DeepSeek Anthropic and DeepSeek Responses presets expose the verified |
| 368 | Flash routes and enable provider-side `web_search` by default; the Responses |
| 369 | variant uses stateless context replay. The existing mixed OpenCode Go Anthropic |
| 370 | preset remains scoped to Qwen and MiniMax so server tools are not sent to |
| 371 | unverified models. DeepSeek Pro remains on the Chat Completions preset because |
| 372 | live Anthropic and Responses requests currently fail in the OpenCode Go upstream |
| 373 | conversion. The OpenCode Go preset includes its native `kimi-k3` subscription |
| 374 | route with image input, |
| 375 | `high`/`max` reasoning effort, and a 1,048,576-token context window. Existing untouched |
| 376 | OpenCode Go preset installs are upgraded automatically; edited model catalogs |
| 377 | are preserved. The Kimi CN and Kimi Global direct-API presets also include |
| 378 | `kimi-k3` with image input, a 1,048,576-token context window, and the official |
| 379 | `low`/`high`/`max` effort scale (default `max`). For the official K3 endpoints, |
| 380 | Reasonix preserves complete assistant messages across turns, sends output limits |
| 381 | as `max_completion_tokens`, and omits K3's fixed sampling parameters. Untouched |
| 382 | legacy Kimi direct-API catalogs are upgraded automatically without changing the |
| 383 | default model; custom catalogs and endpoints are preserved. After adding a |
| 384 | preset, open its provider card if you need to change models, headers, endpoint, |
| 385 | or compatibility settings. |
| 386 | |
| 387 | Fill **API address** with the provider endpoint that should receive the standard |
| 388 | chat path. In this mode Reasonix previews and sends chat requests to: |
| 389 | |
| 390 | ```text |
| 391 | <API address>/chat/completions |
| 392 | ``` |
| 393 | |
| 394 | Enable **Full URL** when the service gives you a complete request URL, for |
| 395 | example `https://gateway.example.com/v1/chat/completions`. Reasonix then sends |
| 396 | chat requests directly to that URL and does not append `/chat/completions`. The |
| 397 | preview under the field shows the exact request URL that will be used. |
| 398 | |
| 399 | Model discovery uses the API address to try likely model-list URLs such as |
| 400 | `/models` and `/v1/models`. If the gateway requires a separate model-list |
| 401 | endpoint, open **Compatibility settings** and set `models_url`, for example |
| 402 | `https://gateway.example.com/v1/models`. If discovery is not available, fill the |
| 403 | model list manually. |
| 404 | |
| 405 | **Full URL** still uses the OpenAI-compatible chat request body. It does not |
| 406 | switch the request schema to the OpenAI Responses API. |
| 407 | |
| 408 | ### Compatibility settings |
| 409 | |
| 410 | The **Compatibility settings (usually leave unchanged)** section is for gateways |
| 411 | whose authentication, model-list endpoint, or reasoning/thinking request shape |
| 412 | differs from the normal OpenAI-compatible defaults. Leave these fields at their |
| 413 | defaults unless the provider documentation or a proxy error tells you otherwise. |
| 414 | For Anthropic-compatible services, such as some coding-plan endpoints, choose |
| 415 | **Anthropic-compatible** as the connection protocol before saving. |
| 416 | |
| 417 | | Field | What it controls | When to change it | |
| 418 | | --- | --- | --- | |
| 419 | | `api_key_env` | The environment-variable name used for this provider's API key. Desktop-saved key values are stored in Reasonix home `.env` under this name; the TOML config stores only the name. | Change it when several providers need distinct keys, or leave it blank for a service that does not require an API key. | |
| 420 | | `models_url` | The URL used only for model discovery. Chat requests still use the API address or Full URL above. | Set it when `/models` or `/v1/models` is not where the gateway exposes its model list. | |
| 421 | | Extra request headers | Static HTTP headers, one `Header: value` per line. | Use for gateways such as OpenRouter that require `HTTP-Referer`, `X-Title`, or similar site headers. Keep bearer/API keys in the key field instead of duplicating them here. | |
| 422 | | Extra request body | A JSON object merged into the top-level chat request body. | Use only for provider-specific flags such as `{"enable_thinking": true}`. Reasonix still owns core fields such as `model`, `messages`, `tools`, `stream`, and `thinking`, and null values are rejected. | |
| 423 | | Authorization: Bearer | For Anthropic-compatible providers, sends the saved API key as `Authorization: Bearer <key>` instead of `x-api-key`. | Enable it only when the gateway documents Bearer auth, such as MiniMax Global or Vercel AI Gateway. | |
| 424 | | Model capability mode | Which reasoning request protocol Reasonix should use for this provider. | Keep **Auto-detect** unless the gateway is misdetected or the model docs require a specific reasoning format. | |
| 425 | | Thinking override | Provider-specific override for `thinking.type`. | Keep **Auto** unless the backend documents `enabled`, `disabled`, or `adaptive`. Unsupported values can make some OpenAI-compatible gateways reject the request. | |
| 426 | | Balance URL | Optional endpoint for wallet/balance lookup. | Set it when the provider exposes a balance endpoint and you want the desktop status bar to show it. | |
| 427 | | Context window | The provider-wide token budget Reasonix uses for automatic context cleanup. `0` disables automatic compaction. | Set it to the provider's model context limit; use a per-model override below when selected models differ. | |
| 428 | |
| 429 | Each selected model also has an optional **Context window** input. Leave it blank |
| 430 | to inherit the provider-wide value, or enter a positive token count to override |
| 431 | that value for this model. This avoids premature compaction for long-context |
| 432 | models and provider errors for shorter-context models sharing the same endpoint. |
| 433 | Use the context-window limit from the model documentation, not the maximum output |
| 434 | tokens. For example, 128K commonly means `128000`; if the provider documents |
| 435 | `131072`, use that exact value. Values below 16384 show a non-blocking warning |
| 436 | because they can trigger frequent compaction and reduce cache hit rates. |
| 437 | |
| 438 | Model capability mode options: |
| 439 | |
| 440 | | Option | Effect | |
| 441 | | --- | --- | |
| 442 | | Auto-detect (recommended) | Reasonix chooses the request shape from model capability metadata and endpoint detection. | |
| 443 | | DeepSeek thinking | Uses DeepSeek-style thinking control, including `thinking.type` and DeepSeek-supported reasoning depth. | |
| 444 | | OpenAI reasoning | Uses the standard OpenAI-compatible `reasoning_effort` levels. | |
| 445 | | Plain chat | Sends no reasoning or thinking control fields. Use this for text-only proxies that reject reasoning parameters. | |
| 446 | |
| 447 | Thinking override options: |
| 448 | |
| 449 | | Option | Effect | |
| 450 | | --- | --- | |
| 451 | | Auto (provider default) | Does not write an explicit provider-level `thinking` override. Reasonix uses the provider/model default behavior. | |
| 452 | | Enabled | Sends `thinking.type = "enabled"` for compatible providers. | |
| 453 | | Disabled | Sends `thinking.type = "disabled"` for compatible providers. On DeepSeek-style providers this also avoids sending a reasoning depth hint. | |
| 454 | | Adaptive (self-adjusting) | Sends or preserves `thinking.type = "adaptive"` only for providers that document adaptive thinking, such as MiniMax-M3-style endpoints. | |
| 455 | |
| 456 | Some OpenAI-compatible gateways require non-standard top-level request body |
| 457 | fields. Add them with `extra_body` on the provider entry: |
| 458 | |
| 459 | ```toml |
| 460 | [[providers]] |
| 461 | name = "spark" |
| 462 | kind = "openai" |
| 463 | base_url = "https://maas-coding-api.cn-huabei-1.xf-yun.com/v2" |
| 464 | models = ["xopglm52"] |
| 465 | api_key_env = "SPARK_API_KEY" |
| 466 | extra_body = { enable_thinking = true } |
| 467 | ``` |
| 468 | |
| 469 | `extra_body` is merged into the chat JSON request body. Reasonix keeps core |
| 470 | fields such as `model`, `messages`, `tools`, `stream`, and `thinking` under its |
| 471 | own control. |
| 472 | |
| 473 | ## Desktop hooks |
| 474 | |
| 475 | Desktop hooks run local commands at lifecycle events such as `SessionStart`, |
| 476 | `UserPromptSubmit`, `PreToolUse`, and `PreCompact`. A successful `SessionStart` |
| 477 | hook may write plain text to stdout, or return JSON with |
| 478 | `hookSpecificOutput.additionalContext`; Reasonix injects that text once into the |
| 479 | next real user turn as `<hook-context event="SessionStart">...</hook-context>`. |
| 480 | This is intended for plugin or workflow bootstrap context, including |
| 481 | Superpowers-style startup instructions, without baking that workflow into |
| 482 | Reasonix's system prompt. |
| 483 | |
| 484 | Plugin packages can provide this startup context through |
| 485 | `hooks/session-start-codex` or a plugin-root `CLAUDE.md`. Claude-style |
| 486 | `.claude/settings.json` command hooks are also mapped to matching Reasonix hook |
| 487 | events. |
| 488 | |
| 489 | The injected hook context is dynamic current-turn context. It does not change |
| 490 | the stable system prompt, memory prefix, or tool schema, though dynamic content |
| 491 | can still reduce cache reuse for that turn. The detailed desktop hook schema and |
| 492 | loading model are documented in [the Chinese desktop hooks guide](./DESKTOP_HOOKS.zh-CN.md). |
| 493 | |
| 494 | ## Keyboard shortcuts |
| 495 | |
| 496 | Shortcuts are documented by client because users usually look for the keys that |
| 497 | work in the surface they are using. On Desktop, `Shift+Tab` toggles Plan and |
| 498 | permission presets stay in the composer menu. In the CLI, `Shift+Tab` cycles |
| 499 | Read only → Workspace write → YOLO → Plan, while `Ctrl+Y` toggles YOLO |
| 500 | directly. YOLO is the visible label for the canonical `danger-full-access` |
| 501 | permission preset. Desktop paste stays on the platform paste key; in the CLI, |
| 502 | terminal-native text paste and application-owned image paste use separate shortcuts. |
| 503 | |
| 504 | `[ui].shortcut_layout` is still accepted for old configs, but the shortcut |
| 505 | behavior below is unified across layouts. |
| 506 | |
| 507 | For CLI/TUI text input, `[ui].cursor_shape` accepts `underline`, `block`, or |
| 508 | `bar`. The default is `bar`: it remains easy to locate without covering |
| 509 | double-width CJK characters in mixed-language input. Set it to `block` for a |
| 510 | traditional terminal cursor or `underline` for a lower-profile cursor. This |
| 511 | setting does not change desktop or web text fields. |
| 512 | |
| 513 | ### Desktop GUI |
| 514 | |
| 515 | The Desktop Todo shelf derives its label from both `todo_write` and the owning |
| 516 | tab's runtime: active work is **In progress**, an approval or question is |
| 517 | **Waiting for input**, and an idle/restored current item is **Ready to continue**. |
| 518 | The latter exposes a **Continue** action that rechecks the captured tab before |
| 519 | sending, so a rapid tab switch cannot route stale work into another session. |
| 520 | |
| 521 | Desktop shortcuts are managed from **Settings → Shortcuts**. Pick a configurable |
| 522 | row, press a new key combination, and Reasonix saves it for the desktop app. |
| 523 | Standard editing shortcuts such as Undo and Redo are shown as locked rows because |
| 524 | the WebView's native text history uses those platform chords. Conflicting |
| 525 | bindings are rejected so one shortcut never triggers two actions. Press `?` or |
| 526 | use the help button in the topic bar to open the shortcuts sheet; it is generated |
| 527 | from the same shortcut registry, so it reflects any custom bindings. |
| 528 | |
| 529 | Global shortcuts: |
| 530 | |
| 531 | | Key or control | What it does | Notes | |
| 532 | | --- | --- | --- | |
| 533 | | `Cmd+K` on macOS, `Ctrl+K` on Windows/Linux | Toggles the command palette | The palette focuses search when it opens; `Esc` closes it. | |
| 534 | | `Cmd+,` on macOS, `Ctrl+,` on Windows/Linux | Opens Settings | Use **Shortcuts** in Settings to customize desktop bindings. | |
| 535 | | `Cmd+W` on macOS, `Ctrl+W` on Windows/Linux | Closes the active top tab | The last tab is kept by the normal close-tab guard. | |
| 536 | | `Cmd+B` / `Ctrl+B` | Shows or hides the left sidebar | Same action as clicking the sidebar toggle. | |
| 537 | | `Cmd+Shift+B` / `Ctrl+Shift+B` | Expands or collapses the most recent shell output | Same action as clicking the collapsed shell-output hint. | |
| 538 | | `Cmd+1`-`Cmd+9` on macOS, `Ctrl+1`-`Ctrl+9` elsewhere | Jumps to the matching visible chat in the sidebar | Hold `Cmd`/`Ctrl` briefly to reveal the numbered badges. Existing custom shortcuts that already use the same key take precedence. | |
| 539 | | `Cmd++`, `Cmd+-`, `Cmd+0` on macOS; `Ctrl++`, `Ctrl+-`, `Ctrl+0` elsewhere | Increases, decreases, or resets text size | `=` is accepted for the plus key on keyboards that report it that way. | |
| 540 | | `?` | Opens the keyboard shortcuts sheet | The sheet shows the current effective desktop bindings. | |
| 541 | |
| 542 | Composer shortcuts: |
| 543 | |
| 544 | | Key or control | What it does | Notes | |
| 545 | | --- | --- | --- | |
| 546 | | `Enter` | Sends the current message | IME composition confirmation is left alone. | |
| 547 | | `Shift+Enter` | Inserts a newline | The composer keeps focus. | |
| 548 | | `Shift+Tab` | Toggles Plan on/off | Plan changes the workflow instruction while the selected permission preset remains active. | |
| 549 | | `Cmd+Z` on macOS, `Ctrl+Z` on Windows/Linux | Undoes the latest composer edit | Native typing stays in the WebView history; Reasonix-managed paste, cut, folded blocks, and structured tokens are restored as complete transactions. | |
| 550 | | `Cmd+Shift+Z` on macOS, `Ctrl+Shift+Z` on Windows/Linux | Redoes the latest composer edit | Uses the platform-native editing history. | |
| 551 | | `Cmd+V` on macOS, `Ctrl+V` on Windows/Linux | Pastes clipboard content | Clipboard images are attached; images can also be dropped into the composer. On official DeepSeek, `deepseek-flash` and `deepseek-v4-flash` accept images natively; V4 Pro stays text-only. | |
| 552 | | Plain `Up` / `Down` at the prompt boundary | Recalls older or newer submitted prompts | Modified arrows and native text navigation stay with the textarea. | |
| 553 | | `Esc` while a turn is running | Cancels the running turn | If the turn has not produced a response yet, the draft is restored. | |
| 554 | |
| 555 | Menus and controls: |
| 556 | |
| 557 | | Key or control | What it does | Notes | |
| 558 | | --- | --- | --- | |
| 559 | | `Up` / `Down` in slash, `@`, or past-chat menus | Moves the highlighted item | Past-chat search uses the same navigation keys. | |
| 560 | | `Enter` / `Tab` in those menus | Accepts the highlighted item | Directory-like entries can keep the menu open for the next level. | |
| 561 | | `Esc` in those menus | Closes the current menu or returns from past-chat search | Regular typing continues after the menu closes. | |
| 562 | | Read only / Workspace write / Full access | Selects the current session permission preset | Settings controls only the default for new sessions. | |
| 563 | | Tool approval card | `Left` / `Right`, `Enter`, `1`-`3`, `Esc` | Move between Allow once, Allow for this session, and Deny. The default is Allow once. | |
| 564 | | Plan approval card | `Left` / `Right`, `Enter`, `1`-`3`, `Esc` | Move between Revise plan, Start execution, and Exit plan. The default highlighted action is Start execution. | |
| 565 | | Plan control | Toggles Plan on/off | Same mode as `Shift+Tab`. | |
| 566 | | Goal item in the collaboration menu | Starts, views, or clears Goal | Goal is not in any keyboard cycle. | |
| 567 | |
| 568 | ### CLI / TUI |
| 569 | |
| 570 | The composer uses theme-coloured top and bottom borders and a slim bar cursor by |
| 571 | default. Long drafts grow to the available maximum height; once they overflow, |
| 572 | wheel events inside the composer scroll the draft without moving the insertion |
| 573 | cursor, while wheel events in the transcript keep scrolling the conversation. |
| 574 | Use `/theme auto|light|dark` to select the background mode, or `/theme <style>` |
| 575 | to select one of the named accent palettes shown by bare `/theme`. |
| 576 | |
| 577 | The responsive footer keeps the active permission preset, Plan state, and current |
| 578 | interaction state on the left. On wider terminals, model and effort |
| 579 | stay together on the right; a second row shows available Git identity, cache hit |
| 580 | rate, context use, compaction headroom, jobs, and balance. `ready` is the idle |
| 581 | composer state, not a model-health check. Pickers, approvals, image paste, shell |
| 582 | mode, and other active interactions replace it. Narrow terminals move, wrap, or |
| 583 | compact whole groups; visible labels follow `/language`. |
| 584 | |
| 585 | Chat and transcript shortcuts: |
| 586 | |
| 587 | | Key or command | What it does | Notes | |
| 588 | | --- | --- | --- | |
| 589 | | `Enter` | Sends the current message | While a turn is running, non-empty input is durably queued as a follow-up before the composer clears. | |
| 590 | | `Ctrl+Enter` or `/steer <text>` | Adds guidance to the active turn | The guidance is persisted first; if the turn cannot accept it, it remains a normal follow-up. | |
| 591 | | `Shift+Enter`, `Alt+Enter`, or `Ctrl+J` | Inserts a newline | Plain `Enter` is reserved for send/confirm. | |
| 592 | | Plain `Up` / `Down` while idle | Recalls older or newer submitted prompts | In a running turn, the same keys navigate queued follow-up feedback. | |
| 593 | | `PageUp` / `PageDown` | Scrolls the transcript | Works regardless of the current chat state. | |
| 594 | | `Ctrl+Home` / `Ctrl+End` | Jumps to the top or bottom of the transcript | Useful after long tool output. | |
| 595 | | `Ctrl+L` or `/cls` | Clears only the visible transcript | The LLM context, session file, tools, memory, and plugins stay loaded. Use `/clear` when you want to discard the conversation context. | |
| 596 | | `Esc` | Backs out of the current action | It un-sends a just-submitted turn before any reply, cancels a running turn, or clears non-empty input. | |
| 597 | | Double `Esc` on an empty idle composer | Opens the rewind picker | Same entry point as `/rewind`. | |
| 598 | | Transcript text selection | Copies transcript text | Releasing an in-app drag writes through the verified native clipboard path in a local session (`pbcopy` on macOS, the available Wayland/X11 tool on Linux, or the Windows clipboard). SSH falls back to OSC 52 and labels the fallback instead of claiming native success. `Ctrl+C`/`Super+C`/`Meta+C` or right-clicking the active selection copies it again. | |
| 599 | | Composer text selection | Selects, copies, or replaces draft text | Releasing an in-app drag copies the selection through the same verified clipboard path as transcript text. Typing or pasting replaces the selection; arrow keys collapse it. | |
| 600 | | Right-click with no active selection | Pastes clipboard text locally | In a local session with in-app mouse capture on, Reasonix reads text only and routes it through the normal bracketed-paste handling. Over SSH, use the terminal paste shortcut because the remote process cannot read the local clipboard; `/mouse` restores the terminal's native right-click menu. Right-click with an active selection still copies that selection. | |
| 601 | | `/mouse` | Toggles in-app mouse capture | Off hands the mouse back to your terminal, restoring its native click-drag selection and right-click context menu, at the cost of in-app drag-select, the transcript scrollbar, and wheel-scroll. Set `REASONIX_DISABLE_MOUSE=1` to start every session with it off. Remote (SSH) sessions start with capture off so native selection works out of the box; `REASONIX_DISABLE_MOUSE=0` forces capture on everywhere. Over SSH the TUI also enables synchronized output (mode 2026) so repaints do not flicker on the round trip; set `REASONIX_DISABLE_SYNC_OUTPUT=1` to opt out. | |
| 602 | | `Ctrl+C` | Copies, cancels, clears, or quits | Copies an active transcript or composer selection first. Otherwise it cancels a running turn, clears non-empty input, or quits on a second empty-composer press. | |
| 603 | | `Ctrl+D` | Quits the TUI | Immediate quit. | |
| 604 | | Your terminal's text-paste shortcut | Pastes text | Text stays on the terminal's bracketed-paste path (`Cmd+V` on macOS, commonly `Ctrl+Shift+V` on Linux, and the terminal's configured shortcut elsewhere). Reasonix consumes the resulting paste event and never probes for an image first. | |
| 605 | | `Ctrl+V` on macOS/Linux; `Alt+V` on Windows | Pastes a clipboard image | Image paste is a separate application action. The footer shows `Pasting image…` while the clipboard is read, then inserts an editable `[image #N]` token at the cursor. | |
| 606 | | `/paste-image` | Pastes a clipboard image | Command form of the same image-only action. | |
| 607 | | A line starting with `!` | Runs a shell command directly | The command runs locally without asking the model. | |
| 608 | |
| 609 | `/queue list` shows bounded previews without loading full bodies. Use `/queue |
| 610 | show|edit|delete|move`, `/queue pause|resume`, and `/queue retry|refresh` to |
| 611 | inspect or manage pending work. After crash recovery the inbox is paused, so |
| 612 | review it and run `/queue resume` before dispatch continues. Each item is |
| 613 | limited to 4 MiB; a session accepts at most 64 items and 64 MiB total. |
| 614 | |
| 615 | Mode and display shortcuts: |
| 616 | |
| 617 | | Key or command | What it does | Notes | |
| 618 | | --- | --- | --- | |
| 619 | | `Shift+Tab` | Cycles Read only → Workspace write → YOLO → Plan | YOLO applies `danger-full-access`; leaving Plan returns to Read only. | |
| 620 | | `Ctrl+Y` | Toggles YOLO | Entering YOLO applies `danger-full-access`; pressing it again restores the prior safe permission preset. | |
| 621 | | `--permission-mode read-only|workspace-write|danger-full-access` | Selects the initial permission preset | New sessions default to `workspace-write`. | |
| 622 | | `/theme [auto|light|dark|style]` | Shows or switches the CLI theme | Bare `/theme` lists background modes and named accent palettes. The choice is saved to the user config; `REASONIX_THEME` and `REASONIX_THEME_STYLE` can override it for one run. | |
| 623 | | `Ctrl+O` | Toggles verbose reasoning display | Also available through `/verbose`. | |
| 624 | | `Ctrl+B` | Expands or collapses long shell output | Long shell-output hint lines can also be clicked in the transcript; text selection is handled in-app while the full-screen TUI has mouse reporting enabled. | |
| 625 | | `/goal <objective>`, `/goal status`, `/goal pause`, `/goal resume`, `/goal clear` | Starts, checks, pauses, resumes, or clears Goal | A Goal is unbounded unless `[agent].goal_token_budget` is set. | |
| 626 | | `/migrate`, `/migrate --from <legacy-dir>` | Retries legacy migration or imports sessions from a chosen v0.x source | Use `--from` for custom Windows v0.52 install/data directories; it imports sessions only. See [Configuration paths](./CONFIG_PATHS.md). | |
| 627 | |
| 628 | Picker and approval shortcuts: |
| 629 | |
| 630 | | Context | Keys | What they do | |
| 631 | | --- | --- | --- | |
| 632 | | Slash or `@` completion | `Up` / `Down`, `Ctrl+P` / `Ctrl+N`, `Tab` / `Enter`, `Esc` | Move, accept, or close the completion menu. | |
| 633 | | Tool approval prompt | `y`/`1`, `a`/`2`, `p`/`3`, `n`/`4`, `Enter`, `Esc`, `Ctrl+C` | Allow once, allow for session, persist allow, deny, accept default allow once, deny, or cancel the turn. | |
| 634 | | Ask question card | `Up`/`Down` or `j`/`k`, `Left`/`Right` or `h`/`l`, `Space`, `Enter`, `1`-`9`, `Esc`, `Ctrl+C` | Navigate answers/tabs, toggle multi-select answers, submit/activate, pick numbered options, dismiss, or cancel the turn. | |
| 635 | | Rewind picker | `Up`/`Down` or `j`/`k`, `Enter`, `b`, `c`, `d`, `f`, `s`, `u`, `Esc` | Choose a turn, apply both/conversation/code/fork/summarize actions, or go back/close. | |
| 636 | | Model, provider, or resume picker | `Up`/`Down` or `Ctrl+P`/`Ctrl+N`; `j`/`k` while search is empty; type to filter; `Enter`; `Esc` | Search, select an item, or close the picker. Once search input starts, `j`/`k` become query text. `/provider` opens that provider's model list. | |
| 637 | | MCP import picker | `Up`/`Down` or `j`/`k`, `Space`, `Enter`, `Esc` / `Ctrl+C` | Move, select servers, import selected servers, or cancel. | |
| 638 | | MCP manager | `Up`/`Down` or `j`/`k`, `Enter`, `Left`/`Right` or `h`/`l`, `r`, number keys, `q` / `Ctrl+C` | Navigate server lists/details, refresh, choose actions, or close. | |
| 639 | | `/clear` confirmation | Arrow keys or `j`/`k` / `Tab`, `Enter`, `y`, `n`, `Esc` / `Ctrl+C` | Toggle Clear/Cancel, confirm clear, or cancel. | |
| 640 | |
| 641 | Mode meanings: |
| 642 | |
| 643 | | Mode | Meaning | |
| 644 | | --- | --- | |
| 645 | | Read only | Reads the workspace; writes and external side effects require a scoped authorization. | |
| 646 | | Workspace write | Writes inside the workspace and private session temporary directory. This is the default. | |
| 647 | | Full access | Runs as the current OS user without Reasonix filesystem or network sandboxing. Explicit host deny rules still apply before launch. | |
| 648 | | Plan | Plans before implementation. State-changing actions are blocked until approval, including Full access, proxy tools, and subagents. After approval, ordinary permissions and sandbox rules still apply. | |
| 649 | | Goal | Pursues a saved objective until complete, blocked, or cleared. | |
| 650 | |
| 651 | ## Permissions & sandbox |
| 652 | |
| 653 | The active permission preset supplies the enforced filesystem boundary for |
| 654 | Bash, file tools, background processes, and subagents. `workspace-write` runs |
| 655 | ordinary builds, tests, pipes, command substitutions, and inline scripts without |
| 656 | syntax-based prompts while confining writes to the workspace and private session |
| 657 | temporary directory. A write outside that boundary can be allowed once or for |
| 658 | the displayed directory during the current session. Permanent approval is not |
| 659 | offered. |
| 660 | |
| 661 | Configured `deny` rules always win. Installed MCP servers and plugins are trusted |
| 662 | in `workspace-write`; unknown side-effect capabilities in `read-only` still need |
| 663 | authorization. If the platform sandbox is unavailable, restricted presets fail |
| 664 | closed instead of offering an unconfined retry. |
| 665 | |
| 666 | Permissions are *policy* (which calls to allow / prompt). The **sandbox** is |
| 667 | *enforcement*: they are two layers. A permitted call still cannot write outside |
| 668 | the approved roots. The file-writers (`write_file` / `edit_file` / `multi_edit` / `move_file`) |
| 669 | refuse any path outside `[sandbox] workspace_root` (default: the current dir, so |
| 670 | edits stay in the project), resolving symlinks and `..` so a link can't tunnel |
| 671 | out. Writing outside the workspace is an interactive *extend write access* |
| 672 | approval (once / this session / add to project `reasonix.toml` / deny), not a |
| 673 | sandbox escape. Bash must name those directories with `additional_write_dirs` |
| 674 | plus a `justification`; the host does not infer paths from the command text. |
| 675 | Headless `reasonix run` does not prompt: pass `--add-dir` or configure |
| 676 | `[sandbox].allow_write`. The whole home directory can be approved with a |
| 677 | high-risk warning; the filesystem root and Reasonix session/state paths cannot. `forbid_read` optionally hides sensitive files or directories from the agent's |
| 678 | read/list/search tools; use absolute paths or `${HOME}` / `${VAR}` references, |
| 679 | not `~`, because config expansion is environment-variable based. `bash` is |
| 680 | itself jailed by default when an OS sandbox is available (`[sandbox] bash`, |
| 681 | Seatbelt on macOS and bubblewrap on Linux): |
| 682 | commands may write only those same roots plus platform-specific command |
| 683 | temp/cache roots, cannot read configured `forbid_read` roots while the OS |
| 684 | sandbox is active, and reach the network only when `[sandbox] network` is set. |
| 685 | Reasonix always removes saved provider and bot credential variables from tool |
| 686 | subprocess environments. On macOS and Linux it also automatically adds the |
| 687 | global credential `.env` to the runtime read-deny boundary. Windows does not: |
| 688 | it has no OS-level shell sandbox, and denying the current user would also deny |
| 689 | the host settings process. Project `.env` files keep their existing |
| 690 | workspace-scoped behavior. |
| 691 | |
| 692 | **Session-private temporary directory.** Within one logical chat session, Bash |
| 693 | commands share a private temporary directory so consecutive calls can exchange |
| 694 | files through `$TMPDIR` (and, on Linux under bubblewrap, through literal |
| 695 | `/tmp`). No user setup is required: Reasonix automatically exports `TMPDIR`, |
| 696 | `TMP`, and `TEMP` for Bash and client-owned ACP terminals. The directory is |
| 697 | created lazily, is never the host public temporary root, and is rotated on |
| 698 | `/new`, `/clear`, resume of another session, and branch switches. |
| 699 | Model/settings hot rebuilds keep the same directory. Temporary files are not |
| 700 | durable storage: resume across process restarts does not restore them, and |
| 701 | scripts that need long-lived data should write into the workspace or a |
| 702 | user-specified path. |
| 703 | |
| 704 | Reasonix-generated and project scripts should use the standard temporary |
| 705 | environment variables rather than hard-coding `/tmp`; users should not set |
| 706 | these variables themselves. For example: |
| 707 | |
| 708 | ```sh |
| 709 | tmp_file="${TMPDIR:?}/result.json" |
| 710 | ``` |
| 711 | |
| 712 | ```powershell |
| 713 | $tmpFile = Join-Path $env:TEMP "result.json" |
| 714 | ``` |
| 715 | |
| 716 | | Platform | `$TMPDIR` / `$TMP` / `$TEMP` | Literal `/tmp` | |
| 717 | | --- | --- | --- | |
| 718 | | Linux + bubblewrap | Virtual `/tmp` (bound to the private dir) | Shared for the session (not a fresh empty tmpfs each call) | |
| 719 | | macOS Seatbelt | Host path of the private dir (allowed by policy) | Host macOS temporary directory; scripts should use `$TMPDIR` | |
| 720 | | Windows (no OS sandbox) | Host path of the private dir | Not promised to match (e.g. Git Bash `/tmp`) | |
| 721 | |
| 722 | Independent sandboxes such as MCP servers keep their own isolation and do not |
| 723 | inherit the chat session's temporary directory. An approved sandbox-escape |
| 724 | command still receives the private temp environment variables, but on Linux its |
| 725 | literal `/tmp` is no longer mapped by bubblewrap. |
| 726 | |
| 727 | **Windows note:** Windows has no OS-level shell sandbox. The restricted-token |
| 728 | backend is retired from enforcement because denying the current user's own SID |
| 729 | locked hosts out of their credential store and the token broke common |
| 730 | toolchains. Permission presets still apply as Reasonix tool-layer |
| 731 | boundaries: Read only refuses file writes and asks before every shell command, |
| 732 | and Workspace write keeps file tools inside `workspace_root` and `allow_write` |
| 733 | and asks before writing elsewhere. Shell commands in every preset run as the |
| 734 | current OS user without confinement, so `[sandbox] network` and shell-level |
| 735 | `forbid_read` are not enforced there; dedicated file tools still honor |
| 736 | `forbid_read`. Saved credential variables are removed from child environments, |
| 737 | but local tools run as the user and can deliberately read other user-readable |
| 738 | files. `[sandbox] bash = "enforce"` resolves to `off` on Windows and |
| 739 | `reasonix doctor` reports the ignored value. |
| 740 | |
| 741 | When no OS sandbox backend is available, `bash = "enforce"` refuses bash |
| 742 | execution instead of running unconfined. Install the platform sandbox backend |
| 743 | (bubblewrap/`bwrap` on Linux, `sandbox-exec` on macOS) or set |
| 744 | `[sandbox] bash = "off"` to explicitly restore the pre-1.16 unconfined shell |
| 745 | behavior. |
| 746 | |
| 747 | For coding-quality reports, run `reasonix doctor quality <branch-id-or-path>` |
| 748 | (add `--json` for structured output). This reads the selected session but emits |
| 749 | only content-free counts and profile categories: model family, runtime profile, |
| 750 | collaboration / approval modes, message and tool-call counts, verification and persisted |
| 751 | compaction-summary counts, plus desktop token/cache telemetry when available. |
| 752 | It omits transcript text, paths, session identifiers, tool arguments and output, |
| 753 | endpoints, and custom model names, so the result is suitable for a public issue |
| 754 | or Discussion. This differs from `reasonix doctor session`, whose support zip |
| 755 | contains the complete unredacted transcript and must remain in a trusted support |
| 756 | channel. |
| 757 | |
| 758 | ## Capability diagnostics |
| 759 | |
| 760 | Use this when a skill, slash command, hook, plugin package, MCP server, or |
| 761 | `AGENTS.md` is missing, shadowed, disabled, or fails to start. Full flag |
| 762 | reference, JSON schema, and issue codes: |
| 763 | **[Capability diagnostics](./CAPABILITY_DIAGNOSTICS.md)**. |
| 764 | |
| 765 | ```bash |
| 766 | # Static (default): no network, no MCP child processes |
| 767 | reasonix doctor capabilities |
| 768 | |
| 769 | # Machine-readable (stdout is pure JSON) |
| 770 | reasonix doctor capabilities --json |
| 771 | |
| 772 | # Another workspace root |
| 773 | reasonix doctor capabilities --root /path/to/project |
| 774 | |
| 775 | # Live MCP probe — only when you explicitly allow starting third-party servers |
| 776 | reasonix doctor capabilities --live --timeout 5s |
| 777 | ``` |
| 778 | |
| 779 | | Surface | How | |
| 780 | | --- | --- | |
| 781 | | CLI | `reasonix doctor capabilities` (above) | |
| 782 | | Desktop | **Settings → Diagnostics** — refresh, copy redacted JSON, optional “include current session runtime” (reads the active tab Host only; does **not** start MCP) | |
| 783 | | Agent | `/reasonix-guide` (built-in inline skill) or ask naturally; it prefers static doctor JSON before `--live` | |
| 784 | |
| 785 | Exit code `0` allows warnings/info; `1` means at least one `error` (or a live |
| 786 | start failure); `2` is bad flags. This is separate from `reasonix doctor` |
| 787 | (providers/sandbox) and `reasonix plugin doctor <name>` (one package). |
| 788 | |
| 789 | ## Plugins (MCP) |
| 790 | |
| 791 | Reasonix is an MCP client. A `[[plugins]]` entry's `type` selects the transport: |
| 792 | `stdio` (default) launches a local subprocess (`command`/`args`/`env`); `http` |
| 793 | (Streamable HTTP) connects to a remote `url` with optional static `headers` |
| 794 | (`${VAR}` / `${VAR:-default}` expanded from the environment, so tokens stay out |
| 795 | of the file); `sse` connects to servers that still use the legacy persistent |
| 796 | GET + announced POST endpoint transport. |
| 797 | |
| 798 | For a remote HTTP server without a static `Authorization` header, an |
| 799 | authentication challenge is shown as **Sign in**. Run |
| 800 | `reasonix mcp auth <name>` in the CLI, or click **Sign in** for that server in |
| 801 | the Desktop MCP panel. Reasonix performs OAuth metadata discovery, dynamic |
| 802 | client registration, PKCE S256 authorization, and refresh-token |
| 803 | rotation. Discovery and token requests use the same Reasonix network-proxy |
| 804 | settings as the MCP connection. |
| 805 | |
| 806 | OAuth client and token state is kept outside the workspace in the server's |
| 807 | private Reasonix state directory, written with mode `0600`, and bound to the |
| 808 | full configured resource URL. An explicit static `Authorization` header always |
| 809 | takes precedence. **Clear authentication** removes only Reasonix's local OAuth |
| 810 | state; it does not sign out the third-party browser session. Reasonix opens the |
| 811 | browser only after an explicit sign-in action, never automatically from a |
| 812 | background tool-call failure. Removing the MCP server also removes its local |
| 813 | OAuth state unless a lower-priority declaration for the same resource becomes |
| 814 | effective. |
| 815 | |
| 816 | Browse the official MCP Registry from **Settings → MCP servers → Browse |
| 817 | registry**, or use `reasonix mcp browse [query]` and |
| 818 | `reasonix mcp install <registry-name>`. Registry access is explicit and never |
| 819 | runs during startup. Entries that need secrets or required arguments are shown |
| 820 | as manual setup instead of being installed with an incomplete configuration; |
| 821 | query-specific cached results remain available during a registry outage. |
| 822 | |
| 823 | The normal setup path is intentionally one step. Use Desktop's **Add and |
| 824 | connect**, `/mcp add`, or ask Reasonix to install a package or URL. These |
| 825 | explicit installs are saved to the user-global `config.toml` and are also |
| 826 | authorization: the server connects in the current session, and no second trust |
| 827 | step appears now or on the next startup. Servers declared by the current |
| 828 | project's `reasonix.toml` or `.mcp.json` remain in that project and are trusted |
| 829 | without a separate launch confirmation. Explicit deny rules still win. The |
| 830 | server's calls run |
| 831 | directly, including tools that declare `destructiveHint`. The dedicated Planner |
| 832 | still refuses destructive tools, and strict read-only sub-agents still expose |
| 833 | only hinted non-destructive readers. |
| 834 | |
| 835 | MCP names are resolved once per workspace. Project declarations override |
| 836 | same-name global installs; inside a project, `reasonix.toml` overrides |
| 837 | `.mcp.json`. Editing updates the effective declaration in its original file, |
| 838 | and removing a higher-priority declaration reveals the next one instead of |
| 839 | deleting every same-name entry. |
| 840 | |
| 841 | stdio servers keep one process for initialize, reads, and writes, so stateful |
| 842 | servers such as browsers retain sessions and open pages. Because an OS sandbox |
| 843 | is fixed when a process starts, this shared process uses the server's normal |
| 844 | process sandbox for every call; `readOnlyHint` and read-only sub-agent filtering |
| 845 | are dispatch policy, not a second per-call process sandbox. |
| 846 | |
| 847 | Tools surface to the model as `mcp__<server>__<tool>`. A tool declaring MCP's |
| 848 | `readOnlyHint: true` joins parallel dispatch and the strict read-only tool |
| 849 | surfaces. Installing a server or declaring it in project configuration |
| 850 | authorizes the dedicated Planner to use all of its non-destructive |
| 851 | tools without another per-tool setting; strict read-only research sub-agents |
| 852 | receive only hinted non-destructive readers. Tools without the hint remain |
| 853 | write-capable for scheduling and mutation accounting. While planning, built-in |
| 854 | writers keep the ordinary permission posture. The dedicated Planner permits |
| 855 | authorized non-destructive MCP (including opaque writers) but hard-blocks |
| 856 | destructive or unauthorized targets; a single-model Plan without that dedicated |
| 857 | Planner keeps the older writer/destructive block until Plan exits. |
| 858 | |
| 859 | Installing an MCP server is the authorization decision. After installation, all |
| 860 | of its tools run directly without a second server-level, per-tool, writer, or |
| 861 | destructive approval setting. Explicit global deny rules still win. The host |
| 862 | keeps `readOnlyHint` and `destructiveHint` internally for parallel scheduling, |
| 863 | Plan restrictions, strict read-only sub-agents, and cached-to-live safety |
| 864 | reclassification; these hints do not add user configuration. |
| 865 | Reasonix deliberately trusts an installed server to describe those hints |
| 866 | honestly. Planner/read-only filtering is therefore a workflow boundary for |
| 867 | trusted servers, not containment against a malicious MCP server; explicit deny |
| 868 | rules and the process sandbox remain host-controlled boundaries. |
| 869 | |
| 870 | The retired `trusted_read_only_tools`, `default_tools_approval_mode`, |
| 871 | `tools.<raw>.approval_mode`, and `approvals_reviewer` fields are ignored when |
| 872 | loading older files and removed the next time Reasonix saves that MCP entry. |
| 873 | |
| 874 | A server's **prompts** surface as `/mcp__<server>__<prompt>` slash commands |
| 875 | (positional args after the command); its **resources** are pulled in by writing |
| 876 | `@<server>:<uri>` in a message; `/mcp` lists connected servers and what each |
| 877 | exposes. `make build` also produces `bin/reasonix-plugin-example` — a runnable |
| 878 | reference stdio server (`echo`, `wordcount`, a `review` prompt, a style-guide |
| 879 | resource) you can copy. |
| 880 | |
| 881 | ```toml |
| 882 | [[plugins]] # local stdio server |
| 883 | name = "example" |
| 884 | command = "reasonix-plugin-example" |
| 885 | # startup_timeout_seconds = 60 # optional initialize + tools/list cap |
| 886 | # call_timeout_seconds = 600 # optional per-server MCP call timeout |
| 887 | # tool_timeout_seconds = { "generate_video" = 1800 } # optional raw MCP tool names |
| 888 | |
| 889 | [[plugins]] # remote server over Streamable HTTP |
| 890 | name = "stripe" |
| 891 | type = "http" |
| 892 | url = "https://mcp.stripe.com" |
| 893 | headers = { Authorization = "Bearer ${STRIPE_KEY}" } |
| 894 | ``` |
| 895 | |
| 896 | Enabled MCP servers start connecting automatically in the background after a |
| 897 | session begins, so chat stays usable while tools come online. Use `/mcp` or the |
| 898 | desktop MCP panel to refresh status, reconnect a server, inspect failures, or |
| 899 | disable a server for the current session. For a read-only config/runtime health |
| 900 | report across skills, hooks, packages, and MCP (without changing settings), see |
| 901 | [Capability diagnostics](./CAPABILITY_DIAGNOSTICS.md) |
| 902 | (`reasonix doctor capabilities` or **Settings → Diagnostics**). |
| 903 | |
| 904 | An interactive caller waits only briefly for a cold server. If that wait ends, |
| 905 | the shared startup continues in the background rather than being killed and |
| 906 | restarted; retry the tool after it comes online. `mcp_startup_timeout_seconds` |
| 907 | (default `30`) bounds the full launch, authorization, initialize, and |
| 908 | `tools/list` sequence. `mcp_call_timeout_seconds` applies only after the server |
| 909 | is connected. Either value can be overridden per server. |
| 910 | |
| 911 | **Already have an `.mcp.json`?** Drop it in the project root and Reasonix |
| 912 | reads it as-is — the `mcpServers` spec (`command`/`args`/`env`, `type`/`url`/ |
| 913 | `headers`, `${VAR}` expansion) maps field-for-field onto `[[plugins]]`. Both |
| 914 | sources are merged; on a name collision `reasonix.toml` wins. |
| 915 | |
| 916 | ```json |
| 917 | { |
| 918 | "mcpServers": { |
| 919 | "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"] }, |
| 920 | "stripe": { "type": "http", "url": "https://mcp.stripe.com", "headers": { "Authorization": "Bearer ${STRIPE_KEY}" } } |
| 921 | } |
| 922 | } |
| 923 | ``` |
| 924 | |
| 925 | **Upgrading from `0.x`?** Your old `~/.reasonix/config.json` is still read for its |
| 926 | `mcpServers` (honouring `mcpDisabled`) as a lowest-priority source, so MCP servers |
| 927 | keep working — move them into `reasonix.toml`'s `[[plugins]]` or a `.mcp.json` when |
| 928 | convenient. |
| 929 | |
| 930 | ## Slash commands |
| 931 | |
| 932 | In an interactive `reasonix` session, built-in commands (`/compact`, `/context`, `/new`, `/clear`, `/rewind`, |
| 933 | `/tree`, `/branch`, `/switch`, `/todo`, `/model`, `/mcp`, `/skills`, `/hooks`, |
| 934 | `/memory`, `/goal`, `/output-style`, `/sandbox`, `/language`, |
| 935 | `/reasoning-language`, `/help`) run |
| 936 | locally — `/help` lists them all. Built-in **skills** such as `/init`, |
| 937 | `/explore`, `/test`, and `/reasonix-guide` also appear in the slash menu and via |
| 938 | `run_skill` (bodies load on demand; only the index line is cache-stable). Use |
| 939 | `/reasonix-guide` when you need config or capability troubleshooting; it points |
| 940 | at `reasonix doctor capabilities` (see |
| 941 | [Capability diagnostics](./CAPABILITY_DIAGNOSTICS.md)). `/new` starts a new |
| 942 | session while saving the previous transcript for history/resume; `/clear` |
| 943 | discards the current context without saving it and asks for confirmation. `/tree` |
| 944 | shows saved conversation branches, `/branch [name]` forks the current |
| 945 | conversation tip, `/branch <turn> [name]` forks from an earlier checkpointed |
| 946 | turn, and `/switch <id|name>` loads another branch. **Custom commands** are |
| 947 | Markdown files under `.reasonix/commands/` (project) or `~/.reasonix/commands/` |
| 948 | (user) — `review.md` becomes `/review`, a subdirectory namespaces it |
| 949 | (`git/commit.md` → `/git:commit`). The body is a prompt template; invoking the |
| 950 | command sends it as a turn. |
| 951 | |
| 952 | ### Subagent profiles |
| 953 | |
| 954 | Subagent profiles are manual Skills with `runAs: subagent` and |
| 955 | `invocation: manual`. They are stored in the same project/global Skill roots as |
| 956 | the desktop settings page, so profiles created on either surface are immediately |
| 957 | available to the other after the session refreshes. In interactive chat, invoke |
| 958 | one with `/<name> <task>`; Reasonix runs an isolated child loop and keeps only |
| 959 | the task and final answer in the parent conversation. |
| 960 | |
| 961 | The headless CLI provides explicit management and execution commands without |
| 962 | changing the ordinary `reasonix run` task semantics: |
| 963 | |
| 964 | ```bash |
| 965 | reasonix subagent list |
| 966 | reasonix subagent create reviewer --description "Review changes" --prompt-file reviewer.md --tools read_file,grep,bash |
| 967 | reasonix subagent edit reviewer --effort high --model deepseek-pro |
| 968 | reasonix subagent try reviewer "review the current diff" # always read-only |
| 969 | reasonix subagent run reviewer "review and fix the current diff" |
| 970 | reasonix subagent delete reviewer --yes |
| 971 | ``` |
| 972 | |
| 973 | `create` defaults to project scope when a workspace is available and to global |
| 974 | scope otherwise; pass `--scope project|global` to choose explicitly. `edit` |
| 975 | changes only explicitly supplied fields, and an empty value such |
| 976 | as `--model=` or `--tools=` clears that field. The profile editors deliberately |
| 977 | refuse custom-path or richer hand-authored Skills so they cannot discard |
| 978 | frontmatter, references, or scripts; manage those files through the Skills |
| 979 | workflow instead. Built-in profiles have no editable file, so `edit` accepts |
| 980 | only `--model` and `--effort` for them and stores the same per-name overrides as |
| 981 | the desktop settings page. |
| 982 | |
| 983 | See [Subagent profiles](./SUBAGENT_PROFILES.md) for the complete CLI reference, |
| 984 | Skill file format, model precedence, safety behavior, and troubleshooting. |
| 985 | |
| 986 | Context Engine v2 separates two intentionally different layers: |
| 987 | |
| 988 | - **Standing instructions** come from hierarchical `REASONIX.md`, `AGENTS.md`, |
| 989 | and `CLAUDE.md` files. Put rules here when they must be present on every |
| 990 | relevant turn. User-global files load first, then workspace and deeper target |
| 991 | directories; within one directory, `.local.md` variants win. |
| 992 | - **Background memory** stores one durable fact per Markdown file. Each fact has |
| 993 | an immutable ID, monotonic revision, timestamps, independent `type` |
| 994 | (`user`, `feedback`, `project`, `reference`) and `scope` (`project`, |
| 995 | `global`), plus freshness metadata. Facts may be stale, so they never outrank |
| 996 | the current request or standing instructions. |
| 997 | |
| 998 | Reasonix automatically recalls a small set of relevant facts before each real |
| 999 | user turn. It searches the raw user message, suppresses generic requests such as |
| 1000 | "continue", prefers project facts over equivalent global fallbacks, down-ranks |
| 1001 | stale facts, and appends at most four facts / 2,400 characters to the user turn. |
| 1002 | This dynamic suffix does not rewrite the cache-stable system prompt or tool |
| 1003 | schemas. Use `/memory recall` to see the selected IDs, scores, reasons, |
| 1004 | freshness, budget, and suppression decision. |
| 1005 | |
| 1006 | New, bounded, non-sensitive project/reference facts can be created |
| 1007 | automatically with no setup or approval click. Other memory changes follow the |
| 1008 | active permission preset and explicit `ask` / `deny` rules. The storage layer |
| 1009 | makes the automatic create grant create-only, so it cannot overwrite a fact |
| 1010 | that appears concurrently. |
| 1011 | A top-level headless controller may use the same one-shot low-risk create path; |
| 1012 | sub-agents and headless surfaces without the owning scoped controller fail closed. |
| 1013 | |
| 1014 | `forget` archives rather than permanently deletes. Every update snapshots the |
| 1015 | previous revision; restore and archive recovery always create a higher revision |
| 1016 | instead of overwriting history: |
| 1017 | |
| 1018 | ```text |
| 1019 | /memory instructions |
| 1020 | /memory recall |
| 1021 | /memory revisions <id-or-name> |
| 1022 | /memory restore <id-or-name> <revision> |
| 1023 | /memory archived |
| 1024 | /memory recover <archive-path> |
| 1025 | ``` |
| 1026 | |
| 1027 | The desktop Context Center shows the same provenance, conflicts, revision |
| 1028 | history, recall trace, and recovery actions. Opening its Suggestions tab scans |
| 1029 | recent local user turns automatically; candidates are deduplicated against both |
| 1030 | memory scopes and instruction bodies, but nothing is saved until the user |
| 1031 | accepts it. Remote workspaces never fall back to local desktop memory or |
| 1032 | sessions. |
| 1033 | |
| 1034 | Legacy facts are upgraded in place with deterministic IDs and revision 1; |
| 1035 | missing scope is inferred from the containing directory. Migration is |
| 1036 | idempotent, old clients retain safe routing, and legacy Memory v5 transcripts |
| 1037 | remain readable. For the complete behavior and privacy/cache contract, see |
| 1038 | [`Context Engine v2`](SESSION_MEMORY_RETRIEVAL.md). |
| 1039 | |
| 1040 | ```markdown |
| 1041 | --- |
| 1042 | description: Review the staged diff |
| 1043 | argument-hint: [focus-area] |
| 1044 | --- |
| 1045 | Review the staged diff. Focus on $ARGUMENTS, list bugs with file:line. |
| 1046 | ``` |
| 1047 | |
| 1048 | `$ARGUMENTS` expands to all space-separated args, `$1`…`$N` to positional ones. |
| 1049 | MCP prompts also appear here as `/mcp__<server>__<prompt>`. |
| 1050 | |
| 1051 | ## Embedded documentation retrieval |
| 1052 | |
| 1053 | Reasonix bundles the Markdown files from `docs/` and the reviewed |
| 1054 | `release-notes/releases.json` catalog into each CLI and Desktop build. The |
| 1055 | read-only `docs` tool searches that exact offline corpus with local BM25 |
| 1056 | retrieval and can read a complete matching section with source provenance. It |
| 1057 | renders every release in both languages under paths such as |
| 1058 | `changelog/v1.19.5.md` and `changelog/v1.19.5.zh-CN.md`, so questions about a |
| 1059 | specific version, upgrades, fixes, or known risks work offline. The agent should |
| 1060 | use the tool before web search or assumptions when a question concerns Reasonix |
| 1061 | configuration, CLI/Desktop behavior, release history, permissions, MCP, memory, |
| 1062 | recovery, providers, or maintainer workflows. |
| 1063 | |
| 1064 | No setup, network connection, vector database, or embedding service is needed. |
| 1065 | Search results prefer the query language while retaining explicit `en`, |
| 1066 | `zh-CN`, audience, and catalog filters. The docs capability is exposed through |
| 1067 | the unified `use_capability` surface for every task. Every result reports |
| 1068 | the product version, immutable source revision, and corpus SHA-256 digest. Release |
| 1069 | CI compiles the CLI and rejects publication unless that embedded manifest matches |
| 1070 | the candidate's `docs/*.md`, `release-notes/releases.json`, and build identity. A |
| 1071 | newer online `main-v2` page therefore cannot silently replace version-matched |
| 1072 | local guidance or release history. |
| 1073 | |
| 1074 | Use `/docs` to inspect the bundled corpus identity and usage examples without |
| 1075 | calling a model. Use `/docs <question>` (for example, |
| 1076 | `/docs 1.19.5 changelog`) to make Reasonix search the corpus locally first and |
| 1077 | then pass the version-matched evidence to the currently configured AI for a |
| 1078 | sourced answer. This command path does not depend on the model deciding to call |
| 1079 | the `docs` tool, while ordinary natural-language questions may still use the |
| 1080 | tool automatically. Existing custom commands and compatible plugin or skill |
| 1081 | aliases keep ownership of `/docs`; when that happens, CLI and Desktop normally |
| 1082 | expose the built-in corpus as `/reasonix:docs` instead. If that qualified name is |
| 1083 | also already owned, Reasonix selects the next free `reasonix:`-qualified fallback |
| 1084 | without displacing it. A remote Desktop uses the host's resolved command catalog, |
| 1085 | so the displayed entry always matches what that host will execute. |
| 1086 | |
| 1087 | Pull requests that change user-visible CLI, Desktop, configuration, provider, |
| 1088 | permission, or tool behavior must declare whether embedded documentation was |
| 1089 | updated. When no documentation change is needed, the declaration must explain |
| 1090 | why the existing version-matched guidance remains correct. |
| 1091 | |
| 1092 | ## Goal |
| 1093 | |
| 1094 | Goal is the unified runtime for long-running objectives. Reasonix keeps working |
| 1095 | until the goal is complete, blocked, paused, or cleared. Ordinary chat never |
| 1096 | changes collaboration mode implicitly; choose Goal in the composer or use |
| 1097 | `/goal` to start a long-running objective. |
| 1098 | |
| 1099 | Goal has no default model-round, cross-Run turn, wall-clock, or numeric |
| 1100 | no-progress limit. It continues until completion, a genuine user/external |
| 1101 | blocker, manual stop/pause, an unrecoverable external error, or an explicit |
| 1102 | user-selected budget. To place an optional ceiling on an unattended loop, set: |
| 1103 | |
| 1104 | ```toml |
| 1105 | [agent] |
| 1106 | goal_token_budget = 20000000 |
| 1107 | ``` |
| 1108 | |
| 1109 | The default is `0` (off). Reaching a positive token budget produces one summary |
| 1110 | and a resumable `budget_spend` pause. `/goal resume` grants a fresh configured |
| 1111 | slice while cumulative Goal statistics remain intact. Explicit positive |
| 1112 | `max_steps`, task time, and task cost budgets remain available as well. |
| 1113 | Cumulative rounds, tokens and real provider requests are tracked and shown as |
| 1114 | statistics; a token limit appears only when explicitly configured. A paused |
| 1115 | goal keeps its objective and runtime history — use `/goal resume` to continue, |
| 1116 | or `/goal pause` to pause a running goal manually. `/goal status` shows rounds, |
| 1117 | requests and tokens. Exact consecutive tool calls receive reminders at the |
| 1118 | third, fifth, and eighth occurrence; the calls still execute. An active, armed |
| 1119 | goal continues after an ordinary model final through the runtime idle driver; |
| 1120 | there is no per-turn `continue` report. The model uses `update_goal(complete)` |
| 1121 | when it judges the whole objective finished and `update_goal(blocked)` for a |
| 1122 | concrete persistent blocker. No evaluator, todo percentage or host quality |
| 1123 | gate decides completion. Restoring, importing or forking loads the durable |
| 1124 | goal disarmed; a directly authorized user turn or explicit UI action must |
| 1125 | resume it. |
| 1126 | |
| 1127 | For complex work, write the objective as a |
| 1128 | [task contract](./TASK_CONTRACT.md): Context, Request, Output format, |
| 1129 | Constraints, and Pause policy. Goal mode treats those sections as the boundary |
| 1130 | for autonomous work. It keeps going with sensible defaults unless the next step |
| 1131 | requires an irreversible or externally visible operation, a scope change, or |
| 1132 | information only the user can provide. |
| 1133 | |
| 1134 | Legacy simple/write/research classes and Goal sidecars are read only at the |
| 1135 | explicit compatibility/import boundary. There is no separate research runtime |
| 1136 | to configure. Current Goal state is a versioned `goal/state` projection in the |
| 1137 | linear v3 session, and activation is process-local. Legacy |
| 1138 | `.reasonix/autoresearch/<task-id>/` archives remain read-only. Deprecated |
| 1139 | budget flags are accepted for compatibility but hidden from help and |
| 1140 | completion. |
| 1141 | |
| 1142 | ### Model task progress |
| 1143 | |
| 1144 | `todo_write` updates progress for the current top-level turn. A newly admitted |
| 1145 | Goal round starts with a fresh todo plan; compaction, steer and interactive |
| 1146 | answers inside that round keep the current list. The host does not finish todos |
| 1147 | when a turn or Goal ends. `complete_step` is absent from discovery; an old call |
| 1148 | returns a normal `tool_retired` result and never changes task state. |
| 1149 | |
| 1150 | ## @ references |
| 1151 | |
| 1152 | Embed `@` references in a message and Reasonix resolves them before sending, as |
| 1153 | tagged context blocks: `@path/to/file` (or `@dir`) injects a local file's |
| 1154 | contents (or a directory listing), and `@<server>:<uri>` injects an MCP |
| 1155 | resource. A local path is only treated as a reference when it actually exists, |
| 1156 | so ordinary `@mentions` stay literal. Typing `/` or `@` opens an autocomplete |
| 1157 | menu — slash commands, or hierarchical file navigation (one directory level at a |
| 1158 | time, descend into folders) plus MCP resources. |
| 1159 | |
| 1160 | ## Two-model collaboration |
| 1161 | |
| 1162 | `reasonix setup` manages providers, model lists, credentials, connection tests, |
| 1163 | and the default model. It stages changes until Save and exit, and synchronizes |
| 1164 | provider access with the desktop app. See the [CLI reference](./CLI.md#configure-providers). |
| 1165 | Running two models together (executor + planner, separate cache-stable sessions) |
| 1166 | is a one-line edit afterwards — set `planner_model` to any other enabled provider: |
| 1167 | |
| 1168 | ```toml |
| 1169 | [agent] |
| 1170 | planner_model = "deepseek-pro" # used as the low-frequency planner |
| 1171 | ``` |
| 1172 | |
| 1173 | The planner sees loaded `REASONIX.md` / `AGENTS.md` memory and a small read-only |
| 1174 | research tool set, so it can inspect relevant files before handing a plan to the |
| 1175 | executor. Writer and workflow tools remain executor-only. |
| 1176 | |
| 1177 | Reasonix routes each turn deterministically without another classifier model. |
| 1178 | Ordinary requests always stay with the executor. The dedicated planner runs |
| 1179 | only for an explicit `plan first` / `先规划` request, an explicit wait-for- |
| 1180 | approval boundary, an explicit `plan only` / `不要执行` request, or Goal |
| 1181 | start. Wording such as "complex refactor" or "fix login" does not start the |
| 1182 | planner. There is no automatic planning depth. Explicit Plan Mode |
| 1183 | remains a separate host workflow on the executor and is never planned twice. |
| 1184 | `just do it` / `直接改` also stays with the executor. Execution boundaries are |
| 1185 | recognized across the request, not only at its beginning, while quoted |
| 1186 | examples are ignored. Bare plan-first requests continue from the planner to |
| 1187 | the executor automatically. Requests that explicitly say to wait for |
| 1188 | confirmation pause at the host approval boundary and continue to the executor |
| 1189 | after approval. Only an explicit `plan only` / `不要执行` request ends the |
| 1190 | current turn with the plan persisted and no execution; a later user instruction |
| 1191 | can continue in the same session. The phase detail records a privacy-safe route |
| 1192 | and reason code for diagnosis without logging the user prompt. |
| 1193 | |
| 1194 | The planner uses one stable system prompt. A small host-authored |
| 1195 | `<planner-turn>` block names the explicit route and preserves the planner |
| 1196 | prefix cache after the one-time prompt upgrade. The plan should separate |
| 1197 | verified from candidate touchpoints and include non-goals, risks, acceptance |
| 1198 | criteria, and command-level verification when evidence supports them. The |
| 1199 | planner must call `submit_plan`; a prose reply without a submitted plan is a |
| 1200 | protocol error. If a planner still does not finalize after its bounded |
| 1201 | research and finalization round, the turn fails closed on every route and the |
| 1202 | executor is not started. The incomplete planner turn is rolled back instead of |
| 1203 | leaving an unusable continuation tail. |
| 1204 | |
| 1205 | Ordinary clean finals end the turn. Goal, review, and guardian flows keep |
| 1206 | their own continuation constraints. In Goal mode, if an active todo produces |
| 1207 | no new completion, unique read, command, or mutation past the stall threshold, |
| 1208 | the host forces a smaller step, different tool/approach, focused delegation, |
| 1209 | or a real blocker report, then execution continues. Exact repeats do not count |
| 1210 | as progress; new host-observed work renews the lease. Two-level task lists keep |
| 1211 | the same single-current contract: the active level-1 sub-step is the one |
| 1212 | `in_progress` item while its level-0 phase stays `pending`; sub-steps are worked |
| 1213 | and signed off in order, and once every sub-step has completed the phase itself |
| 1214 | becomes `in_progress` for its own final sign-off. |
| 1215 | |
| 1216 | Existing `[agent].max_steps` and `planner_max_steps` keys remain syntactically |
| 1217 | accepted during upgrades, but their values are ignored and removed with a |
| 1218 | one-time notice. This prevents a stale hidden limit from truncating automatic |
| 1219 | progress or inherited subagent work. Use the one-off CLI `--max-steps` flag when |
| 1220 | an explicit run budget is needed; unattended bots retain `[bot].max_steps`, |
| 1221 | where `0` means continuous execution and a positive value is explicit. |
| 1222 | |
| 1223 | **An ordinary chat task has no limit of any kind by default** — not rounds, not |
| 1224 | tokens, not time, not money. It runs until the model finishes, an adaptive |
| 1225 | guard decides it stopped making progress, or you stop it. |
| 1226 | |
| 1227 | An optional spend gate is available when you want one. It bounds a whole task |
| 1228 | (every "continue" included, until you start unrelated work), and on crossing it |
| 1229 | the task produces one tool-free summary and pauses; the work is saved and the |
| 1230 | next message continues it. |
| 1231 | |
| 1232 | ```toml |
| 1233 | [agent] |
| 1234 | task_cost_budget = 5.0 # in the model's pricing currency |
| 1235 | task_time_budget_minutes = 60 # wall clock across the whole task |
| 1236 | ``` |
| 1237 | |
| 1238 | Both are off unless set. In particular, `task_time_budget_minutes = 0` (and |
| 1239 | legacy negative values) disables the time gate; only a positive value enables |
| 1240 | it. Neither has a default, because a stop is a judgement |
| 1241 | only you can make: no amount of money is portable across models — a budget |
| 1242 | loose enough for a cheap model would land a frontier model within a couple of |
| 1243 | answers — and a long task is as often the job you asked for as it is a runaway. |
| 1244 | |
| 1245 | Cost applies only to a priced model. Without a price table that axis stays |
| 1246 | inactive rather than reading the task as free; use the time axis for a free or |
| 1247 | local model. |
| 1248 | |
| 1249 | Rounds are deliberately not an axis. A turn that reaches a high round count |
| 1250 | without spending much is one whose rounds are individually cheap and fast, |
| 1251 | which is the case least worth interrupting. Use the one-off `--max-steps` flag |
| 1252 | when you specifically want a run bounded by rounds. |
| 1253 | |
| 1254 | Subagent skills inherit the executor model by default. Set `subagent_model` to |
| 1255 | run them on another configured model, or use `subagent_models` to override only |
| 1256 | specific skills such as `review` or `security_review`. |
| 1257 | |
| 1258 | Subagents may delegate one more layer by default: the root session is depth 0, |
| 1259 | first-layer subagents are depth 1, and the maximum `max_subagent_depth = 2` |
| 1260 | means a depth-1 workflow can dispatch a depth-2 reviewer or implementer. Depth-2 |
| 1261 | subagents do not receive recursive agent/skill tools. Set |
| 1262 | `agent.max_subagent_depth = 1` to restore the old single-layer boundary. This is |
| 1263 | intended for workflows such as Superpowers where a workflow skill may dispatch a |
| 1264 | reviewer subagent, while still avoiding unbounded recursion and background |
| 1265 | fanout. |
| 1266 | |
| 1267 | Use `read_only_task` when planning needs isolated, deeper research without |
| 1268 | granting write-capable delegation. Use `read_only_skill` when the same need is |
| 1269 | best expressed through an existing skill. Both run ephemeral read-only |
| 1270 | subagents with only read-only research tools plus safe foreground bash, return |
| 1271 | only the final answer, and do not create resumable subagent transcripts. |
| 1272 | Read-only nested delegation may be available until `max_subagent_depth` is |
| 1273 | reached, but writer-capable `task` / `run_skill` remain unavailable inside these |
| 1274 | read-only child registries. Every task shares one tool surface: call |
| 1275 | `use_capability` for `read_only_skill` and other optional tools. Subsequent |
| 1276 | writer calls still pass through Permissions/Sandbox. |
| 1277 | |
| 1278 | Every strict read-only child is built through one shared construction |
| 1279 | pairing — `RunReadOnlySubAgentWithSession` / `NewReadOnlyAgent` — which marks |
| 1280 | the child permanently read-only and applies a final registry filter. The filter |
| 1281 | removes writers, destructive MCP targets, readers from unauthorized servers, |
| 1282 | and every host-mutating tool. User-installed and project-configured servers are |
| 1283 | authorized immediately. Eligible readers may still start on demand. These are |
| 1284 | the strict read-only entrances: |
| 1285 | |
| 1286 | | Entrance | Purpose | |
| 1287 | | --- | --- | |
| 1288 | | `read_only_task` | Isolated read-only research child from the main session | |
| 1289 | | `parallel_tasks` (read-only) | Concurrent read-only research children | |
| 1290 | | `fleet` with `read_only: true` | Parallel profile-aware batch (forced read-only per item) | |
| 1291 | | `read_only_skill` | The same isolation driving an existing skill | |
| 1292 | | `reasonix review` (CLI) | Read-only review of a diff or branch | |
| 1293 | | Desktop preview/review subagents | Read-only desktop analysis surfaces | |
| 1294 | |
| 1295 | In persisted sessions, `parallel_tasks` and `fleet` return a bounded preview |
| 1296 | plus one `Subagent reference` per completed child instead of concatenating every |
| 1297 | full answer into a truncation-prone tool result. The parent can call |
| 1298 | `read_subagent_result` with that reference and page by `offset_bytes`; results |
| 1299 | are scoped to the current conversation lineage and workspace. Headless runs |
| 1300 | without a persisted parent session remain ephemeral and receive fair bounded |
| 1301 | previews, but cannot mint durable references. |
| 1302 | |
| 1303 | Persisted child results include `status` (`completed`, `partial`, `failed`, or |
| 1304 | `cancelled`) and `retryable`. Partial or retryable failed runs retain a visible |
| 1305 | answer and reference so the parent can inspect them with `read_subagent_result` |
| 1306 | or continue the same `task`/`run_skill` transcript with `continue_from`. |
| 1307 | |
| 1308 | The interactive two-model Planner uses a dedicated construction path |
| 1309 | (`NewPlannerAgent`): it still blocks bash, file writers, and ordinary writers, |
| 1310 | but may call authorized, non-destructive MCP through the fixed |
| 1311 | `use_capability` proxy without requiring `readOnlyHint`. Direct `mcp__*` |
| 1312 | schemas never enter the Planner tool list, so MCP install/connect churn does |
| 1313 | not change the Planner cache prefix after the one-time schema upgrade. Missing |
| 1314 | `readOnlyHint` no longer blocks the Planner; tools with `destructiveHint` are |
| 1315 | zero-exec and should be written into the plan for the Executor. |
| 1316 | In Balanced two-model sessions the Executor has its own frontend for the same |
| 1317 | stable proxy, so an `auto_start=false` or destructive capability discovered by |
| 1318 | the Planner remains callable by capability ID after handoff. Planner and |
| 1319 | Executor ledgers/audits stay isolated and only the Host connection is shared. |
| 1320 | |
| 1321 | Ordinary `task` / `fleet` sub-agents also get the same fixed proxy (session- |
| 1322 | shared Host and connections, per-agent frontend/ledger) and may call installed |
| 1323 | or project-configured MCP without `readOnlyHint`. Those calls use the trusted |
| 1324 | MCP permission path (live authorization plus explicit deny only); writer and |
| 1325 | destructive calls are still serialized, recorded as mutations, and subject to |
| 1326 | closed-loop evidence/lease guards rather than Planner handoff. Strict |
| 1327 | `read_only_task` / `read_only_skill` / review sub-agents share the stable proxy |
| 1328 | schema and connection reuse but keep the strict execution gate |
| 1329 | (`authorized && readOnlyHint && !destructiveHint`). Profile `allowed-tools` |
| 1330 | MCP names convert to capability-id allowlists on the proxy; children never |
| 1331 | inherit dynamic `mcp__*` schemas. |
| 1332 | |
| 1333 | Inside a strict child, `use_capability` re-checks the resolved target before |
| 1334 | commit/permission/hooks/execution. An unconnected eligible MCP reader may start |
| 1335 | on demand from the current schema cache. Before `tools/call`, cached |
| 1336 | `readOnlyHint`/`destructiveHint` facts are checked against the live |
| 1337 | initialize/tools-list result; a reader-to-writer change or destructive promotion |
| 1338 | means zero executions and a normal retry through the current boundary. A |
| 1339 | schema-only change refreshes the cache for the next session without interrupting |
| 1340 | the authorized call. Runtime enablement, authorization, and the complete |
| 1341 | connection identity are checked again immediately before dispatch, so a |
| 1342 | same-name client from another project/tab cannot be reused accidentally. An |
| 1343 | unauthorized server cannot raise privileges there. This strict-child boundary |
| 1344 | is narrower than the dedicated Planner: the Planner accepts authorized opaque |
| 1345 | non-destructive MCP, while a strict child requires an explicit reader hint and |
| 1346 | never exposes writers at all. |
| 1347 | |
| 1348 | Reasonix uses **fact-driven execution**. Ordinary requests always enter the |
| 1349 | executor. There is no automatic task mode or selectable quality floor. Planner, |
| 1350 | Goal, permission, sandbox, and the task contract are independent states. |
| 1351 | |
| 1352 | Ordinary turns end when the model ends normally, even with unfinished todos or failed checks. There are no quality retries or todo-driven continuation rounds. Active Goals alone drive automatic continuation; approved Plans execute as ordinary tasks. Historical checkpoints remain available through an explicit `Continue checks` request, without restoring quality gates. Protocol recovery, cancellation, and resource limits remain independent. |
| 1353 | |
| 1354 | Every task shares the same provider-visible core tool surface: direct |
| 1355 | read/bash/edit/write, background-shell lifecycle tools, `ask`/`compress` when |
| 1356 | registered, and the stable `use_capability` proxy for optional tools (search, |
| 1357 | MCP, skills, subagents, docs, web_fetch, and so on). Calling `use_capability` |
| 1358 | never expands the top-level provider schema, so the prompt-cache tool prefix |
| 1359 | stays stable across every task. The Harness minimal preset is not a task |
| 1360 | complexity mode. |
| 1361 | |
| 1362 | The model decides whether to investigate, update todos, verify changes, or request review. User and project instructions stay in task context. File counts, authentication paths, schemas, migrations, and explicit verification language do not create host acceptance obligations. The host retains action permissions, preapproval Plan write restrictions, sandboxing, workspace leases, and structured-file stale-version protection. An ordinary tool failure does not skip later independent calls in the same batch. Results show actual commands, failures, interruptions, and checks made stale by later edits; model completion reports are separate from these facts. |
| 1363 | |
| 1364 | For interactive frontends, Plan Mode is always an explicit user choice. Select |
| 1365 | Plan in the desktop collaboration-mode control or cycle to Plan with |
| 1366 | `Shift+Tab` in the CLI. Reasonix first drafts a plan, then waits for approval |
| 1367 | before the workflow switches to implementation. Tool calls made while drafting |
| 1368 | still use the current Permissions and Sandbox. Legacy `agent.auto_plan` and |
| 1369 | `agent.auto_plan_classifier` values are ignored and removed from the user config |
| 1370 | during upgrade. The visible reasoning language can be changed with |
| 1371 | `/reasoning-language auto|zh|en` in the |
| 1372 | session, or `reasonix config reasoning-language auto|zh|en` in a shell/script. |
| 1373 | Pass `--local` |
| 1374 | to the reasoning-language shell command only when you intentionally want a |
| 1375 | project-local override. |
| 1376 | |
| 1377 | The why behind separate sessions (keeping each model's prefix cache-stable) is in |
| 1378 | [`SPEC.md` §3.5](./SPEC.md#35-two-model-collaboration-coordinator). |
| 1379 |