reasonix 0.4.21 → 0.4.22

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
- });
50
+ ▸ 1 pending edit across 1 file — /apply to write · /discard to drop
91
51
 
92
- it("is case-insensitive", () => {
93
- expect(findByEmail("A@B.COM")).toBeDefined();
94
- });
95
- >>>>>>> REPLACE
96
-
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:
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.
102
59
 
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.
109
-
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,38 +209,71 @@ 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
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`.
237
+
238
+ ```markdown
239
+ ---
240
+ name: review
241
+ description: Review uncommitted changes and flag risks
242
+ ---
243
+
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
+ ```
248
+
249
+ Use it:
250
+
251
+ ```
252
+ reasonix code › /skill review
253
+ ▸ running skill: review
254
+ assistant
255
+ ▸ tool<run_command> → git diff --cached
256
+ ▸ 3 改动,1 个需要回归测试 …
264
257
  ```
265
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).
273
+
266
274
  ---
267
275
 
268
- ## Using `reasonix` — general chat
276
+ ## `reasonix` — also works as general chat
269
277
 
270
278
  Same TUI, no filesystem tools unless you opt in via MCP. Good for
271
279
  drafting, Q&A, schema design, architecture discussions, or driving
@@ -274,102 +282,74 @@ your own MCP servers. Sessions persist per name under
274
282
 
275
283
  ```bash
276
284
  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
- ```
281
-
282
- ### Walkthrough: a multi-turn session with R1 reasoning
283
-
285
+ npx reasonix --preset smart # reasoner + R1 harvest for this run
286
+ npx reasonix --session design # named session — resume later with --session design
284
287
  ```
285
- reasonix › /preset smart
286
- ▸ switched to smart · model deepseek-reasoner · harvest on · branch off
287
288
 
288
- reasonix 我要给一个 Flutter 应用设计限时折扣的弹窗展示规则。目标:
289
- 每天首次打开时弹一次,连续弹 3 天后休眠 7 天。怎么实现?
290
-
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
-
302
- ```
303
-
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).
307
-
308
- ### Walkthrough: attach MCP tools on the fly
289
+ Bridge your own MCP servers on the fly:
309
290
 
310
291
  ```bash
311
- # Attach the official filesystem server sandboxed to /tmp/scratch,
312
- # plus a remote knowledge-base over SSE.
313
292
  npx reasonix \
314
- --mcp "fs=npx -y @modelcontextprotocol/server-filesystem /tmp/scratch" \
293
+ --mcp "fs=npx -y @modelcontextprotocol/server-filesystem /tmp/safe" \
315
294
  --mcp "kb=https://mcp.example.com/sse"
316
295
  ```
317
296
 
318
- Inside the chat:
319
-
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
324
-
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 个源文件中。
331
- ```
332
-
333
297
  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.
336
-
337
- ### When to use `reasonix` vs `reasonix code`
338
-
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` |
298
+ plumbing as native tools 32k result cap, live progress-notification
299
+ rendering, retries.
347
300
 
348
301
  ---
349
302
 
350
303
  ## Commands inside the session
351
304
 
305
+ **Core**
306
+
352
307
  | command | what it does |
353
308
  |---|---|
354
- | `/help` | full command reference with hints |
309
+ | `/help` · `/?` | full command reference with hints |
355
310
  | `/status` | current model · flags · context · session |
311
+ | `/new` · `/reset` | fresh conversation in the same session |
312
+ | `/clear` | clear visible scrollback only (log kept) |
313
+ | `/retry` | truncate and resend your last message (fresh sample) |
314
+ | `/exit` · `/quit` | quit |
315
+
316
+ **Model**
317
+
318
+ | command | what it does |
319
+ |---|---|
356
320
  | `/preset <fast\|smart\|max>` | one-tap bundle (model + harvest + branch) |
357
321
  | `/model <id>` | switch DeepSeek model (`deepseek-chat`, `deepseek-reasoner`) |
358
322
  | `/harvest [on\|off]` | toggle R1 plan-state extraction |
359
323
  | `/branch <N\|off>` | run N parallel samples per turn, pick best (N ≥ 2) |
324
+ | `/think` | dump the last turn's full R1 reasoning |
325
+
326
+ **Context & tools**
327
+
328
+ | command | what it does |
329
+ |---|---|
360
330
  | `/mcp` | list attached MCP servers and their tools |
361
331
  | `/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
332
  | `/compact [cap]` | shrink oversized tool results in the log |
333
+
334
+ **Memory & skills**
335
+
336
+ | command | what it does |
337
+ |---|---|
338
+ | `/memory` | show pinned memory (REASONIX.md + ~/.reasonix/memory) |
339
+ | `/memory list` · `show <name>` · `forget <name>` · `clear <scope> confirm` | manage the store |
340
+ | `/skill` · `/skill list` | list discovered skills (project + global) |
341
+ | `/skill show <name>` | dump one skill's body |
342
+ | `/skill <name> [args]` | run a skill (inject body as user turn) |
343
+
344
+ **Sessions**
345
+
346
+ | command | what it does |
347
+ |---|---|
365
348
  | `/sessions` | list saved sessions (current marked with `▸`) |
366
349
  | `/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
350
  | `/setup` | reconfigure (exit and run `reasonix setup`) |
370
- | `/exit` | quit |
371
351
 
372
- Additional commands in `reasonix code`:
352
+ **Code mode only** (`reasonix code`)
373
353
 
374
354
  | command | what it does |
375
355
  |---|---|
@@ -377,32 +357,36 @@ Additional commands in `reasonix code`:
377
357
  | `/discard` | drop the pending edit blocks without writing |
378
358
  | `/undo` | roll back the last applied edit batch |
379
359
  | `/commit "msg"` | `git add -A && git commit -m "msg"` |
360
+ | `/plan [on\|off]` | toggle read-only plan mode |
361
+ | `/apply-plan` | force-approve a pending plan |
380
362
 
381
- **Keyboard:**
363
+ **Keyboard**
382
364
 
383
365
  - `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
366
+ - `Shift+Enter` / `Ctrl+J` — newline (multi-line paste also supported;
367
+ `\` + Enter as a portable fallback)
368
+ - `↑` / `↓` — walk prompt history while idle; navigate slash-autocomplete
386
369
  - `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)
370
+ - `Esc` — abort the current turn (stops the API call, cancels any
371
+ in-flight tool, rejects pending MCP requests)
388
372
  - `y` / `n` on confirm prompts — hotkey accept / reject
389
373
 
390
374
  ---
391
375
 
392
376
  ## Sessions and safety nets
393
377
 
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.
378
+ - Sessions live as JSONL under `~/.reasonix/sessions/<name>.jsonl`
379
+ (per directory for `reasonix code`). Every message appended
380
+ atomically; `Ctrl+C` never loses context.
397
381
  - Tool results are capped at 32k chars per call. Oversized sessions
398
382
  self-heal on load (shrinks + rewrites the file).
399
383
  - Malformed `assistant.tool_calls` / `tool` pairing is validated on
400
384
  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.
385
+ - Context gauge turns yellow at 50%, red at 80% with a `/compact`
386
+ nudge. Approaching the 131k window triggers an automatic
387
+ compaction attempt before falling back to a forced summary.
388
+ - The `reasonix code` sandbox refuses any path that resolves outside
389
+ the launch directory, including symlink escape and `..` traversal.
406
390
 
407
391
  ### Troubleshooting: duplicate rows / ghost rendering
408
392
 
@@ -416,18 +400,12 @@ If you hit this, run with plain mode:
416
400
 
417
401
  ```bash
418
402
  REASONIX_UI=plain npx reasonix code
419
- # or
420
- REASONIX_UI=plain npx reasonix
421
403
  ```
422
404
 
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.
405
+ Plain mode suppresses live/animated rows and disables the internal
406
+ tick timer. You lose the streaming preview and spinners but gain
407
+ stable scrollback. Windows Terminal, PowerShell 7 in Windows
408
+ Terminal, and WezTerm don't need this opt-out.
431
409
 
432
410
  ---
433
411
 
@@ -439,19 +417,11 @@ something the model wasn't trained on (new releases, current events,
439
417
  obscure APIs), it decides to call `web_search` on its own; if a
440
418
  snippet isn't enough it follows up with `web_fetch`.
441
419
 
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.)
420
+ Backed by **Mojeek**'s public search page — an independent web
421
+ index, bot-friendly, no cookies/sessions. Coverage on niche or very
422
+ recent queries can be thinner than Google/Bing, but it's reliable
423
+ from scripts. (DDG was the original backend but started serving
424
+ anti-bot pages in 2026.)
455
425
 
456
426
  **Turn it off** (offline mode / privacy / CI):
457
427
 
@@ -461,37 +431,11 @@ backend but it started serving anti-bot pages in 2026.)
461
431
  ```
462
432
 
463
433
  ```bash
464
- # Or one env var (wins over config):
465
- REASONIX_SEARCH=off npx reasonix
466
- ```
467
-
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).
434
+ REASONIX_SEARCH=off npx reasonix code
477
435
  ```
478
436
 
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
437
+ **Bring your own** (Kagi, SearXNG, internal caches): implement the
438
+ `WebSearchProvider` interface and call
495
439
  `registerWebTools(registry, { provider })` yourself, or bridge an
496
440
  existing MCP search server via `--mcp`.
497
441
 
@@ -499,14 +443,14 @@ existing MCP search server via `--mcp`.
499
443
 
500
444
  ## MCP — bring your own tools
501
445
 
502
- Any [MCP](https://spec.modelcontextprotocol.io/) server works. Wizard
503
- lets you pick from a catalog, or drive it by flag:
446
+ Any [MCP](https://spec.modelcontextprotocol.io/) server works. The
447
+ wizard lets you pick from a catalog, or drive it by flag:
504
448
 
505
449
  ```bash
506
450
  # stdio (local subprocess)
507
451
  npx reasonix --mcp "fs=npx -y @modelcontextprotocol/server-filesystem /tmp/safe"
508
452
 
509
- # multiple servers at once
453
+ # multiple at once
510
454
  npx reasonix \
511
455
  --mcp "fs=npx -y @modelcontextprotocol/server-filesystem /tmp/safe" \
512
456
  --mcp "demo=npx tsx examples/mcp-server-demo.ts"
@@ -515,21 +459,22 @@ npx reasonix \
515
459
  npx reasonix --mcp "kb=https://mcp.example.com/sse"
516
460
  ```
517
461
 
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.
462
+ `reasonix mcp list` shows the curated catalog. `reasonix mcp inspect
463
+ <spec>` connects once and dumps the server's tools / resources /
464
+ prompts without starting a chat. Progress notifications from
465
+ long-running tools (2025-03-26 spec) render live as a progress bar
466
+ in the spinner.
522
467
 
523
- Supported transports: **stdio** (local command) and **HTTP+SSE** (remote,
524
- MCP 2024-11-05 spec).
468
+ Supported transports: **stdio** (local command) and **HTTP+SSE**
469
+ (remote, MCP 2024-11-05 spec).
525
470
 
526
471
  ---
527
472
 
528
473
  ## CLI reference
529
474
 
530
475
  ```bash
531
- npx reasonix # chat (uses saved config)
532
476
  npx reasonix code [path] # coding mode scoped to path (default: cwd)
477
+ npx reasonix # chat (uses saved config)
533
478
  npx reasonix setup # reconfigure the wizard
534
479
  npx reasonix chat --session work # named session
535
480
  npx reasonix chat --no-session # ephemeral
@@ -561,6 +506,9 @@ Env vars (win over config):
561
506
  ```bash
562
507
  export DEEPSEEK_API_KEY=sk-...
563
508
  export DEEPSEEK_BASE_URL=https://... # optional alternate endpoint
509
+ export REASONIX_MEMORY=off # disable REASONIX.md + user memory
510
+ export REASONIX_SEARCH=off # disable web_search / web_fetch
511
+ export REASONIX_UI=plain # disable live rows (ghosting workaround)
564
512
  ```
565
513
 
566
514
  ---
@@ -606,13 +554,14 @@ for await (const ev of loop.step("What is 17 + 25?")) {
606
554
  console.log(loop.stats.summary());
607
555
  ```
608
556
 
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.
557
+ `ChatOptions.seedTools` accepts a pre-built `ToolRegistry` for
558
+ callers who want the `reasonix code` loop wiring without the CLI
559
+ wrapper. See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for
560
+ internals.
612
561
 
613
562
  ---
614
563
 
615
- ## Why Reasonix (not LangChain)
564
+ ## Benchmarks verify the cache-hit claim yourself
616
565
 
617
566
  Every abstraction here earns its weight against a DeepSeek-specific
618
567
  property — dirt-cheap tokens, R1 reasoning traces, automatic prefix
@@ -626,11 +575,10 @@ caching, JSON mode. Generic wrappers leave these on the table.
626
575
  | Scavenge tool calls leaked into `<think>` | yes | no |
627
576
  | Call-storm breaker on identical-arg repeats | yes | no |
628
577
  | Live cache-hit / cost / vs-Claude panel | yes | no |
629
- | First-run config prompt + Markdown TUI | yes | no |
630
578
 
631
579
  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:
580
+ repeats = 48 runs per side, live DeepSeek `deepseek-chat`, sole
581
+ variable prefix stability:
634
582
 
635
583
  | metric | baseline (cache-hostile) | Reasonix | delta |
636
584
  |---|---:|---:|---:|
@@ -638,7 +586,7 @@ prefix stability:
638
586
  | cost / task | $0.002599 | $0.001579 | **−39%** |
639
587
  | pass rate | 96% (23/24) | **100% (24/24)** | — |
640
588
 
641
- **Verify it yourself no API key, zero cost:**
589
+ **Reproduce without spending an API credit:**
642
590
 
643
591
  ```bash
644
592
  git clone https://github.com/esengine/reasonix.git && cd reasonix && npm install
@@ -654,8 +602,10 @@ model call; baseline's churns on every turn. The cache delta is
654
602
  *mechanically* attributable to log stability, not to a different
655
603
  system prompt.
656
604
 
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`.
605
+ Full 48-run report:
606
+ [`benchmarks/tau-bench/report.md`](./benchmarks/tau-bench/report.md).
607
+ Reproduce with your own API key: `npx tsx
608
+ benchmarks/tau-bench/runner.ts --repeats 3`.
659
609
 
660
610
  MCP reference runs (one single prefix hash across all 5 turns even
661
611
  with two concurrent MCP subprocesses):
@@ -670,10 +620,16 @@ with two concurrent MCP subprocesses):
670
620
 
671
621
  ## Non-goals
672
622
 
673
- - Multi-agent orchestration (use LangGraph).
674
- - RAG / vector stores (use LlamaIndex).
675
- - Multi-provider abstraction (use LiteLLM).
676
- - Web UI / SaaS.
623
+ - **Multi-agent orchestration / sub-agents** (use LangGraph).
624
+ - **Workflow DSL / DAG scheduler / parallel-branch engine** — skills
625
+ are prose; the model sequences via the normal tool-use loop.
626
+ Keeps single-loop + append-only + cache-first invariants intact.
627
+ - **Multi-provider abstraction** (use LiteLLM). Reasonix is
628
+ DeepSeek-only on purpose — every pillar (cache-first loop, R1
629
+ harvesting, tool-call repair) is tuned against DeepSeek-specific
630
+ behavior and economics. Coupling to one backend is the feature.
631
+ - **RAG / vector stores** (use LlamaIndex).
632
+ - **Web UI / SaaS.**
677
633
 
678
634
  Reasonix does DeepSeek, deeply.
679
635
 
@@ -685,9 +641,9 @@ Reasonix does DeepSeek, deeply.
685
641
  git clone https://github.com/esengine/reasonix.git
686
642
  cd reasonix
687
643
  npm install
688
- npm run dev chat # run CLI from source via tsx
644
+ npm run dev code # run CLI from source via tsx
689
645
  npm run build # tsup to dist/
690
- npm test # vitest (444 tests)
646
+ npm test # vitest (648 tests)
691
647
  npm run lint # biome
692
648
  npm run typecheck # tsc --noEmit
693
649
  ```