reasonix 0.4.21 → 0.4.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,8 +6,9 @@
6
6
  [![downloads](https://img.shields.io/npm/dm/reasonix.svg)](https://www.npmjs.com/package/reasonix)
7
7
  [![node](https://img.shields.io/node/v/reasonix.svg)](./package.json)
8
8
 
9
- **A DeepSeek-native AI coding assistant in your terminal.** Ink TUI. MCP
10
- first-class. No LangChain.
9
+ **A DeepSeek-native AI coding agent in your terminal.** Edits files as
10
+ reviewable SEARCH/REPLACE blocks. Ink TUI. MCP first-class. No
11
+ LangChain.
11
12
 
12
13
  ---
13
14
 
@@ -16,60 +17,27 @@ first-class. No LangChain.
16
17
  **1. Get a DeepSeek API key.** Free credit on signup:
17
18
  <https://platform.deepseek.com/api_keys>
18
19
 
19
- **2. Run it.** No install needed.
20
-
21
- ```bash
22
- npx reasonix
23
- ```
24
-
25
- First run walks you through a 30-second wizard:
26
-
27
- - paste your API key (saved to `~/.reasonix/config.json`)
28
- - pick a preset — `fast` (cheap chat, default), `smart` (+R1 reasoning), `max` (+self-consistency branching)
29
- - multi-select MCP servers from a catalog (filesystem, memory, github, puppeteer, …)
30
-
31
- Every run after that drops you straight into chat.
32
-
33
- **3. Inside the chat.** Type anything and hit Enter. Type `/help` to see
34
- every command. The status bar at the top shows cache hit %, cost so far,
35
- balance, and context usage. Press `Esc` to cancel whatever is running.
36
-
37
- ```
38
- reasonix › explain what this project does
39
- assistant
40
- …streams R1 reasoning into a dim preview, then writes the answer…
41
- status bar: cache hit 92% · cost $0.001 · ctx 8k/131k (6%) · balance 12.34 CNY
42
- ```
43
-
44
- Requires Node ≥ 18. Works on macOS, Linux, Windows (Git Bash + PowerShell).
45
-
46
- ---
47
-
48
- ## Using `reasonix code` — your terminal pair programmer
49
-
50
- Scoped to the directory you launch from. The model has native
51
- `read_file` / `write_file` / `edit_file` / `list_directory` /
52
- `search_files` / `directory_tree` / `get_file_info` /
53
- `create_directory` / `move_file` tools, all sandboxed — any path that
54
- resolves outside the launch root (including `..` and symlink escapes)
55
- is refused.
20
+ **2. Point it at a project.** No install needed.
56
21
 
57
22
  ```bash
58
23
  cd my-project
59
24
  npx reasonix code
60
25
  ```
61
26
 
62
- ### Walkthrough: fix a bug
27
+ First run walks you through a 30-second wizard (paste API key → pick
28
+ preset → multi-select MCP servers). Every run after that drops you
29
+ straight in.
30
+
31
+ **3. Ask it to edit.** The model proposes edits as SEARCH/REPLACE
32
+ blocks — nothing hits disk until you `/apply`.
63
33
 
64
34
  ```
65
- reasonix code › users.ts 里 findByEmail 对大小写敏感导致登录失败,帮我改成大小写不敏感
35
+ reasonix code › users.ts 里 findByEmail 对大小写敏感导致登录失败,帮我改
66
36
 
67
37
  assistant
68
- ▸ R1 reasoning · 1243 chars of thought
69
38
  ▸ tool<search_files> → src/users.ts, src/users.test.ts
70
39
  ▸ tool<read_file> → (src/users.ts, 412 chars)
71
- tool<read_file> → (src/users.test.ts, 820 chars)
72
- ▸ 找到了。findByEmail 直接用 === 比对。我把查询和存储都规范化为小写,并补上一条测试。
40
+ 找到了。findByEmail 直接用 === 比对。改成小写规范化并补一条测试。
73
41
 
74
42
  src/users.ts
75
43
  <<<<<<< SEARCH
@@ -79,49 +47,34 @@ src/users.ts
79
47
  return users.find(u => u.email.toLowerCase() === needle);
80
48
  >>>>>>> REPLACE
81
49
 
82
- src/users.test.ts
83
- <<<<<<< SEARCH
84
- it("finds by email", () => {
85
- expect(findByEmail("a@b.com")).toBeDefined();
86
- });
87
- =======
88
- it("finds by email", () => {
89
- expect(findByEmail("a@b.com")).toBeDefined();
90
- });
91
-
92
- it("is case-insensitive", () => {
93
- expect(findByEmail("A@B.COM")).toBeDefined();
94
- });
95
- >>>>>>> REPLACE
50
+ ▸ 1 pending edit across 1 file — /apply to write · /discard to drop
96
51
 
97
- 2 pending edits across 2 files — /apply to write · /discard to drop
52
+ reasonix code /apply
53
+ ▸ ✓ applied src/users.ts
98
54
  ```
99
55
 
100
- **At this point nothing has been written to disk.** You have three
101
- options:
102
-
103
- - `/apply` — commit the pending blocks. You'll see `✓ applied
104
- src/users.ts` and `✓ applied src/users.test.ts`. A snapshot of the
105
- pre-edit file is kept so `/undo` can roll back.
106
- - `/discard` — throw the blocks away without writing.
107
- - Keep chatting — ask for adjustments. Say "also cover the empty
108
- string case" and the model proposes another block set.
56
+ Requires Node 20.10. macOS, Linux, Windows (PowerShell / Git Bash /
57
+ Windows Terminal). Press `Esc` anytime to abort; `/help` for the full
58
+ command list.
109
59
 
110
- After applying:
60
+ ---
111
61
 
112
- ```
113
- reasonix code › /commit "fix: findByEmail case-insensitive"
114
- ▸ git add -A && git commit -m "fix: findByEmail case-insensitive"
115
- [main a1b2c3d] fix: findByEmail case-insensitive
116
- ```
62
+ ## `reasonix code` — pair programmer in your terminal
117
63
 
118
- `/commit` runs `git add -A && git commit -m ...` from the sandbox root.
64
+ Scoped to the directory you launch from. The model has native
65
+ `read_file` / `write_file` / `edit_file` / `list_directory` /
66
+ `search_files` / `directory_tree` / `get_file_info` /
67
+ `create_directory` / `move_file` tools, all sandboxed — any path that
68
+ resolves outside the launch root (including `..` and symlink escapes)
69
+ is refused. Plus `run_command` with a read-only allowlist; anything
70
+ state-mutating (`npm install`, `git commit`, …) is gated behind a
71
+ confirmation picker.
119
72
 
120
73
  ### Walkthrough: explore before editing
121
74
 
122
75
  For "what does this code do?" questions the model uses the read-side
123
- tools and replies in prose — no SEARCH/REPLACE blocks, no file writes.
124
- Ask to change something only when you mean it:
76
+ tools and replies in prose — no SEARCH/REPLACE blocks, no file
77
+ writes. Ask to change something only when you mean it:
125
78
 
126
79
  ```
127
80
  reasonix code › 这个项目的路由是怎么组织的?
@@ -132,23 +85,10 @@ assistant
132
85
  nested routes 写子路径,最后 …
133
86
  ```
134
87
 
135
- If the SEARCH text doesn't match the file byte-for-byte, `edit_file`
136
- refuses the edit loudly rather than fuzzy-matching. The model sees the
137
- error and retries with the correct search text — silent wrong edits are
138
- worse than visible rejections.
139
-
140
- ### Things to try
141
-
142
- - `/tool 1` — dump the last tool call's full output (when the 400-char
143
- inline clip isn't enough).
144
- - `/think` — see the model's full R1 reasoning for the last turn
145
- (reasoner preset only).
146
- - `/memory` — show the project's `REASONIX.md` (see below).
147
- - `/plan` — toggle read-only plan mode (see below).
148
- - `/undo` — roll back the last applied edit batch.
149
- - `/new` — start fresh in the same directory without losing the
150
- session file.
151
- - Drop `--no-session` for an ephemeral session that doesn't persist.
88
+ If an `edit_file` SEARCH block doesn't match the file byte-for-byte,
89
+ the edit is refused loudly rather than fuzzy-matched. The model sees
90
+ the error and retries — silent wrong edits are worse than visible
91
+ rejections.
152
92
 
153
93
  ### Plan mode — review before executing
154
94
 
@@ -179,24 +119,58 @@ Swap JWT middleware for session cookies, keep user table intact.
179
119
  Cancel
180
120
  ```
181
121
 
182
- **Approve** exits plan mode and the model starts executing.
183
- **Refine** keeps the model exploring and asking for an updated plan.
184
- **Cancel** drops it and asks you what you actually want.
185
-
186
- Small fixes skip this — the model goes straight to `edit_file`.
187
-
188
122
  **Force it** with `/plan` — enters an explicit read-only phase where
189
123
  the model *must* submit a plan before any edit or non-allowlisted
190
- shell call will execute. Use it for high-stakes changes where you
191
- want to audit the plan before the model touches disk. `/plan off` or
192
- picker Approve/Cancel exits.
124
+ shell call will execute. Use for high-stakes changes you want to
125
+ audit before the model touches disk. `/plan off` or picker
126
+ Approve/Cancel exits.
127
+
128
+ ### `/commit` — stage + commit in one step
129
+
130
+ ```
131
+ reasonix code › /commit "fix: findByEmail case-insensitive"
132
+ ▸ git add -A && git commit -m "fix: findByEmail case-insensitive"
133
+ [main a1b2c3d] fix: findByEmail case-insensitive
134
+ ```
135
+
136
+ ### Things to try
137
+
138
+ - `/tool 1` — dump the last tool call's full output (when the 400-char
139
+ inline clip isn't enough).
140
+ - `/think` — see the model's full R1 reasoning for the last turn
141
+ (reasoner preset only).
142
+ - `/undo` — roll back the last applied edit batch.
143
+ - `/new` — start fresh in the same directory without losing the
144
+ session file.
145
+ - `npx reasonix code --preset max` — R1 + 3-way self-consistency
146
+ branching for gnarly refactors.
147
+ - `npx reasonix code src/` — narrower sandbox (only `src/` is
148
+ writable).
149
+ - `npx reasonix code --no-session` — ephemeral; nothing saved.
150
+
151
+ ### Staying current
152
+
153
+ The panel header shows the running version next to `Reasonix` (e.g.
154
+ `Reasonix v0.4.22 · model …`). A quiet 24-hour background check against
155
+ the npm registry surfaces a yellow `update: X.Y.Z` on the right side
156
+ of the same row when a newer version has been published. No blocking,
157
+ no nagging — the check runs once per day max and is silent on failure
158
+ (offline, firewall, etc.).
159
+
160
+ ```bash
161
+ reasonix update # print current vs latest, run `npm i -g reasonix@latest`
162
+ reasonix update --dry-run # print the plan without running anything
163
+ ```
164
+
165
+ Running via `npx`? The command detects that and prints a
166
+ cache-refresh hint instead — npx picks up the newest version on
167
+ its next invocation automatically.
193
168
 
194
- ### Project memory — `REASONIX.md`
169
+ ### Project conventions — `REASONIX.md`
195
170
 
196
171
  Drop a `REASONIX.md` in the project root and its contents are pinned
197
- into the immutable-prefix system prompt every time you launch
198
- `reasonix` in that directory. Good for house conventions, domain
199
- glossary, or things the model keeps forgetting:
172
+ into the system prompt every launch. Committable team memory — house
173
+ conventions, domain glossary, things the model keeps forgetting:
200
174
 
201
175
  ```bash
202
176
  cat > REASONIX.md <<'EOF'
@@ -210,7 +184,7 @@ EOF
210
184
  Re-launch (or `/new`) to pick it up; the prefix is hashed once per
211
185
  session to keep the DeepSeek cache warm. `/memory` prints what's
212
186
  currently pinned. `REASONIX_MEMORY=off` disables every memory source
213
- (REASONIX.md + `~/.reasonix/memory/`) for CI / offline repro.
187
+ for CI / offline repro.
214
188
 
215
189
  ### User memory — `~/.reasonix/memory/`
216
190
 
@@ -218,15 +192,16 @@ A second, **private per-user** memory layer lives under your home
218
192
  directory. Unlike `REASONIX.md` it's never committed, and the model
219
193
  can write to it itself via the `remember` tool. Two scopes:
220
194
 
221
- - `~/.reasonix/memory/global/` — cross-project (your preferences, tooling).
222
- - `~/.reasonix/memory/<project-hash>/` — scoped to one sandbox root in
223
- `reasonix code` (decisions, local facts, per-repo shortcuts).
195
+ - `~/.reasonix/memory/global/` — cross-project (your preferences,
196
+ tooling).
197
+ - `~/.reasonix/memory/<project-hash>/` scoped to one sandbox root
198
+ in `reasonix code` (decisions, local facts, per-repo shortcuts).
224
199
 
225
- Each scope keeps an always-loaded `MEMORY.md` index of one-liners plus
226
- zero or more `<name>.md` detail files (loaded on demand via
200
+ Each scope keeps an always-loaded `MEMORY.md` index of one-liners
201
+ plus zero or more `<name>.md` detail files (loaded on demand via
227
202
  `recall_memory`). Writes land immediately; pinning into the system
228
- prompt takes effect on next `/new` or launch so the cache prefix stays
229
- stable for the current session.
203
+ prompt takes effect on next `/new` or launch so the cache prefix
204
+ stays stable for the current session.
230
205
 
231
206
  ```
232
207
  reasonix code › 我用 bun 而不是 npm,请以后都用 bun 跑构建
@@ -234,142 +209,201 @@ reasonix code › 我用 bun 而不是 npm,请以后都用 bun 跑构建
234
209
  assistant
235
210
  ▸ tool<remember> → project/bun_build saved
236
211
  "Build command on this machine is `bun run build`"
237
-
238
- reasonix code › /memory list
239
- project/project bun_build Build command on this machine is `bun run build`
240
212
  ```
241
213
 
242
- **Slash commands:**
214
+ **Slash**: `/memory` · `/memory list` · `/memory show <name>` ·
215
+ `/memory forget <name>` · `/memory clear <scope> confirm`.
216
+ **Model tools**: `remember(type, scope, name, description, content)` ·
217
+ `forget(scope, name)` · `recall_memory(scope, name)`.
243
218
 
244
- - `/memory` show everything pinned (REASONIX.md + both MEMORY.md scopes)
245
- - `/memory list` every memory file with scope + type + description
246
- - `/memory show <name>` — dump one file's full body
247
- - `/memory forget <name>` — delete one memory (no LLM turn)
248
- - `/memory clear <global|project> confirm` — wipe a scope (typed literal)
219
+ Project scope is only available inside `reasonix code` (needs a real
220
+ sandbox root to hash); plain `reasonix` gets the global scope only.
249
221
 
250
- **Model tools** (available in every session):
222
+ ### Skills user-authored prompt packs
251
223
 
252
- - `remember(type, scope, name, description, content)` save a memory
253
- - `forget(scope, name)` delete it
254
- - `recall_memory(scope, name)` read the full body when the one-liner isn't enough
224
+ Skills are prose instruction blocks you drop on disk. Reasonix pins
225
+ their names + one-line descriptions into the system prompt; the
226
+ model can call `run_skill({name: "..."})` on its own when a match
227
+ fits, or you can type `/skill <name> [args]` to run one manually.
255
228
 
256
- Project scope is only available inside `reasonix code` (there has to be
257
- a real sandbox root to hash); plain `reasonix` / `reasonix chat` gets
258
- the global scope only.
229
+ Two scopes, same layout as user memory:
259
230
 
260
- ```bash
261
- npx reasonix code src/ # narrower sandbox (only src/ is writable)
262
- npx reasonix code --no-session # ephemeral nothing saved to disk
263
- npx reasonix code --preset max # R1 reasoning + 3-way self-consistency
264
- ```
231
+ - `<project>/.reasonix/skills/` — per-project skills (commit them to
232
+ share with your team, or add to `.gitignore` for personal drafts).
233
+ - `~/.reasonix/skills/`global skills available everywhere.
234
+
235
+ Either layout works: `<name>/SKILL.md` (preferred — can bundle
236
+ additional assets alongside) or flat `<name>.md`.
265
237
 
238
+ ```markdown
239
+ ---
240
+ name: review
241
+ description: Review uncommitted changes and flag risks
266
242
  ---
267
243
 
268
- ## Using `reasonix` general chat
244
+ Run `git diff` on staged and unstaged changes. Summarize what each
245
+ hunk does, call out potential regressions, and list files that might
246
+ need additional tests. Don't propose edits unless I ask.
247
+ ```
269
248
 
270
- Same TUI, no filesystem tools unless you opt in via MCP. Good for
271
- drafting, Q&A, schema design, architecture discussions, or driving
272
- your own MCP servers. Sessions persist per name under
273
- `~/.reasonix/sessions/`.
249
+ Use it:
274
250
 
275
- ```bash
276
- npx reasonix # uses saved config + wizard-selected MCP
277
- npx reasonix --preset smart # one-shot override
278
- npx reasonix --session design # named session
279
- npx reasonix --session design # resume it later — history intact
280
251
  ```
252
+ reasonix code › /skill review
253
+ ▸ running skill: review
254
+ assistant
255
+ ▸ tool<run_command> → git diff --cached
256
+ ▸ 3 改动,1 个需要回归测试 …
257
+ ```
258
+
259
+ Or let the model pick autonomously — because the skill's name +
260
+ description are pinned in the prefix, asking "帮我看下未提交的改动有没
261
+ 有风险" triggers `run_skill({name: "review"})` without you typing the
262
+ slash command.
263
+
264
+ **Slash**: `/skill` (list) · `/skill show <name>` · `/skill <name>
265
+ [args]` (inject body as user turn).
266
+
267
+ **Deliberately not tied** to any other client's directory convention
268
+ (`.claude/skills`, etc.) — Reasonix is model-agnostic at the
269
+ conversation layer. Any SKILL.md you author works; the body is
270
+ prose, so skills authored for other tools usually port over unchanged
271
+ (Reasonix's tool names differ — `filesystem` / `shell` / `web` — but
272
+ the model reads the instructions and picks our equivalents).
281
273
 
282
- ### Walkthrough: a multi-turn session with R1 reasoning
274
+ ### Hooks automate around tool calls and turns
283
275
 
276
+ Drop a `settings.json` under `.reasonix/` (project or `~/`) and
277
+ Reasonix will fire shell commands at four well-known points in
278
+ the loop: before a tool runs, after a tool returns, before your
279
+ prompt reaches the model, and after the turn ends.
280
+
281
+ ```json
282
+ // <project>/.reasonix/settings.json ← committable
283
+ // ~/.reasonix/settings.json ← per-user
284
+ {
285
+ "hooks": {
286
+ "PreToolUse": [{ "match": "edit_file|write_file", "command": "bun scripts/guard.ts" }],
287
+ "PostToolUse": [{ "match": "edit_file", "command": "biome format --write" }],
288
+ "UserPromptSubmit": [{ "command": "echo $(date +%s) >> ~/.reasonix/prompts.log" }],
289
+ "Stop": [{ "command": "bun test --run", "timeout": 60000 }]
290
+ }
291
+ }
284
292
  ```
285
- reasonix › /preset smart
286
- ▸ switched to smart · model deepseek-reasoner · harvest on · branch off
287
293
 
288
- reasonix 我要给一个 Flutter 应用设计限时折扣的弹窗展示规则。目标:
289
- 每天首次打开时弹一次,连续弹 3 天后休眠 7 天。怎么实现?
294
+ Each hook is a shell command. Reasonix invokes it with stdin = a
295
+ JSON envelope describing the event:
290
296
 
291
- assistant
292
- R1 reasoning · 2410 chars of thought
293
- subgoals (3): 持久化展示计数 · 判断是否过了 24h · 休眠窗口判断
294
- ‹ hypotheses (2): SharedPreferences 存计数 · lastShownAt 时间戳
295
- ‹ uncertainties (1): 用户换设备后重置的策略
296
-
297
- 建议数据模型:
298
- lastShownAt: DateTime
299
- consecutiveShows: int (0..3)
300
- sleepUntil: DateTime?
301
-
297
+ ```json
298
+ { "event": "PreToolUse", "cwd": "/path/to/project",
299
+ "toolName": "edit_file", "toolArgs": { "path": "src/x.ts", "..." } }
302
300
  ```
303
301
 
304
- `/think` dumps the full R1 thought trace; `/status` shows the current
305
- model / flags / context use; `/retry` re-samples the same prompt with
306
- a fresh random seed (useful when the first answer missed something).
302
+ Exit code drives the decision:
307
303
 
308
- ### Walkthrough: attach MCP tools on the fly
304
+ - **0** pass; loop continues normally
305
+ - **2** — block (only on `PreToolUse` / `UserPromptSubmit`); the
306
+ hook's stderr becomes the synthetic tool result the model sees,
307
+ or the prompt is dropped entirely
308
+ - **anything else** — warn; loop continues, stderr renders as a
309
+ yellow row inline
309
310
 
310
- ```bash
311
- # Attach the official filesystem server sandboxed to /tmp/scratch,
312
- # plus a remote knowledge-base over SSE.
313
- npx reasonix \
314
- --mcp "fs=npx -y @modelcontextprotocol/server-filesystem /tmp/scratch" \
315
- --mcp "kb=https://mcp.example.com/sse"
316
- ```
311
+ `match` is anchored regex on the tool name; `*` or omitted matches
312
+ every tool. Project hooks fire before global hooks. Default
313
+ timeouts: 5s for blocking events, 30s for logging events; per-hook
314
+ `timeout` overrides.
317
315
 
318
- Inside the chat:
316
+ **Slash**: `/hooks` (list active hooks) · `/hooks reload` (re-read
317
+ `settings.json` from disk without losing your session).
319
318
 
320
- ```
321
- reasonix › /mcp
322
- ▸ fs (stdio, 11 tools) fs_read_file · fs_list_directory · fs_write_file · …
323
- ▸ kb (sse, 4 tools) kb_search · kb_get · kb_list_collections · kb_stat
319
+ ### Staying current from inside the TUI
324
320
 
325
- reasonix /tmp/scratch 下把所有 .log 文件里含 "ERROR" 的行收集到 errors.txt
326
- assistant
327
- tool<fs_search_files> 4 matches
328
- tool<fs_read_file> →
329
- tool<fs_write_file> → wrote 2.4 KB to errors.txt
330
- 已写入 errors.txt 38 行,分布在 4 个源文件中。
321
+ `/update` inside a running session shows your current version, the
322
+ last-resolved latest version (from the quiet 24h background check),
323
+ and the shell command to run. The slash does *not* spawn
324
+ `npm install` — stdio:inherit into a running Ink renderer corrupts
325
+ the display. Exit the session and run `reasonix update` in a
326
+ fresh shell when you actually want to install.
327
+
328
+ ---
329
+
330
+ ## `reasonix` — also works as general chat
331
+
332
+ Same TUI, no filesystem tools unless you opt in via MCP. Good for
333
+ drafting, Q&A, schema design, architecture discussions, or driving
334
+ your own MCP servers. Sessions persist per name under
335
+ `~/.reasonix/sessions/`.
336
+
337
+ ```bash
338
+ npx reasonix # uses saved config + wizard-selected MCP
339
+ npx reasonix --preset smart # reasoner + R1 harvest for this run
340
+ npx reasonix --session design # named session — resume later with --session design
331
341
  ```
332
342
 
333
- MCP tools go through the same Cache-First + repair + context-safety
334
- plumbing as native tools, including the 32k result cap and live
335
- progress-notification rendering.
343
+ Bridge your own MCP servers on the fly:
336
344
 
337
- ### When to use `reasonix` vs `reasonix code`
345
+ ```bash
346
+ npx reasonix \
347
+ --mcp "fs=npx -y @modelcontextprotocol/server-filesystem /tmp/safe" \
348
+ --mcp "kb=https://mcp.example.com/sse"
349
+ ```
338
350
 
339
- | situation | command |
340
- |---|---|
341
- | Editing files in the current project | `reasonix code` |
342
- | Exploring a project without writing files | `reasonix code` (it only writes on `/apply`) |
343
- | Design / architecture / research chat | `reasonix` |
344
- | Driving your own MCP servers | `reasonix --mcp "..."` |
345
- | One-shot question, no TUI | `reasonix run "..."` |
346
- | Reproducing a prior session / benchmark | `reasonix replay path.jsonl` |
351
+ MCP tools go through the same Cache-First + repair + context-safety
352
+ plumbing as native tools — 32k result cap, live progress-notification
353
+ rendering, retries.
347
354
 
348
355
  ---
349
356
 
350
357
  ## Commands inside the session
351
358
 
359
+ **Core**
360
+
352
361
  | command | what it does |
353
362
  |---|---|
354
- | `/help` | full command reference with hints |
363
+ | `/help` · `/?` | full command reference with hints |
355
364
  | `/status` | current model · flags · context · session |
365
+ | `/new` · `/reset` | fresh conversation in the same session |
366
+ | `/clear` | clear visible scrollback only (log kept) |
367
+ | `/retry` | truncate and resend your last message (fresh sample) |
368
+ | `/exit` · `/quit` | quit |
369
+
370
+ **Model**
371
+
372
+ | command | what it does |
373
+ |---|---|
356
374
  | `/preset <fast\|smart\|max>` | one-tap bundle (model + harvest + branch) |
357
375
  | `/model <id>` | switch DeepSeek model (`deepseek-chat`, `deepseek-reasoner`) |
358
376
  | `/harvest [on\|off]` | toggle R1 plan-state extraction |
359
377
  | `/branch <N\|off>` | run N parallel samples per turn, pick best (N ≥ 2) |
378
+ | `/think` | dump the last turn's full R1 reasoning |
379
+
380
+ **Context & tools**
381
+
382
+ | command | what it does |
383
+ |---|---|
360
384
  | `/mcp` | list attached MCP servers and their tools |
361
385
  | `/tool [N]` | dump the Nth tool call's full output (1 = latest) |
362
- | `/think` | dump the last turn's full R1 reasoning |
363
- | `/retry` | truncate and resend your last message (fresh sample) |
364
386
  | `/compact [cap]` | shrink oversized tool results in the log |
387
+
388
+ **Memory & skills**
389
+
390
+ | command | what it does |
391
+ |---|---|
392
+ | `/memory` | show pinned memory (REASONIX.md + ~/.reasonix/memory) |
393
+ | `/memory list` · `show <name>` · `forget <name>` · `clear <scope> confirm` | manage the store |
394
+ | `/skill` · `/skill list` | list discovered skills (project + global) |
395
+ | `/skill show <name>` | dump one skill's body |
396
+ | `/skill <name> [args]` | run a skill (inject body as user turn) |
397
+
398
+ **Sessions**
399
+
400
+ | command | what it does |
401
+ |---|---|
365
402
  | `/sessions` | list saved sessions (current marked with `▸`) |
366
403
  | `/forget` | delete the current session from disk |
367
- | `/new` (alias `/reset`) | start a fresh conversation in the same session |
368
- | `/clear` | clear visible scrollback only (log kept) |
369
404
  | `/setup` | reconfigure (exit and run `reasonix setup`) |
370
- | `/exit` | quit |
371
405
 
372
- Additional commands in `reasonix code`:
406
+ **Code mode only** (`reasonix code`)
373
407
 
374
408
  | command | what it does |
375
409
  |---|---|
@@ -377,32 +411,36 @@ Additional commands in `reasonix code`:
377
411
  | `/discard` | drop the pending edit blocks without writing |
378
412
  | `/undo` | roll back the last applied edit batch |
379
413
  | `/commit "msg"` | `git add -A && git commit -m "msg"` |
414
+ | `/plan [on\|off]` | toggle read-only plan mode |
415
+ | `/apply-plan` | force-approve a pending plan |
380
416
 
381
- **Keyboard:**
417
+ **Keyboard**
382
418
 
383
419
  - `Enter` — submit
384
- - `Shift+Enter` / `Ctrl+J` — newline (multi-line paste also supported; `\` + Enter as a portable fallback)
385
- - `↑ / ↓` walk prompt history while idle; navigate slash-autocomplete matches
420
+ - `Shift+Enter` / `Ctrl+J` — newline (multi-line paste also supported;
421
+ `\` + Enter as a portable fallback)
422
+ - `↑` / `↓` — walk prompt history while idle; navigate slash-autocomplete
386
423
  - `Tab` / `Enter` on a `/foo` prefix — accept the highlighted suggestion
387
- - `Esc` — abort the current turn (stops the API call, cancels any in-flight tool, rejects pending MCP requests)
424
+ - `Esc` — abort the current turn (stops the API call, cancels any
425
+ in-flight tool, rejects pending MCP requests)
388
426
  - `y` / `n` on confirm prompts — hotkey accept / reject
389
427
 
390
428
  ---
391
429
 
392
430
  ## Sessions and safety nets
393
431
 
394
- - Sessions live as JSONL under `~/.reasonix/sessions/<name>.jsonl` (per
395
- directory for `reasonix code`). Every message appended atomically; `Ctrl+C`
396
- never loses context.
432
+ - Sessions live as JSONL under `~/.reasonix/sessions/<name>.jsonl`
433
+ (per directory for `reasonix code`). Every message appended
434
+ atomically; `Ctrl+C` never loses context.
397
435
  - Tool results are capped at 32k chars per call. Oversized sessions
398
436
  self-heal on load (shrinks + rewrites the file).
399
437
  - Malformed `assistant.tool_calls` / `tool` pairing is validated on
400
438
  every outgoing API call so a corrupted session can't keep 400ing.
401
- - Context gauge turns yellow at 50%, red at 80% with a `/compact` nudge.
402
- Approaching the 131k window triggers an automatic compaction attempt
403
- before falling back to a forced summary.
404
- - The model's sandbox in `reasonix code` refuses any path that resolves
405
- outside the launch directory, including symlink escape and `..` traversal.
439
+ - Context gauge turns yellow at 50%, red at 80% with a `/compact`
440
+ nudge. Approaching the 131k window triggers an automatic
441
+ compaction attempt before falling back to a forced summary.
442
+ - The `reasonix code` sandbox refuses any path that resolves outside
443
+ the launch directory, including symlink escape and `..` traversal.
406
444
 
407
445
  ### Troubleshooting: duplicate rows / ghost rendering
408
446
 
@@ -416,18 +454,12 @@ If you hit this, run with plain mode:
416
454
 
417
455
  ```bash
418
456
  REASONIX_UI=plain npx reasonix code
419
- # or
420
- REASONIX_UI=plain npx reasonix
421
457
  ```
422
458
 
423
- Plain mode suppresses every live/animated row and disables the
424
- internal tick timer. You lose the streaming preview and spinners
425
- but gain stable scrollback. Committed events (your prompts, tool
426
- results, the model's final responses) still render normally via
427
- Ink's `<Static>` append path.
428
-
429
- Windows Terminal, PowerShell 7 in Windows Terminal, and WezTerm
430
- don't need this opt-out.
459
+ Plain mode suppresses live/animated rows and disables the internal
460
+ tick timer. You lose the streaming preview and spinners but gain
461
+ stable scrollback. Windows Terminal, PowerShell 7 in Windows
462
+ Terminal, and WezTerm don't need this opt-out.
431
463
 
432
464
  ---
433
465
 
@@ -439,19 +471,11 @@ something the model wasn't trained on (new releases, current events,
439
471
  obscure APIs), it decides to call `web_search` on its own; if a
440
472
  snippet isn't enough it follows up with `web_fetch`.
441
473
 
442
- ```
443
- you Flutter 3.19 新加了什么?
444
- assistant
445
- tool<web_search> query: "Flutter 3.19 new features"
446
- tool<web_fetch> https://docs.flutter.dev/release/3-19
447
- ▸ 3.19 主要新增了 …
448
- ```
449
-
450
- Backed by **Mojeek**'s public search page — an independent web index,
451
- no API key, no signup, bot-friendly. Coverage on niche or very recent
452
- queries can be thinner than Google/Bing, but it's reliable from
453
- scripts and doesn't gate on cookies or sessions. (DDG was the original
454
- backend but it started serving anti-bot pages in 2026.)
474
+ Backed by **Mojeek**'s public search page — an independent web
475
+ index, bot-friendly, no cookies/sessions. Coverage on niche or very
476
+ recent queries can be thinner than Google/Bing, but it's reliable
477
+ from scripts. (DDG was the original backend but started serving
478
+ anti-bot pages in 2026.)
455
479
 
456
480
  **Turn it off** (offline mode / privacy / CI):
457
481
 
@@ -461,37 +485,11 @@ backend but it started serving anti-bot pages in 2026.)
461
485
  ```
462
486
 
463
487
  ```bash
464
- # Or one env var (wins over config):
465
- REASONIX_SEARCH=off npx reasonix
488
+ REASONIX_SEARCH=off npx reasonix code
466
489
  ```
467
490
 
468
- **Bring your own provider** (Kagi, SearXNG, Serper, an internal
469
- cache) implement the two tools however you want and register them
470
- manually:
471
-
472
- ```ts
473
- import { ToolRegistry } from "reasonix";
474
- // Register your own `web_search` / `web_fetch` on a ToolRegistry,
475
- // then pass it to CacheFirstLoop (or `reasonix chat --no-config`
476
- // with seedTools via library API).
477
- ```
478
-
479
- Inside the session:
480
-
481
- ```
482
- reasonix › Flutter 3.19 引入了什么新的 Navigator API?
483
- assistant
484
- ▸ tool<web_search> → query: "Flutter 3.19 new Navigator API"
485
- answer: Flutter 3.19 introduces the NavigatorObserver changes …
486
- 1. Flutter 3.19 Release Notes — https://docs.flutter.dev/…
487
- 2. What's new in Flutter 3.19 — https://medium.com/…
488
- ▸ tool<web_fetch> → https://docs.flutter.dev/release/release-notes/3-19-0
489
- (full page text, clipped at 32k)
490
- ▸ 3.19 新增了 …
491
- ```
492
-
493
- For advanced / self-hosted search (Kagi, SearXNG, internal caches)
494
- implement the `WebSearchProvider` interface and call
491
+ **Bring your own** (Kagi, SearXNG, internal caches): implement the
492
+ `WebSearchProvider` interface and call
495
493
  `registerWebTools(registry, { provider })` yourself, or bridge an
496
494
  existing MCP search server via `--mcp`.
497
495
 
@@ -499,14 +497,14 @@ existing MCP search server via `--mcp`.
499
497
 
500
498
  ## MCP — bring your own tools
501
499
 
502
- Any [MCP](https://spec.modelcontextprotocol.io/) server works. Wizard
503
- lets you pick from a catalog, or drive it by flag:
500
+ Any [MCP](https://spec.modelcontextprotocol.io/) server works. The
501
+ wizard lets you pick from a catalog, or drive it by flag:
504
502
 
505
503
  ```bash
506
504
  # stdio (local subprocess)
507
505
  npx reasonix --mcp "fs=npx -y @modelcontextprotocol/server-filesystem /tmp/safe"
508
506
 
509
- # multiple servers at once
507
+ # multiple at once
510
508
  npx reasonix \
511
509
  --mcp "fs=npx -y @modelcontextprotocol/server-filesystem /tmp/safe" \
512
510
  --mcp "demo=npx tsx examples/mcp-server-demo.ts"
@@ -515,21 +513,22 @@ npx reasonix \
515
513
  npx reasonix --mcp "kb=https://mcp.example.com/sse"
516
514
  ```
517
515
 
518
- `reasonix mcp list` shows the curated catalog. `reasonix mcp inspect <spec>`
519
- connects once and dumps the server's tools / resources / prompts without
520
- starting a chat. Progress notifications from long-running tools (2025-03-26
521
- spec) render live as a progress bar in the spinner.
516
+ `reasonix mcp list` shows the curated catalog. `reasonix mcp inspect
517
+ <spec>` connects once and dumps the server's tools / resources /
518
+ prompts without starting a chat. Progress notifications from
519
+ long-running tools (2025-03-26 spec) render live as a progress bar
520
+ in the spinner.
522
521
 
523
- Supported transports: **stdio** (local command) and **HTTP+SSE** (remote,
524
- MCP 2024-11-05 spec).
522
+ Supported transports: **stdio** (local command) and **HTTP+SSE**
523
+ (remote, MCP 2024-11-05 spec).
525
524
 
526
525
  ---
527
526
 
528
527
  ## CLI reference
529
528
 
530
529
  ```bash
531
- npx reasonix # chat (uses saved config)
532
530
  npx reasonix code [path] # coding mode scoped to path (default: cwd)
531
+ npx reasonix # chat (uses saved config)
533
532
  npx reasonix setup # reconfigure the wizard
534
533
  npx reasonix chat --session work # named session
535
534
  npx reasonix chat --no-session # ephemeral
@@ -561,6 +560,9 @@ Env vars (win over config):
561
560
  ```bash
562
561
  export DEEPSEEK_API_KEY=sk-...
563
562
  export DEEPSEEK_BASE_URL=https://... # optional alternate endpoint
563
+ export REASONIX_MEMORY=off # disable REASONIX.md + user memory
564
+ export REASONIX_SEARCH=off # disable web_search / web_fetch
565
+ export REASONIX_UI=plain # disable live rows (ghosting workaround)
564
566
  ```
565
567
 
566
568
  ---
@@ -606,13 +608,14 @@ for await (const ev of loop.step("What is 17 + 25?")) {
606
608
  console.log(loop.stats.summary());
607
609
  ```
608
610
 
609
- `ChatOptions.seedTools` accepts a pre-built `ToolRegistry` for callers
610
- who want the `reasonix code` loop wiring without the CLI wrapper.
611
- See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for internals.
611
+ `ChatOptions.seedTools` accepts a pre-built `ToolRegistry` for
612
+ callers who want the `reasonix code` loop wiring without the CLI
613
+ wrapper. See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for
614
+ internals.
612
615
 
613
616
  ---
614
617
 
615
- ## Why Reasonix (not LangChain)
618
+ ## Benchmarks verify the cache-hit claim yourself
616
619
 
617
620
  Every abstraction here earns its weight against a DeepSeek-specific
618
621
  property — dirt-cheap tokens, R1 reasoning traces, automatic prefix
@@ -626,11 +629,10 @@ caching, JSON mode. Generic wrappers leave these on the table.
626
629
  | Scavenge tool calls leaked into `<think>` | yes | no |
627
630
  | Call-storm breaker on identical-arg repeats | yes | no |
628
631
  | Live cache-hit / cost / vs-Claude panel | yes | no |
629
- | First-run config prompt + Markdown TUI | yes | no |
630
632
 
631
633
  On the same τ-bench-lite workload — 8 multi-turn tool-use tasks × 3
632
- repeats = 48 runs per side, live DeepSeek `deepseek-chat`, sole variable
633
- prefix stability:
634
+ repeats = 48 runs per side, live DeepSeek `deepseek-chat`, sole
635
+ variable prefix stability:
634
636
 
635
637
  | metric | baseline (cache-hostile) | Reasonix | delta |
636
638
  |---|---:|---:|---:|
@@ -638,7 +640,7 @@ prefix stability:
638
640
  | cost / task | $0.002599 | $0.001579 | **−39%** |
639
641
  | pass rate | 96% (23/24) | **100% (24/24)** | — |
640
642
 
641
- **Verify it yourself no API key, zero cost:**
643
+ **Reproduce without spending an API credit:**
642
644
 
643
645
  ```bash
644
646
  git clone https://github.com/esengine/reasonix.git && cd reasonix && npm install
@@ -654,8 +656,10 @@ model call; baseline's churns on every turn. The cache delta is
654
656
  *mechanically* attributable to log stability, not to a different
655
657
  system prompt.
656
658
 
657
- Full 48-run report: [`benchmarks/tau-bench/report.md`](./benchmarks/tau-bench/report.md).
658
- Reproduce with your own API key: `npx tsx benchmarks/tau-bench/runner.ts --repeats 3`.
659
+ Full 48-run report:
660
+ [`benchmarks/tau-bench/report.md`](./benchmarks/tau-bench/report.md).
661
+ Reproduce with your own API key: `npx tsx
662
+ benchmarks/tau-bench/runner.ts --repeats 3`.
659
663
 
660
664
  MCP reference runs (one single prefix hash across all 5 turns even
661
665
  with two concurrent MCP subprocesses):
@@ -670,10 +674,16 @@ with two concurrent MCP subprocesses):
670
674
 
671
675
  ## Non-goals
672
676
 
673
- - Multi-agent orchestration (use LangGraph).
674
- - RAG / vector stores (use LlamaIndex).
675
- - Multi-provider abstraction (use LiteLLM).
676
- - Web UI / SaaS.
677
+ - **Multi-agent orchestration / sub-agents** (use LangGraph).
678
+ - **Workflow DSL / DAG scheduler / parallel-branch engine** — skills
679
+ are prose; the model sequences via the normal tool-use loop.
680
+ Keeps single-loop + append-only + cache-first invariants intact.
681
+ - **Multi-provider abstraction** (use LiteLLM). Reasonix is
682
+ DeepSeek-only on purpose — every pillar (cache-first loop, R1
683
+ harvesting, tool-call repair) is tuned against DeepSeek-specific
684
+ behavior and economics. Coupling to one backend is the feature.
685
+ - **RAG / vector stores** (use LlamaIndex).
686
+ - **Web UI / SaaS.**
677
687
 
678
688
  Reasonix does DeepSeek, deeply.
679
689
 
@@ -685,9 +695,9 @@ Reasonix does DeepSeek, deeply.
685
695
  git clone https://github.com/esengine/reasonix.git
686
696
  cd reasonix
687
697
  npm install
688
- npm run dev chat # run CLI from source via tsx
698
+ npm run dev code # run CLI from source via tsx
689
699
  npm run build # tsup to dist/
690
- npm test # vitest (444 tests)
700
+ npm test # vitest (648 tests)
691
701
  npm run lint # biome
692
702
  npm run typecheck # tsc --noEmit
693
703
  ```