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