返回 CodeWhale
CHANGELOG_ARCHIVE.md
根目录 / docs / CHANGELOG_ARCHIVE.md
1 # Changelog Archive
2
3 Older releases of CodeWhale (v0.8.39 and earlier). Recent releases live in [CHANGELOG.md](../CHANGELOG.md).
4
5 ## [0.8.39] - 2026-05-17
6
7 ### Fixed
8
9 - **Feishu/Lark bridge startup order is guarded.** The bridge now keeps
10 `ThreadStore` initialized before startup opens persisted thread state, with a
11 regression test to prevent moving it below its first use.
12 - **`/model` picker opens instantly with the curated list again.** Reverted
13 the v0.8.38 live-catalog rework: the picker no longer makes a blocking
14 network call on open and once again shows the curated `auto` /
15 `deepseek-v4-pro` / `deepseek-v4-flash` rows. The `/models` command still
16 lists the live provider catalog.
17 - **"Approve for session" groups by command family again.** Session approvals
18 are keyed by a lossy, arity-aware fingerprint once more, so approving
19 `cargo build` also covers `cargo build --release`. Denials keep the exact
20 per-call fingerprint from #1617, so denying one call no longer over-blocks
21 later, different calls to the same tool.
22 - **Docker first-run state directories are writable.** The image now
23 pre-creates `/home/deepseek/.deepseek` with `deepseek` ownership so the
24 documented named-volume launch can create runtime thread state on first use
25 (#1684).
26 - **Runtime API system prompt overrides survive the first turn.** Threads
27 created with a `system_prompt` override now keep that prompt through
28 mode/context refreshes before the model request is built (#1688).
29 - **Compaction keeps a user text query in tool-heavy histories.** Automatic
30 compaction now pins the latest user text message when the retained tail only
31 contains tool calls/results, avoiding OpenAI-compatible Jinja template
32 failures on the next request (#1704).
33 - **Pager jumps land at the visible bottom.** Pressing `G` or End in the pager
34 no longer overshoots the render clamp, so `k`/Up scrolls upward immediately
35 afterward, and mouse wheels now scroll pager overlays directly (#1706,
36 #1716).
37 - **Mouse-wheel-as-arrow scrolling preserves composer drafts.** When
38 `composer_arrows_scroll` is enabled, Up/Down now scroll the transcript even
39 with text in the composer instead of replacing the draft with input history
40 (#1677).
41 - **Multiline composer arrows move between input lines.** Plain Up/Down now
42 move the cursor within multiline drafts before falling back to input history,
43 while single-line mouse-wheel-as-arrow scrolling remains unchanged (#1721).
44 - **Third-party `reasoning_content` streams no longer corrupt text output.**
45 Generic OpenAI-compatible providers that stream answer text in
46 `reasoning_content` now render it as normal text unless the selected provider
47 is one whose reasoning-content semantics are supported (#1673).
48 - **macOS system theme detection recognizes Light mode.** When `COLORFGBG` is
49 missing or unusable, `theme = "system"` now falls back to macOS appearance
50 detection and treats a missing `AppleInterfaceStyle` key as Light mode
51 (#1670).
52 - **`rlm_open` accepts schema-filled blank source fields.** Empty `file_path`,
53 `content`, and `url` strings now count as absent, so calls that provide one
54 real source no longer fail the exactly-one-source validator (#1712).
55 - **Resize keeps transcript paging usable immediately.** After a terminal
56 resize, PageUp/PageDown now use the resized viewport height instead of
57 falling back to one-line jumps before the next render (#1724).
58 - **ACP responses stringify JSON-RPC ids.** `serve --acp` now returns string
59 ids even when clients send numeric ids, matching Zed's stricter ACP client
60 expectations (#1696).
61
62 ### Thanks
63
64 Thanks to **Matt Van Horn ([@mvanhorn](https://github.com/mvanhorn))** for the
65 Docker first-run permission fix in #1699 and the runtime system-prompt
66 regression tests harvested from #1702. Thanks to **Kristopher Clark
67 ([@krisclarkdev](https://github.com/krisclarkdev))** for the compaction
68 user-query preservation fix in #1704. Thanks to **Stephen Xu
69 ([@wlon](https://github.com/wlon))** for the pager jump-bottom fix in #1706.
70 Thanks to **tdccccc ([@tdccccc](https://github.com/tdccccc))** for the
71 composer scroll fix in #1715 and pager mouse-wheel support in #1716.
72 Thanks to **Paulo Aboim Pinto
73 ([@aboimpinto](https://github.com/aboimpinto))** for the multiline composer
74 arrow navigation tests harvested from #1719. Thanks to **LittleBlacky
75 ([@LittleBlacky](https://github.com/LittleBlacky))** for the provider-gated
76 `reasoning_content` stream fix in #1680.
77 Thanks to **Eosin Ai ([@Aitensa](https://github.com/Aitensa))** for the macOS
78 system appearance fallback in #1674.
79 Thanks to **Anaheim ([@AnaheimEX](https://github.com/AnaheimEX))** for the
80 `rlm_open` schema validation report in #1712.
81 Thanks to **THatch26 ([@THatch26](https://github.com/THatch26))** for the
82 terminal resize paging fix in #1724.
83 Thanks to **Alvin ([@alvin1](https://github.com/alvin1))** for the Zed ACP id
84 compatibility report in #1696.
85
86 ## [0.8.38] - 2026-05-15
87
88 ### Changed
89
90 - **Update guidance is clearer on the website.** The homepage and install page
91 now surface `deepseek update` while keeping package-manager update paths
92 visible for Homebrew, npm, and Cargo installs.
93 - **README setup docs are current again.** The English, Simplified Chinese,
94 and Japanese READMEs now use the current Docker volume/workspace invocation,
95 document update paths, list the current provider/model switching surface, and
96 send release-specific feature notes back to the changelog.
97
98 ### Fixed
99
100 - **OpenAI-compatible providers receive stricter request bodies.** Fireworks
101 requests now use `reasoning_effort` without the DeepSeek/Anthropic-style
102 top-level `thinking` field, and chat tool schemas no longer include
103 Anthropic-only metadata such as `allowed_callers`, `defer_loading`, or
104 `input_examples` (#1592).
105 - **pnpm global installs no longer hang in optional postinstall.** pnpm
106 postinstall now skips install-time binary downloads and leaves the existing
107 runtime downloader to verify or fetch binaries on first run (#1637).
108 - **Terminal modes are restored on early TUI exits.** A cleanup guard now
109 restores raw mode, alternate screen, focus events, mouse capture, bracketed
110 paste, keyboard flags, and cursor visibility if startup returns early after
111 terminal initialization (#1593, #1582).
112 - **Wrapped OSC 8 links keep their full target.** Long clickable URLs now
113 reopen the original full link target on each wrapped visual chunk instead of
114 exposing truncated hyperlink targets (#1577).
115 - **Provider-selected models survive startup and picker reselects.** The
116 `/model` picker now uses live provider model catalogs when available, saved
117 default providers sync into the runtime config before the first request, and
118 reselecting the active provider from the picker keeps the current model
119 instead of falling back to the provider default (#1632).
120 - **OpenAI-compatible batch tool calls keep all start events.** Streaming
121 responses with multiple `tool_calls` in one assistant message now preserve
122 every tool-use block instead of pairing many tool results with only the last
123 tool start event (#1686).
124 - **Diagnostics tool schemas include an empty `required` list.** The built-in
125 `diagnostics` tool now sends `required: []` with its empty object schema so
126 DeepSeek no longer rejects it as a null required array (#1685).
127 - **Windows wheel-as-arrow scrolling works with mouse capture enabled.**
128 `composer_arrows_scroll` now defaults on for Windows terminals even when
129 mouse capture is enabled, so wheel events that arrive as arrow keys scroll the
130 transcript instead of cycling composer history (#1578).
131 - **Plain Windows PowerShell / ConHost uses calmer rendering.** Unmarked
132 legacy Windows console hosts now automatically enable low-motion rendering,
133 disable fancy animations, and resolve `synchronized_output = "auto"` to off
134 so streaming redraws do not overlap or visibly flicker (#1590).
135 - **LoopGuard blocks now count as failed tool calls.** Identical tool-call
136 blocks now return a failed tool result instead of a success, so repeated
137 blocked checklist/tool retries can trip the existing failure warning and halt
138 path instead of spinning indefinitely (#1574).
139 - **Denied tool approvals are scoped to the exact call.** Denying one
140 write/shell approval now caches the canonical argument fingerprint instead of
141 a lossy tool/prefix key, so later calls to the same tool with different
142 arguments can still be reviewed and approved (#1617).
143
144 ### Thanks
145
146 Thanks to **DC ([@duanchao-lab](https://github.com/duanchao-lab))** for the
147 terminal cleanup-guard idea harvested from #1630, and **imkingjh999
148 ([@imkingjh999](https://github.com/imkingjh999))** for the provider/model
149 switching fixes harvested from #1642. Thanks to **Photo
150 ([@eng2007](https://github.com/eng2007))** for the provider-aware `/model`
151 picker catalog work harvested from #1201. Thanks to **hexin
152 ([@h3c-hexin](https://github.com/h3c-hexin))** for the OpenAI batch tool-call
153 streaming fix in #1686. Thanks to **chennest
154 ([@chennest](https://github.com/chennest))** for the diagnostics schema report
155 in #1685. Thanks to
156 **[@kunpeng-ai-lab](https://github.com/kunpeng-ai-lab)** for the Windows
157 composer scroll fix harvested from #1578, and **WuMing
158 ([@asdfg314284230](https://github.com/asdfg314284230))** for the Windows
159 PowerShell flicker fix harvested from #1591. Thanks to
160 **[@maker316](https://github.com/maker316)** for the LoopGuard/checklist loop
161 report in #1574. Thanks to **lalala
162 ([@lalala-233](https://github.com/lalala-233))** for the approval denial
163 regression report in #1617, and **Nightt
164 ([@nightt5879](https://github.com/nightt5879))** for the exact-call approval
165 key work harvested from #1624.
166
167 ## [0.8.37] - 2026-05-14
168
169 ### Added
170
171 - **Tencent Lighthouse + Feishu/Lark bridge setup.** Added a `/opt/whalebro`
172 Lighthouse runbook, systemd deploy assets, a long-connection Feishu/Lark
173 bridge, a bridge config validator, and a VPS doctor for runtime, Node,
174 binaries, env, systemd, and localhost health checks.
175 - **Tencent Cloud remote-first onboarding.** Documented the CNB + Lighthouse +
176 Feishu/Lark + optional EdgeOne teaching path and added non-active CNB deploy
177 templates for a future Lighthouse deploy button. Feishu/Lighthouse branches
178 are now mirrored to CNB for Tencent-first bootstrap.
179 - **Homebrew tap automation is release-gated.** The release workflow can update
180 `Hmbown/homebrew-deepseek-tui` from the checksum manifest when a tap token is
181 configured, and skips cleanly before downloading release assets when no tap
182 token exists.
183
184 ### Changed
185
186 - **Bing is the default `web_search` backend.** DuckDuckGo remains selectable
187 with `[search] provider = "duckduckgo"` and keeps its Bing fallback path.
188
189 ### Fixed
190
191 - **First-run onboarding stays usable without an API key.** Missing-key startup
192 no longer aborts the TUI before onboarding can collect provider settings.
193 - **Streamable HTTP MCP sessions keep their server-issued session ID.** Custom
194 headers also apply to GET preflight requests, fixing authenticated MCP
195 servers that require both.
196 - **DeepSeek model completions use canonical IDs.** Alias completions now
197 resolve to stable DeepSeek model names before being written to config.
198 - **Terminal and child-process reliability is tighter.** Signal shutdown now
199 restores the terminal, child tasks preserve proxy environment variables, and
200 Windows Enter / CSI-u input handling avoids the prior event mismatch.
201 - **Long terminal text wraps instead of overflowing.** Streaming output, diff
202 rendering, and the pager now hard-wrap overlong no-whitespace and CJK runs.
203 - **Release and platform edges are safer.** The TUI no longer trips the Windows
204 Instant-underflow test path, unsupported desktop targets compile the external
205 URL opener, and legacy DeepSeek CN provider aliases deserialize to the
206 canonical DeepSeek provider.
207 - **Footer diagnostics are less cryptic.** Prefix-cache stability is no longer
208 shown in the default footer, and the opt-in `/statusline` chip now says
209 `cache prefix 100%` instead of the ambiguous `P 100%`.
210 - **Feishu/Lark bridge dependency installs are locked and audited.** The
211 bridge now ships a package lock, installs with `npm ci` on Lighthouse when
212 available, and overrides the Lark SDK's transitive `axios` dependency to a
213 patched line.
214 - **China-friendly update fallback.** `deepseek update` now supports mirrored
215 release assets through `DEEPSEEK_TUI_RELEASE_BASE_URL` plus
216 `DEEPSEEK_TUI_VERSION`, and its network-failure hints point users behind
217 GitHub-blocking networks to the CNB `cargo install --git` path for both
218 shipped binaries.
219 - **CNB is the default Tencent release-candidate mirror.** The CNB sync
220 workflow now mirrors Feishu/Lighthouse release branches, so Tencent
221 Lighthouse bootstrap can use CNB before the release branch merges.
222
223 ### Thanks
224
225 Thanks to **ZzzPL ([@Oliver-ZPLiu](https://github.com/Oliver-ZPLiu))** for
226 the MCP Streamable HTTP and Homebrew automation fixes (#1643, #1631),
227 **Reid ([@reidliu41](https://github.com/reidliu41))** for CI, streaming wrap,
228 and model-completion fixes (#1603, #1628, #1601), **MidoriKurage
229 ([@mdrkrg](https://github.com/mdrkrg))** for the onboarding crash fix (#1598),
230 **Gordon ([@gordonlu](https://github.com/gordonlu))** for the Windows Enter /
231 CSI-u fix (#1612), **Aitensa ([@Aitensa](https://github.com/Aitensa))** for
232 the CJK diff/pager wrap fix (#1622), **qiyan233
233 ([@qiyan233](https://github.com/qiyan233))** for legacy DeepSeek CN provider
234 aliases (#1645), **jieshu666 ([@jieshu666](https://github.com/jieshu666))**
235 for the repaint-flicker reduction (#1563), **Vishnu
236 ([@Vishnu1837](https://github.com/Vishnu1837))** for terminal restoration on
237 signals (#1586), and **axobase001
238 ([@axobase001](https://github.com/axobase001))** for proxy environment
239 preservation in child tasks (#1608).
240
241 ## [0.8.36] - 2026-05-14
242
243 ### Added
244
245 - **The right sidebar can be hidden for copy-friendly terminals.**
246 `sidebar_focus = "hidden"` (or `Ctrl+Alt+0` for the current session) removes
247 the Work/Tasks/Agents/Context rail so raw terminal selection cannot copy
248 sidebar borders alongside transcript text.
249
250 ### Changed
251
252 - **Sub-agent completion handoffs are leaner and more cache-friendly.**
253 Internal `<deepseek:subagent.done>` sentinels now point to the preceding
254 human summary line instead of duplicating the summary, elapsed time, and
255 step count inside JSON sent to the parent model.
256 - **Prefix stability is visible beside cache telemetry by default.** The
257 footer now includes the prefix-stability chip in the default status layout,
258 and low last-request cache hit rates are no longer colored as hard errors
259 when the system/tool prefix itself is stable.
260 - **RLM batch helpers now require an explicit independence assertion.**
261 `sub_query_batch`, `sub_query_map`, and low-level `*_batched` helpers refuse
262 dependency-unsafe parallel fanout unless callers pass
263 `dependency_mode="independent"`, and RLM now exposes `sub_query_sequence`
264 for A-to-B dependent work.
265
266 ## [0.8.35] - 2026-05-13
267
268 A post-0.8.34 cleanup release focused on prompt hygiene, context-pressure
269 guidance, and keeping the next release branch clearly separated from the
270 already-published v0.8.34 tag.
271
272 > **Note on v0.8.34 contributor credits:** Horace Liu ([@liuhq](https://github.com/liuhq))
273 > contributed Nix package support and install documentation in the v0.8.34
274 > cycle but was inadvertently omitted from that release's changelog. The
275 > README contributor list and this note correct the record.
276
277 ### Changed
278
279 - **First-turn prompt context is leaner and easier to audit.** The
280 generated project context pack now ignores hidden tool/cache state,
281 balances top-level directories before descending, and `/context`
282 shows named prompt layers instead of a single opaque system blob.
283 - **Model-visible prompt policy de-conflicted.** The base and mode
284 prompts no longer forbid useful `deepseek` CLI diagnostics, no
285 longer require checklists for simple one-step work, and align
286 long-session compaction guidance around the 60% suggestion threshold.
287 - **Context-pressure guidance now has one split rule.** Manual
288 `/compact` suggestions start around 60% during sustained work, while
289 automatic replacement compaction remains an opt-in hard guardrail near
290 80% so DeepSeek V4 prefix-cache economics stay intact.
291 - **The Tasks sidebar now ages out stale live-tool noise.** Completed
292 active tool rows linger briefly and then leave the right rail; very old
293 running shell rows collapse to a single row instead of occupying the
294 whole Tasks panel.
295
296 ### Fixed
297
298 - **`auto_compact` settings help now reports the real default**, which
299 has been off since v0.8.11 to avoid unnecessary cache-prefix rewrites.
300
301 ## [0.8.34] - 2026-05-13
302
303 A polish, terminal-protocol, and internal-cleanup release. The model-facing
304 surface is stable; this cycle focused on prefix-cache stability metrics,
305 broader terminal protocol coverage, bundled skills, and shrinking the
306 mega-files that had grown around the agent loop and TUI.
307
308 ### Added
309
310 - **Prefix-cache stability tracking.** A footer chip surfaces how stable
311 the cached prefix has been across recent turns (inspired by Reasonix),
312 so users can spot cache-busting edits before cost climbs.
313 - **Bundled DeepSeek-native workflow skills.** A starter set of skills
314 ships in-binary so a fresh install has a usable `/skills` catalog
315 without external assets.
316 - **Native Kitty + Ghostty notification protocols.** `OSC 99` (Kitty)
317 and `OSC 777` (Ghostty) are now first-class alongside the existing
318 desktop notification fallback.
319 - **Theme picker with more presets.** Catppuccin, Tokyo Night, Dracula,
320 and Gruvbox join the built-in palette set; `/theme` now shows a
321 live picker.
322 - **Chunked parallel-safe tool execution.** The engine batches
323 side-effect-free tool calls into a chunked dispatch so independent
324 reads/searches finish in one turn instead of serialising round-trip
325 by round-trip.
326 - **Cancel-all shell jobs.** A single action stops every running
327 background shell command instead of cancelling them one-by-one.
328 - **`edit_file` tolerates typographic punctuation drift.** When the
329 exact-match and leading-whitespace-fuzzy passes both fail and
330 `fuzz: true` is set, the tool retries with smart quotes (`"`/`"` →
331 `"`, `'`/`'` → `'`), en/em-dashes (`–`/`—` → `-`), and non-breaking
332 spaces (U+00A0 → space) normalized to ASCII. Catches the copy-paste
333 failure mode where a browser or chat client substituted Unicode
334 punctuation for the ASCII the file actually contains.
335
336 ### Changed
337
338 - **`crates/tui/src/tui/ui.rs` split into focused modules.** The
339 former 10k-line single-file TUI dispatcher is decomposed into smaller
340 modules with clearer responsibilities so reviewing a UI change does
341 not require holding the entire surface in head.
342 - **`crates/tui/src/core/engine.rs` reduced.** Helper clusters moved
343 into the existing `core/engine/` submodule directory next to the
344 turn loop and tool execution code, making the agent-loop core
345 easier to read end-to-end.
346 - **Structured tracing on tool dispatch.** Tool entry, exit, duration,
347 and result/error are emitted through `tracing` events so
348 `RUST_LOG=engine.tool_execution=debug` produces a coherent timeline
349 instead of scattered ad-hoc prints.
350 - **`/init` updates `AGENTS.md` in place** instead of refusing when
351 the file already exists, so adding new project guidance does not
352 require manual stitching.
353 - **Reasoning tokens included in cost calculations**, and the cost
354 display auto-switches to CNY when the session locale is `zh-Hans`.
355 - **Stale repo-root development docs removed.** `TAKEOVER_PROMPT.md`
356 (v0.8.6 era), `PROMPT_ANALYSIS.md`, and the redundant
357 `DEPENDENCY_GRAPH.md` no longer ship in releases; `docs/ARCHITECTURE.md`
358 remains the canonical crate-layout reference.
359
360 ### Fixed
361
362 - **Auth keys checked against the saved provider on startup**, so a
363 stored DeepSeek key is no longer rejected after switching providers
364 mid-session.
365 - **Auto router skipped for decisive local routes**, removing an
366 extra model round-trip on prompts the dispatcher can route directly.
367 - **Reasoning content stripped for generic providers** that do not
368 understand the `reasoning_content` field, preventing HTTP 400s when
369 pointing at an OpenAI-compatible gateway that lacks DeepSeek
370 thinking semantics.
371 - **`FocusGained` debounced** so terminals (Tabby) that emit rapid
372 focus events no longer trigger a repaint flicker loop.
373 - **MCP HTTP transport defaults `Accept: application/json,
374 text/event-stream`** and persists `Mcp-Session-Id` across requests,
375 matching the spec for resumable streams.
376 - **Shell output tail preserved when truncating**, so the last lines
377 of a long command output (usually the error trailer) survive the
378 in-transcript summary.
379 - **Prefix cache preserved while pruning tool results.** Old
380 side-effect tool payloads no longer invalidate the prefix that
381 the next turn would otherwise reuse.
382 - **Review sub-agents prevented from spawning further sub-agents**
383 (#1489), keeping recursive depth bounded.
384 - **Help overlay closes cleanly** and repaints without a stale frame.
385 - **Pinyin `/skills` alias dispatched correctly** so Chinese-locale
386 users reach the same surface.
387 - **VTE flicker terminals get reduced motion** by default to avoid
388 thrashing on terminals that mishandle frequent partial redraws.
389 - **Composer border no longer shows the derived session title**, keeping
390 the composer chrome reserved for editor and mode state.
391
392 ## [0.8.33] - 2026-05-12
393
394 A sub-agent and RLM renovation release. The model-facing delegation
395 surface is now session-oriented instead of one-shot: RLM work happens
396 through `rlm_open` / `rlm_eval` / `rlm_configure` / `rlm_close`,
397 sub-agent work happens through `agent_open` / `agent_eval` /
398 `agent_close`, and large outputs can be parked behind typed handles
399 that the model reads back explicitly with `handle_read`.
400
401 ### Added
402
403 - **Persistent RLM sessions with bounded REPL helpers.** RLM prompts now
404 use `peek`, `search`, `chunk`, `context_meta`, `sub_query`,
405 `sub_query_batch`, `sub_query_map`, `sub_rlm`, and
406 `finalize(value, confidence)` instead of exposing the full parent
407 context as an ambient variable.
408 - **Fork-aware sub-agent sessions.** `agent_open` supports named
409 sessions, `fork_context`, and bounded recursive depth so the parent can
410 ask for multiple perspectives while preserving prompt-cache-friendly
411 prefix context where available.
412 - **Shared `handle_read` storage.** RLM finals, sub-agent transcripts,
413 and other large structured results can return `var_handle` references
414 with slice, range, count, and JSONPath projections.
415 - **Slash-command routing for the new surface.** `/rlm [N] ...` and
416 `/agent [N] ...` now prompt the assistant to use the persistent tools
417 instead of the removed foreground RLM operation.
418 - **Harness-friendly non-interactive exec sessions.** `deepseek exec`
419 now supports `--resume`, `--session-id`, `--continue`, and
420 `--output-format stream-json` so backend wrappers such as ClawBench can
421 keep conversation state and parse one JSON event per line without running
422 a long-lived server.
423 - **`/relay` slash command with CJK aliases** (`/接力`). Hands the
424 assistant a structured handoff prompt for coordinated multi-turn
425 continuation across sessions.
426 - **`checklist_write` sidebar rename.** The sidebar focus tab formerly
427 known as "Plan" / "Todos" is now "Work" — one panel for the active
428 checklist and optional plan, consistent across all three modes.
429 - **Grayscale theme.** `/theme grayscale` and
430 `/set theme grayscale --save` provide a low-opinion black/white palette
431 for users who want less brand color in the terminal.
432
433 ### Changed
434
435 - **Prompts and docs now teach only the new tool names.** Legacy
436 RLM/sub-agent helpers remain internally where needed for durable
437 transcript compatibility, but the registry exposes the session tools.
438 - **Large or noisy tool results are easier to keep out of context.**
439 Tool output summaries, sub-agent results, and transcript snapshots now
440 point the model toward `handle_read` when it needs raw detail.
441 - **Tool-surface smoke guidance is explicit.** Release checks now document
442 the exact version commands and registry-name searches for `handle_read`,
443 persistent RLM tools, and persistent sub-agent tools.
444 - **README acknowledgements expanded.** The project thanks OpenWarp and
445 Open Design for support and collaboration around terminal-agent and
446 design-forward workflows.
447 - **Light theme tuned for calmer contrast.** The canvas, panel, elevated,
448 border, and selection tokens now separate surfaces without the washed-out
449 white-on-white feel.
450 - **Session picker is history-first.** `/sessions` and `Ctrl+R` now show
451 the full selected session history on the left with the session list on
452 the right; number keys `1`-`9` open visible session histories, `PgUp` /
453 `PgDn` scroll that history, and `Enter` still resumes.
454 - **Foreground RLM operation removed.** The old `Op::Rlm` path and its
455 `handle_rlm` engine method are gone; all RLM work now flows through
456 the persistent-session tools.
457 - **Stale competitive-analysis doc removed.** The old cross-agent matrix
458 had become an unreliable inventory of tool names rather than useful
459 release guidance.
460
461 ### Fixed
462
463 - **Local/custom endpoints stay prompt-free when auth is optional.**
464 The dispatcher no longer reads the secret store for SGLang, vLLM,
465 Ollama, or loopback custom URLs unless API-key auth is explicitly
466 requested, and the direct TUI treats loopback model endpoints as
467 no-key by default. This avoids macOS Keychain prompts and stale
468 DeepSeek keys when users point the app at local OpenAI-compatible
469 servers.
470 - **Transcript browsing stays put across resizes.** If the user is reading
471 older chat history, terminal resize events preserve the current transcript
472 position instead of jumping back to the live tail; the scrollbar and
473 jump-to-latest affordance now follow the active theme.
474 - **Backtrack preview opens near the selected turn.** Pressing Esc twice no
475 longer opens the live transcript preview at the oldest conversation line;
476 the highlighted recent user turn is pinned into view, and changing the
477 backtrack target re-pins only that selection.
478 - **Completed thinking no longer masquerades as prompt text.** Collapsed
479 completed reasoning now shows only explicit `Summary:` content inline; raw
480 reasoning remains available through Ctrl+O/transcript instead of appearing
481 as assistant self-talk in the main flow. When Ctrl+O starts from a reasoning
482 block, it opens a full-session reasoning timeline instead of a single
483 isolated chunk.
484 - **Transcript selection keeps working while the agent is streaming.**
485 The loading-state mouse filter now drops inert move events but allows
486 active transcript and scrollbar drags to continue (reported as a known
487 issue in v0.8.32).
488 - **Empty-composer arrow scrolling feels less twitchy.** When configured to
489 scroll the transcript, plain Up/Down now move by a small wheel-like step
490 instead of a single-line flick.
491 - **Mouse and trackpad scrolling feel less sticky in long logs.** Rapid
492 same-direction transcript scrolls now get bounded acceleration while
493 direction changes reset to precise single-line movement.
494 - **RLM smoke-test papercuts fixed.** `rlm_eval` now binds `content` as a
495 convenience alias for `_context`, tolerates common `timeout_secs` keyword
496 guesses on child-query helpers while preserving session-level timeout
497 policy, and stores JSON-serializable `finalize(...)` values as JSON handles
498 so `handle_read` can project them directly.
499 - **RLM REPL uses the shared Python resolver.** RLM startup now tries
500 `python3`, `python`, and `py -3`, matching the dependency resolver used by
501 code execution and avoiding Windows failures where `python3` is absent
502 (harvested from PR #1540).
503 - **Session titles and history previews hide metadata noise.** Saved
504 session titles and the picker history strip leading `<turn_meta>` envelopes
505 and thinking-tag blocks so historical conversations read like user-visible
506 chat rather than prompt plumbing (harvested from PR #1510).
507 - **Companion binary version smoke is unambiguous.** `deepseek-tui --version`
508 now reports the `deepseek-tui` binary name instead of the dispatcher label.
509 - **Vision path boundary test is platform-native.** The absolute-path
510 rejection smoke uses a Windows absolute path on Windows and `/etc/hosts`
511 elsewhere (harvested from PR #1526).
512 - **Tool papercuts:** `file_search` has safer default excludes and an
513 explicit `exclude` option; `grep_files` returns single-line context as
514 strings; `fetch_url` can project JSON fields and returns headers;
515 `edit_file` can opt into leading-indentation fuzz; `exec_shell` can
516 merge stdout/stderr in chronological order; `revert_turn` rejects
517 no-op snapshot boundaries.
518 - **CLI reasoning-effort honoured on non-auto exec routes** (PR #1511
519 from **@h3c-hexin**). `deepseek -p "..." --reasoning-effort high` now
520 applies the flag correctly instead of falling back to the config-file
521 default.
522 - **Edit-file replacement boundaries clarified** (PR #1516). The tool
523 description and error messages now make it unambiguous that
524 `edit_file` is for one clear replacement in one file.
525 - **Pandoc output validated before probing** (PR #1523). Binary-format
526 conversions that produce empty or invalid output now surface a clear
527 error instead of a confusing pandoc stack trace.
528 - **Running turns can be steered and repainted** (PR #1533, #1537).
529 Composer input during an active turn no longer stalls; the TUI
530 redraws the transcript as the agent streams.
531 - **Tasks and Activity Detail are calmer under load.** The Tasks panel now
532 keeps live/background/recent activity from double-counting the same shell
533 or RLM work, groups repeated read/search/checklist noise, and keeps
534 failures, status, command summaries, and durations visible. Ctrl+O now
535 opens Activity Detail for selected/live/recent tool work and the reasoning
536 timeline for thinking blocks, while Alt+V remains the direct tool-detail
537 pager; the idle footer now advertises that split for the visible activity.
538 - **npm retry shows timeout hint on first failure** (PR #1538).
539 Installations behind slow proxies now see a clear "retrying" message
540 instead of a silent hang.
541 - **Issue templates improved** (PR #1525 from **@reidliu41**). Bug and
542 feature-request templates are clearer and easier for new contributors.
543
544 ### Credits
545
546 Thanks to **@reidliu41** (#1525/#1526), **@h3c-hexin** (#1511),
547 **@xulongzhe** (#1530/#1544), **@tyouter** (#1510), and
548 **@Duducoco** (#1540) for community contributions in this release.
549
550 ## [0.8.32] - 2026-05-12
551
552 A "more useful tools" release. v0.8.31 made the tool surface
553 reliable on every host; v0.8.32 expands it. Anchor is the question
554 every new contributor asks: "what does the model actually have to
555 work with?" — and the answer is now closer to "everything you'd
556 reach for from a shell, including the document formats the real
557 world uses." Five new tools (`pdf-extract` swap, `js_execution`,
558 `pandoc_convert`, `image_ocr`, `image_analyze`), ten community PR
559 harvests targeting model-protocol bugs (vLLM thinking) and UX
560 papercuts (Shift+Enter on Windows VSCode, mention truncation
561 splitting CJK codepoints, approval modal hiding the transcript),
562 and a snapshot-self-disable on workspaces over 2 GB of
563 non-excluded content so first-turn `git add -A` no longer hangs
564 the TUI on multi-hundred-GB project directories.
565
566 ### Performance
567
568 - **Move `instructions = [...]`, user memory, and session goal
569 below the prompt's volatile-content boundary so DeepSeek's KV
570 prefix cache survives mid-session edits** (harvested from PR
571 #1345 by **@Duducoco**). Before this change, the per-workspace
572 `instructions` block, the user memory file (`/memory`), and the
573 current session goal (`/goal`) were rendered at position 2.5
574 in the system prompt — inside the static prefix layer that the
575 cache hits. Any edit to those files (or any `# foo`
576 quick-add to memory) busted the cached prefix from that byte
577 onwards, forcing the next turn to re-tokenize the rest of the
578 static layer. Relocating them to position 6 (immediately above
579 the previous-session handoff block) means the cache hit covers
580 the entire static prefix — mode, project context, env, skills,
581 context management, compact template — regardless of how often
582 the user edits their memory file. Skills, context management,
583 and the compact template stay always-cacheable in the static
584 layer where they belong.
585
586 ### Removed
587
588 - **Shift-to-bypass-mouse-capture is gone.** The #376 escape-hatch
589 feature (hold Shift while moving the mouse → temporarily disable
590 alt-screen mouse capture so terminal-native text selection works,
591 then re-enable on release) was causing visible scroll/redraw
592 thrash: every Shift transition flipped the mouse-capture mode AND
593 pushed a status toast ("Native selection — release Shift to
594 return" / "Mouse capture restored"). On modern terminals that
595 honor `xterm-modifyOtherKeys` the toast cycle fired on stray
596 Shift events and produced what users described as a "scroll
597 demon." Removing the bypass path entirely: text selection in
598 alt-screen sessions now goes through the same path as any other
599 TUI (your terminal's modifier-bypass — typically Option/Alt on
600 macOS, Shift in some Linux terminals — still works at the
601 terminal level, this just stops us from second-guessing it).
602
603 ### Fixed
604
605 - **Tool-result spillover and wire-dedup now share a retrieval
606 namespace, so `retrieve_tool_result` finds what the model was
607 pointed at.** Two systems used to mint reference blocks
608 independently — disk spillover keyed by tool-call id
609 (`~/.deepseek/tool_outputs/<id>.txt`, only above 100 KB) and the
610 Chat-Completions wire compactor that replaced repeated tool
611 results with `<TOOL_RESULT_REF sha="…"/>` (any size, keyed by
612 SHA256 of the content). The SHA refs were impossible to
613 retrieve: `retrieve_tool_result ref=<sha>` looked in the
614 tool-call-id directory and 404'd. Worse, the wire dedup fired
615 on tiny outputs (a 65-byte `gh run view --json` could turn into
616 a ref the model then chased through three guesses), and the
617 `[artifact: …]` block emitted by `apply_spillover_with_artifact`
618 showed `id:` (with `art_` prefix), `path:` (with a slash), and
619 `tool_call_id:` separately with no indication of which one
620 `retrieve_tool_result` accepted. Reported by users hitting
621 "spilled tool result was not found" 4–5 times per session while
622 polling CI runs.
623 - The wire compactor now persists deduped content to
624 `~/.deepseek/tool_outputs/sha_<sha>.txt` on first sighting,
625 and only dedupes outputs ≥ 1 KiB — tiny results stay inline
626 on both occurrences instead of becoming a ref the model has
627 to chase. The `<TOOL_RESULT_REF>` block grew a
628 literal `retrieve: retrieve_tool_result ref=sha:<sha>` line.
629 - `retrieve_tool_result` learns five new ref shapes:
630 `sha:<64-hex>`, bare 64-hex, `art_<tool_call_id>`,
631 `artifacts/art_<id>.txt`, and absolute paths anywhere under
632 the session-artifact root. The lookup tries the legacy
633 spillover dir, the current session's artifact dir, and the
634 `art_` → legacy fallback in one call. When everything misses,
635 the error enumerates every candidate path tried and lists
636 every accepted ref form so the model can correct on the next
637 attempt instead of guessing blind.
638 - The `[artifact: …]` block emitted alongside spilled outputs
639 now includes a literal `retrieve: retrieve_tool_result
640 ref=art_<id>` line so the model never has to guess between
641 `id:`, `path:`, and `tool_call_id:`.
642 - **`<TURN_META_REF sha="…" original_chars="…" />` is gone.** The
643 legacy wire-level dedup for identical per-turn metadata blocks
644 emitted an opaque SHA-tagged reference that periodically leaked
645 into model reasoning and user-visible debug dumps with no
646 retrieval mechanism — the SHA was an artifact of the cache
647 optimization, not a content address the model could resolve.
648 The compactor now emits a self-explanatory
649 `<turn_meta_unchanged />` marker instead. Same KV-cache
650 friendliness (bytes in the same prompt position when nothing
651 changed), zero ambiguity if the marker ever surfaces.
652 - **"Request cancelled while awaiting approval" now says
653 *why*.** The approval and user-input handlers used to emit the
654 same opaque string regardless of source — user Esc, runtime-API
655 DELETE, parent-agent cancel, or a torn-down channel all
656 produced an identical error. A new `CancelReason` enum is
657 latched alongside the `CancellationToken` and surfaced as a
658 `(reason: …)` suffix: `user cancelled the request`, `request
659 cancelled by external caller`, `request was preempted by a new
660 turn`, `engine torn down before approval resolved`. A closed
661 approval channel reports the teardown race explicitly instead
662 of just "Approval channel closed." Remaining non-user
663 cancellation call sites are tracked in #1541.
664 - **`pandoc_convert` validates binary-output requests before
665 resolving the `pandoc` binary** (harvested from PR #1523 by
666 **@muyuliyan**). Hosts without pandoc installed now still get
667 the intended validation error for `target_format = "docx"`
668 without `output_path`, which keeps the CI test independent of
669 runner packages.
670 - **Mouse movement no longer leaks xterm tracking bytes into the
671 composer while the model is streaming** (harvested from PR #1533
672 by **@Oliver-ZPLiu**, fixes #1529). When mouse capture is
673 enabled, move/drag events can arrive faster than the TUI needs
674 them during a streaming turn; those stale movement events are now
675 discarded while loading, while click/scroll handling remains
676 active when the TUI is idle.
677 - **Resize and successful turn completion avoid blank-frame
678 flicker** (harvested from PR #1537 by **@czf0718**, addresses
679 #1515 and #1539). Resize now performs the viewport reset, clear,
680 and redraw inside a single synchronized-output batch. Successful
681 `TurnComplete` events use the incremental renderer instead of
682 forcing a clear+redraw every time; full repaint remains reserved
683 for interrupted/failed turns and periodic resyncs.
684 - **The npm wrapper shows binary-download remediation on the first
685 retryable timeout** (harvested from PR #1538 by **@jieshu666**,
686 addresses #1532). Users behind networks that time out when
687 fetching GitHub Release assets now see the mirror/proxy/Cargo
688 alternatives immediately, and the installer points at the fixed
689 `docs/INSTALL.md#npm-binary-download-times-out` anchor.
690 - **`edit_file` states its exact-replacement boundary and warns on
691 multi-match replacements** (from #1516). The tool description and
692 base prompt now steer structural or intertwined edits toward
693 `apply_patch` / `write_file`, while keeping legitimate repeated
694 replacements compatible with an advisory "verify with read_file"
695 hint.
696 - **Shift+Enter explicitly steers a running turn.** Plain Enter
697 while busy continues to queue (the agreed default since
698 #1331). Pressing **Shift+Enter** during an in-flight turn
699 routes the draft directly through `engine.steer()` — the same
700 path Ctrl+Enter already drove — without going through the
701 queue at all. When the agent is idle, Shift+Enter still inserts
702 a composer newline as before. Ctrl+Enter remains bound for
703 terminals that swallow the Shift modifier on Enter at the
704 protocol level. (Pattern cross-checked against pi-agent's
705 `streamingBehavior: "steer"` API: see `agent-session.ts:156` —
706 same `Shift+Enter → steer / Plain Enter → queue` split, just
707 surfaced as a keypress instead of a programmatic flag.)
708 - **`exec_shell_wait` default timeout raised from 5 s → 30 s.**
709 The 5 s default was fine for "did the command exit yet?" polls
710 but forced models into hand-rolled `while true; do
711 exec_shell_wait …; sleep 30; done` loops for `gh run watch`,
712 long `cargo build`s, and `cargo login`-style interactives. 30 s
713 covers the common case in a single tool call without burning a
714 whole turn on the timeout boundary; the model can still pass
715 any value up to 600 s.
716 - **Snapshots no longer try to index a multi-hundred-GB workspace
717 on first turn.** Reported by users running `deepseek-tui` inside
718 project directories with hundreds of GB of content — datasets,
719 model weights (`.safetensors`, `.gguf`, `.pt`), Docker image
720 dumps, parquet / arrow caches — where the side-git snapshot
721 initialization would hang the TUI for minutes or hours while
722 `git add -A` walked the workspace. v0.8.32 adds a default
723 2 GB ceiling on non-excluded workspace content (measured before
724 any git work, walking the same excludes the snapshot path
725 already honors). When the cap is exceeded the side repo isn't
726 initialized; subsequent snapshots are skipped with a clear
727 WARN-level log line referencing the new
728 `[snapshots] max_workspace_gb` config knob users can raise (or
729 set to `0` to disable the cap entirely and restore v0.8.31
730 behaviour). The bounded estimator also early-exits past 200k
731 file entries, so a workspace full of tiny files trips the cap
732 before paying for a full walk. Pre-existing v0.8.27 fixes for
733 the growth-over-time angle (#1112: retention cap, mid-session
734 prune, expanded built-in excludes) continue to apply; this
735 closes the orthogonal "snapshots-too-big-to-start" path.
736 - **Toast stack overlay no longer renders on top of the composer
737 input** (harvested from PR #1485 by **@MeAiRobot**). When a
738 deferred tool's schema auto-loaded after the model requested
739 it, the resulting status toast ("Auto-loaded deferred tool
740 'edit_file' after model request.") could render at
741 `footer_area.y - 1` — which on tight layouts is the bottom row
742 of the composer area, visibly overwriting the start of the
743 user's typed text. `render_toast_stack_overlay` now clamps
744 `max_above` to the gap between `composer_area.y +
745 composer_area.height` and `footer_area.y`, so when the composer
746 and footer are adjacent the overlay collapses to zero rows and
747 the toast is suppressed rather than drawn on top.
748 - **`/sessions` picker highlights the selected row more strongly
749 in dark terminals** (harvested from PR #1493 by **@reidliu41**).
750 Previously the selection background was subtle enough to lose
751 in low-contrast dark themes; keyboard navigation up/down didn't
752 obviously change which row was active. The selected row now
753 uses a bolded label on a stronger background so the focused row
754 reads cleanly across the dark palettes the TUI ships with.
755 - **TUI input no longer freezes while long-running shell jobs
756 flood stdout** (#1299, harvested from PR #1494 by
757 **@CrepuscularIRIS / autoghclaw**). The job-panel refresh path
758 was calling `full_output()` from inside the `ShellManager`
759 mutex, which cloned the entire accumulated stdout/stderr buffer
760 every 2.5 seconds. For browser-automation or large-build jobs
761 the buffer grew unboundedly; cloning held the mutex for
762 O(total_bytes) time, starving the `crossterm::event::poll` loop
763 and dropping keystrokes. The refresh now reads only the last
764 `max_tail_chars * 4` bytes under the lock (lock hold time is
765 O(1) regardless of total output volume) and decodes those into
766 a tail string for display. `stdout_len` / `stderr_len` still
767 report the true total byte counts so no caller invariant
768 breaks. Also tightens `take_delta_from_buffer` to slice
769 `[cursor..total]` inside the lock guard instead of cloning the
770 whole buffer first, and skips UTF-8 continuation bytes at
771 `tail_start` so `from_utf8_lossy` never emits a leading U+FFFD
772 in the job panel.
773 - **`@`-mention truncation no longer splits multi-byte UTF-8
774 sequences** (#1441, harvested from PR #1495 by
775 **@CrepuscularIRIS / autoghclaw**). When `@`-mentioning a file
776 larger than 128 KB the composer truncated the buffer at exactly
777 `MAX_MENTION_FILE_BYTES`, which on CJK / emoji content landed
778 mid-codepoint and produced a stray U+FFFD at the cut point. The
779 truncator now uses `str::from_utf8(...).error_len()` to detect
780 the incomplete-tail case and rounds down to the last valid
781 codepoint boundary before decoding. Genuinely invalid UTF-8
782 files still surface the "file is not UTF-8" error (the rounding
783 is only applied when the error is an incomplete tail, not a
784 real decoding failure mid-buffer).
785 - **vLLM provider: `reasoning_effort = "off"` now actually
786 disables thinking on Qwen3 / DeepSeek-R1 servers, cutting
787 TTFT from ~13s to ~270ms** (harvested from PR #1480 by
788 **@h3c-hexin**). The vLLM branch of `apply_reasoning_effort`
789 was injecting `thinking: {type: "disabled"}` at the top of
790 the request body — but vLLM speaks OpenAI's chat-completions
791 protocol, not Anthropic-native fields, and silently ignored
792 the directive. The model then emitted a full hidden reasoning
793 trace into the non-standard `reasoning` field (which this
794 client doesn't surface), so users saw a multi-second freeze
795 before any content token arrived. The vLLM branch now emits
796 the OpenAI extension `chat_template_kwargs.enable_thinking`
797 (which vLLM forwards into the model's chat template — the
798 canonical way to toggle Qwen3's `<think>...</think>` mode).
799 Measurement against vLLM + Qwen3.6-35B-A3B-FP8: TTFT
800 13039ms → 274ms, total LLM call 13s → 5.7s. The `high` /
801 `max` effort levels likewise switch to the OpenAI extension.
802 No change for non-vLLM providers.
803 - **`/sessions` picker no longer shows `<turn_meta>` as the
804 session title** (harvested from PR #1498 by **@wdw8276**).
805 `session_manager::create_saved_session_with_id_and_mode`
806 picked the first text content block off the user message via
807 `find_map`; the engine prepends an internal `<turn_meta>` block
808 ahead of the real user text, so the picker rendered that
809 metadata blob as the session name. Guard added so titles fall
810 through to the actual user input. Existing sessions without
811 the prefix block are unaffected.
812 - **Kitty keyboard protocol now activates on Windows (VSCode +
813 Windows Terminal), so `Shift+Enter` inserts a newline instead
814 of submitting** (#1359, harvested from PR #1483 by
815 **@CrepuscularIRIS / autoghclaw**). Root cause: crossterm's
816 `PushKeyboardEnhancementFlags` gates the escape sequence on
817 `is_ansi_code_supported()`, which on Windows queries the
818 console mode rather than the VT capability and unconditionally
819 returns false — so the Kitty push (`\x1b[>1u`) was never
820 written, leaving xterm.js in legacy mode where `Shift+Enter`
821 and `Enter` both produce `\r` and are indistinguishable.
822 `Alt+Enter` / `Ctrl+J` were affected the same way. The fix
823 writes the push and pop escapes directly under `#[cfg(windows)]`,
824 bypassing the capability gate; terminals that don't speak the
825 protocol silently discard the sequences. Also extends the
826 pop-on-exit path to two missed call sites (the `main.rs` panic
827 hook and `external_editor.rs::spawn_editor_for_input`) so a
828 crash or `$EDITOR` invocation can no longer leave the parent
829 shell's keyboard state corrupted.
830 - **Approval modal can be collapsed to a one-line banner with
831 Tab** (harvested from PR #1455 by **@tiger-dog**). Previously the
832 approval prompt rendered as a full-screen takeover that hid the
833 transcript behind it, so users had to dismiss the modal just to
834 remember which tool call they were being asked to approve. Tab
835 now toggles between the takeover card and a single-line bottom
836 banner — the rest of the conversation stays visible while the
837 decision is pending. Tab again restores the full card; the
838 selection state is preserved across the toggle.
839 - **Markdown renderer no longer eats underscores inside
840 identifiers** (harvested from PR #1455 by **@tiger-dog**). The
841 inline parser was matching `_italic_` against the underscore in
842 `deepseek_tui` / `foo_bar_baz` and rendering the second half of
843 the identifier in italic, which made transcript snippets that
844 named code symbols read as garbled prose. Both `_italic_` and
845 `*italic*` now apply a CommonMark-style boundary check on the
846 closing delimiter — when the next character is a letter, digit,
847 or underscore, the delimiter is treated as literal text instead
848 of markup. Regression-pinned with cases like `crate deepseek_tui
849 handles approvals` and `look at *not_emphasised*tail`.
850
851 ### Added
852
853 - **npm wrapper installs cleanly on OpenHarmony / HarmonyPC**
854 (#1072, harvested from PR #1499 by **@CrepuscularIRIS /
855 autoghclaw**). `os.platform()` returns `openharmony` on
856 HarmonyPC and on OpenHarmony's Linux ABI-compatible userspace,
857 but the npm wrapper's platform-asset matrix only covered
858 `linux` / `darwin` / `win32`, so `npm i -g deepseek-tui` would
859 abort with `Unsupported platform: openharmony` even though the
860 Linux x64 / arm64 binaries run unchanged on that environment.
861 Added a `PLATFORM_ALIASES` mapping that resolves `openharmony`
862 to the `linux` asset family before lookup so install succeeds
863 on those hosts. The error message for genuinely unsupported
864 platforms still reports the raw platform name (`freebsd`,
865 etc.) so OS-mismatch reports stay diagnostic.
866 - **Startup empty-state shows useful context instead of
867 repeating the header** (harvested from PR #1444 by
868 **@reidliu41**). The center of the welcome view used to repeat
869 information already displayed in the header and footer. It now
870 shows the build version, the active model with a `/model`
871 hint, and the current working directory so first-time users
872 have somewhere to look while they decide what to type.
873 - **Opt-in `v4-best-practices` bundled skill** (harvested from
874 PR #1448 by **@SamhandsomeLee**). A single 50-line `SKILL.md`
875 encoding three V4-specific workflow rules for multi-step
876 thinking-mode tasks. Each rule maps to a concrete observable
877 failure class. Discovered through the existing
878 `crates/tui/assets/skills/...` mechanism alongside the
879 `skill-creator` skill — not enabled by default; users opt in
880 via the standard `/skills` UI.
881 - **`image_analyze` tool — vision-model image understanding**
882 (harvested from PR #1467 by **@MMMarcinho**). Sends an image
883 file to an OpenAI-compatible vision endpoint and returns the
884 model's natural-language description. Complements `image_ocr`:
885 use `image_ocr` for "what text is on this image", `image_analyze`
886 for "what is this image about". **Opt-in only** — gated by both
887 the `[features] vision_model = true` flag and a `[vision_model]`
888 config block specifying `model` (and optionally `api_key` /
889 `base_url`). Default configuration ships the feature flag at
890 `false`, so no install sees vision API calls fire without an
891 explicit two-step opt-in. **Billing**: each call hits the
892 configured vision endpoint (OpenAI by default), so usage is
893 billed by the third-party provider; calls are stateless (no
894 conversation context attached). Workspace-boundary check: the
895 tool rejects absolute paths and any `..` parent-dir traversal
896 before any base64 encoding or API call. To disable later: set
897 `[features] vision_model = false` (or omit `[vision_model]`).
898 Supports PNG, JPEG, GIF, WebP, and BMP inputs.
899 - **`image_ocr` tool — extract text from images via local
900 tesseract.** Lets the model OCR a screenshot, scanned receipt,
901 whiteboard photo, or image-only PDF the user drops into the
902 workspace, without bouncing through `exec_shell`. Spawns
903 `tesseract <image> -` and returns the recognised text inline;
904 no file is written. PNG / JPEG / TIFF inputs supported.
905 Registration is gated on `dependencies::resolve_tesseract()`;
906 when tesseract is missing the tool isn't advertised, so the
907 model never tries to call an OCR engine the host can't run.
908 `deepseek doctor` reports tesseract status alongside the other
909 external-binary dependencies with platform-aware install hints
910 (`brew install tesseract` / `apt install tesseract-ocr` /
911 `winget install UB-Mannheim.TesseractOCR`). For non-default
912 language packs or PSM modes, users can still drop into
913 `exec_shell` with the full tesseract CLI surface.
914 - **`pandoc_convert` tool — convert documents between formats via
915 the local pandoc binary.** Pandoc is the Swiss Army knife the
916 real world uses for moving prose around — Markdown to HTML,
917 HTML to Markdown, reST to anything, anything to DOCX / EPUB /
918 LaTeX — and surfacing it as a model-callable tool unblocks
919 "rewrite this report as ..." / "publish this changelog as ..."
920 workflows that previously needed the user to drop into a
921 terminal between turns. Curated target whitelist of 11 formats
922 (markdown, gfm, commonmark, html, rst, latex, docx, odt, epub,
923 plain, asciidoc) so the model can't ask for `pdf` (would need
924 LaTeX) or typos like `markown`. Binary targets (docx, odt,
925 epub) require an `output_path`; text targets can return the
926 converted text inline. Approval routes through the WritesFiles
927 / Suggest tier on every call. Registration is gated on
928 `dependencies::resolve_pandoc()`; `deepseek doctor` surfaces
929 the binary's status with platform-aware install hints.
930 - **`js_execution` tool — execute model-provided JavaScript via a
931 local Node.js runtime.** Mirrors `code_execution` (Python) so
932 the model has a single consistent surface for "run this snippet
933 locally and tell me what it printed" across both interpreters.
934 Same tempfile-spawn pattern, same 120-second timeout, same
935 stdout/stderr/return_code result shape — so prompt-cache
936 layouts that cover one tool also cover the other. Registration
937 is gated on `crate::dependencies::resolve_node()`: when Node is
938 missing the tool is simply not advertised, so the model never
939 sees a runtime it can't actually use. `deepseek doctor` reports
940 Node availability under "Tool Dependencies" with platform-aware
941 install hints (`brew install node` / `apt install nodejs` /
942 `winget install OpenJS.NodeJS`). Approval routes through the
943 same Suggest tier as `code_execution`.
944 - **`/translate` opt-in: respond in the user's UI locale, with a
945 post-hoc fallback for English that leaks through** (harvested
946 from PR #1462 by **@YaYII**). Two-layer design: when the user
947 enables translation via the `/translate` slash command, a
948 `## Language Output Requirement` block is appended to the
949 system prompt instructing the model to reply in the resolved
950 session locale (Simplified Chinese, Traditional Chinese,
951 Japanese, or Brazilian Portuguese — code identifiers and
952 user-requested English code blocks are exempt). For replies
953 that still surface English despite the directive, a heuristic
954 in `tui::translation` (Latin-vs-CJK character ratio with
955 weighting for CJK information density) detects the leak and
956 invokes a focused per-message translation API call to render
957 the localised version before display. Both layers are off by
958 default and have no effect on installs that don't enable them.
959 Trust-boundary scope: opt-in only, system prompt addition is
960 conditional on the runtime flag, no model behaviour change for
961 English-locale users.
962 - **AtlasCloud is now a first-class provider** (harvested from
963 PR #1436 by **@lucaszhu-hue**). AtlasCloud hosts the V4 family
964 (and other DeepSeek-compatible models) on its own endpoint at
965 `https://api.atlascloud.ai/v1`, and several contributors had
966 been running it through the OpenAI-compatible passthrough with
967 manual `base_url` / model overrides. Selecting
968 `provider = "atlascloud"` in `~/.deepseek/config.toml` (or via
969 `DEEPSEEK_PROVIDER=atlascloud`) now wires up the documented
970 defaults, a `[providers.atlascloud]` config block for per-user
971 api_key / base_url / model / http_headers overrides, the
972 `ATLASCLOUD_API_KEY` env var path, and the
973 provider-picker / `/provider` slash command entries — same
974 shape as the existing NVIDIA NIM / Fireworks / OpenAI provider
975 rows. Default remains DeepSeek; nothing changes for installs
976 that don't opt in.
977 - **`web_search` supports Tavily and Bocha as configurable
978 backends** (harvested from PR #1294 by **@sandofree**). DuckDuckGo
979 with Bing fallback remains the default — no API key required —
980 but users in regions where those scrapers are unreliable can now
981 set `[search] provider = "tavily" | "bocha"` plus
982 `api_key = "..."` in `config.toml` (or via the
983 `DEEPSEEK_SEARCH_PROVIDER` / `DEEPSEEK_SEARCH_API_KEY` env vars)
984 to route every `web_search` call through the chosen API. Tavily
985 is an AI-search API targeted at general use; Bocha is the
986 mainland-China-friendly equivalent. Trust-boundary pins: an
987 unset `api_key` on an opted-in provider surfaces a clear
988 `ToolError` naming the missing key rather than silently falling
989 through to a different provider, the network policy gate
990 (`[network]`) is consulted for the provider host on every call,
991 and the default path is unchanged so no install sees provider
992 behaviour change unless they explicitly opt in.
993 - **`/change` slash command** displays the most recent
994 CHANGELOG.md version section from inside the TUI, so users can
995 see what they just upgraded into without leaving the chat
996 (harvested from PR #1416 by **@zhuangbiaowei**). The command
997 works against the bundled release-notes copy when no workspace
998 CHANGELOG is available, and on non-English locales it requests
999 a model-side translation of the section so localised users see
1000 the changelog in their UI language. Pure offline fallback when
1001 no API key is configured.
1002
1003 ### Fixed
1004
1005 - **`deepseek update` now refreshes the companion TUI binary
1006 alongside the dispatcher** (harvested from PR #1492 by
1007 **@NorethSea**). Closes the documented two-binary footgun:
1008 `~/.cargo/bin/deepseek` would update to the latest dispatcher,
1009 but `~/.cargo/bin/deepseek-tui` would stay at the previously
1010 installed version, so users saw the dispatcher report a new
1011 release while the TUI runtime they actually interacted with
1012 reported the old version. Most painful for Volta-managed npm
1013 installs and any maintainer flow that calls `update` instead of
1014 re-running both `cargo install --path crates/{cli,tui}`. The
1015 updater now enumerates colocated binaries up front, downloads
1016 and verifies every release asset before replacing anything,
1017 then swaps the sibling first and the running dispatcher last so
1018 a partial network failure cannot leave the launcher updated
1019 while the TUI remains stale.
1020
1021 ### Changed
1022
1023 - **`read_file` now extracts PDFs in pure Rust by default — no
1024 Poppler install required.** Before v0.8.32 the PDF path shelled
1025 out to `pdftotext` (Poppler), so first-time users on hosts without
1026 it saw `read_file` return a `binary_unavailable` sentinel and had
1027 to `brew install poppler` / `apt install poppler-utils` before
1028 the model could open a PDF. The bundled `pdf-extract` crate
1029 (which already powered URL-fetched PDFs in `web_run`) now drives
1030 the local `read_file` path too. The `pages` parameter still
1031 filters by 1-indexed inclusive page range; both the whole-file
1032 and per-page variants run with no system dependency. Users with
1033 column-heavy or complex-table PDFs (academic papers, financial
1034 filings) where `pdftotext -layout` still wins can opt into the
1035 external path with `prefer_external_pdftotext = true` in
1036 `~/.config/deepseek/settings.toml` — when set, the previous
1037 Poppler dispatch (and the `binary_unavailable` install hint when
1038 the binary is missing) returns. `deepseek doctor` now reports
1039 `pdftotext` as optional and explains how to opt in instead of
1040 framing it as a missing dependency.
1041
1042 ### Known issues
1043
1044 - **Terminal-native text selection can still be blocked while the
1045 agent is thinking or streaming a response.** v0.8.32 removed the
1046 noisy Shift-to-bypass-mouse-capture path that caused visible
1047 scroll/redraw thrash, but the replacement selection path is not
1048 complete yet. v0.8.33 is planned to ship the text-selection fix
1049 alongside the sub-agent and RLM renovation.
1050
1051 ## [0.8.31] - 2026-05-12
1052
1053 A "tools that actually work" release. `code_execution` no longer
1054 fails on Windows hosts where `python3` isn't on `PATH` — we probe
1055 for the interpreter at catalog-build time and only advertise the
1056 tool when one resolves, so the model never sees a runtime it can't
1057 actually use. The new `deepseek doctor` "Tool Dependencies" and
1058 "Terminal Quirks" sections surface external-binary status and
1059 active env-driven overrides so flicker / motion / missing-tool
1060 puzzles answer themselves before a bug report gets filed. Ptyxis
1061 50.x users on Ubuntu 26.04 get a manual `synchronized_output = off`
1062 knob plus auto-detection that opts them out of the DEC 2026
1063 synchronized-output wrap their VTE 0.84 mishandles. The CNB Cool
1064 mirror workflow is rewritten with concurrency and scoped pushes so
1065 release tags reliably reach `cnb.cool/deepseek-tui.com/DeepSeek-TUI`
1066 for users behind GitHub-blocking networks. Plus a new auto-close
1067 workflow that closes contributor PRs whose code has been harvested
1068 into `main`, so credit lands at the same moment the fix does.
1069
1070 ### Fixed
1071
1072 - **Windows `exec_shell` preserves MSVC toolchain env** (harvested
1073 from PR #1487 by **@Jianfengwu2024**). When the parent shell has
1074 already loaded `VsDevCmd` / `vcvars` (Developer Command Prompt,
1075 the standard way to run Rust + MSVC on Windows), `exec_shell` was
1076 stripping `LIB` / `LIBPATH` / `INCLUDE` and the related VS / SDK /
1077 CRT root variables on its way to the child. That made
1078 model-driven `cargo build` calls fail to resolve `kernel32.lib`
1079 even though `link.exe` was reachable via `PATH`. The allowlist
1080 in `child_env.rs` now preserves the 13 MSVC env vars so the
1081 toolchain context survives the sanitisation pass.
1082 - **`code_execution` no longer fails with "program not found" on
1083 Windows** (and any other host without `python3` on `PATH`). Before
1084 v0.8.31 the tool hardcoded `python3` and was unconditionally
1085 advertised in Agent / YOLO modes — so the model would call it,
1086 spawn would fail, and the error surfaced as a generic tool failure
1087 with no upstream hint. The fix probes for a Python interpreter
1088 (`python3` → `python` → `py -3`) at catalog-build time, caches the
1089 resolved interpreter, and only advertises `code_execution` when one
1090 resolves. On hosts with no Python the tool is not registered at all
1091 — the model never sees a tool it can't actually run. Reported by a
1092 Windows contributor; resolver lives at
1093 `crates/tui/src/dependencies.rs` and is also surfaced by
1094 `deepseek doctor`. Folds in the contributor's "write code to a
1095 tempfile and run the file" suggestion at the same time, so multiline
1096 code with quote nesting no longer round-trips through `python3 -c`.
1097 - **Termius and every SSH session auto-enable low-motion**
1098 (#1433, harvested from PR #1479 by **@CrepuscularIRIS / autoghclaw**).
1099 Termius desktop sets `TERM_PROGRAM=Termius`; sshd exports
1100 `SSH_CLIENT` for every TCP session and `SSH_TTY` for interactive
1101 PTY logins. Any of those signals now flips `low_motion` and
1102 `fancy_animations` like the existing VS Code / Ghostty path, so
1103 the 120 FPS cursor-repositioning that races the SSH round-trip
1104 no longer flickers a remote TUI. Disk-loaded `fancy_animations =
1105 true` is unconditionally overridden under these signals,
1106 matching the existing env-precedence contract.
1107 - **DEC 2026 synchronized output is auto-disabled on Ptyxis** (the new
1108 default terminal on Ubuntu 26.04 and an increasingly common Linux
1109 TUI host). Ptyxis 50.x ships on VTE 0.84.x, which parses the
1110 `\x1b[?2026h` / `\x1b[?2026l` begin/end pair but still flashes the
1111 entire viewport on every wrapped frame instead of deferring
1112 rendering — so a TUI that uses DEC 2026 to avoid tearing
1113 experiences visible flicker on every redraw. gnome-terminal 3.58
1114 on the same VTE renders cleanly, so the heuristic must stay narrow:
1115 we trigger only on `TERM_PROGRAM` matching `ptyxis`
1116 case-insensitively, or `PTYXIS_VERSION` set to any non-empty value.
1117 Either signal flips the new `synchronized_output` setting from
1118 `auto` to `off`; the renderer then skips the begin/end pair on
1119 every draw, in `reset_terminal_viewport`, and in `resume_terminal`.
1120 Users on Ptyxis who upgrade past the upstream fix (or who want to
1121 confirm a fix landed) can override with
1122 `/set synchronized_output on` or by adding
1123 `synchronized_output = "on"` to `~/.config/deepseek/settings.toml`.
1124
1125 ### Added
1126
1127 - **`deepseek doctor` now reports tool-dependency status.** A new
1128 "Tool Dependencies" section lists which external binaries the
1129 registered tools rely on, with ✓ when present and ✗ + an
1130 install hint when missing. Today this covers the Python
1131 interpreter (`code_execution`) and `pdftotext` (`read_file` PDF
1132 path). A separate "Terminal Quirks" section shows which env-driven
1133 auto-overrides (VS Code / Ghostty / Termius / SSH / Ptyxis) are
1134 currently active so users can see at a glance why a particular
1135 rendering compromise is in effect. Foundation for surfacing future
1136 tool dependencies as the toolset grows.
1137 - **New `synchronized_output` setting** controls whether the renderer
1138 wraps each frame in DEC mode 2026 synchronized output. Accepts
1139 `auto` (default; respect the Ptyxis env opt-out), `on` (always emit
1140 DEC 2026, override the heuristic), or `off` (never emit DEC 2026).
1141 The cost of `off` is brief tearing on terminals that handle DEC
1142 2026 cleanly; it is purely a rendering-quality knob, not a
1143 correctness one. Set via `/set synchronized_output <auto|on|off>`
1144 or in `~/.config/deepseek/settings.toml`.
1145 - **`read_file` accepts `start_line` and `max_lines`** for chunked,
1146 bounded reads of large files (#1450, harvested from PR #1451 by
1147 **@Oliver-ZPLiu**). Default window is 200 lines / ~16 KB; the hard
1148 cap is 500 lines. Small files (≤ 200 lines AND ≤ 16 KB) still
1149 return their contents unchanged, so existing prompts that read
1150 config files / single source files see no behavior change. Large
1151 files now return a `<file …>`-wrapped, line-numbered window with
1152 `shown_lines`, `truncated`, and `next_start_line` attributes plus
1153 a `[TRUNCATED]` continuation hint — so the model can page through
1154 a 50 KB file in 16 KB slices instead of dragging the whole thing
1155 into the conversation context on every turn. PDFs continue to use
1156 `pages`; `start_line` / `max_lines` apply to text files only.
1157 - **`web/` dependency security updates.** Bumps:
1158 - `next` 15.5.16 → 15.5.18 (GHSA-26hh-7cqf-hhc6 — App Router
1159 middleware/proxy bypass via segment-prefetch routes; high
1160 severity).
1161 - `mermaid` 11.14.0 → 11.15.0 (GHSA family: Gantt-chart infinite-
1162 loop DoS, `classDef` HTML injection, `classDefs` /
1163 configuration CSS injection; all medium severity).
1164 - `eslint-config-next` 15.5.16 → 15.5.18 (matches Next.js).
1165 `npm run build` confirmed clean on the bumped lockfile. None of
1166 these affect the Rust TUI binary; the bumps are for the
1167 separately-deployed `deepseek-tui.com` site.
1168 - **MCP HTTP servers accept custom headers** for authentication
1169 (#1454, harvested from PR #1456 by **@Oliver-ZPLiu**). Mirrors the
1170 `headers` field that Claude Code, Codex, and OpenCode already
1171 accept in their MCP config — add e.g.
1172 `"headers": { "Authorization": "Bearer ${HF_TOKEN}" }` under any
1173 HTTP server entry in `~/.deepseek/mcp.json` and the headers are
1174 sent on every Streamable HTTP request. Headers are sent
1175 literally — env-var interpolation is a follow-up, so tokens
1176 pasted directly into mcp.json live there as plain text. The
1177 Streamable HTTP transport filters out empty keys, framing
1178 overrides (`Accept`, `Content-Type`), and CR/LF in values
1179 (response-splitting defense) so a single bad entry can't break
1180 protocol negotiation or smuggle a header through a misbehaving
1181 proxy. Stdio servers (`command`-based) and the legacy SSE
1182 transport ignore the field; SSE coverage is a follow-up.
1183
1184 ## [0.8.30] - 2026-05-11
1185
1186 A "tighten what we shipped" release. Bare single-letter keystrokes
1187 (`g`, `G`, `[`, `]`, `?`, `l`, `v`) no longer get eaten as transcript-
1188 nav shortcuts when the composer is empty — every one of them is now
1189 freely usable as the first character of a message. The water-spout
1190 animation in the footer is decoupled from `low_motion` so typewriter
1191 mode no longer hides the wave, and the v0.3.5-era 🐳→🐋 cycling
1192 indicator is back next to the effort chip after a long detour through
1193 geometric dots. Plus a handful of provider, shell, and config fixes
1194 that surfaced during v0.8.29 testing.
1195
1196 ### Added
1197
1198 - **The whale is back.** Restored the `🐳 → 🐳. → 🐳.. → 🐳... → 🐋 → 🐋.
1199 → 🐋.. → 🐋... → 🐋.. → 🐋. → 🐳..` cycling status indicator that
1200 originally shipped in v0.3.5 and silently disappeared in commit
1201 `1a04659a9` (the "smoother TUI streaming" pass, which swapped the
1202 12-frame whale sequence for a 6-frame geometric `◍ ◉ ◌` ring) and then
1203 was deleted outright in `f4dbf828c` (footer-polish commit). The chip
1204 renders in the header status cluster, immediately before the
1205 reasoning-effort chip — exactly where long-time users remember it.
1206 Idle frame is a steady 🐳; the cycle advances every 420 ms keyed off
1207 `App::turn_started_at`, so the breaching whale shows up halfway
1208 through any active turn.
1209
1210 Configurable via the new `status_indicator` setting:
1211 - `whale` (default) — the historical cycling whale.
1212 - `dots` — the geometric `◍ ◉ ◌` frames from the dots era.
1213 - `off` — hide the chip entirely.
1214
1215 Set via `/config status_indicator <whale|dots|off>` or in
1216 `settings.toml`.
1217
1218 ### Changed
1219
1220 - **Transcript-nav single-letter shortcuts now require `Alt`.** Before
1221 v0.8.30, pressing a bare `g`, `G`, `[`, `]`, `?`, `l`, or `v` with an
1222 empty composer hijacked the keystroke for transcript navigation — so
1223 typing "good morning" produced "ood morning" with no warning, and the
1224 v0.8.29 spot-fix at `c13ddb04d` (gg double-tap) only suppressed the
1225 scroll, not the lost character. The bindings are now uniformly
1226 `Alt+<key>`, mirroring `Alt+R` (history search) and `Alt+V` (tool
1227 details) which already followed this pattern:
1228
1229 | Old (bare) | New (`Alt+…`) | What it does |
1230 |---|---|---|
1231 | `gg` (double-tap) | `Alt+G` | scroll transcript to top |
1232 | `G` or `Shift+G` | `Alt+Shift+G` | scroll transcript to bottom |
1233 | `[` | `Alt+[` | jump to previous tool output |
1234 | `]` | `Alt+]` | jump to next tool output |
1235 | `?` | `Alt+?` | open the searchable help overlay (F1 / `Ctrl+/` also bound) |
1236 | `l` | `Alt+L` | open pager for last message |
1237 | `v` / `V` | `Alt+V` | open tool-details pager |
1238
1239 Plain letters are now always inserted into the composer as text. The
1240 `App::transcript_pending_g` field from the v0.8.29 half-fix is removed;
1241 the unified `alt_nav_modifiers` predicate replaces the per-key
1242 `is_empty()` checks.
1243
1244 ### Fixed
1245
1246 - **`low_motion = true` no longer hides the footer water-spout** when
1247 `fancy_animations = true`. The spout-strip animation in the footer was
1248 hard-gated on `!low_motion`, collapsing two unrelated concerns —
1249 streaming pacing and footer animation — onto one flag. The two are now
1250 orthogonal: `low_motion` governs only streaming pacing (typewriter vs.
1251 upstream cadence), and `fancy_animations` alone decides whether the
1252 water-spout strip renders. The wave itself is unchanged from prior
1253 releases (wall-clock-driven sine, same cadence as v0.8.29).
1254 - **Custom-base-URL providers preserve the user's model name** (#857
1255 class). Only OpenRouter was previously whitelisted; Sglang, Novita,
1256 Fireworks, Vllm, Ollama, and NvidiaNim users hitting custom gateways
1257 with a bare model name were getting HTTP 400s because the dispatcher
1258 rewrote the model identifier. Now any provider with a user-set
1259 `base_url` is treated as a custom endpoint and passes the model name
1260 through unchanged.
1261 - **`exec_shell` no longer freezes the TUI when a background subprocess
1262 outlives its parent shell** (#828, cherry-picked from PR #1475 by
1263 **@CrepuscularIRIS / autoghclaw**). Orphaned children that kept the
1264 pipe write-end open made `handle.join()` in `collect_output` block
1265 indefinitely; every transcript-rendering tick that called
1266 `list_jobs()` then hung the UI. The collector now kills the process
1267 group before joining the reader threads, and the previously dead
1268 `cleanup()` is now wired to drop completed jobs older than an hour.
1269
1270 ## [0.8.29] - 2026-05-11
1271
1272 A maintenance release anchored by a regression fix for the
1273 "scroll demon" (#1085 class, re-introduced by v0.8.27's flicker
1274 patch) and a wrong-project session-restore bug (#1395). Plus 25
1275 community PRs covering MCP transport, prompt steering, auto-routing
1276 language coverage, web-search SERP filtering, and broad test
1277 coverage additions.
1278
1279 ### Fixed
1280
1281 - **Scroll demon — alt-screen no longer drifts under parallel
1282 sub-agent load** (#1085 regression). The v0.8.27 flicker fix
1283 dropped the `\x1b[2J\x1b[3J` deep-clear from the viewport-reset
1284 path, which had been silently masking three `eprintln!` sites
1285 inside the sub-agent and network-policy modules. Each leak
1286 scrolled the alt-screen up by one row while ratatui's diff
1287 renderer remained convinced its model matched reality. Three
1288 layers of defence now ship together: a `tracing-subscriber`
1289 writing to `~/.deepseek/logs/tui-YYYY-MM-DD.log`, an fd-level
1290 `dup2` stderr redirect for the alt-screen lifetime (Unix only;
1291 Windows follow-up tracked), and module-level
1292 `#![deny(clippy::print_stdout, clippy::print_stderr)]` on
1293 `tools/`, `core/`, `tui/`, `runtime_threads.rs`, and
1294 `network_policy.rs`. The three known leak sites
1295 (`subagent::persist_state_best_effort`,
1296 `subagent::new_shared_subagent_manager`, `network_policy::record`)
1297 now route through `tracing::warn!` with structured fields.
1298 - **`Ctrl+R` session-restore picker is workspace-scoped** (#1395,
1299 PR #1397 from **@linzhiqin2003**). `SessionPickerView::new`
1300 previously listed every saved session on disk sorted globally —
1301 so opening DeepSeek-TUI in Project B and pressing `Ctrl+R` could
1302 hand back Project A's last conversation. The picker now filters
1303 by current workspace, with a fallback hint when no in-workspace
1304 sessions exist.
1305 - **MCP discovery survives malformed items** (PR #1410 from
1306 **@Liu-Vince**). The `tools/list`, `resources/list`,
1307 `resources/templates/list`, and `prompts/list` walks previously
1308 did `serde_json::from_value::<Vec<…>>(…).unwrap_or_default()`,
1309 which silently discarded the entire page when any single entry
1310 was misshapen. Each list now iterates per-item, skipping
1311 malformed entries with a `tracing::debug!` instead of dropping
1312 the rest of the catalogue. Composes with the v0.8.x pagination
1313 loop landed for #1256.
1314 - **MCP SSE transport accepts CRLF-framed endpoint events** (#1309,
1315 PR #1358 from **@reidliu41**). FastMCP / uvicorn-style SSE
1316 streams using `\r\n\r\n` separators now discover the endpoint and
1317 send initialization requests instead of timing out while waiting
1318 for an LF-only event boundary.
1319 - **Composer ignores leaked SGR mouse-report bursts** (#1418,
1320 PR #1421 from **@reidliu41**). Some SSH / IDE terminal chains
1321 leak fragments like `[<35;44;18M` into stdin while mouse capture
1322 is enabled; the composer now filters those bursts at the insertion
1323 boundary without stripping ordinary coordinate-like typed text.
1324 - **Footer right-cluster chips can no longer crowd the left status
1325 line** (#1357, PR #1417 from **@Wenjunyun123**). The footer now
1326 reserves visible space for the left status before selecting cache /
1327 aux chips, dropping oversized right-side chips instead of pushing
1328 the row over the available terminal width.
1329 - **Web search drops spam-stuffed SERPs** (#964, PR #1396 from
1330 **@linzhiqin2003**). The Bing / DDG fallback paths now filter
1331 the SEO-farm domains that were poisoning quick lookups.
1332 - **Language directive: `reasoning_content` follows the user's
1333 message language** (#1118, PR #1398 from **@linzhiqin2003**) —
1334 previously the project context's inferred `lang` could override
1335 the latest user message, leading to English thinking for a
1336 Chinese turn.
1337 - **Deferred tools hydrate their schema before first execution**
1338 (#1419, PR #1429 from **@SamhandsomeLee**). When the model asks
1339 for a deferred tool such as `edit_file` before seeing its schema,
1340 the engine now loads the tool, returns a non-executed hydration
1341 result with the expected fields, and requires a retry instead of
1342 executing guessed argument names. Common `edit_file` aliases such
1343 as `old_string -> search` and `new_string -> replace` are called
1344 out in the retry hint.
1345 - **DeepSeek public aliases replay thinking-mode tool turns**
1346 (PR #1428 from **@Beltran12138**). `deepseek-chat` and
1347 `deepseek-reasoner` now classify as V4 reasoning models for
1348 `reasoning_content` replay, preventing second-turn HTTP 400s
1349 after tool calls when users keep the onboarding default model
1350 alias.
1351 - **`Ctrl+O` expands thinking blocks still in flight.**
1352 Two compounding bugs were making the "thinking collapsed; press
1353 Ctrl+O for full text" affordance a lie. (1) `open_thinking_pager`
1354 only searched `app.history`, but after `ThinkingComplete` the
1355 finalized thinking entry sits in `app.active_cell` with
1356 `streaming = false` until the active cell flushes at end-of-turn;
1357 during that window the handler surfaced "No thinking blocks to
1358 expand" while the affordance pointed at the live entry. Routed
1359 through the existing `cell_at_virtual_index` / `virtual_cell_count`
1360 resolver that `open_tool_details_pager` already uses, so
1361 selection-based and most-recent lookups both reach in-flight
1362 entries. (2) The keybinding guard required `key.modifiers ==
1363 KeyModifiers::CONTROL` (exact match), so any extra modifier bit
1364 set by the terminal — Shift while a native-selection bypass was
1365 active, Caps Lock indicator on some keyboard layouts — silently
1366 fell through to the `$EDITOR` arm and did nothing visible on an
1367 empty composer. Relaxed to `contains(KeyModifiers::CONTROL)` to
1368 match the existing Ctrl+P / Ctrl+B pattern. Regression-guarded by
1369 `open_thinking_pager_finds_thinking_in_active_cell`.
1370 - **Skill completions no longer flood the top-level slash menu**
1371 (#1437, PR #1442 from **@reidliu41**). Installed skills now
1372 complete under `/skill <name>` while the root `/` menu stays
1373 focused on built-in commands.
1374 - **`edit_file` rejects no-op replacements** (PR #1460 from
1375 **@xiluoduyu**). Identical `search` / `replace` arguments now
1376 fail fast with a clear validation error instead of producing an
1377 empty diff that can trap the model in retry loops.
1378 - **Windows-terminal glyph widths are stable** (#1314, PR #1465
1379 from **@CrepuscularIRIS**). SMP emoji in the header and file tree
1380 were replaced with BMP-width-safe symbols / text so cmd,
1381 PowerShell, WezTerm, and Alacritty do not mismeasure rows.
1382 - **Ghostty defaults to low-motion rendering** (#1445, PR #1468
1383 from **@CrepuscularIRIS**). `TERM_PROGRAM=ghostty` now receives
1384 the same animation cap as VS Code terminals to avoid redraw
1385 flicker on affected setups.
1386 - **Docker buildx provenance permission failures get an actionable
1387 hint** (#1449, PR #1469 from **@CrepuscularIRIS**). macOS shell
1388 outputs matching the restricted provenance metadata failure now
1389 include guidance to disable provenance for that build.
1390 - **Windows CMD mouse-wheel fallback scrolls the transcript**
1391 (#1443, PR #1471 from **@CrepuscularIRIS**). When mouse capture is
1392 off, composer arrow-scroll defaults on so terminal wheel events
1393 mapped to Up / Down do not cycle composer history.
1394
1395 ### Added
1396
1397 - **MCP HTTP transport honors `HTTP(S)_PROXY` / `NO_PROXY`** (#1408
1398 from **@hlx98007**). Reqwest 0.13 does not auto-detect proxy env
1399 vars by default, so MCP HTTP connections were bypassing the
1400 proxy that every other tool on the box (curl, npm, git, …) was
1401 using. Connections behind corporate egress proxies and
1402 China-mainland Clash / Shadowsocks tunnels now work transparently.
1403 Malformed `HTTPS_PROXY` values log a `tracing::warn!` and the
1404 connection proceeds without a proxy rather than failing the MCP
1405 attach.
1406 - **Note management slash commands** (PR #1407 from
1407 **@reidliu41**). `/note add`, `/note list`, and friends for
1408 persistent maintainer-style notes inside the TUI, backed by
1409 `~/.deepseek/notes/`.
1410 - **Header surfaces the runtime version chip.** A `v0.8.29` tag
1411 sits in the header's right cluster after the provider / effort /
1412 Live / context chips. Styled with `palette::TEXT_HINT` so it
1413 reads behind the streaming indicators. Drops first under tight
1414 terminal width.
1415 - **Global `~/.deepseek/AGENTS.md` now merges with project
1416 AGENTS.md** (#1157, PR #1399 from **@linzhiqin2003**) instead of
1417 being shadowed when a workspace ships its own.
1418 - **Auto-routing recognises CJK debug / search keywords** (PRs
1419 #1401 and #1402 from **@linzhiqin2003**) — `--model auto` and
1420 the reasoning-effort picker correctly route Chinese / Japanese
1421 technical queries that previously fell through to the generic
1422 baseline.
1423
1424 ### Security
1425
1426 - **`sync-cnb.yml` workflow hardened** (CodeQL finding from
1427 v0.8.28). Adds explicit `permissions: contents: read`
1428 (least-privilege), bumps `actions/checkout` v3 → v4, and
1429 narrows the trigger from `on: [push]` to `on: push.branches:
1430 [main]` + `tags: ['v*']`. Feature branches no longer mirror to
1431 CNB; only `main` and tagged releases do.
1432 - **Post-exit resume hint avoids session-id taint.** The TUI now
1433 checks whether a session exists separately from the constant
1434 resume-hint text it prints after leaving the alt-screen, resolving
1435 the `rust/cleartext-logging` CodeQL alert without reintroducing
1436 scroll-demon stdout writes.
1437
1438 ### Internal
1439
1440 - **+438 LOC of new test coverage** across four PRs from
1441 **@linzhiqin2003**: `error_taxonomy::classify_error_message`
1442 and Display impls (#1403), `parse_pages_arg` edge cases (#1404),
1443 `optional_search_max_results` precedence (#1405), and
1444 `sanitize_stream_chunk` control-byte filtering (#1406).
1445 - **`runtime_log` module** ships with a regression test pinning
1446 the `HOME` / `USERPROFILE` / `dirs::home_dir()` resolution
1447 order, holding the process-wide `test_support::lock_test_env()`
1448 lock for env-mutation safety.
1449 - **Header rendering** gains two regression tests
1450 (`header_renders_version_chip_when_width_allows` and
1451 `narrow_header_drops_version_chip_before_dropping_mode`)
1452 pinning the version chip's cascade priority.
1453 - **Workspace/session test isolation** tightened (PR #1431 from
1454 **@reidliu41**). Git-root detection ignores invalid parent `.git`
1455 markers, env-mutating tests share the crate-wide test lock, and
1456 the streamable HTTP MCP mock server stays alive for the full test.
1457 - **Config-mutating smoke tests now isolate `DEEPSEEK_CONFIG_PATH`.**
1458 The command registry and web-config commit tests no longer rewrite
1459 the developer's real `~/.deepseek/config.toml` while validating
1460 release candidates locally.
1461
1462 ## [0.8.28] - 2026-05-10
1463
1464 A maintenance release bundling four streaming / approvals / cache
1465 bug-fix cherry-picks, six smaller community fixes, a Cmux
1466 notification probe, GPU-terminal flicker hardening via DEC 2026
1467 synchronized output, VS Code low-motion auto-detection, a CNB
1468 mirror workflow, V4-steered tool descriptions, and test-suite
1469 stabilization for parallel-test environment races.
1470
1471 ### Added
1472
1473 - **CNB mirror workflow** (PR #1373 from **@Anyexyz**) — a
1474 GitHub Actions workflow (`sync-cnb.yml`) mirrors every push to
1475 the `cnb.cool/deepseek-tui.com/DeepSeek-TUI` repository,
1476 closing out the long-standing China-mirror request. Requires the
1477 `CNB_GIT_TOKEN` repo secret.
1478 - **Cmux desktop notification support via `LC_TERMINAL`** (#1281,
1479 PR #1340 from **@CrepuscularIRIS**) — Cmux sets
1480 `LC_TERMINAL=Cmux` rather than `TERM_PROGRAM`, so the previous
1481 notification probe fell back to `BEL` instead of using OSC 9.
1482 `resolve_method()` now checks `LC_TERMINAL` as a secondary probe
1483 and adds Cmux to the OSC 9 allowlist. Terminals that set
1484 neither env var can still force OSC 9 via
1485 `[notifications].method = "osc9"`. Two regression tests pin the
1486 Cmux and WezTerm `LC_TERMINAL` paths; the existing
1487 unknown-terminal-on-Unix test now clears `LC_TERMINAL` before
1488 asserting fallback so it doesn't flake on CI hosts that set it.
1489 - **DEC 2026 synchronized output around terminal repaints** (PR
1490 #1361 from **@xuezhaoyu**) — the viewport-reset path now wraps
1491 `terminal.clear()` in `\x1b[?2026h` / `\x1b[?2026l` so
1492 GPU-accelerated terminals (Ghostty, VSCode Terminal, Kitty,
1493 WezTerm) defer rendering until the whole frame is staged,
1494 eliminating mid-frame flicker on resize / focus / TurnComplete.
1495 The earlier "drop destructive 2J/3J" fix from v0.8.27 stays;
1496 this PR is complementary, batching the same lighter reset
1497 sequence into a single synchronized frame. Terminals without
1498 DEC 2026 support silently ignore the sequence.
1499 - **`low_motion` auto-enables under VS Code integrated terminal**
1500 (PR #1365 from **@CrepuscularIRIS**) — `apply_env_overrides()`
1501 now treats `TERM_PROGRAM=vscode` the same way it treats
1502 `NO_ANIMATIONS=1`: force `low_motion = true` and
1503 `fancy_animations = false`. The VS Code terminal compositor
1504 cannot keep up with 120 fps redraws and produces rapid flicker
1505 (#1356); the 30 fps low-motion cap is the right default there.
1506 Env overlays always win over the disk-loaded value, matching
1507 the existing precedence for `NO_ANIMATIONS`.
1508
1509 ### Fixed
1510
1511 - **Cache usage shows 0 when API omits cache data** (#1391, PR #1392
1512 from **@Oliver-ZPLiu**) — `SessionUsage.cache_creation_input_tokens` /
1513 `cache_read_input_tokens` are now `Option<u64>` instead of `u64`
1514 defaulting to 0. When the upstream API doesn't report cache
1515 hit/miss, the model sees `null` instead of misleading zeros, and
1516 reasoning about cache utilization is accurate.
1517 - **Deny of one tool call no longer blocks all future calls of the
1518 same tool** (#1377, PR #1388 from **@Oliver-ZPLiu**) — denying a
1519 tool call now only caches the per-call `approval_key`, not the
1520 tool type. Subsequent invocations of the same tool prompt for
1521 approval again instead of being silently auto-denied.
1522 - **Streaming thinking blocks no longer drop their tail on
1523 MessageComplete** (#861 RC3, PR #1389 from **@linzhiqin2003**) —
1524 the active streaming entry is now drained into the finalized
1525 cell on `MessageComplete`, eliminating a data-loss path where
1526 the last chunk(s) of a streaming "thinking" reply could be
1527 discarded when `MessageComplete` arrived ahead of
1528 `ThinkingComplete` in a bursty event stream. Also closes a
1529 related HTTP 400 on the next turn (DeepSeek V4 requires
1530 `reasoning_content` replay for assistant messages that carry
1531 tool calls).
1532 - **Streaming thinking renders live in collapsed view** (#861 RC4,
1533 #1324, PR #1390 from **@linzhiqin2003**) — collapsed thinking
1534 cells now stream their content as it arrives instead of staying
1535 at a static "thinking..." placeholder until streaming ends. When
1536 the live body exceeds the collapsed budget, the truncation
1537 affordance ("thinking continues; press Ctrl+O for full text")
1538 now fires during streaming with head lines dropped so the
1539 visible window tracks the live cursor at the bottom.
1540 - **First-turn latency bounded on large workspaces** (#697, PR #1386
1541 from **@linzhiqin2003**) — the working-set file walker now caps
1542 the number of entries it visits during initial indexing, so
1543 starting a session in a workspace with a deep `node_modules`,
1544 `target`, or `.venv` no longer stalls the first response on
1545 filesystem traversal.
1546 - **Duplicate error toast on transcript-rendered turn errors** (PR
1547 #1368 from **@douglarek**) — when a turn error is already in the
1548 transcript as a system/error cell, the status-line toast is
1549 suppressed so the user doesn't see the same failure twice.
1550 - **Clearer continue tip on idle prompts** (PR #1370 from
1551 **@nightfallsad**) — the "press Tab to continue" affordance now
1552 uses concrete language instead of a vague hint.
1553 - **Ctrl+Enter content lost when engine is idle** (#1331, PR #1347
1554 from **@Oliver-ZPLiu**) — when no turn was active, `Ctrl+Enter`
1555 routed the message to `rx_steer` (only monitored inside
1556 `handle_deepseek_turn`), so the user saw their message in the
1557 transcript via the local mirror but the LLM never received it —
1558 the next regular Enter would drain it as a "stale steer". The
1559 idle path now sends through the standard `handle_send_message`
1560 flow so the submission reaches the engine.
1561 - **Explicit hidden / ignored `@`-mention completions work**
1562 (#1270 follow-up) — PR #1270 from **@SamhandsomeLee** landed
1563 the `add_local_reference_completions` helper and tests in
1564 v0.8.27 but never wired it into `Workspace::completions()` or
1565 `build_file_index`. The two regression tests were ignored with
1566 a "v0.8.28 follow-up" marker. This release wires the helper
1567 into both entry points so `@.deepseek/commands/start-task.md`
1568 and `@.generated/specs/device-layout.md` (and the basename
1569 fuzzy-resolve equivalent) now surface from gitignored
1570 user-folders while `.deepseekignore` entries stay blocked.
1571 Both tests un-ignored.
1572
1573 ### Changed
1574
1575 - **Prompt-side reliability guidance** (PR #1393 from
1576 **@Oliver-ZPLiu**) — `prompts/base.md` gains three Verification
1577 Principle bullets steering the model to verify before reporting
1578 complete, preserve only key facts from tool results, and
1579 inspect errors before retrying. Combined with the truthful-
1580 reporting addition from #1392, the model is less likely to claim
1581 unverified successes or repeat the identical failing tool call.
1582 - **V4-steered tool descriptions** (#711, PR #1379 from
1583 **@linzhiqin2003**) — every model-visible tool description
1584 (`read_file`, `write_file`, `edit_file`, `list_dir`,
1585 `grep_files`, `file_search`, `web_search`, `apply_patch`,
1586 `fetch_url`) now opens with a short *"use this instead of X
1587 in exec_shell"* steering line, the return shape, and the
1588 limits. Routes V4 toward our typed tools and away from
1589 shell footguns. All description strings stay under 1024
1590 chars (max: 350) with no embedded newlines so the cached
1591 tool catalogue stays prefix-stable for V4's KV cache.
1592 Removes the unused legacy `normal.txt` / `plan.txt` /
1593 `yolo.txt` prompt templates (referenced only by their own
1594 self-tests).
1595
1596 ### Internal
1597
1598 - Test-suite parallelism stabilization (commit
1599 `test: stabilize parallel test execution`). Folds three local
1600 test-mutex implementations into the process-wide
1601 `test_support::lock_test_env`, eliminating a class of
1602 intermittent failures (`refresh_system_prompt_is_noop_when_unchanged`,
1603 `save_api_key_for_openrouter_writes_provider_table`,
1604 `list_archives_sorts_by_cycle_number`) observed during the
1605 v0.8.27 release cycle.
1606 - Windows `task_manager` timeout bumped 3s → 10s on four tests
1607 exercising durable task recovery, addressing an intermittent
1608 CI timeout on Windows under file-I/O load.
1609 - `provider_switch_clears_turn_cache_history` now isolates
1610 `HOME` / `USERPROFILE` to a tempdir for its lifetime. The test
1611 was silently writing `default_provider = "ollama"` to the
1612 developer's real `~/Library/Application Support/deepseek/settings.toml`
1613 on every run, which then contaminated parallel-running picker
1614 tests because Ollama is a pass-through provider that hides the
1615 DeepSeek model rows.
1616 - `settings::tests::no_animations_test_guard` and
1617 `term_program_test_guard` both now return
1618 `crate::test_support::lock_test_env()` instead of their own
1619 module-local mutexes — folding them into the same
1620 process-wide test env lock the v0.8.27 EnvGuard family was
1621 migrated to. Without this, a `NO_ANIMATIONS=1` write from one
1622 test family could race a `TERM_PROGRAM=iTerm.app` write from
1623 the other through the shared `apply_env_overrides` path and
1624 flip `low_motion` to `true` on the assertion side.
1625
1626 ## [0.8.27] - 2026-05-10
1627
1628 A polish release bundling 17 community PRs plus a focused user-issue
1629 sweep over the 24–48 hours after v0.8.26 shipped. Headline fixes:
1630 cross-terminal flicker on Ghostty / VSCode / Win10 conhost (most-
1631 reported v0.8.26 regression), long-text right-edge overflow, an
1632 in-app pager copy-out, context-sensitive Ctrl+C, an MCP pool that
1633 auto-reloads on config changes, and a model-callable `notify` tool.
1634 Big thanks to every contributor below.
1635
1636 ### Added
1637
1638 - **Unified `/mode` command** (#1247) — `/mode [agent|plan|yolo|1|2|3]`
1639 replaces the separate `/agent`, `/plan`, and `/yolo` commands. Running
1640 `/mode` without arguments opens a picker modal. The legacy aliases
1641 (`/yolo`, `/agent`, `/plan`) are kept as compatibility shorthands.
1642 Thanks **@reidliu41**.
1643 - **`/status` runtime diagnostics** (#1223) — shows version, provider,
1644 model, workspace, mode, permissions, context-window usage, cache
1645 hit/miss, and session cost. Previously `/status` was an alias for
1646 `/statusline` (footer config); that alias is now `/statusline` only.
1647 Thanks **@reidliu41**.
1648 - **`/feedback` command** (#1185) — opens the matching GitHub issue
1649 template (bug report, feature request) in the browser. Security
1650 vulnerability reports route through the project's security policy
1651 page first. Thanks **@reidliu41**.
1652 - **Session artifact metadata** (#1220) — large tool outputs spilled to
1653 the session artifacts directory are now tracked in a durable metadata
1654 index, so saved sessions retain references across save/restore cycles.
1655 Thanks **@THINKER-ONLY**.
1656 - **Subagent results are self-reports** (#1140) — the compacted result
1657 summary now notes that child-agent outputs are unverified self-reports.
1658 The parent model should verify side effects with tools like `read_file`
1659 or `list_dir` before claiming success. Thanks **@THINKER-ONLY**.
1660 - **Global AGENTS.md fallback** (#1197) — when the workspace and its
1661 parents don't provide project instructions, the TUI now loads
1662 `~/.deepseek/AGENTS.md` before falling back to auto-generated
1663 instructions. Repo-local context still takes priority.
1664 Thanks **@manaskarra**.
1665 - **`--yolo` forwarded from CLI to TUI** (#1233) — the `deepseek --yolo`
1666 flag now propagates through the dispatcher to the TUI binary via
1667 `DEEPSEEK_YOLO=true`. Previously the flag set `yolo` in the CLI
1668 process but the TUI session started in its default mode.
1669 Thanks **@fuleinist**.
1670 - **`composer_arrows_scroll` config** (#1211) — a new
1671 `tui.composer_arrows_scroll` option (default `false`) makes plain
1672 Up/Down arrow keys scroll the transcript when the composer is empty,
1673 instead of navigating input history. Helpful for terminals that map
1674 trackpad gestures to arrow keys. Thanks **@lbcheng888**.
1675 - **Session cost persistence** (#1192) — accumulated costs (session +
1676 sub-agents, both USD and CNY) and the displayed-cost high-water mark
1677 now survive session save/restore, so the monotonic cost guarantee
1678 (#244) holds across restarts. Thanks **@lbcheng888**.
1679 - **Provider-aware model picker and provider persistence** (#1320) —
1680 switching providers now persists the choice to
1681 `~/.deepseek/settings.toml` so it survives restarts. The model
1682 picker hides DeepSeek-specific models when a non-DeepSeek provider
1683 is active. `OPENAI_MODEL` env var now overrides the per-provider
1684 model rather than the global `default_text_model`. Bailian / ZhiPu
1685 Coding Plan endpoints are now supported.
1686 Thanks **@imkingjh999**.
1687 - **HTTP User-Agent header** (#1320) — all outbound API requests now
1688 carry `deepseek-tui/{version}` in the User-Agent, matching the format
1689 `fetch_url` already uses. Thanks **@imkingjh999**.
1690
1691 ### Fixed
1692
1693 - **Cross-terminal flicker on TurnComplete / focus / resize** (#1119,
1694 #1260, #1295, #1352, #1356, #1363, #1366) — the viewport-reset
1695 sequence emitted before each forced repaint no longer includes
1696 `\x1b[2J\x1b[3J`. Combined with the immediately-following ratatui
1697 `terminal.clear()`, the destructive pair produced a double-clear that
1698 Ghostty, the VSCode integrated terminal, and Win10 conhost rendered
1699 as a visible blank-then-repaint flicker. The lighter sequence
1700 (`\x1b[r\x1b[?6l\x1b[H`) plus the alt-screen buffer's double-buffering
1701 handles viewport correctness without flicker. macOS Terminal.app /
1702 iTerm2 / alacritty users were already unaffected and remain so.
1703 - **`/skills --remote` and `/skills sync` diagnostics** (#1329) — the
1704 underlying anyhow chain has always been formatted with `{err:#}`, but
1705 the chain alone is often opaque (e.g. "error sending request"). The
1706 error message now appends a one-line hint when the chain matches a
1707 common failure pattern: DNS / connection refused / TLS / 4xx / 429 /
1708 timeout. Each hint points at the most likely cause and a concrete
1709 next step.
1710
1711 ### Added
1712
1713 - **Pager copy-out** (#1354) — full-screen pagers (`Alt+V` tool details,
1714 `Ctrl+O` thinking content, shell-job / task / MCP-manager pagers, and
1715 the selection pager) now accept `c` or `y` to copy the entire body to
1716 the system clipboard. The pager intercepts mouse capture so terminal-
1717 native selection isn't available inside it; this restores the
1718 copy-out path that users on macOS / Windows / WSL expect. The footer
1719 hint now reads `… / search c copy q/Esc close`. A status toast
1720 confirms success ("Pager content copied"), empty-body, or failure.
1721 - **`notify` tool** (#1322) — model-callable desktop notification.
1722 Always-loaded (no ToolSearch round-trip). Routes through the existing
1723 `tui::notifications` infrastructure: OSC 9 on iTerm2 / Ghostty /
1724 WezTerm, BEL fallback on macOS / Linux, `MessageBeep` on Windows when
1725 explicitly opted in. Honours the user's `[notifications].method`
1726 config — when set to `off`, the tool is a silent no-op. Title and
1727 body are length-capped (80 / 200 chars) on character (not byte)
1728 boundaries to keep the OSC 9 escape clean and avoid mid-grapheme
1729 truncation. The tool description steers the model away from chatter:
1730 use only when a long-running task completes or genuinely needs the
1731 user's attention.
1732
1733 ### Fixed (cont.)
1734
1735 - **Long output text overflowed the right edge** (#1344, #1351) —
1736 paragraph rendering (`render_line_with_links`) and code-block
1737 wrapping (`wrap_text` for `Block::Code`) were word-based: a single
1738 word wider than the available column was placed alone on a line and
1739 silently overflowed. Long URLs, paths, hashes, and no-whitespace CJK
1740 runs all hit this. Both paths now hard-break overlong words at the
1741 character level, matching the v0.8.25 fix for table cells. The
1742 rendered width is capped at the budget for every line; full content
1743 is preserved across wrapped segments. Snapshot-style tests pin the
1744 invariant at widths 40, 60, 80, and 120.
1745
1746 ### Changed
1747
1748 - **`Ctrl+C` now copies an active transcript selection** (#1337) — on
1749 Windows, plain `Ctrl+C` is the OS-wide copy chord, and treating it
1750 as "exit" stole work whenever a user copy-pasted from the
1751 transcript. `Ctrl+C` is now a four-stage decision: 1) selection
1752 active → copy + clear (matches the OS convention); 2) turn in
1753 flight → cancel (unchanged); 3) quit-armed within 2s → exit cleanly
1754 (unchanged); 4) idle, no selection → arm the 2-second
1755 "press Ctrl+C again to quit" prompt (unchanged). The decision is
1756 factored into a `CtrlCDisposition` helper with a unit-tested
1757 priority table. `Cmd+C` (macOS) and `Ctrl+Shift+C` continue to copy
1758 unchanged.
1759 - **Cancel-key discoverability hint on turn start** (#1367) — when a
1760 turn begins, the status-message slot now surfaces "Press Esc or
1761 Ctrl+C to cancel" if the slot is otherwise empty. Real transient
1762 status messages still take precedence; the hint clears as soon as
1763 any other update fires. Closes the loop on users who didn't know
1764 how to interrupt a long-running turn.
1765 - **Lazy auto-reload of MCP pool on config-file change** (#1267 part 2) —
1766 v0.8.26 surfaced the underlying spawn errors; v0.8.27 closes the
1767 loop on the second half of the report (manual `/mcp reload` after
1768 `~/.deepseek/mcp.json` edits). `McpPool::get_or_connect` now does a
1769 cheap `stat` + content-hash check before each connection lookup. If
1770 the on-disk file's mtime moved AND its content hash changed since
1771 the pool was loaded, all live connections are dropped so the next
1772 `get_or_connect` reattaches under the new config. Pool-construction
1773 via `McpPool::new` (tests, ad-hoc snapshots) is unaffected — only
1774 pools built with `from_config_path` watch the source file. No file
1775 watcher; no long-lived task. mtime-only churn (touched but
1776 byte-unchanged content) does not trigger a reload, so networked
1777 filesystems with coarse mtime granularity won't churn the pool.
1778 - **Paste consolidation now happens at paste time, not submit time** —
1779 large bracketed pastes that exceed the 16 000-char safety cap are
1780 now folded into a workspace `.deepseek/pastes/paste-…md` file and
1781 swapped for an `@`-mention immediately on paste, instead of waiting
1782 until the user presses Enter. The user sees the `@`-mention in the
1783 composer (and the "consolidated → @mention" toast) before deciding
1784 whether to send, eliminating the "I pressed Enter and an `@`-mention
1785 appeared in the chat I didn't authorise" surprise. The submit-time
1786 consolidation remains as a safety net for any other code path that
1787 fills the buffer above the cap, so the cap is still enforced exactly
1788 once.
1789 - **Auto-disable paste-burst once bracketed paste verified** — the
1790 rapid-keystroke paste-burst heuristic (default-on for terminals
1791 without bracketed paste) used to keep running on every session.
1792 Once a real `Event::Paste` arrives in a session, paste-burst now
1793 short-circuits — bracketed paste is verified working, and running
1794 the heuristic alongside it just creates false positives on fast
1795 typing / IME commits / autocomplete bursts. Terminals that never
1796 deliver bracketed paste (the original target audience) are
1797 unaffected; the heuristic still fires there.
1798 - **Short CJK multi-line paste no longer auto-submits first line**
1799 (#1302) — pasting `请联网搜索:\nSTM32 …` (short non-ASCII first line
1800 followed by a newline) used to fail the paste-burst detection
1801 heuristic because the first line had no whitespace and was under
1802 the 16-char threshold; the trailing pasted newline then fell
1803 through as a real Enter and submitted the first line on its own.
1804 The heuristic now treats any non-ASCII run as paste-like, so the
1805 Enter is absorbed into the burst buffer. Thanks **@reidliu41**
1806 (PR #1342).
1807 - **Onboarding screens render in the selected language** — when a
1808 user picked 简体中文 / 日本語 / Português (Brasil) at the language
1809 step, every subsequent screen (API key entry, workspace trust
1810 prompt, final tips) used to remain in English. The
1811 `set_locale_from_onboarding` path now drives the title, body
1812 copy, hints, and footer of each onboarding screen through the
1813 localization table, so once you pick your language the rest of
1814 the flow is in that language. Particularly nice for users on
1815 CJK input methods who want to avoid IME juggling during setup.
1816 - **`/skills <prefix>` filters the local skills list** (#1318) — on
1817 top of the v0.8.26 inter-row spacing (#1328 from @reidliu41), the
1818 list now narrows to skills whose names start with the typed
1819 prefix. Case-insensitive. The header reflects matched count vs
1820 registry total; an empty match set says so explicitly and points
1821 back at unfiltered `/skills`. `--remote` and `sync` stay
1822 reserved as subcommands; any `--`-prefixed argument is rejected
1823 rather than being silently treated as a no-match prefix.
1824 - **HTTP 400 quota errors retried** (#1203) — some OpenAI-compatible
1825 gateways return quota/rate-limit errors as HTTP 400 instead of 429.
1826 These are now classified as retryable `RateLimited` errors.
1827 Thanks **@dst1213**.
1828 - **Explicit hidden/ignored file completions** (#1270) — when the user
1829 types an explicit path starting with `.` (e.g., `.deepseek/commands/`),
1830 the file-completion system now surfaces hidden and gitignored entries
1831 while still respecting `.deepseekignore`. Thanks **@SamhandsomeLee**.
1832
1833 ### Changed
1834
1835 - **Windows mouse capture docs** (#1181) — the `--mouse-capture` help
1836 text and the configuration docs now mention scrollbar dragging and
1837 note that raw terminal selection on Windows may cross the sidebar.
1838 Thanks **@Oliver-ZPLiu**.
1839 - **README zh-CN sync** (#1235) — the Chinese README's quickstart section
1840 now shows `deepseek run pr <N>` instead of the outdated
1841 `deepseek pr <N>`. Thanks **@whtis**.
1842 - **Tool output render perf** (#1098) — tool output summaries and the
1843 "is this a diff?" check are now pre-computed once at cell creation
1844 instead of re-parsed every frame. Tool output cells also got a visual
1845 card-rail (`╭ │ ╰`) for clearer grouping. Thanks **@lbcheng888**.
1846
1847 ### Internal
1848
1849 - Test coverage for approval decision branches (@tuohai666, #1316)
1850 - Test coverage for hook event dispatch paths (@tuohai666, #1317)
1851
1852 ## [0.8.26] - 2026-05-09
1853
1854 A security + polish release. Two responsibly-disclosed issues were
1855 patched, plus a small batch of internal release-pipeline fixes. Big
1856 thanks to **@JafarAkhondali** and **@47Cid** for the disclosures.
1857
1858 ### Security
1859
1860 - Hardened the `fetch_url` tool's network-target validation
1861 (GHSA-88gh-2526-gfrr). Thanks to **@JafarAkhondali**.
1862 - Tightened the default privileges of sub-agents created through
1863 `task_create` (GHSA-72w5-pf8h-xfp4). Thanks to **@47Cid**.
1864
1865 Both items will have full advisory text once the GHSA entries are
1866 published.
1867
1868 ### Fixed
1869
1870 - **Hint when root `base_url` is set with a non-DeepSeek provider
1871 (#1308)** — config load now logs a warning telling the user to
1872 move the URL under the matching `[providers.<name>]` table or use
1873 the `*_BASE_URL` env var. Closes the silent-ignore footgun for
1874 Ollama / vLLM / OpenAI-compatible setups.
1875 - **Insecure base-URL error message is more discoverable (#1303)** —
1876 the rejection now spells out which env var to set (with underscores
1877 visible), notes that loopback hosts are auto-allowed, and shows a
1878 one-line `DEEPSEEK_ALLOW_INSECURE_HTTP=1 deepseek` example.
1879 - **Workspace skills survive prompt truncation** — when the skill
1880 catalog needs trimming to fit the prompt budget, workspace-local
1881 skills now keep precedence over global ones rather than being
1882 truncated indiscriminately. Thanks **@hhhaiai**.
1883 - **`/skills` listing has visual spacing** between entries so long
1884 skill descriptions don't run together. Thanks **@reidliu41**.
1885 - **Provider base-URL overrides reach the active provider** — the
1886 per-provider `*_BASE_URL` env vars (e.g. `OPENAI_BASE_URL`,
1887 `OPENROUTER_BASE_URL`) now propagate into the active provider's
1888 config entry consistently. Closes a gap where the override was
1889 parsed but never applied. Thanks **@reidliu41**.
1890 - **WSL2 turn-start timeout** — `TurnStarted` is now emitted before the
1891 snapshot step so a slow snapshot on WSL2's `/mnt/*` volumes doesn't
1892 push past the runtime watchdog and surface a spurious "engine may
1893 have stopped" error. Thanks **@michaeltse321**.
1894 - **`/init` auto-adds `.deepseek/` to `.gitignore` (#1326)** when the
1895 workspace is a git repo, so workspace-local snapshots, instructions,
1896 and pastes don't get accidentally committed. Idempotent on repeated
1897 runs. Thanks **@Giggitycountless**.
1898 - **MCP tool ordering is deterministic** — discovered tools and the
1899 resulting API tool block are now sorted by name so the prompt
1900 prefix the model sees is stable across runs, regardless of
1901 server-side pagination order. Improves prompt-cache hit rates with
1902 multi-server MCP setups. Thanks **@hxy91819**.
1903 - **Error cells render as plain text** so env-var names (`API_KEY_FOO`)
1904 in error messages keep their underscores instead of being parsed as
1905 markdown emphasis. Thanks **@douglarek**.
1906 - **`/clear` resets the Todos sidebar (#1258)** — previously `/clear`
1907 only reset the Plan panel; the Todos checklist persisted across
1908 clears. Thanks **@Giggitycountless**.
1909 - **Drag-select past the viewport edge auto-scrolls (#1163, #1255,
1910 #1292, #1298)** — when the mouse drag reaches the top or bottom of
1911 the transcript area the viewport now scrolls to follow the
1912 selection, the way text editors do. **Copy strips every visual-only
1913 decoration glyph** — tool-card rails (`╭│╰`), transcript rails
1914 (`▏`), reasoning rails (`╎`), tool-status symbols (`·•◦`), and
1915 tool-family glyphs no longer leak into clipboard output. Thanks
1916 **@Oliver-ZPLiu**.
1917 - MCP stdio servers no longer discard stderr. The spawn site now pipes
1918 stderr through a bounded ring buffer; when a server crashes
1919 mid-session, the transport-closed error includes the captured stderr
1920 tail instead of disappearing into `Stdio::null`. Useful for debugging
1921 Node/Python MCP servers that fail well after `initialize`.
1922 - Mouse capture now defaults on inside Windows Terminal (#1169, #1298,
1923 #1331). When `WT_SESSION` is set, in-app text selection is enabled
1924 by default and the wheel scrolls the transcript again (rather than
1925 the terminal interpreting wheel events as input-history keys).
1926 Legacy conhost stays opt-in via `--mouse-capture` or `[tui]
1927 mouse_capture = true` to preserve the protections from #878 / #898.
1928 Selection now clamps to the transcript region instead of the
1929 terminal painting native selection across the sidebar.
1930 - The build script now invalidates its cache on `.git/HEAD` changes, so
1931 the embedded short-SHA in `deepseek --version` stays current after
1932 commits and branch switches without needing `cargo clean`. Both
1933 regular checkouts and `git worktree` layouts are handled.
1934 - The release-time `changelog_entry_exists_for_current_package_version`
1935 gate walks up from the crate manifest to find `CHANGELOG.md` instead
1936 of assuming a fixed `../../CHANGELOG.md` layout. The workspace path
1937 still resolves; running the suite from a packaged crate skips the
1938 gate quietly instead of panicking.
1939
1940 ## [0.8.25] - 2026-05-09
1941
1942 A stabilization + drift-fixes release. Headline work hardens the
1943 self-update path (no more `curl` shellout, real SHA-256 verification),
1944 fixes long-cell truncation in markdown tables, centralizes the MCP
1945 JSON-RPC framing, and unifies terminal-mode recovery on focus events.
1946 Big thanks to **Reid Liu (@reidliu41)** (Streamable HTTP MCP transport,
1947 `/config` column alignment), **Duducoco (@Duducoco)** (cache-stable
1948 `reasoning_content` replay), **jinpengxuan (@jinpengxuan)** (provider
1949 credentials during onboarding), **heloanc (@heloanc)** (Home/End cursor
1950 keys), **Wenjunyun123 (@Wenjunyun123)** (docs anchor scroll), and
1951 **Liu-Vince (@Liu-Vince)** (zh-Hans approval-dialog wording) for the
1952 contributions below.
1953
1954 ### Added
1955
1956 - **Streamable HTTP MCP endpoints with SSE fallback (#1300)** — adds
1957 the third MCP transport alongside stdio and SSE. The new transport
1958 posts JSON-RPC over plain HTTP with optional SSE upgrade for servers
1959 that prefer streaming responses. Thanks **Reid Liu (@reidliu41)**.
1960 - **`recall_archive` exposed in the parent agent registry** — the
1961 read-only BM25 archive search tool was previously only available to
1962 sub-agents; it is now callable from Plan, Agent, and YOLO parent
1963 registries. Plan mode's read-only contract is preserved (the existing
1964 registry test was updated to assert membership while still rejecting
1965 write/exec tools).
1966
1967 ### Changed
1968
1969 - **Markdown tables wrap long cells instead of truncating (#1163-adjacent)**
1970 — long cell content is word-wrapped within the column instead of
1971 collapsing to `…`. Column separators are preserved on every wrapped
1972 line so the table grid stays readable.
1973 - **MCP JSON-RPC framing centralized** — request/response correlation,
1974 timeout handling, and message framing now live above the byte-level
1975 transports. Stdio, SSE, and the new Streamable HTTP transport share a
1976 single protocol layer instead of each maintaining its own copy of the
1977 framing code.
1978 - **Self-update is curl-free and verifies SHA-256** — `deepseek update`
1979 no longer shells out to system `curl` (and no longer needs the
1980 Schannel `--ssl-no-revoke` Windows hack from v0.8.23). Downloads now
1981 use `reqwest::blocking` with rustls, and the aggregated
1982 `deepseek-artifacts-sha256.txt` manifest is parsed and checked
1983 against each downloaded asset before it is installed. Verification
1984 status is surfaced in the update output.
1985 - **Terminal-mode recovery unified in `recover_terminal_modes()`** —
1986 startup, `FocusGained`, and `resume_terminal` all route through one
1987 idempotent helper that re-establishes keyboard enhancement flags,
1988 mouse capture, bracketed paste, and focus events. Adding a new mode
1989 flag now only has to happen in one place.
1990
1991 ### Fixed
1992
1993 - **`reasoning_content` replay stable for prompt cache (#1297)** —
1994 reasoning text replayed from saved sessions now hashes consistently
1995 across turns so the cache-aware prompt builder's static-prefix
1996 stability isn't broken by replays. Thanks **Duducoco (@Duducoco)**.
1997 - **Active provider credentials respected during onboarding (#1265)**
1998 — the onboarding flow now reads credentials from the active provider
1999 instead of falling back to the default DeepSeek path when another
2000 provider is selected. Thanks **jinpengxuan (@jinpengxuan)**.
2001 - **Home/End keys move the input cursor (#1246)** — Home and End now
2002 jump the composer cursor to line start/end instead of being
2003 swallowed. Thanks **heloanc (@heloanc)**.
2004 - **Docs anchor scroll-margin overrideable (#1282)** — the
2005 scroll-margin offset on docs anchors is now overrideable so embedded
2006 contexts can adjust it without forking the stylesheet. Thanks
2007 **Wenjunyun123 (@Wenjunyun123)**.
2008 - **`/config` view columns aligned (#1290)** — the `/config` table now
2009 sizes the key column from the actual data instead of a fixed width,
2010 so long keys no longer overflow into the value column. Thanks
2011 **Reid Liu (@reidliu41)**.
2012 - **zh-Hans approval dialog wording (#1274)** — uses 终止 (terminate)
2013 instead of 中止 (abort) in the Chinese approval dialog, matching the
2014 English semantics. Thanks **Liu-Vince (@Liu-Vince)**.
2015
2016 ### Removed
2017
2018 - **Unwired `[context.per_model]` config field** — the field had no
2019 runtime consumer and was only present in the config schema. Removed
2020 to keep the schema honest. Existing configs that still contain a
2021 `[context.per_model.*]` table continue to load (serde ignores
2022 unknown keys; covered by a regression test).
2023 - **Stale aspirational `[cycle.per_model]` comments** — reference to a
2024 config table that was never wired. No behavior change.
2025
2026 ### Documentation
2027
2028 - **`.claude/CODEMAP_v0.8.25_dead_code.md`** — committed the
2029 cycle/seam/coherence/capacity codemap with a softened
2030 `cycle_manager` classification: live by code trace, design
2031 load-bearing, practical load-bearing unproven. Use this to decide
2032 the v0.8.26+ product direction for the cycle/seam/capacity
2033 subsystems.
2034
2035 ### Known issues
2036
2037 - **Windows 10 conhost flicker regression (#1260, #1251)** —
2038 v0.8.22-and-later content flickering on Windows 10 is still present.
2039 The viewport-reset escape sequence added in v0.8.22 needs a Windows
2040 guard. Deferred to v0.8.26.
2041 - **Snapshot system still snapshots every turn** — the v0.8.24 500 MB
2042 hard cap protects against blowups, but the underlying design still
2043 snapshots on every turn regardless of whether the workspace changed.
2044 A write-aware skip is planned for v0.8.26.
2045 - **`▏` glyph leak in code blocks (#1212)**, **mouse selection
2046 crossing the sidebar (#1169)**, **drag-select edge auto-scroll
2047 (#1163)**, **mid-run MCP server stderr capture** — all deferred to
2048 v0.8.26.
2049
2050 ## [0.8.24] - 2026-05-09
2051
2052 A bugfix + refactor release picking up the backlog after the v0.8.23 security
2053 release. Big thanks to **wplll** (cache-aware prompt + `/cache inspect`),
2054 **Liu-Vince** (MCP pagination diagnosis), **@Giggitycountless** (snapshot cap
2055 proposal), and to issue reporters **@SamhandsomeLee**,
2056 **@barjatiyasaurabh**, **@tyculw**, **@hongyuatcufe**, and **@ljlbit** for
2057 the bugs fixed below.
2058
2059 ### Fixed
2060
2061 - **Mouse-wheel scroll survives focus toggles** — on macOS, switching away
2062 (Cmd+Tab, opening the screenshot tool, etc.) and back can drop the
2063 terminal's mouse-tracking mode, leaving wheel scroll dead until restart.
2064 The TUI now re-arms `EnableMouseCapture` on `FocusGained` alongside the
2065 existing keyboard-mode recapture, so wheel events keep flowing after a
2066 focus round-trip.
2067 - **Workspace-local slash commands are now loaded (#1259)** — user command
2068 files placed in `<workspace>/.deepseek/commands/`,
2069 `<workspace>/.claude/commands/`, and `<workspace>/.cursor/commands/` are
2070 now discovered alongside the existing global `~/.deepseek/commands/`.
2071 Workspace-local commands shadow global by name, matching the precedence
2072 model already used for skills. Reported by **@SamhandsomeLee**.
2073 - **`@`-mention completion finds AI-tool dot-directories** — files inside
2074 `.deepseek/`, `.cursor/`, `.claude/`, and `.agents/` are now discoverable
2075 in `@`-mention Tab-completion even when those directories are excluded by
2076 `.gitignore`. The fix also applies to the Ctrl+P file picker and fuzzy
2077 file resolution.
2078 - **MCP paginated discovery (#1250, #1256)** — tools, resources, resource
2079 templates, and prompts from MCP servers that paginate their responses
2080 (e.g., gbrain at 5 items per page) are now fully discovered by following
2081 the MCP spec's `nextCursor` across all pages. Reported by
2082 **@hongyuatcufe**; thanks to **Liu-Vince** for the diagnosis and PR
2083 #1256 with the same fix shape.
2084 - **Snapshot storage has a disk-space cap (#1112)** — the snapshot side repo
2085 now enforces a 500 MB hard limit. When the limit is exceeded at snapshot
2086 time, the oldest snapshots are pruned aggressively to stay under a 400 MB
2087 target. Guards against the reported 1.2 TB snapshot blowup during
2088 high-churn sessions. Reported by **@tyculw**; thanks to
2089 **@Giggitycountless** for the PR #1131 proposal that informed the
2090 hard-cap approach.
2091 - **`/clear` now resets the Todos sidebar (#1258)** — previously `/clear`
2092 only reset the Plan panel; the Todos checklist persisted across clears
2093 until app restart. The fix ensures `clear_todos()` clears the
2094 `SharedTodoList` inner state. Reported by **@barjatiyasaurabh**.
2095
2096 ### Added
2097
2098 - **Cache-aware prompt diagnostics + payload optimization (#1196)** — adds
2099 a `PromptBuilder` that classifies the system prompt into `static` /
2100 `history` / `dynamic` layers for cache-prefix stability, plus:
2101 - `/cache inspect` — shows SHA-256 hashes per layer, base static prefix
2102 hash vs full request prefix hash, static-prefix stability across
2103 turns, and first-divergence tracking. Does not print prompt text.
2104 - `/cache warmup` — prefetches the stable prefix to seed the DeepSeek
2105 context cache.
2106 - **Project Context Pack injected into the stable prefix by default**
2107 — a structured workspace summary (directory listing up to 4 levels /
2108 400 entries, README excerpt up to 4 KB, config + key source file
2109 lists). Adds **~1–10 KB to every prompt depending on repo size**, in
2110 exchange for a much more cacheable prefix. **Default ON**; disable
2111 with `[context] project_pack = false` in `~/.deepseek/config.toml`
2112 if you'd rather keep prompts minimal.
2113 - Wire-payload optimization: large tool outputs are budgeted, repeated
2114 identical tool outputs and `<turn_meta>` blocks are deduplicated
2115 with stable refs (wire-only — local session messages stay intact).
2116 - Footer cache-hit % chip from `prompt_cache_hit_tokens` /
2117 `prompt_cache_miss_tokens` in the API response.
2118
2119 Thanks **wplll** for the design and implementation.
2120
2121 ### Changed
2122
2123 - **Language directive strengthened against project-context bias (#1118)**
2124 — the system prompt now explicitly instructs the model that project
2125 context (AGENTS.md, auto-generated instructions, file trees) is NOT a
2126 language signal. Chinese filenames in a repo no longer bias the model
2127 toward Chinese replies when the user writes in English. Reported by
2128 **@ljlbit**.
2129
2130 ### Known issues
2131
2132 - **Windows flicker/shake regression (#1260, #1251)** — v0.8.22 and v0.8.23
2133 exhibit content flickering on Windows 10 (v0.8.20 works correctly). The
2134 issue is likely caused by the viewport-reset escape sequence
2135 (`\x1b[r\x1b[?6l\x1b[H\x1b[2J\x1b[3J`) added in v0.8.22 to fix viewport
2136 drift. On Windows conhost, this sequence may trigger a full screen clear
2137 on every repaint. A platform guard or less aggressive sequence is needed.
2138
2139 ## [0.8.23] - 2026-05-08
2140
2141 A security-focused follow-up to v0.8.22. The bulk of the diff is hardening of
2142 the child-process surface — shells, MCP stdio servers, and other spawned
2143 subprocesses — plus a related set of MCP, secret-store, and tool-policy
2144 fixes uncovered during follow-up review.
2145
2146 ### Security
2147
2148 - **Sanitized child-process environments** - shells, MCP stdio servers, hooks,
2149 and other child processes spawned from the TUI now start from an explicit
2150 allowlist of parent environment variables rather than inheriting every
2151 parent var. The base allowlist covers `PATH`, `HOME`, `USER`, `LANG`/`LC_*`,
2152 `TERM`/`COLORTERM`, `SHELL`, `TMPDIR`/`TMP`/`TEMP`, and the corresponding
2153 Windows variables. Stops casual exfiltration of `*_API_KEY`, `AWS_*`,
2154 `GITHUB_TOKEN`, and similar through a spawned subprocess.
2155 - **Tighter shell safety classification** - the `exec_shell` deny-list was
2156 reviewed and broadened to cover additional dangerous command patterns.
2157 - **Plan mode tool surface narrowed** - planning sub-agents see a smaller,
2158 read-only tool surface so a plan-mode call can no longer mutate workspace
2159 state.
2160 - **Sub-agent approval boundaries preserved** - sub-agents inherit the
2161 parent's approval policy and cannot escalate beyond it.
2162 - **Symlinked workspace walks no longer followed** - workspace-relative
2163 walkers (file-search, project context) now refuse to traverse symlinks
2164 pointing outside the workspace root.
2165 - **Path and output handling tightened** - several tools that build paths
2166 from model output now reject `..` segments and absolute paths outside the
2167 workspace.
2168 - **Runtime API requires authentication by default** - `deepseek serve --http`
2169 no longer accepts unauthenticated requests in its default configuration.
2170 - **Security-sensitive dependencies bumped** - routine bump pass for crates
2171 with recent advisories.
2172 - **MCP config paths reject traversal** - `load_config`/`save_config` now
2173 refuse paths containing `..` components.
2174 - **Hardened `run_tests` approval policy.** Thanks to **@47Cid** for the
2175 responsible disclosure.
2176
2177 ### Fixed
2178
2179 - **macOS Keychain prompt at startup** - the file-backed secret store is now
2180 the default. The OS keyring is opt-in via
2181 `DEEPSEEK_SECRET_BACKEND=system|keyring`, and the auth status surface
2182 refers to "secret store" rather than "keyring" where appropriate.
2183 - **MCP stdio spawn errors are now visible (#1244)** - when spawning a stdio
2184 MCP server fails (e.g., `npx` not on `PATH`), the underlying OS error is
2185 now shown ("No such file or directory (os error 2)") instead of the opaque
2186 wrapper "MCP stdio spawn failed (...)". The fix applies to the snapshot,
2187 the `mcp connect` / `mcp validate` CLI commands, and the in-TUI status
2188 events.
2189 - **MCP servers no longer break under env scrub (#1244)** - MCP stdio launches
2190 now inherit a wider env allowlist than arbitrary shell tools, so common
2191 `npx ...`, `uvx ...`, `python -m mcp_server_*`, and proxy-bound corporate
2192 setups keep working under the new child-env scrub. Pass-through includes
2193 `NVM_DIR`, `NODE_OPTIONS`, `NODE_PATH`, `NODE_EXTRA_CA_CERTS`,
2194 `NPM_CONFIG_*`, `VOLTA_HOME`, `COREPACK_HOME`, `PYTHONPATH`, `PYTHONHOME`,
2195 `VIRTUAL_ENV`, `PIPX_*`, `POETRY_HOME`, `UV_*`, `GEM_*`, `BUNDLE_*`,
2196 `JAVA_HOME`, `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` / `ALL_PROXY` /
2197 `FTP_PROXY` (case-insensitive), `SSL_CERT_FILE`, `SSL_CERT_DIR`,
2198 `REQUESTS_CA_BUNDLE`, `CURL_CA_BUNDLE`. Secret-bearing parent env stays
2199 scrubbed.
2200
2201 ### Changed
2202
2203 - **Live thinking is compact by default** - the streaming "thinking" panel
2204 collapses by default; expand via the existing details toggle.
2205
2206 ### Added
2207
2208 - **`docs/RELEASE_CHECKLIST.md`** - explicit pre-tag checklist (CHANGELOG,
2209 versions, preflight, npm wrapper smoke) so the v0.8.21/v0.8.22 CHANGELOG
2210 gap does not recur.
2211
2212 ### Known issues
2213
2214 - **Mid-run MCP server stderr is still suppressed** - if a stdio MCP server
2215 spawns successfully but exits later (e.g., crashes during `initialize`),
2216 its stderr is not yet captured. Spawn-time OS errors (the most common
2217 case from #1244) are visible. Full mid-run stderr capture is planned for
2218 v0.8.24.
2219
2220 ## [0.8.22] - 2026-05-08
2221
2222 A focused security release.
2223
2224 ### Security
2225
2226 - **Hardened `fetch_url` redirect handling.** Thanks to **@47Cid** for the
2227 responsible disclosure.
2228
2229 ## [0.8.21] - 2026-05-08
2230
2231 A community-heavy release rolling up two weeks of contributor PRs across the
2232 TUI, runtime, and docs. Big thanks to **Reid (@reidliu41)**,
2233 **jiaren wang (@JiarenWang)**, **Friende (@pengyou200902)**,
2234 **ZzzPL (@Oliver-ZPLiu)**, **Sun**, **Liu-Vince**, **kitty**, and
2235 **Aqil Aziz** for the contributions below.
2236
2237 ### Added
2238
2239 - **Distinct user-message body color** (#1168) - user turns now render in a
2240 green body color so the conversation flow is easier to scan at a glance.
2241
2242 ### Fixed
2243
2244 - **Plan mode enforces read-only tool boundaries** (#1114) - planning calls
2245 can no longer reach into write-side tools. Thanks **jiaren wang**.
2246 - **Composer arrow keys navigate input history** (#1117) - up/down in the
2247 composer cycles through prior prompts when the cursor is on the first/last
2248 line. Thanks **Reid**.
2249 - **RLM preserves prompt cache usage** (#1127) - the RLM batch path no longer
2250 resets prompt-cache hits between calls. Thanks **Sun**.
2251 - **`fetch_url` proxy DNS opt-in** (#1103) - the proxy DNS path is now opt-in
2252 rather than always forced, fixing breakage in environments where the proxy
2253 cannot resolve the target host. Thanks **Sun**.
2254 - **Undo syncs session context after snapshot restore** (#1150, fixes #1139) -
2255 rolling back a turn now correctly resyncs the in-memory session so a
2256 follow-up turn doesn't see stale context. Thanks **jiaren wang**.
2257 - **Stale busy-state watchdog** (#1170) - the TUI now recovers if the busy
2258 indicator gets stuck after an aborted turn. Thanks **ZzzPL**.
2259 - **`gh` discovered across common install paths** - the `gh` tool is found
2260 whether installed via Homebrew, apt, the Windows MSI, or the GitHub CLI
2261 installer. Thanks **kitty**.
2262 - **Code block indentation preserved in transcript** - leading whitespace
2263 inside fenced code blocks is no longer collapsed during rendering.
2264 Thanks **Liu-Vince**.
2265 - **Stream pacing preserves upstream cadence** - long streaming responses
2266 no longer chunk together when the upstream is bursty.
2267 Thanks **Sun**.
2268 - **Task list output gets headers** - the long-form `/tasks` output now has
2269 group headers so it scans cleanly. Thanks **Reid**.
2270 - **macOS option-V details shortcut** - the details toggle now works correctly
2271 on US Mac keyboards where Option+V produces `√`.
2272 - **Uppercase approval shortcuts accepted** - `[A]/[D]/[V]` work in either
2273 case in the approval dialog.
2274 - **Transcript scrollbar inert** - the transcript scrollbar no longer captures
2275 clicks intended for content below it.
2276 - **Hide transcript rail before code blocks** - the rail glyph no longer
2277 bleeds onto the line just above a fenced code block.
2278 - **Pager exit hint prominent** - the "press q to exit" hint is now visible
2279 on the pager footer.
2280 - **Empty tool call names fall back to a placeholder** - a model that returns
2281 an empty `function.name` in a tool call no longer hangs the turn.
2282 - **MCP SSE waits for endpoint before connect returns** (#1225) - the SSE
2283 transport no longer reports "connected" before the endpoint event has been
2284 received, fixing a race where the first request was lost.
2285 - **Git branch status item renders** (#1226, fixes #1217) - the
2286 `StatusItem::GitBranch` toggle now produces a footer entry instead of a
2287 blank slot.
2288 - **Beta endpoint routes non-beta paths to v1** (#1174) - paths that aren't
2289 available on the DeepSeek beta host are transparently redirected to the v1
2290 host instead of failing.
2291 - **Skill packs accept workflow-pack archive layouts** (#1164) - skill
2292 archives produced by the workflow pack tool now install correctly.
2293 - **Interactive sessions stay in alternate screen** (#1158) - returning from
2294 a sub-process no longer kicks the TUI back to the primary screen mid-turn.
2295 - **Slash-menu arrow navigation wraps** (#1152) - up at the top / down at the
2296 bottom of the slash menu wraps to the other end.
2297 - **CLI preserves split prompt words from Windows shims** (#1160) - prompt
2298 arguments forwarded by the npm wrapper on Windows are no longer joined into
2299 one giant token.
2300 - **`libc` extended to all Unix targets** (#1173) - improves FreeBSD build
2301 compatibility.
2302 - **Memory truncation marker reports omitted bytes** - the `[…N bytes
2303 omitted]` marker now shows an accurate count. Thanks **Friende**.
2304
2305 ### Docs
2306
2307 - **Memory skill link** (#1096) - corrected. Thanks **Aqil Aziz**.
2308 - **Help keybinding reference** (#1095) - corrected. Thanks **Friende**.
2309 - **Additional environment variables** documented in the config reference.
2310 Thanks **Liu-Vince**.
2311 - **Docker volume guidance** - the install snippet now uses a writable named
2312 data volume rather than a bind mount that may be read-only on some hosts.
2313 - **Competitive analysis reflects LSP diagnostics** (#1171) - the doc now
2314 matches the shipping LSP diagnostics implementation.
2315 - **Dispatcher path for `/run-pr`** (#1227) - the README now points at the
2316 dispatcher binary.
2317
2318 ## [0.8.20] - 2026-05-08
2319
2320 ### Added
2321 - **Global AGENTS.md fallback** - when a workspace and its parents do not
2322 provide project instructions, DeepSeek TUI now loads `~/.deepseek/AGENTS.md`
2323 before falling back to auto-generated `.deepseek/instructions.md`, keeping
2324 repo-local instructions higher priority while supporting shared defaults.
2325
2326 ### Fixed
2327 - **Chinese reasoning stays Chinese** - restore the #588 language contract after
2328 the deterministic environment prompt regressed it. The latest user message now
2329 chooses the natural language for both `reasoning_content` and the final reply;
2330 the resolved `lang` field is only a fallback when the user turn is ambiguous.
2331
2332 ## [0.8.19] - 2026-05-08
2333
2334 ### Fixed
2335 - **DeepSeek beta endpoint stays default for Chinese locales** - the legacy
2336 `deepseek-cn` runtime path no longer routes users to the non-beta
2337 `https://api.deepseek.com` base URL. It is now a backwards-compatible alias
2338 for the normal `deepseek` provider default, `https://api.deepseek.com/beta`,
2339 so strict tool mode and other beta-gated features stay available worldwide.
2340 - **Provider docs stop advertising `deepseek-cn` as a separate provider** -
2341 runtime docs now describe it only as a legacy config alias. DeepSeek uses the
2342 same official host worldwide; users with private mirrors should set
2343 `base_url` explicitly.
2344
2345 ## [0.8.18] - 2026-05-07
2346
2347 This is the v0.8.17 follow-up release: a tighter TUI/runtime/install pass with
2348 safer session startup semantics, Docker images promoted to a supported install
2349 path, and several community PRs harvested into the release branch. VS Code and
2350 Feishu/Lark/mobile companion work remain out of scope for this release.
2351
2352 ### Added
2353 - **Prebuilt Docker images on GHCR** - release builds now publish
2354 `ghcr.io/hmbown/deepseek-tui` with `latest`, semver, and `vX.Y.Z` tags, and
2355 the GitHub release notes include a Docker install snippet. Docker publishing
2356 is now a release gate rather than a best-effort check.
2357 - **Draggable transcript scrollbar** (#1075, #1076) - when mouse capture is
2358 enabled, drag the transcript scrollbar thumb to move through long sessions.
2359 The implementation also clears stale drag state on resize and new left-clicks.
2360 Thanks @Oliver-ZPLiu.
2361 - **PTY regression for viewport drift** (#1085) - the QA harness now covers the
2362 blank-top-rows failure after a failed/long turn so future layout changes catch
2363 terminal viewport drift.
2364
2365 ### Changed
2366 - **Plain `deepseek` starts a fresh session** - opening a second `deepseek` in
2367 the same folder no longer silently attaches to the same in-flight checkpoint.
2368 Crash/interrupted checkpoints are preserved as saved sessions and recovered
2369 explicitly through `deepseek --continue`.
2370 - **npm postinstall is recoverable for transient download failures** (#1059) -
2371 install-time GitHub download/extract failures are non-blocking and documented,
2372 while unsupported platforms, checksum mismatches, glibc preflight failures,
2373 and runtime wrapper failures remain fatal. Thanks @Fire-dtx.
2374 - **Docker Buildx cargo caches are platform-isolated and locked** - registry,
2375 git, and target caches now use platform-specific cache IDs plus locked
2376 sharing to avoid the `.cargo-ok File exists` unpack race in release checks.
2377 - **Long-session palette is easier to read** (#1070, #936 partial) - default
2378 body text is slightly softer, reasoning/thinking text uses a warmer accent,
2379 and `/theme` now updates the terminal color adapter so light mode keeps those
2380 contrasts coherent after an in-session toggle. Thanks @bevis-wong and
2381 @oooyuy92 for the readability reports.
2382 - **Install docs add a second rustup mirror fallback** (#1011) - `rsproxy.cn`
2383 is documented as an alternate rustup mirror, and old Debian/Ubuntu Cargo
2384 `edition2024` failures now point users to rustup stable. Thanks @wuwuzhijing.
2385
2386 ### Fixed
2387 - **Chinese destructive approval dialogs keep explicit risk wording** (#1087,
2388 #1091) - zh-Hans destructive approval copy now localizes the operation label,
2389 title, prompt, and destructive-risk warning without changing English default
2390 behavior. Thanks @qinxianyuzou and @axobase001.
2391 - **Terminal viewport is reset before repaint** (#1085) - the TUI now clears
2392 scroll margins/origin mode before key repaints after resume, resize, and turn
2393 completion, preventing alt-screen content from drifting downward and leaving
2394 blank rows at the top.
2395 - **Interactive subprocesses wait for terminal release** (#1085) - shell/editor
2396 handoff now waits until the UI has actually left alt-screen/raw mode before
2397 launching the child process, preventing the TUI from repainting into host
2398 scrollback after interactive tool use.
2399 - **Light theme reasoning blocks stay light** (#1070, #936 partial) -
2400 thinking/reasoning background tints now map to the light reasoning surface
2401 instead of keeping the dark-mode tint after `/theme light`.
2402 - **FreeBSD can compile the secrets crate** (#1089) - platforms without a native
2403 `keyring` dependency now fail the OS-keyring probe cleanly and fall back to
2404 the file-backed secret store instead of referencing a missing crate. Thanks
2405 @avysk for the FreeBSD report.
2406 - **Windows sandbox docs no longer overstate guarantees** (#1015, #1058) - the
2407 docs and code comments now describe the future Windows helper as
2408 process-tree containment only until filesystem, network, registry, or
2409 AppContainer isolation is actually implemented. Thanks @axobase001.
2410
2411 ## [0.8.17] - 2026-05-07
2412
2413 A focused reliability release built almost entirely from community contributions.
2414 Fixes Plan-mode safety, paste-Enter auto-submit, slash-menu skills coverage, the
2415 `deepseek-cn` endpoint preset, and a handful of platform / streaming /
2416 gateway-compatibility issues. Also lands a small PTY-driven QA harness so the
2417 next round of TUI fixes can be verified against real terminal behaviour.
2418
2419 ### Added
2420 - **`/theme` command** (#1057) — toggle between dark and light themes inline,
2421 without round-tripping through `/config`. Thanks @MengZ-super.
2422 - **PTY/frame-capture TUI QA harness** — new
2423 `crates/tui/tests/support/qa_harness/` lets integration tests spawn
2424 `deepseek-tui` in a real pseudo-terminal, send scripted keys / paste /
2425 resize, and assert on the parsed terminal frame plus the workspace
2426 filesystem. Initial scenarios cover boot smoke and the #1073 paste regression.
2427 Adding-a-scenario walkthrough lives in `crates/tui/tests/support/qa_harness/README.md`.
2428 - **Whalescale desktop runtime bridge** — the local runtime API now exposes
2429 `POST /v1/approvals/{id}`, `GET /v1/runtime/info`, `enabled` flags on
2430 `GET /v1/skills`, and `POST /v1/skills/{name}` toggles. Runtime thread
2431 events also carry `agent_reasoning` items so desktop clients can render
2432 thinking separately from assistant text.
2433
2434 ### Changed
2435 - **`deepseek-cn` provider preset now defaults to the official
2436 `https://api.deepseek.com` host** (#1079, #1084) — matches
2437 [api-docs.deepseek.com](https://api-docs.deepseek.com/). The legacy typo
2438 host `api.deepseeki.com` is still recognized in URL heuristics and chat-client
2439 normalization so existing user configs keep working. Thanks @Jefsky.
2440 - **Plan mode runs shell commands in a read-only sandbox** (#1077) — was
2441 `WorkspaceWrite` with the workspace as a writable root, which let
2442 `python -c "open('f','w').write('x')"` mutate files inside the workspace.
2443 Now `SandboxPolicy::ReadOnly`: no writes anywhere on the filesystem, no
2444 network. Read-only inspection commands (`ls`, `git log`, `grep`,
2445 `cargo metadata`, …) keep working through the per-platform sandbox; for
2446 anything that creates or modifies files, switch to Agent mode (`/agent`).
2447 Thanks @DI-HUO-MING-YI.
2448
2449 ### Fixed
2450 - **Pasting multi-line text with a trailing newline no longer auto-submits**
2451 (#1073) — the composer's Enter handler now consults the paste-burst
2452 suppression state and either appends `\n` to the in-flight burst buffer or
2453 inserts it into the composer text directly, instead of falling through to
2454 `submit_input()`. Reproduced from the original Windows / PowerShell
2455 symptom; fix covers both the bracketed-paste and rapid-keystroke detection
2456 paths. Thanks @bevis-wong for the precise reproducer.
2457 - **Slash menu, `/skills`, and `/skill <name>` show project-local AND global
2458 skills** (#1068, #1083) — switched the cache to `discover_in_workspace`, so
2459 the UI surfaces stay in sync with the system-prompt skills block. Bonus
2460 fix: `SKILL.md` frontmatter values are now stripped of surrounding YAML
2461 quotes, so `name: "hud"` registers as `hud` and matches prefix lookup.
2462 Thanks @AlphaGogoo / @Duducoco.
2463 - **Windows shell output is decoded as UTF-8 even on non-UTF-8 system code
2464 pages** (#982, #1018) — Windows shell commands are now wrapped with
2465 `chcp 65001 >NUL & ` so subprocesses output UTF-8 instead of GBK / other
2466 ANSI code pages. `display_command` strips the prefix so transcripts and
2467 approval prompts stay clean. Thanks @chnjames.
2468 - **Stale snapshot `tmp_pack_*` files are cleaned up on startup** (#975,
2469 #1055) — interrupted side-repo git pack operations no longer leak orphaned
2470 temp files; `prune_unreachable_objects` runs during the regular prune
2471 cycle to drop loose objects from rolled-back snapshots. Closes the
2472 ~30 GB+ disk-usage report. Thanks @axobase001.
2473 - **Window-resize artifacts on macOS Terminal.app and Windows ConHost are
2474 gone** (#993) — forces the resize-event size during the post-resize draw
2475 so ratatui's internal `autoresize()` cannot shrink the viewport back to a
2476 stale dimension and leave the newly-expanded area filled with stale
2477 content. Same class as #582 for additional emulator families. Thanks
2478 @ArronAI007.
2479 - **Streaming thinking blocks finalize cleanly on stream errors and
2480 restarts** (#861 partial, #1078) — the engine-error handler now drains
2481 the in-flight thinking block into the transcript instead of leaving the
2482 partial reasoning orphaned in `StreamingState`. Refactor extracts the
2483 thinking lifecycle into named helpers (`start_streaming_thinking_block`,
2484 `finalize_current_streaming_thinking`, `stash_reasoning_buffer_into_last_reasoning`).
2485 Thanks @reidliu41.
2486 - **OpenRouter and other custom-endpoint providers preserve explicit model
2487 IDs** (#1066) — when a provider has an explicit model AND a custom
2488 `base_url` (different from the provider default), the model name is no
2489 longer rewritten by provider-specific normalization. Lets OpenAI-compatible
2490 gateways accept bare IDs like `deepseek/deepseek-v4-pro`,
2491 `accounts/fireworks/models/...`, or `glm-5`. Thanks @THINKER-ONLY.
2492 - **Auto-generated `.deepseek/instructions.md` stabilizes the KV prefix
2493 cache** (#1080) — replaces the per-turn filesystem-scan fallback in
2494 `prompts.rs` with a real on-disk artifact when no context file exists, so
2495 the system prompt's prefix stays byte-stable across turns and prefix-cache
2496 hit-rate improves. The auto-generated file is plainly labelled and the
2497 user can edit or delete it freely. Thanks @lloydzhou.
2498 - **SSE responses behind compressing gateways decode correctly** (#1061) —
2499 enables reqwest's `gzip` and `brotli` features so streams through proxies
2500 that compress the response come through clean instead of as protocol
2501 corruption. Quiets one of the failure modes behind some "stuck working"
2502 reports. Thanks @MengZ-super.
2503 - **NVIDIA NIM provider configs use their own API key even when a legacy
2504 root DeepSeek key is present** (#1081) — `[providers.nvidia_nim] api_key`
2505 now wins for NIM requests, avoiding 401s caused by accidentally sending the
2506 top-level DeepSeek credential to NVIDIA. Thanks @wlon for the focused
2507 diagnosis.
2508 - **npm installs explain the release-mirror escape hatch when GitHub Releases
2509 are blocked** (#1051, #1056) — network/DNS failures now point at the
2510 existing `DEEPSEEK_TUI_RELEASE_BASE_URL` override and the required checksum
2511 manifest / binary layout instead of stopping at a raw `ENOTFOUND github.com`.
2512 Thanks @axobase001.
2513
2514 ### Notes for contributors
2515
2516 This release shifts the project's PR-handling philosophy: every contribution
2517 has value somewhere; the maintainer's job is to find it, use it, and credit
2518 the contributor — never to close a PR with nothing taken. If a PR is too
2519 large or scope-mixed to merge whole, useful commits / files / ideas are
2520 harvested directly rather than asking the contributor to split it. Trust
2521 boundary on credentials, sandbox, providers, publishing, telemetry,
2522 sponsorship, branding, and global prompts still requires explicit
2523 maintainer sign-off, but the burden of getting there is on us. See
2524 `AGENTS.md` for the full text.
2525
2526 ## [0.8.16] - 2026-05-07
2527
2528 A focused hotfix for v0.8.15 regressions in RLM, sub-agent visibility, and
2529 terminal ownership. This release keeps the v0.8.15 feature set intact while
2530 making long-running delegated work easier to inspect and safer to run.
2531
2532 ### Changed
2533 - **RLM has no fixed 180s wall-clock timeout** (#955) — RLM turns can continue
2534 past the old hard limit when the long-input REPL is still making progress.
2535 - **RLM output is easier to audit** (#955) — final reports now include compact
2536 execution metadata: input size, iteration count, elapsed time, sub-LLM RPC
2537 count, and termination state.
2538 - **RLM chunking guidance is stricter for exact work** (#955) — prompts now
2539 tell the sub-agent to use deterministic Python over the full `context` for
2540 counts/aggregation and to report chunk coverage when splitting a whole input.
2541 - **Tool guidance is less defensive** (#955) — the system prompt now explains
2542 when to use tools instead of discouraging the model from using capabilities
2543 that are actually available.
2544
2545 ### Fixed
2546 - **Active RLM work stays visible** (#955) — foreground RLM calls surface in the
2547 active task/right-rail state instead of leaving the Tasks panel saying
2548 `No active tasks`.
2549 - **`/subagents` no longer reports false emptiness** (#955) — the sub-agent
2550 overlay now includes live progress-only agents and transcript fanout workers
2551 when the manager cache has not refreshed yet.
2552 - **Sub-agent cards are quieter and more useful** (#955) — low-signal scheduler
2553 lines such as `step 1/100: requesting model response` are hidden, while
2554 compact tool activity remains visible.
2555 - **Sub-agent completion protocol stays internal** (#955) — completion
2556 sentinels are routed as internal runtime events instead of user messages, so
2557 the parent agent does not explain raw protocol XML back to the user.
2558 - **Sub-agents cannot take over the parent terminal** (#955) — background
2559 agents reject `exec_shell` with `interactive=true`; they can still use
2560 non-interactive shell, background shell, `tty=true`, and task-shell tools.
2561 - **Terminal scrollback ownership is restored** (#955) — the TUI re-enters
2562 alternate-screen mode after foreground/sub-agent work drains, preventing the
2563 host terminal scrollbar from taking over the live interface.
2564
2565 ## [0.8.15] - 2026-05-06
2566
2567 An auth, Windows, editor-integration, and setup stabilization release. This
2568 release keeps the existing DeepSeek V4 architecture intact while landing small
2569 community fixes that make first-run setup, terminal behavior, skills, cost
2570 display, and recovery paths easier to trust.
2571
2572 ### Added
2573 - **ACP stdio adapter for Zed/custom agents** (#782) — `deepseek serve --acp`
2574 starts a local Agent Client Protocol server over stdio. The first slice
2575 supports new sessions and prompt responses through the user's existing
2576 DeepSeek config/API key; tool-backed editing and checkpoint replay remain
2577 outside the ACP surface for now.
2578 - **Yuan/CNY cost display** (#806) — `cost_currency = "cny"` (also accepts
2579 `yuan` / `rmb`) switches footer, context panel, `/cost`, `/tokens`, and
2580 long-turn notification summaries from USD to CNY.
2581 - **Slash autocomplete for skills** (#808) — installed skills are visible in
2582 the slash-command autocomplete menu.
2583 - **`/rename` session titles** (#836) — sessions can be renamed without
2584 editing save files manually.
2585
2586 ### Changed
2587 - **Current local date in turn metadata** (#893, closes #865) — real user turns
2588 now include the current local date in `<turn_meta>`, without changing the
2589 stable system prompt/cache prefix.
2590 - **Doctor endpoint diagnostics** (#823) — `deepseek doctor` shows the resolved
2591 provider/API endpoint to make proxy, China endpoint, and inherited-env
2592 debugging more concrete.
2593 - **More conservative request sizing** (#826) — API requests cap `max_tokens`
2594 against the active model/context budget before dispatch.
2595 - **Safer config and secret file writes** (#833, #837) — generated config files
2596 use restrictive permissions and improved secret redaction.
2597
2598 ### Fixed
2599 - **Env-only API key failure recovery** (#892) — runtime auth failures now say
2600 when the rejected key came from inherited `DEEPSEEK_API_KEY` and no saved
2601 config key is present, matching the clearer `deepseek doctor` guidance.
2602 - **Windows Unicode output** (#887, closes #872) — TUI startup now best-effort
2603 switches the Windows console input/output codepages to UTF-8, improving
2604 Chinese and other non-ASCII rendering.
2605 - **Windows resume picker** (#886, closes #866) — the dispatcher keeps the
2606 resume picker path on Windows instead of bypassing it.
2607 - **Windows clipboard fallback** (#850) — copy operations have a fallback path
2608 when the primary clipboard backend is unavailable.
2609 - **Workspace trust persistence** (#870) — approval/trust choices persist in
2610 global config instead of surprising users on the next launch.
2611 - **Ctrl+E composer behavior** (#883, closes #876) — plain Ctrl+E moves to the
2612 end of the composer again; file-tree toggling moved to the shifted shortcut.
2613 - **Plain Markdown skills** (#869) — `SKILL.md` files without frontmatter now
2614 fall back to the first `# Heading` instead of being ignored.
2615 - **Workspace-scoped latest resume** (#830, closes #779) — `resume --last`,
2616 `--continue`, and fork/resume helpers choose the latest session for the
2617 current workspace/repo rather than the newest saved session globally.
2618 - **Npm wrapper version fallback** (#885) — `deepseek --version` / `-v` can
2619 report the package version when the native binary has not been downloaded
2620 yet.
2621 - **TUI exit resume hint** (#863, closes #682) — exiting the TUI now points
2622 users toward the relevant resume command.
2623 - **Startup and terminal reliability** — includes bounded stream-open waits
2624 (#847), cursor-lag reduction for `@` mentions (#849), OSC52 clipboard fallback
2625 for SSH (#845), legacy Ctrl+V paste recognition (#786), Windows mouse capture
2626 defaulting off (#785), and UTF-8-preserving ANSI stripping (#784).
2627 - **Install and policy reliability** — avoids unstable Rust file-locking APIs
2628 (#821), enforces network policy in `web_run` (#800), fixes repeated setup
2629 language prompts after API-key setup (#844), and explains dispatcher TUI spawn
2630 failures (#853).
2631 - **Workspace safety** — refuses dangerous snapshots for `$HOME` or unsafe
2632 workspaces (#798, #804), fixes path-escape false positives for double-dots in
2633 names (#824), scopes snapshot built-in excludes (#854), and replaces provider
2634 `unreachable!()` paths with proper errors (#835).
2635 - **Skills discovery** — recursively reads the skills directory (#811), ignores
2636 symlinks outside the selected install root (#814), discovers global Agents
2637 skills (#848), and includes `.cursor/skills` (#817).
2638 - **Provider/model compatibility** — restores auto model routing (#772),
2639 completes vLLM provider integration (#737), accepts provider-prefixed DeepSeek
2640 model IDs (#794), preserves requested model ID casing (#733), and pins RLM
2641 child calls to Flash (#832).
2642
2643 ### Thanks
2644 - Thanks to [@reidliu41](https://github.com/reidliu41) for the resume hint and
2645 workspace trust fixes (#863, #870).
2646 - Thanks to [@Oliver-ZPLiu](https://github.com/Oliver-ZPLiu) for the Windows
2647 clipboard fallback (#850).
2648 - Thanks to [@xieshutao](https://github.com/xieshutao) for the plain Markdown
2649 skill fallback (#869).
2650 - Thanks to [@GK012](https://github.com/GK012) for the npm wrapper version
2651 fallback (#885).
2652 - Thanks to everyone filing Windows, Chinese-language setup, auth, and
2653 first-run reports. Those concrete reproductions shaped the release.
2654
2655 ## [0.8.13] - 2026-05-05
2656
2657 A stabilization release for DeepSeek V4 runtime and TUI reliability. The
2658 v0.8.13 milestone was narrowed to direct runtime/TUI fixes; prompt hygiene,
2659 trajectory logging, Anthropic-wire support, and larger UI cleanup were moved
2660 out of this release.
2661
2662 ### Added
2663 - **No-LLM tool-result prune before compaction** (#710) — old verbose tool
2664 results are mechanically summarized before the paid summary pass. Duplicate
2665 reads keep the freshest full body and replace older copies with one-line
2666 summaries; if that gets the session back under the compaction threshold, the
2667 LLM summary call is skipped entirely.
2668 - **Repeated-tool anti-loop guard** (#714) — the engine now tracks
2669 `(tool_name, args)` pairs per user turn. On the third identical call it
2670 inserts a synthetic corrective tool result instead of running the same tool
2671 again unchanged; per-tool failures warn at three and halt at eight.
2672 - **V4 cache-hit telemetry fallback** (#721) — usage parsing now recognizes
2673 `usage.prompt_tokens_details.cached_tokens`, so the existing footer cache-hit
2674 chip works with DeepSeek V4's automatic prefix-cache telemetry as well as the
2675 older explicit hit/miss fields.
2676
2677 ### Fixed
2678 - **Invalid tool-call JSON repair** (#712) — malformed streamed tool arguments
2679 now pass through a deterministic repair ladder before dispatch.
2680 - **Hallucinated tool-name recovery** (#713) — common non-canonical tool names
2681 are resolved through the registry before the engine reports a missing tool.
2682 - **Tool-schema sanitation** (#715) — schemas are normalized before API
2683 emission so provider-strict JSON Schema handling does not reject valid tools.
2684 - **Case-sensitive model IDs** (#717, #729) — valid configured model IDs keep
2685 caller-provided case while compact DeepSeek aliases still canonicalize.
2686 - **Stale `working...` state after failed dispatch** (#738) — if the UI fails
2687 to send a message to the engine before a turn starts, the composer loading
2688 state is cleared instead of trapping later input in pending state.
2689 - **Prompt-free doctor key checks** — `deepseek doctor` no longer reads the OS
2690 keyring, avoiding macOS Keychain prompts during diagnostics.
2691 - **macOS Terminal color compatibility** — `xterm-256color` sessions now
2692 receive 256-color palette indexes instead of truecolor SGR, preventing
2693 Apple Terminal from misrendering whale blues as green/cyan blocks.
2694 - **Chat client repair after Responses cleanup** — restored the chat client
2695 body and regression coverage after removing the dead experimental Responses
2696 fallback path.
2697 - **Up/Down arrow transcript scroll when composer is empty** — bare Up/Down
2698 arrows now scroll the transcript when the composer input is empty (or
2699 whitespace-only); with text present they still navigate composer history.
2700 Previously the gate was hardcoded to false, leaving users in virtual
2701 terminals (Ghostty, Codex, Kitty-protocol) unable to scroll without
2702 modifier shortcuts.
2703
2704 ## [0.8.11] - 2026-05-04
2705
2706 ### Changed
2707 - **Cache-maxing prompt path for DeepSeek V4** — the engine now skips
2708 system-prompt reassignment when the assembled stable prompt is unchanged,
2709 keeps the volatile repo working-set summary out of the system prompt, and
2710 injects it as per-turn metadata on the latest user message instead.
2711 - **Tool catalog cache anchor** — the model-visible tool array now marks
2712 the final native tool with `cache_control: ephemeral` so DeepSeek can
2713 anchor the stable tool prefix explicitly.
2714 - **V4-scale automatic compaction defaults** — automatic compaction keeps a
2715 500K-token hard floor and the fallback compaction threshold now reflects
2716 the V4-scale late-trigger policy instead of the old 50K-era default.
2717 - **Token-only compaction trigger** — the message-count compaction trigger
2718 was a 128K-era heuristic that fired on long sessions of small messages
2719 — exactly the case where rewriting V4's prefix cache is most wasteful.
2720 Removed `CompactionConfig::message_threshold` and the message-count
2721 branch in `should_compact`; token budget is now the sole automatic
2722 trigger (gated by the 500K floor). Manual `/compact` is unchanged.
2723
2724 ### Fixed
2725 - **Legacy 128K context naming** — the 128K fallback is now named and
2726 documented as legacy DeepSeek-only behavior, reducing ambiguity with the
2727 1M-token DeepSeek V4 defaults.
2728 - **`npm install` resilience for slow / firewalled networks** — the
2729 postinstall binary fetch from GitHub Releases now retries on transient
2730 errors (5 attempts, 1-16 s exponential backoff with jitter), enforces a
2731 per-attempt timeout (default 5 min, configurable via
2732 `DEEPSEEK_TUI_DOWNLOAD_TIMEOUT_MS`) plus a 30 s stall detector, honors
2733 `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` env vars (pure-Node CONNECT
2734 tunneling, no new dependencies), and prints a download-progress line
2735 to stderr so users know it isn't hung. Suppressible with
2736 `DEEPSEEK_TUI_QUIET_INSTALL=1`. Reported by a community user from China
2737 whose install through a CN npm mirror took 18 minutes — the bottleneck
2738 was the GitHub fetch, which CN npm mirrors do not proxy.
2739 - **YOLO sandbox dropped to DangerFullAccess** — YOLO mode was still
2740 routing shell commands through the WorkspaceWrite sandbox, which
2741 intercepted legitimate outside-workspace writes (package installs,
2742 sub-agent workspaces, `~/.cache`, brew, `npm install -g`, pipx) and
2743 forced approval round-trips — contradicting the "no guardrails"
2744 contract. YOLO already auto-approves all tools and enables trust mode;
2745 the sandbox was the last residual restriction. Now uses
2746 DangerFullAccess (no sandbox), consistent with the full YOLO posture.
2747 - **Scroll position lock preserved across render resolve** — user
2748 scroll-up during live streaming was being yanked back to the live tail
2749 on the next chunk. The `user_scrolled_during_stream` lock was cleared
2750 prematurely when content briefly fit in one screen, or when the
2751 transcript shrank between renders (e.g. sub-agent card collapsed).
2752 Fixed by snapshotting the prior tail state before `resolve_top` and
2753 only clearing the lock when the user was deliberately at the bottom.
2754 - **Capacity controller disabled by default** — the capacity controller
2755 was silently clearing the transcript (`messages.clear()`) based on
2756 slack-based `p_fail` calculations, independent of token utilization or
2757 the `auto_compact` setting. This contradicted the v0.8.11 default of
2758 `auto_compact = false` — the user opted into trusting the model with
2759 the full 1M-token V4 window, and the controller was auto-managing the
2760 prefix on their behalf. The controller now defaults to `enabled = false`;
2761 power users can opt in via `capacity.enabled = true`.
2762
2763 ### Docs
2764 - **README clarity pass** (#685) — title-cased section headings, an explicit
2765 Node + npm prerequisites block before the `npm install -g` snippet, a
2766 China-friendly `--registry=https://registry.npmmirror.com` install
2767 variant, a DeepWiki badge for AI-assisted repo browsing, and a 🐳 mark
2768 on the title. *Thanks to [@Agent-Skill-007](https://github.com/Agent-Skill-007)
2769 for this PR.*
2770
2771 ## [0.8.12] - 2026-05-05
2772
2773 A feature release built on the v0.8.11 cache-maxing foundation: 20 community
2774 PRs merged, covering reasoning-effort automation, V4 FIM edits, bash-arity
2775 execpolicy, skill-registry sync, vim composer mode, large-tool-output routing,
2776 pluggable sandbox backends, layered permission rulesets, and cache-aware
2777 resident sub-agents. No breaking changes.
2778
2779 ### Added
2780 - **Reasoning-effort auto mode** (#669) — `reasoning_effort = "auto"` inspects
2781 the last user message for keywords (debug/error → Max, search/lookup → Low,
2782 default → High) and resolves the tier before each API request. Sub-agents
2783 always get Low.
2784 - **FIM edit tool for V4 /beta** (#668) — `fim_edit` tool sends
2785 fill-in-the-middle requests to DeepSeek's `/beta` endpoint for surgical code
2786 edits.
2787 - **Bash arity dictionary** (#655) — `auto_allow = ["git status"]` now matches
2788 `git status -s` but NOT `git push`. The arity dictionary knows command
2789 structure for git, cargo, npm, yarn, pnpm, docker, kubectl, aws, make, and
2790 others. Legacy flat prefix matching still works for unlisted commands.
2791 - **Unified slash-command namespace** (#661) — user-defined commands in
2792 `~/.deepseek/commands/` support `$1`, `$2`, `$ARGUMENTS` template
2793 substitution. User commands override built-in commands.
2794 - **Skill registry sync** (#654) — `/skills sync` fetches the community skill
2795 registry and installs/updates all listed skills. Network-gated by the
2796 existing `[network]` policy.
2797 - **Vim modal editing in composer** (#659) — `vim.insert_mode` / `vim.normal_mode`
2798 settings enable modal editing in the message composer with standard Vim
2799 keybindings.
2800 - **Separate tui.toml** (#657) — theme colors and keybind overrides can live in
2801 `~/.deepseek/tui.toml` alongside the main `config.toml`. *Note: file format
2802 is defined but not yet loaded at startup — wiring deferred to v0.8.13.*
2803 - **Large-tool-output routing** (#658) — tool results exceeding a configurable
2804 token threshold are routed through a workshop with truncated previews,
2805 protecting the parent context window. Synthesis is currently truncation-only;
2806 V4-Flash sub-agent synthesis deferred to follow-up.
2807 - **Pluggable sandbox backends** (#645) — a `SandboxBackend` trait and
2808 Alibaba OpenSandbox HTTP adapter let `exec_shell` route commands to a remote
2809 sandbox instead of spawning locally. Config keys: `sandbox_backend`,
2810 `sandbox_url`, `sandbox_api_key`.
2811 - **Layered permission rulesets** (#653) — `ExecPolicyEngine` supports
2812 builtin, agent, and user-priority layers for allow/deny prefix rules.
2813 Deny-always-wins semantics.
2814 - **Cache-aware resident sub-agents** (#660) — sub-agents spawned with
2815 `resident_file` prepend the file contents to their system prefix for V4
2816 prefix-cache locality. A global lease table prevents two agents from holding
2817 a resident lease on the same file simultaneously. Leases are released on
2818 agent completion.
2819 - **Context-limit handoff** (#667) — engine-level support for replacing
2820 routine compaction with a `.deepseek/handoff.md` file write when context
2821 pressure triggers. *Note: config knob removed pending implementation.*
2822 - **LSP auto-attach diagnostics** (#656) — edit results now include post-edit
2823 diagnostics via the engine-level LSP hooks path.
2824
2825 ### Docs
2826 - **README install section rewritten** (#672) — the previous lede claimed
2827 "no Node.js or Python runtime" but the very next paragraph told readers to
2828 install Node before continuing. Replaced with a three-path Install block
2829 (npm / cargo / direct download) that makes the npm wrapper's role explicit:
2830 it downloads the prebuilt binary, but `deepseek` itself does not depend on
2831 Node at runtime. zh-CN README mirrored.
2832 - **Windows Scoop install instructions** (#696) — README and zh-CN README now
2833 document `scoop install deepseek-tui` for Windows users. *Thanks to
2834 [@woyxiang](https://github.com/woyxiang) for this PR.*
2835 - **DeepSeek Pro discount window extended** (#692) — pricing footnote updated
2836 from 5 May 2026 to 31 May 2026 to match the platform-side promotion. *Thanks
2837 to [@wangfeng](mailto:wangfengcsu@qq.com) for this PR.*
2838 - **`deepseek resume <SESSION_ID>` surfaced in Usage** — the command exists
2839 since v0.7 but was undocumented. Reported via #682.
2840 - **SECURITY.md** (#648) — vulnerability reporting policy and supported
2841 versions.
2842 - **CODE_OF_CONDUCT.md** (#686) — Contributor Covenant v2.1. *Thanks to
2843 [@zichen0116](https://github.com/zichen0116) for this PR.*
2844 - **zh-Hans locale activation docs** (#652) — README.zh-CN.md and
2845 config.example.toml now document `locale = "zh-Hans"`.
2846
2847 ### Fixed
2848 - **Cross-workspace session bleed (security)** — launching `deepseek` from
2849 any directory silently auto-recovered the most recent interrupted session,
2850 even if that session originated in a completely different workspace. Tools
2851 then operated on the prior workspace's file paths while the status bar
2852 displayed the *current* workspace name — a confusing trust-boundary
2853 violation that could leak `api_messages`, `working_set` entries, and any
2854 secrets the prior session had accumulated into a new terminal that was
2855 never meant to see them. `try_recover_checkpoint()` now compares the saved
2856 session's workspace to `std::env::current_dir()` (canonicalised, with a
2857 strict-equality fallback when canonicalisation fails) and only auto-recovers
2858 on a match. On a mismatch the checkpoint is persisted as a regular session
2859 (so the user can find it via `deepseek sessions` / `deepseek resume <id>`)
2860 and cleared, and the new launch starts fresh — no data is lost. Hotfixed
2861 to `main` ahead of the v0.8.12 tag.
2862 - **`cargo install` on stable Rust** — the language-picker match guard at
2863 `crates/tui/src/tui/ui.rs:1603` used `&& let Some(...) = ...` inside an
2864 `if`-guard, which requires the nightly-only `if_let_guard` feature on Rust
2865 before 1.94. Reported by an external user whose `cargo install
2866 deepseek-tui` failed with E0658. Rewrote as a plain match guard with a
2867 nested `if let` inside the arm body. The workspace also now declares
2868 `rust-version = "1.88"` (the actual minimum for `let_chains` in
2869 `if`/`while`) so users on too-old toolchains see a clear cargo error
2870 instead of a confusing rustc one. AGENTS.md gains a "stable Rust only"
2871 section so this doesn't regress.
2872 - **Resident-file lease never released after spawn** (#660) — the lease was
2873 stamped as `"pending"` at spawn time because the agent id is only assigned
2874 by the manager after the spawn call returns. The release-on-terminal-state
2875 path (added in the original #660 commit) matched leases by agent id, so
2876 it could never find these placeholder entries. Now the placeholder is
2877 replaced with the real agent id immediately after spawn so existing
2878 release wiring fires. Resolves the v0.8.12 caveat documented at RC time.
2879 - **Color::Reset across all UI widgets** (#651, #671) — replaced hardcoded
2880 `Color::Black` and `Color::Rgb(18, 29, 39)` backgrounds with `Color::Reset`
2881 so the TUI respects the terminal's actual background color on light-themed
2882 and non-standard terminals.
2883 - **Windows MessageBeep** (#646) — `notify_done_to` now calls `MessageBeep` on
2884 Windows when BEL method is selected.
2885 - **truncate_id optimization** (#649) — replaced manual string slicing with a
2886 shared `truncate_id` helper across session, picker, and UI call sites.
2887
2888 ### Maintenance
2889 - Workspace `cargo fmt` sweep across community PRs that landed unformatted.
2890 - Issue-triage GitHub Actions added (#688): keyword-driven auto-labeller,
2891 stale-bot for `needs-info` issues (14 d → stale → 7 d → close), and a
2892 spam lockdown that auto-closes promotional issues from accounts <30 d
2893 old. All pure GitHub Actions — no third-party services.
2894 - Annotated `TuiPrefs` (#657) and `handoff::THRESHOLDS` (#667) with
2895 `#[allow(dead_code)]` so the deferred APIs don't trip CI's `-D warnings`
2896 flag while their call sites are staged for v0.8.13.
2897 - Removed dead `prefer_handoff` field from `CompactionConfig` — config knob
2898 existed but zero code paths consulted it (#667).
2899 - Removed dead `use_terminal_colors` field from `TuiConfig` — no rendering
2900 code read the value (#671).
2901 - Fixed `expect()` panic risk in `OpenSandboxBackend::new()` — now returns
2902 `Result` (#645).
2903 - Fixed broken `section_bg` test assertion after Color::Reset migration (#651).
2904 - Fixed `resolve_prefixes` docstring to accurately describe deny-always-wins
2905 behavior (#653).
2906 - Wired `create_backend()` into `Engine::build_tool_context` — sandbox backend
2907 was defined but never activated (#645).
2908 - Wired resident lease release on agent completion/cancellation/failure (#660).
2909
2910 ### Contributors
2911
2912 First-time contributor to this release: **@zichen0116** (#686). Welcome — and
2913 thank you.
2914
2915 Bulk community contributions by [@merchloubna70-dot](https://github.com/merchloubna70-dot)
2916 (#645–#681, 28 PRs spanning features, fixes, and VS Code extension scaffolding).
2917 *Thank you for the remarkable volume and quality of work.*
2918
2919 ## [0.8.10] - 2026-05-04
2920
2921 A patch release: hotfixes, small UX polish, and four whalescale-unblocking
2922 runtime API additions. No breaking changes.
2923
2924 ### Added
2925 - **OPENCODE shell.env hook** (#456) — lifecycle hooks can now inject
2926 shell environment into spawned commands without hard-coding env in
2927 prompts or wrapper scripts.
2928 - **Stacked toast overlay** (#439) — status toasts can queue and render
2929 together instead of overwriting each other.
2930 - **File @-mention frecency** (#441) — file mention suggestions learn
2931 from recent selections via `~/.deepseek/file-frecency.jsonl`.
2932 - **Durable keybinding catalog** (#559) — `docs/KEYBINDINGS.md` is now
2933 the source-of-truth audit for current shortcuts and the future
2934 configurable-keymap registry.
2935 - **Runtime API quartet for whalescale-desktop integration** (#561, #562, #563,
2936 #564, #567) — addresses whalescale#255/256/260/261:
2937 - `[runtime_api] cors_origins` config / `--cors-origin URL` flag (repeatable) /
2938 `DEEPSEEK_CORS_ORIGINS` env var, all stacking on top of the built-in
2939 dev-origin defaults (#561 / whalescale#255).
2940 - `PATCH /v1/threads/{id}` extended from `archived`-only to the full
2941 editable field set: `allow_shell`, `trust_mode`, `auto_approve`, `model`,
2942 `mode`, `title`, `system_prompt`. Empty string clears `title` /
2943 `system_prompt`. New `title` field on `ThreadRecord` is additive — no
2944 schema_version bump (#562 / whalescale#256).
2945 - `archived_only=true` query param on `GET /v1/threads` and
2946 `/v1/threads/summary`, backed by a new `ThreadListFilter` enum
2947 (#563 / whalescale#260).
2948 - `GET /v1/usage?since=&until=&group_by=<day|model|provider|thread>`
2949 aggregates token totals + cost (via `pricing.rs`) across all
2950 threads/turns. Empty time ranges yield empty `buckets` (never 404)
2951 (#564 / whalescale#261).
2952 - **Language picker in first-run onboarding** (#566) — new step between
2953 Welcome and ApiKey lists every shipped locale (`auto` / `en` / `ja` /
2954 `zh-Hans` / `pt-BR`) with the native name (日本語, 简体中文, …) plus an
2955 English label so the target language is reachable without already
2956 speaking it. Hotkeys 1-5 select; persists immediately to
2957 `~/.deepseek/settings.toml`.
2958 - **Windows + China install documentation** (#578) — expanded
2959 `docs/INSTALL.md` with Windows source-build setup, Visual Studio Build
2960 Tools / MSVC environment notes, rustup and Cargo mirror guidance, and
2961 antivirus troubleshooting. *Thanks to
2962 [@loongmiaow-pixel](https://github.com/loongmiaow-pixel) for this PR.*
2963
2964 ### Changed
2965 - **Agent prompt now explicitly describes DeepSeek cache-aware behavior**
2966 — long-session guidance explains why stable prompt prefixes, sub-agents,
2967 RLM, and late compaction matter for V4 cache economics.
2968 - **Whale sub-agent nicknames now interleave Simplified Chinese with
2969 English** (`Blue` / `蓝鲸` / `Humpback` / `座头鲸` / …). Pure cosmetic;
2970 doubles the labeling pool size and gives a roughly even mix on each
2971 new spawn.
2972 - **User memory docs + help polish** (#497, #569) — `/memory` is now
2973 listed in slash-command help, supports `/memory help`, and the README
2974 / configuration docs now point at the full `docs/MEMORY.md` guide and
2975 document both `[memory].enabled` and `DEEPSEEK_MEMORY`. *Thanks to
2976 [@20bytes](https://github.com/20bytes) for this PR.*
2977
2978 ### Fixed
2979 - **Compaction summaries are cache-aligned for DeepSeek V4** (#575, #580)
2980 — when the summarized message prefix fits the large V4 context budget,
2981 the summary request now reuses the original messages and appends the
2982 summary instruction as a normal user message instead of rebuilding a
2983 fresh `SUMMARY_PROMPT + dropped messages` input. This lets the summary
2984 call benefit from DeepSeek prefix caching. *Thanks to
2985 [@lloydzhou](https://github.com/lloydzhou) and
2986 [@jeoor](https://github.com/jeoor) for the cost reports and concrete
2987 strategy.*
2988 - **Windows Terminal API-key paste during onboarding** (#577) — the
2989 setup wizard now handles Ctrl/Cmd+V before generic character input and
2990 filters control/meta-modified keys out of the API-key text path.
2991 *Thanks to [@toi500](https://github.com/toi500) for the report and
2992 workaround details.*
2993 - **Terminal startup repaint** (#581) — the TUI clears the terminal
2994 immediately after initialization so normal-screen startup no longer
2995 leaves stale default-background rows above the first frame. *Thanks to
2996 [@xsstomy](https://github.com/xsstomy) for the screenshot.*
2997 - **Markdown rendering for tables, bold/italic, and horizontal rules**
2998 (#579) — transcript markdown now handles table rows, strips separator
2999 rows, renders horizontal rules, applies inline bold/italic styles, and
3000 avoids an infinite-loop edge case on unclosed markers. *Thanks to
3001 [@WyxBUPT-22](https://github.com/WyxBUPT-22) for the PR, screenshots,
3002 and tests.*
3003 - **Slash-prefix Enter activation** (#573) — typing a short prefix such
3004 as `/mo` and pressing Enter now activates the first slash-command
3005 match. *Thanks to [@melody0709](https://github.com/melody0709) for
3006 the report.*
3007 - **macOS seatbelt blocked `~/.cargo/registry`** (#558) — `cargo publish`
3008 / `cargo build` from inside the TUI's shell tool was getting
3009 sandbox-denied. The seatbelt now allows read on `(param "CARGO_HOME")`
3010 and write on the `registry/` and `git/` subpaths whenever the policy
3011 isn't read-only. Honors `CARGO_HOME` env with a `$HOME/.cargo`
3012 fallback.
3013 - **Stdio MCP servers now receive SIGTERM on shutdown** (#420) — instead
3014 of SIGKILL via `kill_on_drop`. New `async fn shutdown` on
3015 `McpTransport` overrides on `StdioTransport` to send SIGTERM and wait
3016 up to 2s for graceful exit before drop fires SIGKILL as the backstop.
3017 Wired into the engine's `Op::Shutdown` path so graceful exit is the
3018 default. A Drop fallback still SIGTERMs on abnormal exit paths.
3019 - **Shell-spawned children get `PR_SET_PDEATHSIG(SIGTERM)` on Linux**
3020 (#421) — the kernel sends SIGTERM the moment the parent (TUI) exits,
3021 even on SIGKILL of the parent. Closes the leak window the cooperative
3022 cancellation path can't cover. macOS / Windows watchdog tracked as a
3023 follow-up; the existing `kill_on_drop` + process_group SIGKILL on
3024 cancellation still cover normal shutdown there.
3025 - **npm install on older glibc now fails fast** (#555, #560, #556, #565)
3026 — the prebuilt Linux x64 / arm64 binaries are now built via
3027 `cargo zigbuild` targeting `x86_64-unknown-linux-gnu.2.28` /
3028 `aarch64-unknown-linux-gnu.2.28`, lowering the requirement from glibc
3029 ≥ 2.39 to ≥ 2.28. The npm postinstall also runs a Linux-only glibc
3030 preflight that fails fast with a clear "build from source" message
3031 when the host is incompatible (or musl). *Thanks to
3032 [@staryxchen](https://github.com/staryxchen) (#556) and
3033 [@Vishnu1837](https://github.com/Vishnu1837) (#565) for these PRs.*
3034 - **Shell tool `cwd` parameter now validated against the workspace
3035 boundary** (#524) — the model could previously pass `cwd` paths
3036 outside the workspace; now `exec_shell` runs `ToolContext::resolve_path`
3037 on `cwd` like every other path-taking file tool, returning
3038 `PathEscape` on violations. `trust_mode = true` still bypasses,
3039 consistent with the file-tool pattern. *Thanks to
3040 [@shentoumengxin](https://github.com/shentoumengxin) for this PR.*
3041
3042 ### Contributors
3043
3044 First-time contributors to this release: **@staryxchen** (#556),
3045 **@shentoumengxin** (#524), **@Vishnu1837** (#565), **@20bytes**
3046 (#569), **@loongmiaow-pixel** (#578), and **@WyxBUPT-22** (#579).
3047 Welcome — and thank you.
3048
3049 ## [0.8.8] - 2026-05-03
3050
3051 ### Added
3052 - **User memory MVP** (#489–#493) — opt-in persistent note file
3053 injected into the system prompt as a `<user_memory>` block.
3054 - `# foo` typed in the composer appends a timestamped bullet
3055 without firing a turn (#492).
3056 - `/memory [show|path|clear|edit]` slash command for inline
3057 inspection / editing hints (#491).
3058 - `remember` model-callable tool so the agent can capture
3059 durable preferences itself; auto-approved because writes are
3060 scoped to the user's own file (#489).
3061 - Hierarchy loader pulls `~/.deepseek/memory.md` (path
3062 configurable via `memory_path` / `DEEPSEEK_MEMORY_PATH`) and
3063 injects above the volatile-content boundary in the prompt
3064 (#490).
3065 - Default off; enable with `[memory] enabled = true` or
3066 `DEEPSEEK_MEMORY=on` (#493).
3067 - Full feature documentation in `docs/MEMORY.md`.
3068 - **Inline diff rendering for `edit_file` / `write_file`** (#505) —
3069 tool results now emit a unified diff at the head of the body,
3070 picked up by the existing diff-aware renderer with line numbers
3071 and coloured `+`/`-` gutters. New `similar` crate dep.
3072 - **OSC 8 hyperlinks** (#498) — URLs in the transcript become
3073 Cmd+click-openable in supporting terminals (iTerm2, Terminal.app
3074 13+, Ghostty, Kitty, WezTerm, Alacritty). Clipboard path strips
3075 the escapes so yanked text stays clean. Off-switch:
3076 `[tui] osc8_links = false`.
3077 - **Retry/backoff visual countdown** (#499) — `⟳ retry N in Ms — reason`
3078 banner ticks down during HTTP backoff. On exhaustion the row turns
3079 red `× failed: <reason>` until the next turn starts.
3080 - **MCP server health chip** (#502) — colour-coded `MCP M/N` in the
3081 footer's right-cluster: success / warning / error / muted by
3082 reachability. Hidden when zero MCP servers are configured.
3083 - **Per-project config overlay** (#485) — `<workspace>/.deepseek/config.toml`
3084 overlays a curated set of fields on top of the user-global config:
3085 `model`, `reasoning_effort`, `approval_policy`, `sandbox_mode`,
3086 `notes_path`, `max_subagents`, `allow_shell`, plus the
3087 `instructions = [...]` array (#454). Pass `--no-project-config`
3088 to bypass for one launch.
3089 - **Project-scope deny-list for credentials/redirects** (#417) —
3090 `api_key`, `base_url`, `provider`, and `mcp_config_path` are
3091 refused at project scope. A malicious
3092 `<workspace>/.deepseek/config.toml` would otherwise be able to
3093 exfiltrate prompts to an attacker-controlled endpoint by
3094 swapping the user's credentials and target host with
3095 project-controlled values, or redirect the MCP loader at a
3096 config that spawns arbitrary stdio servers under the user's
3097 identity. The denied key emits a stderr warning so a user who
3098 expected the override sees the deny instead of a silent drop.
3099 - **Project-scope value-deny for the loosest postures** (#417
3100 follow-up) — `approval_policy = "auto"` and
3101 `sandbox_mode = "danger-full-access"` are pure escalation
3102 values, denied unconditionally at project scope regardless
3103 of the user's prior value. Sub-tightening comparisons
3104 (e.g. user `"never"` → project `"on-request"` is allowed
3105 even though it loosens) stay v0.8.9 follow-up because they
3106 need a richer ordering check.
3107 - **`SSL_CERT_FILE` honored in the HTTPS client** (#418) — corporate
3108 proxy / TLS-inspecting MITM users can now point at their custom
3109 CA bundle and have it added alongside the platform's system
3110 trust store. Tries PEM-bundle parsing first (covers single-cert
3111 files too), falls back to DER. Failures log a warning and
3112 continue — the existing system roots still apply, so a
3113 malformed env var won't bring down the launch. Documented in
3114 `docs/CONFIGURATION.md`.
3115 - **Execpolicy heredoc handling** (#419) — `normalize_command` now
3116 strips heredoc bodies before shlex tokenization so a user's
3117 `auto_allow = ["cat > file.txt"]` pattern matches the heredoc
3118 form `cat <<EOF > file.txt\nbody\nEOF` cleanly. Recognises the
3119 common forms (`<<DELIM`, `<<-DELIM`, `<<'DELIM'`, `<<"DELIM"`)
3120 while leaving the here-string operator (`<<<`) untouched.
3121 Without this fix, heredoc-form file writes would skip the
3122 user's auto-approve list and route through the approval modal
3123 even for explicitly-blessed commands.
3124 - **Sub-agent role taxonomy expansion** (#404) — adds `Implementer`
3125 ("land this change with the minimum surrounding edit") and
3126 `Verifier` ("run the test suite, report pass/fail with evidence")
3127 to the existing `general` / `explore` / `plan` / `review` /
3128 `custom` set. Each role has a distinct system prompt posture.
3129 Documented in `docs/SUBAGENTS.md`.
3130 - **`docs/SUBAGENTS.md`** — full sub-agent reference: role taxonomy,
3131 alias map, concurrency cap, lifecycle, session-boundary
3132 classification, output contract.
3133 - **`docs/MEMORY.md`** — user-facing memory feature documentation.
3134 - **Competitive analysis doc** — `docs/COMPETITIVE_ANALYSIS.md`
3135 catalogues capability matrix vs OpenCode and Codex CLI.
3136 - **Session prune helper + `/sessions prune <days>`** (#406 phase-1) —
3137 drops persisted sessions older than N days from
3138 `~/.deepseek/sessions/`. Skips the checkpoint subdirectory and
3139 compares against metadata `updated_at` (not fs mtime, which can
3140 lie after an rsync). 10 total tests cover the helper's contract
3141 and the slash-command dispatch surface. Phase 2 (boot-prune +
3142 retention policy) stays v0.8.9 work.
3143 - **`deepseek doctor --json`** now surfaces a `memory` block
3144 (`enabled` / `path` / `file_present`) so operators can verify
3145 memory configuration without booting the TUI.
3146 - **Tool-output spillover** (#422 + #423 + #500) — tool outputs over
3147 100 KiB now spill to `~/.deepseek/tool_outputs/<id>.txt` from the
3148 engine's tool-execution path. The model receives a 32 KiB head plus
3149 a footer pointing at the spillover file (`Use read_file path=…`),
3150 the tool cell renders an inline `full output: <path>` annotation in
3151 live mode, and a 7-day boot prune keeps the directory bounded.
3152 Spillover is skipped on error results so the model still sees the
3153 failure message verbatim. The existing tool-details pager surfaces
3154 the truncated head so the user can verify what the model saw.
3155
3156 ### Changed
3157 - **Sub-agent concurrency cap raised to 10 by default** (#509) —
3158 was 5; configurable via `[subagents].max_concurrent` (hard
3159 ceiling 20). Running-count now ignores non-running, no-handle,
3160 and finished handles so completed agents stop occupying slots.
3161 - **`SharedSubAgentManager` is `Arc<RwLock<...>>`** (#510) — read
3162 paths take read locks, eliminating the multi-agent fan-out UI
3163 freeze.
3164 - **Sub-agent output summarized before parent context** (#511) —
3165 `compact_tool_result_for_context` now compresses
3166 `agent_result` / `agent_wait` payloads instead of dumping the
3167 full snapshot back into the parent's context window.
3168 - **`agent_list` defaults to current-session view** (#405) — each
3169 manager mints a `session_boot_id` and stamps every spawn; agents
3170 loaded from prior sessions are filtered unless
3171 `include_archived=true` is passed. Each result carries a
3172 `from_prior_session` flag.
3173 - **Concise todo / checklist update rendering** (#403) — repeat
3174 `todo_update` / `checklist_update` calls render a one-line
3175 `Todo #N: <title> → STATUS` card with full list still
3176 reachable via Alt+V instead of dumping the entire item array on
3177 every call.
3178 - **Compact `agent_spawn` rendering** (#409) — the generic tool
3179 block for `agent_spawn` collapses to one header line in live
3180 mode (`◐ delegate · agent-abc12 [running]`) since the
3181 `DelegateCard` already owns live action progress. Transcript
3182 replay keeps the full block.
3183 - **Plan panel role clarified** (#408) — drops the "No active
3184 plan" placeholder when the panel is otherwise empty; documents
3185 the panel's narrow role (`update_plan` tool output + `/goal` +
3186 cycle counter, distinct from todos).
3187 - **Sub-agent description copy** — `agent_spawn` tool description
3188 and `prompts/base.md` updated to reflect the new default cap of
3189 10 (was stale "Max 5 in flight").
3190 - **`agent_spawn` / `agent_assign` schema descriptions** (#404
3191 follow-up) — type/agent_name property descriptions now list
3192 `implementer` and `verifier` so the model surfaces those roles
3193 without having to discover them from `docs/SUBAGENTS.md`. Adds
3194 the long-form aliases (`builder` / `validator` / `tester`) on
3195 `agent_assign` for parity with the alias map.
3196 - **Multi-day duration formatting** (#447) — `humanize_duration`
3197 now caps at two units and promotes through h/d/w boundaries.
3198 Long-running sessions render as `2d 3h` instead of `188415s`,
3199 and the previous "192m 30s" cycle output becomes `3h 12m`. The
3200 `/goal` status line picks up the same formatter so multi-day
3201 goal-elapsed times stay readable.
3202 - **Accessibility flag** (#450) — `NO_ANIMATIONS=1` env var now
3203 forces `low_motion = true` and `fancy_animations = false` at
3204 startup, regardless of the saved `settings.toml`. Recognises
3205 the standard truthy spellings (`1`, `true`, `yes`, `on`).
3206 Documented end-to-end in the new `docs/ACCESSIBILITY.md`,
3207 including the existing `low_motion` / `calm_mode` /
3208 `show_thinking` / `show_tool_details` toggles for
3209 screen-reader users.
3210 - **Cumulative session-elapsed footer chip** (#448) — a
3211 low-priority `worked 3h 12m` chip in the footer's right
3212 cluster shows session age once it crosses 60s. Hidden during
3213 the first minute of a launch so a fresh start doesn't flash a
3214 ticker. Drops first under narrow widths so the existing chips
3215 (coherence / agents / replay / cache / mcp) keep their slots.
3216 Sampled at props-build time (matches the `retry` capture
3217 pattern) so render stays pure for tests.
3218 - **`instructions = [...]` config array** (#454) — declare
3219 additional instruction files (`./AGENTS.md`,
3220 `~/.deepseek/global.md`, …) and they're concatenated into the
3221 system prompt in declared order, above the skills block. Each
3222 file is capped at 100 KiB; missing files log a warning and are
3223 skipped instead of failing the launch. Project config replaces
3224 the user-level array wholesale (the typical "merge" pattern is
3225 for users who want both — they list `~/global.md` inside the
3226 project array). Documented in `config.example.toml`.
3227 - **Keyboard-enhancement flags pop on suspend paths too** (#443
3228 follow-up) — `pause_terminal` (Ctrl+Z / shell-suspend) and
3229 `external_editor::spawn_editor_for_input` (composer `$EDITOR`
3230 launch) now pop the flags before handing the terminal to the
3231 child process, matching the existing shutdown and panic-hook
3232 paths. Defense-in-depth: if a future code path enables the
3233 flags explicitly, the suspend handlers won't leak them to a
3234 Vim / less / shell child that hasn't asked for them.
3235 - **`load_skill` tool** (#434) — model-callable tool that takes a
3236 skill id and returns the SKILL.md body plus the sibling
3237 companion-file list in one call. Faster than the existing
3238 `read_file` + `list_dir` dance; surfaces the skill's
3239 description as a quote block at the head so a single tool
3240 result is self-contained. Resolves the skills directory with
3241 the same hierarchy `App::new` uses (`.agents/skills` →
3242 `skills` → `~/.deepseek/skills`). Available in Plan and
3243 Agent/Yolo modes.
3244 - **Kitty keyboard protocol opt-in** (#442) — pushes
3245 `DISAMBIGUATE_ESCAPE_CODES` at startup so terminals that
3246 support the protocol (Kitty, Ghostty, Alacritty 0.13+,
3247 WezTerm, recent Konsole / xterm) report unambiguous events
3248 for Option/Alt-modified keys, plain Esc, and multi-byte
3249 sequences. Legacy terminals silently discard the escape and
3250 see no change. Only the disambiguation tier is pushed —
3251 release-event reporting was deliberately skipped because the
3252 existing handlers would mis-route releases as duplicate
3253 presses. The flags are popped on shutdown / panic / suspend
3254 paths (#443).
3255 - **Multi-directory skill discovery** (#432) — the system
3256 prompt's `## Skills` listing and the `load_skill` tool now
3257 walk every candidate directory in the workspace plus the
3258 global default: `<workspace>/.agents/skills` →
3259 `<workspace>/skills` → `<workspace>/.opencode/skills` →
3260 `<workspace>/.claude/skills` → `~/.deepseek/skills`. Skills
3261 installed for any AI-tool convention show up in the same
3262 catalogue. Name conflicts resolve first-match-wins per the
3263 precedence order so workspace-local skills shadow user/global
3264 ones. New `skills_directories()` and
3265 `discover_in_workspace()` helpers in
3266 `crates/tui/src/skills/mod.rs`.
3267 - **`tool.spillover` audit event** (#500 polish) — emit a
3268 discrete audit-log entry whenever `apply_spillover` writes a
3269 spillover file, so operators tailing
3270 `~/.deepseek/audit.log` can correlate large-output episodes
3271 with disk-usage growth in `~/.deepseek/tool_outputs/`. Fires
3272 in both the sequential and parallel tool paths.
3273 - **Prompt stash** (#440) — Ctrl+S in the composer parks the
3274 current draft to a JSONL-backed stash at
3275 `~/.deepseek/composer_stash.jsonl` (no-op on empty composer).
3276 `/stash list` shows parked drafts (oldest first, with one-line
3277 previews and timestamps); `/stash pop` restores the most
3278 recently parked draft into the composer (LIFO). Self-healing
3279 parser drops malformed lines instead of poisoning the stash.
3280 Capped at 200 entries; multiline drafts round-trip intact via
3281 JSON's newline escaping.
3282 - **`deepseek pr <N>` subcommand** (#451) — fetches PR
3283 title/body/diff via `gh` and launches the interactive TUI
3284 with a review prompt pre-populated in the composer. The
3285 diff is capped at 200 KiB (codepoint-safe truncation) so a
3286 massive PR doesn't blow the context window before the user
3287 hits Enter. Optional `--repo <owner/name>` and `--checkout`
3288 flags; falls back gracefully with an actionable error
3289 message if `gh` isn't on PATH. Adds a new
3290 `TuiOptions::initial_input` plumb that any future caller can
3291 reuse to drop the model into a session with text already
3292 typed.
3293 - **`/stash clear` subcommand** (#440 polish) — wipes the
3294 entire stash file and reports how many parked drafts were
3295 dropped. Pairs with `/stash list` and `/stash pop` so the
3296 user can fully manage the stash from inside the TUI without
3297 reaching for `rm`.
3298 - **`/hooks` read-only listing** (#460 MVP) — slash command
3299 enumerates configured lifecycle hooks grouped by event,
3300 showing each hook's name, command preview, timeout, and
3301 condition. Notes the global `[hooks].enabled` flag's state.
3302 No more `cat ~/.deepseek/config.toml` to debug "did my hook
3303 actually load". The picker / persisted enable-disable
3304 surface from #460 stays as v0.8.9 follow-up. Available via
3305 `/hooks` or `/hooks list`; aliased to `/hook`. Localized in
3306 en/ja/zh-Hans/pt-BR.
3307 - **`deepseek doctor` reports cross-tool skill dirs** (#432
3308 follow-up) — both the human-readable and JSON outputs now
3309 surface `.opencode/skills/` and `.claude/skills/` presence /
3310 count, so operators can confirm at a glance whether any
3311 cross-tool skill folder is contributing to the merged
3312 catalogue. Empty dirs are omitted from the human-readable
3313 output to keep the report scannable; JSON always emits all
3314 five slots (`global`, `agents`, `local`, `opencode`,
3315 `claude`) for stable machine consumption.
3316 - **`deepseek doctor` reports storage surfaces** (#422 / #440 /
3317 #500 follow-up) — new `Storage:` section surfaces the
3318 tool-output spillover dir
3319 (`~/.deepseek/tool_outputs/`) with file count and the
3320 composer stash file
3321 (`~/.deepseek/composer_stash.jsonl`) with parked-draft
3322 count. Mirrored under `storage.{spillover,stash}` in the
3323 JSON output so `deepseek doctor --json` keeps a stable
3324 schema.
3325 - **`/hooks events` subcommand** (#460 polish) — lists every
3326 supported `HookEvent` value with a short blurb so users can
3327 discover which events to target in `[[hooks.hooks]]` entries
3328 without reading source. Ordered lifecycle → per-tool →
3329 situational, stable across releases.
3330 - **Structured-Markdown compaction template** (#429) —
3331 `prompts/compact.md` switches from the legacy
3332 Active-task/Files-touched/Key-decisions/Open-blockers
3333 framing to the spec'd structure: Goal / Constraints /
3334 Progress (Done / In Progress / Blocked) / Key Decisions /
3335 Next step. The richer Progress sub-bullets help long
3336 resumed sessions distinguish "what's verified done" from
3337 "what's mid-flight" — useful when the model writes
3338 `.deepseek/handoff.md` before a long break. Backwards-
3339 compat: existing handoff.md files continue to render fine
3340 because the loader injects them as plain markdown (the
3341 template only guides what NEW handoffs look like). The
3342 pinned-tool-output configurability part of #429's spec
3343 stays a v0.8.9 follow-up — that requires changes to
3344 `cycle_manager.rs` compaction logic itself.
3345 - **`tool_call_before` / `tool_call_after` / `message_submit` /
3346 `on_error` hooks all fire now** (#455 observer-only slice) —
3347 these events were defined in the `HookEvent` enum but never
3348 fired from production code. Wired through:
3349 `tool_call_before` and `tool_call_after` fire from
3350 `tool_routing.rs`; `message_submit` fires from
3351 `dispatch_user_message` before engine dispatch; `on_error`
3352 fires from `apply_engine_error_to_app` before the error cell
3353 reaches the transcript. Hook contexts populate the relevant
3354 fields (`tool_name` + `tool_args` / `tool_result`,
3355 `message`, `error`). Hooks remain read-only in this slice;
3356 argument / result / message mutation is a v0.8.9 follow-up
3357 because it needs a synchronous-gate contract that doesn't
3358 exist today. Combined with the existing `session_start` /
3359 `session_end` / `mode_change` events, every variant in the
3360 `HookEvent` enum now has a live producer. Each fire is
3361 fast-path-gated by
3362 `HookExecutor::has_hooks_for_event(event)` so per-tool
3363 dispatch never pays for `HookContext` allocation when the
3364 user has no hooks configured (the common case).
3365 - **RLM tool family** (#512) — `rlm` tool cards map to
3366 `ToolFamily::Rlm` and render `rlm`, not `swarm`. Stale "swarm"
3367 wording cleaned out of docs / comments / tests.
3368 - **Foreground RLM visible in Agents sidebar** (#513 — stopgap)
3369 — projection now shows foreground RLM work; full async
3370 lifecycle remains v0.8.9.
3371
3372 ### Fixed
3373 - **`Don't auto-approve git -C ...`** (#416, shipped 2026-05-03) —
3374 v0.8.8 release runtime fix; foundation for the rest of the
3375 stabilization batch.
3376 - **Self-update arch mapping** (#503) — `update.rs` uses release
3377 asset naming (`arm64`/`x64`) instead of raw Rust constants
3378 (`aarch64`/`x86_64`); rejects `.sha256` siblings as primary
3379 binaries.
3380 - **Composer Option+Backspace deletes by word** (#488) — was
3381 deleting by character.
3382 - **Offline composer queue is session-scoped** (#487) — legacy
3383 unscoped queues fail closed instead of leaking content into
3384 unrelated chats.
3385 - **`display_path` test race + Windows separator** (#506) —
3386 tests no longer mutate `$HOME`; `display_path_with_home` walks
3387 components and joins with `MAIN_SEPARATOR_STR` so Windows shows
3388 `~\projects\foo` not `~\projects/foo`.
3389 - **Footer reads statusline colours from `app.ui_theme`** (#449) —
3390 was using a bespoke palette.
3391 - **Keyboard-enhancement flags pop on panic exit too** (#443/#444) —
3392 raw-mode startup probe is now bounded by a configurable
3393 timeout.
3394 - **CI workflow cleanup** (#507) — pruned three duplicated/dead
3395 workflows (`crates-publish.yml`, `parity.yml`, `publish-npm.yml`);
3396 `release.yml` `build` job now allows `parity` to be skipped on
3397 manual `workflow_dispatch`; release-runbook reconciled.
3398 - **Slash-menu layout jitter on Windows** — typing through a
3399 `/foo` autocomplete used to shrink the matched-entry count,
3400 which shrank the composer height every keystroke, which forced
3401 the chat area above to repaint. On Windows 10 PowerShell + WSL
3402 the per-cell write cost made the jitter visible. Composer now
3403 reserves its panel-max envelope for the whole slash/mention
3404 session so the chat-area Rect stays stable; the menu still
3405 renders only the entries that actually match.
3406
3407 - **Linux ARM64 prebuilt binaries** — the release workflow now publishes
3408 `deepseek-linux-arm64` and `deepseek-tui-linux-arm64` (built natively on
3409 GitHub's `ubuntu-24.04-arm` runner). The npm wrapper picks them up
3410 automatically on `arm64` Linux hosts, so HarmonyOS thin-and-light,
3411 openEuler/Kylin, Asahi Linux, Raspberry Pi, AWS Graviton, etc. now work
3412 with a plain `npm i -g deepseek-tui`.
3413 - **Interactive TUI hangs on `working.` at 100% CPU (#549)** — the event
3414 loop's blocking terminal poll starved the tokio runtime, preventing the
3415 engine task from dispatching the API request. Fixed by yielding to the
3416 scheduler before each poll cycle and clamping the event-poll timeout to
3417 a minimum of 1ms so a zero-timeout hot-loop can't monopolize the thread.
3418 - **Backspace key inserts "h" instead of deleting (#550)** — terminals
3419 that send `^H` (Ctrl+H) for Backspace were not recognized. Added
3420 `is_ctrl_h_backspace()` guard in both the composer and API-key input
3421 handlers so Ctrl+H is treated as a delete, matching the existing
3422 `KeyCode::Backspace` behavior.
3423
3424 ### Changed
3425 - **npm `postinstall` failure messages** — when no prebuilt is available for
3426 the host's `os.platform() / os.arch()` combo, the wrapper now prints the
3427 full `cargo install` fallback recipe and a link to
3428 [`docs/INSTALL.md`](INSTALL.md) instead of just the bare error.
3429 - **`DEEPSEEK_TUI_OPTIONAL_INSTALL=1`** — new env knob that downgrades a
3430 postinstall failure to a warning + `exit 0`, so CI matrices that include
3431 unsupported platforms don't fail the whole `npm install`.
3432
3433 ### Docs
3434 - New [`docs/INSTALL.md`](docs/INSTALL.md) — every supported platform,
3435 prebuilt vs. `cargo install` vs. manual download, cross-compiling x64 → ARM64
3436 Linux with `cross` or `gcc-aarch64-linux-gnu`, and a troubleshooting section
3437 covering the common `Unsupported architecture`, `MISSING_COMPANION_BINARY`,
3438 and self-update mismatch errors.
3439 - README and `README.zh-CN.md` now have an explicit **Linux ARM64** quickstart
3440 pointing ARM64 users at `cargo install deepseek-tui-cli deepseek-tui --locked`
3441 for v0.8.7 and at `npm i -g deepseek-tui` for v0.8.8+.
3442
3443 ### Releases
3444 - npm wrapper publish remains manual (npm 2FA OTP requirement).
3445 - GitHub release automation depends on `RELEASE_TAG_PAT` secret —
3446 without it `auto-tag.yml` creates the tag but `release.yml`
3447 doesn't fire.
3448
3449 ## [0.8.7] - 2026-05-03
3450
3451 ### Fixed
3452 - **Selection across transcript cell types** — the selection-tightening from
3453 v0.8.6 (#383) restricted copy/select to user and assistant message bodies
3454 only, so text in system notes, thinking blocks, and tool output could not be
3455 copied. v0.8.7 removes the body-start gate; the rendered transcript block is
3456 fully selectable again.
3457
3458 ## [0.8.6] - 2026-05-03
3459
3460 ### Added
3461 - **Long-session survivability by default** (#402) — capacity control and
3462 compaction defaults are enabled, transcript history is bounded, persisted
3463 sessions are capped, and oversized history folds into archived context
3464 placeholders instead of freezing the TUI.
3465 - **v0.8.6 feature batch** (#373-#402) — adds goal tracking, cache-hit chips,
3466 cycle-boundary visualization, file-tree pane, `/share`, `/model auto`,
3467 user-defined slash commands, `/profile`, LSP diagnostic wiring,
3468 crash-recovery, self-update, `/init`, `/diff`, patch-aware `/undo`,
3469 `/edit`, inline diff highlighting, smart clipboard, native-copy escape,
3470 right-click context menus, clickable file:line styling, and MCP Phase A.
3471
3472 ### Fixed
3473 - **Lag and rendering regressions** (#399, #400) — moves git/file-tree work
3474 off the UI thread where possible, bounds render history, and tightens redraw
3475 behavior to avoid sidebar/chat text bleed-through.
3476 - **Release-hardening follow-ups** — `/share` now writes via secure temp files,
3477 self-update uses secure same-directory temps with Windows-safe replacement,
3478 and docs/rustfmt release gates are clean.
3479
3480 ## [0.8.4] - 2026-05-02
3481
3482 ### Added
3483 - **Localization expansion (Phase 1, #285)** — every slash command's help
3484 description, the full `/tokens` / `/cost` / `/cache` debug output, the
3485 footer state and chip text, and the help-overlay section headings are
3486 now translated for all four shipped locales (`en`, `ja`, `zh-Hans`,
3487 `pt-BR`). Set the language with `/config locale zh-Hans` (or
3488 `LANG=zh_CN.UTF-8` / `LC_ALL=zh_CN.UTF-8` from the shell). Non-Latin
3489 scripts render via the same `unicode_width` plumbing the existing 27
3490 chrome strings already use; the `shipped_first_pack_has_no_missing_core_messages`
3491 test enforces full coverage across all four locales for every new
3492 `MessageId`. Tool descriptions sent to the model and the base system
3493 prompt intentionally remain English (training-data alignment, prefix
3494 cache stability).
3495 - Phase 1a (#294): 44 new IDs covering slash commands.
3496 - Phase 1b (#295): 13 new IDs covering `/tokens` / `/cost` / `/cache`
3497 debug output. Templates use `{placeholder}` substitution so a
3498 translator can re-order args freely.
3499 - Phase 1c (#296): 11 new IDs covering footer state, sub-agent chip,
3500 quit-confirmation toast, and help-overlay section labels.
3501 - **Stable cache prefix** (#263) — five companion fixes to keep the
3502 DeepSeek prefix cache stable across turns: drop volatile fields from
3503 the working-set summary block (#280, #287), place handoff and
3504 working-set after the static prompt blocks (#288 → #292), memoise the
3505 tool catalog so descriptions stay byte-stable (#289), sort
3506 `project_tree` and `summarize_project` output (#290), and use a unique
3507 fallback id for parallel streaming tool calls so downstream tool-result
3508 routing doesn't match the first call twice (#291). The combined effect
3509 is a meaningful jump in cache hit rate after the third turn.
3510
3511 ### Fixed
3512 - **Agent-mode shell exec could not reach the network** (#272) — the seatbelt
3513 default policy denies all outbound network including DNS, so any
3514 `exec_shell` command needing the network (`curl`, `yt-dlp`, package
3515 managers, …) failed in Agent mode unless the user dropped to Yolo. The
3516 engine now elevates the sandbox policy to `WorkspaceWrite { network_access:
3517 true, … }` for both Agent and Yolo. Plan mode is unchanged (read-only
3518 investigation never registers the shell tool). The application-level
3519 `NetworkPolicy` (`crates/tui/src/network_policy.rs`) remains the only
3520 outbound-traffic boundary.
3521 - **`/skill install <github-repo-url>` failed with `invalid gzip header`** (#269)
3522 — `https://github.com/<owner>/<repo>` parsed as a raw direct URL, so the
3523 installer downloaded the HTML repo page and tried to gzip-decode HTML.
3524 Bare GitHub repo URLs (with or without `.git`, with or without `www.`,
3525 with or without a trailing slash) now route to the `GitHubRepo` source the
3526 same as `github:<owner>/<repo>`. URLs that already point at a specific
3527 archive / blob / tree path still go through `DirectUrl`.
3528 - **V4 Pro discount expiry extended** (#267) — DeepSeek extended the V4 Pro 75%
3529 promotional discount from 2026-05-05 15:59 UTC to 2026-05-31 15:59 UTC. Without
3530 this update the TUI would have started showing 4× the actual billed cost on
3531 May 6 onwards. Verified at https://api-docs.deepseek.com/quick_start/pricing.
3532
3533 ## [0.8.3] - 2026-05-01
3534
3535 ### Fixed
3536 - **Skills prompt referenced fabricated paths** — `render_available_skills_context`
3537 rendered each skill's file as `<skills_dir>/<frontmatter-name>/SKILL.md`,
3538 which did not exist when the directory name differed from the frontmatter
3539 `name` (community installs, manually-placed skills). `Skill` now carries the
3540 real path captured at discovery and renders that.
3541 - **Missing-companion error was hostile to direct GitHub Release downloaders**
3542 (#258) — replaced "Build workspace default members to install it" wall of
3543 text with a concrete three-path checklist: `npm install -g deepseek-tui`,
3544 `cargo install deepseek-tui-cli deepseek-tui --locked`, or downloading both
3545 `deepseek-<platform>` AND `deepseek-tui-<platform>` from the same Release
3546 page. `DEEPSEEK_TUI_BIN` stays as a power-user fallback.
3547
3548 ### Added
3549 - **Privacy: `$HOME` contracts to `~` in viewer-visible paths** — the TUI,
3550 `deepseek doctor`, `deepseek setup`, and onboarding now contract the home
3551 directory to `~` in every path shown on screen, so screenshots, screencasts,
3552 and pasted help output do not leak the OS account name. Persisted state,
3553 audit log, session checkpoints, and LLM-bound system prompts intentionally
3554 keep absolute paths for full fidelity.
3555 - **`crates.io` badge** alongside the CI and npm badges in both English and
3556 Simplified Chinese READMEs.
3557 - **Engine decomposition** (#227) — `core/engine.rs` is split into focused
3558 submodules (`engine/{streaming,turn_loop,dispatch,tool_setup,tool_execution,tool_catalog,context,approval,capacity_flow,lsp_hooks,tests}.rs`).
3559 No behavior change; preparation for the future agent-loop work.
3560
3561 ### Tests
3562 - RLM bridge: `batch_guard` extracted and tested for the empty-batch and
3563 oversize-batch invariants; depth-guard fallback covered (partial #231).
3564 - Persistence: schema-version rejection covered for `load_session`,
3565 `load_offline_queue_state`, `runtime_threads::load_turn`,
3566 `runtime_threads::load_item` (partial #233).
3567 - Command palette: `[disabled]` server description tag (closes the
3568 remaining #197 acceptance gap).
3569 - Protocol-recovery contract tests now scan the engine submodules in
3570 addition to `engine.rs` so the decomposition refactor doesn't silently
3571 hide the fake-wrapper marker assertions.
3572
3573 ### Issue triage
3574 - 10 issues closed with verification commits cited (#247, #235, #197,
3575 #250, #234, #243, #238, #236, #239, #195).
3576
3577 ## [0.8.2] - 2026-05-01
3578
3579 ### Fixed
3580 - **Windows release build (LNK1104)** — drop the `deepseek` shim binary in
3581 `crates/tui` that 0.8.1 introduced for the bundled `cargo install`. It
3582 produced a second `target/release/deepseek.exe` that collided with the
3583 `deepseek-tui-cli` artifact during workspace builds; the second linker
3584 invocation hit `LNK1104: cannot open file deepseek.exe` on Windows. The
3585 cli crate is now the single source of `deepseek`; workspace default
3586 members still produce both binaries (one per crate).
3587 - **npm wrapper offline robustness** — `bin/deepseek(-tui).js` no longer
3588 re-fetches the GitHub-hosted SHA-256 checksum manifest on every invocation.
3589 When the binary is already installed and its `.version` marker matches the
3590 package version, the wrapper trusts the local file. The manifest is fetched
3591 lazily on actual download (first install or `DEEPSEEK_TUI_FORCE_DOWNLOAD=1`),
3592 so GitHub flakes, captive portals, corporate proxies, and offline state no
3593 longer break every command.
3594
3595 ### Added
3596 - **Model-visible skills block** — installed skills (name, description, file
3597 path) are now exposed in the agent's system prompt under a `## Skills`
3598 section, with progressive disclosure: bodies stay on disk, the model opens a
3599 specific `SKILL.md` only when it decides to use that skill. Capped at a 12k
3600 prompt budget with 512-char per-description truncation. Threaded through
3601 `EngineConfig.skills_dir` so the TUI app, exec agent, and runtime thread
3602 manager all populate it from `Config::skills_dir()`.
3603 - **Simplified Chinese README** (`README.zh-CN.md`) with cross-link from the
3604 English README.
3605
3606 ### Changed
3607 - **`cargo install` UX** — to install the canonical `deepseek` command,
3608 `cargo install deepseek-tui-cli` (the historical path). The 0.8.1
3609 one-command flow (`cargo install deepseek-tui` providing both binaries) is
3610 reverted because it broke Windows release builds; install both packages
3611 separately if you want the TUI binary too.
3612
3613 ## [0.8.1] - 2026-05-01
3614
3615 ### Fixed
3616 - **One-command Cargo install** — `cargo install deepseek-tui --locked` now
3617 provides both the canonical `deepseek` dispatcher and the `deepseek-tui`
3618 companion binary from the main `deepseek-tui` package, so dispatcher
3619 subcommands such as `deepseek doctor --json` work without installing
3620 `deepseek-tui-cli` separately.
3621
3622 ## [0.8.0] - 2026-05-01
3623
3624 ### Fixed
3625 - **Shell FD leak / post-send lag** — completed background shell jobs now release
3626 their process, stdin, stdout, and stderr handles as soon as completion is
3627 observed, while keeping the job record inspectable. This prevents long-running
3628 TUI sessions from hitting `Too many open files (os error 24)`, which could
3629 make checkpoint saves fail and cause shell spawning, message send, close, and
3630 Esc/cancel paths to lag or fail.
3631 - **Windows REPL runtime CI startup** — Windows gets a longer Python bootstrap
3632 readiness timeout for the REPL runtime tests, matching GitHub runner startup
3633 contention without weakening bootstrap failures on other platforms.
3634
3635 ### Added
3636 - **China / mirror-friendly Cargo install docs** — README now documents
3637 installing through the TUNA Cargo mirror and direct release assets for users
3638 with slow GitHub/npm access.
3639
3640 ### Tests
3641 - Added a regression test proving completed background shell jobs drop their
3642 live process handles after `exec_shell_wait`.
3643 - Re-ran the focused shell cancellation and Python REPL runtime slices.
3644
3645 ## [0.7.9] - 2026-05-02
3646
3647 ### Fixed
3648 - **Post-turn freeze** — the checkpoint-restart cycle boundary (`maybe_advance_cycle`) now runs *before* `TurnComplete` emission instead of after, so the terminal is immediately responsive when the UI receives the completion event. The status chip ("↻ context refreshing…") remains visible during the cycle wait. (#234)
3649 - **Enter during streaming no longer corrupts the turn** — a new `QueueFollowUp` submit disposition parks the draft on `queued_messages` when the model is actively streaming text. Previously, pressing Enter during streaming would forward the message as a mid-turn steer, which could interfere with the in-flight response. The message now dispatches as a normal user message after `TurnComplete`. (#234)
3650 - **Idempotent Esc during fanout** — `finalize_active_cell_as_interrupted` and `finalize_streaming_assistant_as_interrupted` are now guarded by `Option::take()`. When Esc cancels a turn and the engine later delivers `TurnComplete(Interrupted)`, the second call is a no-op — no double `[interrupted]` prefix, no corrupted cell state. Regression test locks in the contract. (#243)
3651
3652 ### Tests
3653 - 2 new tests: `submit_disposition_queue_follow_up_when_streaming` (Enter/steering fix), `turn_complete_after_esc_is_idempotent` (Esc fanout double-call hardening)
3654 - 1 expanded test: `submit_disposition_queue_when_offline_and_busy` now covers streaming state
3655
3656 ## [0.7.8] - 2026-05-01
3657
3658 ### Added
3659 - **`exec_shell_cancel` tool** — cancel a running background shell task by id, or cancel all running tasks with `all: true`. Requires approval. (#248)
3660 - **Foreground-to-background shell detach** — press `Ctrl+B` while a foreground command is running to open shell controls and either detach the command to the background (where it can be polled via `exec_shell_wait`) or cancel the current turn. (#248)
3661 - **`exec_shell_wait` turn-cancellation awareness** — canceling a turn while `exec_shell_wait` is blocking now stops the wait but leaves the background task running, with `wait_canceled: true` in metadata. (#248)
3662 - **`ShellControlView` modal** (Ctrl+B) — two-option dialog (Background / Cancel) rendered as a popup over the transcript. (#248)
3663
3664 ### Changed
3665 - **`exec_shell` foreground path** now spawns all foreground commands through the background job table, enabling the detach-to-background flow. Metadata now includes `backgrounded: true/false`. (#248)
3666 - **`exec_shell_interact`** poll loop now observes the turn cancel token so stalled interactive sessions don't block turn cancellation. (#248)
3667 - **Transcript running-tool hint** — executing shell cells now show "Ctrl+B opens shell controls" while running. (#248)
3668 - **Keybinding registry** now includes `Ctrl+B` (opens shell controls) next to `Ctrl+C` (cancel/exits). (#248)
3669 - **Deferred swarm card creation** — `agent_swarm` no longer pre-seeds an all-pending FanoutCard from `ToolCallStarted`; the card is created only when the first `SwarmProgress` event carries real worker state. Until then the sidebar uses the declared task count as a pending dispatch placeholder. (#236, #238)
3670 - **Swarm wording normalized** — fanout-family fallback labels now render as `swarm`, matching the canonical `agent_swarm` / `rlm` model and avoiding mixed `fanout` / `swarm` terminology in the transcript. (#236, #238)
3671 - **OPERATIONS_RUNBOOK** and **TOOL_SURFACE** updated with new shell control paths and `exec_shell_cancel` documentation.
3672
3673 ### Fixed
3674 - **Nonblocking swarm state drift** — the sidebar no longer falls back to `0` or a contradictory seeded placeholder before the first progress event arrives, which removes the visible `pending` vs `running/done` mismatch during early `agent_swarm` dispatch. (#236, #238)
3675 - **Unicode-safe search globbing** — search wildcard matching now iterates on UTF-8 char boundaries instead of raw byte offsets, preventing panics on filenames like `dialogue_line__冰糖.mp3`. (#249)
3676
3677 ### Tests
3678 - 7 new integration tests: foreground-to-background detach, wait-cancel-leaves-process, single-task cancel, bulk cancel (kill-all), foreground-cancel-kills, ShellControlView default/select states
3679 - Expanded swarm/sidebar regression coverage for deferred card creation and pending-count fallback before first `SwarmProgress`. (#236, #238)
3680 - Added a Unicode filename regression test for wildcard search matching. (#249)
3681
3682 ## [0.7.7] - 2026-04-30
3683
3684 ### Added
3685 - **Checklist card rendering** — `checklist_write` / `todo_*` results now render as a purpose-built card with completed/total + percent header, per-item status markers (✅ / `●` / `○`), and a collapsing affordance for long lists. Plumbed through `GenericToolCell` so no new variant threading is needed. (#241)
3686 - **Context menu for transcript operations** — right-click or `Ctrl+M` opens a context-sensitive menu with Copy, Copy All, and selection-aware actions. (`crates/tui/src/tui/context_menu.rs`)
3687 - **Windows .exe sibling lookup** — `locate_sibling_tui_binary` in the CLI dispatcher finds `deepseek-tui.exe` on Windows, honours `DEEPSEEK_TUI_BIN` override, and falls back to suffix-less lookup. Tests lock in platform-correct name resolution and env override. (#247)
3688
3689 ### Changed
3690 - **Swarm/sub-agent canonical data model** — `SwarmTaskOutcome` and `SwarmOutcome` are now the single source of truth. Every UI surface (sidebar, transcript FanoutCard, footer) reads from `swarm_jobs` rather than maintaining parallel projections. (#236, #238)
3691 - **`swarm_card_index`** binds each swarm to its own FanoutCard by `swarm_id`, so overlapping fanouts no longer have one swarm's late progress clobber another's card. (#236, #238)
3692 - **Fanout-class tools suppressed from footer** — `agent_swarm`, `spawn_agents_on_csv`, `rlm`, and `agent_spawn` no longer appear as active tools in the status strip; sidebar and FanoutCard show the actual worker counts. (#236, #238)
3693 - **Esc clears active tool entries optimistically** — the active cell is finalized immediately on cancel rather than waiting for the engine's `TurnComplete` echo. Background `block:false` swarms remain durable and tracked through `swarm_jobs`. (#243)
3694 - **Post-turn workspace snapshot detached** — the snapshot still runs on `spawn_blocking` but the engine no longer awaits its `JoinHandle`, so the UI accepts input immediately after `TurnComplete`. (#234)
3695 - **Shell output preserves Cargo/test summaries under truncation** — high-signal tail lines (`test result:`, `failures:`, `error[E…]`, `Finished`, `Compiling`, panic markers) survive truncation so the agent doesn't re-run gates. (#242)
3696 - **Monotonic spend display** — `displayed_session_cost` + `displayed_cost_high_water` ensure the visible session+sub-agent total never decreases across reconciliation events (cache discounts, provisional → final). (#244)
3697 - Clipboard module expanded with additional platform-aware copy/paste paths. (`crates/tui/src/tui/clipboard.rs`)
3698 - Context inspector enriched with additional metadata columns and session-scoped agent state. (`crates/tui/src/tui/context_inspector.rs`)
3699 - Configuration documentation updated for v0.7.7 settings. (`docs/CONFIGURATION.md`, `docs/MODES.md`)
3700
3701 ### Fixed
3702 - **Windows npm install path** — the npm-distributed `deepseek` dispatcher now locates the platform-correct `deepseek-tui` binary (`.exe` suffix on Windows), fixing runtime failures for Windows users. (#247)
3703 - **Sidebar/transcript/footer agreement** — all three surfaces now agree on agent counts and status because they share the canonical `swarm_jobs` store. (#236, #238)
3704 - **Fanout card clobbering** — overlapping swarms no longer overwrite each other's progress cards. (#238)
3705 - **Cost display regression** — negative reconciliation events (cache-hit discount applied after provisional count) no longer briefly drop the displayed cost. (#244)
3706
3707 ### Tests
3708 - 65+ new/expanded tests: checklist card rendering, swarm card index binding, fanout tool suppression, Esc cancel contract, monotonic spend under reconciliation, shell summary preservation, Windows sibling binary lookup, clipboard platform paths, context menu state transitions
3709
3710 ### Added
3711 - **UI Localization registry** — `locale` setting in `settings.toml` (`auto`, `en`, `ja`, `zh-Hans`, `pt-BR`) with `LC_ALL`/`LC_MESSAGES`/`LANG` auto-detection. Core packs shipped for English, Japanese, Chinese Simplified, and Brazilian Portuguese covering composer placeholder, history search, `/config` chrome, and help overlay. Missing/unsupported locales fall back to English. (`crates/tui/src/localization.rs`, `docs/CONFIGURATION.md`)
3712 - **Grouped, searchable `/config` editor** — settings organized by section (Model, Permissions, Display, Composer, Sidebar, History, MCP) with live substring filter. Typing `j`/`k` navigates when the filter is empty; otherwise they enter the filter. (`crates/tui/src/tui/views/mod.rs`)
3713 - **Pending input preview widget** — while a turn is running, queued messages, pending steers, rejected steers, and context chips render above the composer. Three-row-per-message truncation with ellipsis overflow. (`crates/tui/src/tui/widgets/pending_input_preview.rs`)
3714 - **Alt+↑ edit-last-queued** — pops the most recently queued message back into the composer for editing. No-op when the composer is dirty. (`crates/tui/src/tui/app.rs`)
3715 - **Composer history search and draft recovery** — `Alt+R` opens a live substring search across `input_history` and `draft_history` (max 50 entries). `Enter` accepts, `Esc` restores the pre-search draft. Unicode case-insensitive matching. (`crates/tui/src/tui/app.rs`)
3716 - **Paste-burst detection** — fallback rapid-key paste detection independent of terminal bracketed-paste mode. Configurable via `paste_burst_detection` setting (default on). CRLF normalization (`\r\n` → `\n`, `\r` → `\n`). (`crates/tui/src/tui/paste_burst.rs`)
3717 - **Composer attachment management** — `↑` at the composer start selects the attachment row; `Backspace`/`Delete` removes it without editing placeholder text. (`crates/tui/src/tui/app.rs`)
3718 - **Searchable help overlay** — live substring filter across slash commands and keybindings, multi-term AND matching, localized chrome. (`crates/tui/src/tui/views/help.rs`)
3719 - **Keyboard-binding documentation catalog** — single source of truth for help overlay rendering. Documents 38+ keyboard chords across Navigation, Editing, Submission, Modes, Sessions, Clipboard, and Help sections. (`crates/tui/src/tui/keybindings.rs`)
3720 - **Legacy Rust deprecation audit** — non-destructive compatibility audit covering legacy MCP sync API, prompt constants, `/compact`, `todo_*` aliases, sub-agent aliases, provider `api_key` compatibility, model alias canonicalization, and palette aliases. Tracked by #218–#221. (`docs/LEGACY_RUST_AUDIT_0_7_6.md`)
3721
3722 ### Changed
3723 - **Shift+Tab cycles reasoning-effort** through Off → High → Max (three behaviorally distinct tiers). Previously Tab cycled modes; Shift+Tab is now the reasoning-effort shortcut. (`crates/tui/src/tui/app.rs:1119`)
3724 - **Reasoning-effort `Off` now sends `"off"`** to the API (was `None`). Allows explicit thinking disable. (`crates/tui/src/tui/app.rs`)
3725 - **Media `@`-mentions now emit `<media-file>` hints** directing users to `/attach` instead of inlining binary bytes. Tests lock in the contract. (`crates/tui/src/tui/file_mention.rs`)
3726 - **`/attach` rejects non-media files** with a descriptive error pointing to `@path` for text. (`crates/tui/src/commands/attachment.rs`)
3727 - **Configuration reference updated** to cover all v0.7.6 settings: `locale`, `paste_burst_detection`, `reasoning_effort`, `composer_density`, `sidebar_focus`, and more. (`docs/CONFIGURATION.md`)
3728
3729 ### Fixed
3730 - **Unicode-safe truncation** in pending-input preview and view text — no more mid-character breaks on multi-byte UTF-8. (`crates/tui/src/tui/widgets/pending_input_preview.rs`, `crates/tui/src/tui/views/mod.rs`)
3731 - **CJK/emoji display-width handling** in locale tests and config view rendering. (`crates/tui/src/localization.rs`)
3732 - **Context preview distinguishes `@media`, `/attach`, missing, and included files** with separate kind labels and inclusion status. (`crates/tui/src/tui/file_mention.rs`)
3733 - **Config view filter accept `j`/`k` only when filter is empty** — typing `j` or `k` into the filter field no longer navigates away. (`crates/tui/src/tui/views/mod.rs`)
3734
3735 ### Tests
3736 - 7 localization tests (tag normalization, env resolution, shipped pack completeness, missing-key fallback, Unicode width truncation)
3737 - 11 pending-input preview tests (context buckets, truncation, URL overflow, narrow-width)
3738 - 13 paste tests (burst detection, CRLF normalization, clipboard images, Unicode)
3739 - 9 draft/history search tests (match filter, unicode, accept/cancel, recovery)
3740 - 93 config tests (grouping, filter, edit, j/k, localization, escape/cancel)
3741 - 24 workspace tests (context refresh, scroll, mention completion)
3742 - 7 file-mention tests (context references, media/attach distinction, removability)
3743
3744 ## [0.7.1] - 2026-04-28
3745
3746 ### Added
3747 - Grouped active tool-call cards with compact rails and a live working-status row while tools run. (#142, #149)
3748 - Selected-card-aware Alt+V details so the visible or selected tool card opens the matching detail payload. (#143)
3749 - Compact terminal-native session context inspector with persisted `@path` and `/attach` reference metadata for resumed transcripts. (#146, #150)
3750
3751 ### Changed
3752 - Polished tool cards, diff summaries, and pending context previews for denser terminal-native scanning. (#141, #144, #145, #148)
3753 - Ranked Ctrl+P file-picker results with working-set relevance from modified files, recent `@file` mentions, and recent tool paths while keeping fuzzy filtering in memory. (#147)
3754
3755 ## [0.7.0] - 2026-04-28
3756
3757 ### Added
3758 - OS keyring-backed auth storage with `deepseek auth` subcommands, migration from plaintext config, provider-aware key resolution, and doctor visibility. (#134)
3759 - Egress network policy with allow/deny/prompt decisions, deny-wins matching, audit logging, and enforcement hooks for network-capable tools. (#135)
3760 - LSP diagnostics auto-injection after edits so compile feedback can be reinjected into the next agent turn. (#136)
3761 - Side-git workspace snapshots, `/restore`, and `revert_turn` so agent edits can be rolled back without moving the user's repository HEAD. (#137)
3762 - Esc-Esc backtrack over prior user turns, desktop turn-complete notifications, Alt+V tool-details access, safer command-prefix auto-allow matching, bundled `skill-creator`, and `/skill install` management for community skills. (#131, #132, #133, #138, #139, #140)
3763
3764 ### Changed
3765 - Split more engine/tool primitives into focused modules and workspace crates, including shared tool result primitives and extracted turn/capacity flow. (#67, #74)
3766
3767 ### Tests
3768 - Added mock LLM and skill-install integration coverage for streaming turns, reasoning replay, tool-call loops, network policy, and skill validation. (#69, #140)
3769
3770 ## [0.6.5] - 2026-04-27
3771
3772 ### Added
3773 - **`rlm_process` tool — recursive language model as a tool call.** The previous `/rlm` slash command had a UI rendering gap (the answer never made it back to the model's view) and required the user to remember to invoke it manually. `rlm_process` exposes the full RLM loop as a structured tool the model itself can choose, the same way it reaches for `agent_spawn` or `rlm_query`. Inputs: `task` (small instruction, shown to the root LLM each iteration) plus exactly one of `file_path` (workspace-relative, preferred — keeps the long input out of the model's context entirely) or `content` (inline, capped at 200k chars). Optional `child_model` (default `deepseek-v4-flash`) and `max_depth` (default 1, paper experiments). Returns the synthesized answer with metadata (iterations, duration, tokens, termination reason). Loaded across Plan / Agent / YOLO; never deferred via ToolSearch. (`crates/tui/src/tools/rlm_process.rs`)
3774 - **Reference-aligned REPL surface.** Aligned the in-REPL Python helpers with the canonical reference RLM (alexzhang13/rlm). The sub-agent now sees `context` (the full input, not `PROMPT`), `llm_query`, `llm_query_batched`, `rlm_query` (was `sub_rlm`), `rlm_query_batched`, `SHOW_VARS()`, `FINAL(...)`, `FINAL_VAR(...)`, plus `repl_get`/`repl_set`. Same prompt patterns and decomposition strategies from the paper now apply verbatim. (`crates/tui/src/repl/runtime.rs`)
3775 - **Concurrent fanout from inside the REPL.** `llm_query_batched(prompts, model=None)` runs up to 16 child completions in parallel via a new `POST /llm_batch` sidecar endpoint — much faster than serial `[llm_query(p) for p in prompts]`. `rlm_query_batched(prompts)` does the same for recursive RLM sub-calls via `POST /rlm_batch`. (`crates/tui/src/rlm/sidecar.rs`)
3776 - **`SHOW_VARS()`** — returns `{name: type-name}` for every user variable in the REPL. Lets the model inspect what it has accumulated across rounds before deciding whether to call `FINAL_VAR(name)`.
3777 - **Auto-persistence of REPL variables across rounds.** Any top-level JSON-serializable variable the sub-agent creates in a `repl` block now persists to the next round automatically — no `repl_set` ceremony needed unless you want explicit control. Matches the in-process reference REPL semantics.
3778
3779 ### Changed
3780 - **Code fence is `repl`, not `python`.** Matches the reference RLM language identifier so the same prompts and few-shot examples work here. Backward-compat fallback to `python` / `py` retained for older model behaviors.
3781 - **`FINAL` / `FINAL_VAR` parseable from raw response text.** The reference RLM lets the model write `FINAL(value)` on its own line outside any code block to terminate the loop. Added `parse_text_final()` so that path works alongside the existing in-REPL Python sentinel mechanism. Code-fenced occurrences of `FINAL(...)` are correctly ignored to avoid false positives.
3782 - **Strict termination loop.** The sub-agent must emit a ```repl block (or text-level FINAL) to make progress. One fence-less round triggers a reminder; two consecutive trigger a `RlmTermination::DirectAnswer` exit so we don't loop forever.
3783 - **`rlm_process` separates `task` (root_prompt) from `file_path`/`content` (context).** The `task` rides along as `root_prompt` and is shown to the root LLM each iteration; the big input lives only in the REPL as `context`. Mirrors the reference's `completion(prompt, root_prompt=...)` API.
3784 - **System prompt rewritten** with the reference's strategy patterns (PREVIEW → CHUNK + map-reduce via `llm_query_batched` → RECURSIVE decomposition via `rlm_query` → programmatic computation + LLM interpretation).
3785 - The `/rlm` slash command stays for manual experimentation but is no longer the recommended path; the description in `commands/mod.rs` now points the model toward `rlm_process` for the in-agent flow.
3786
3787 ### Reference
3788 - Zhang, Kraska, Khattab. "Recursive Language Models." arXiv:2512.24601.
3789 - alexzhang13/rlm — reference implementation by the paper authors. Variable names, helper surface, and code-fence convention align with that repo so prompts and patterns transfer.
3790
3791
3792 ### Fixed
3793 - **`/rlm` actually recurses now (Algorithm 1 substrate, paper-faithful).** The v0.6.3 RLM loop had the right *shape* but its recursive substrate was non-functional: `llm_query()` was a Python stub that returned a hardcoded string, and `child_model` was bound with an underscore prefix and silently dropped. The loop ran but the sub-LLM never fired. v0.6.4 fixes this end-to-end:
3794 - **HTTP sidecar.** Each RLM turn spins up a localhost-only axum server on a kernel-assigned port for the duration of the turn. Python's `llm_query()` and `sub_rlm()` are real `urllib.request.urlopen` POSTs; Rust services them via the existing DeepSeek client and returns the completion text. No long-lived python process, no FIFOs, no two-pass replay — Python blocks on HTTP, Rust answers it. (`crates/tui/src/rlm/sidecar.rs`)
3795 - **`child_model` is plumbed through.** `Op::RlmQuery` and `AppAction::RlmQuery` carry the configured child model (default `deepseek-v4-flash`) all the way to the sidecar, where every `llm_query()` call uses it. Token usage is folded into `RlmTurnResult.usage` so cost tracking works.
3796 - **`sub_rlm()` is exposed as a paper-faithful recursive RLM call.** The Python REPL gets a real `sub_rlm(prompt)` function that runs another full Algorithm-1 turn at depth-1 inside the same process (different sidecar route, decremented recursion budget). Default `max_depth = 2` from the `/rlm` command — the model can recurse twice before the budget hits zero. The recursive opaque-future cycle (`run_rlm_turn_inner` → `start_sidecar` → `sub_rlm_handler` → `run_rlm_turn_inner`) is broken by returning a concrete `Pin<Box<dyn Future + Send>>` from `run_rlm_turn_inner`.
3797 - **Strict termination.** The loop only ends via `FINAL(value)` (or the iteration cap). The previous "no fence = direct answer, end loop" early-exit deviated from the paper and could short-circuit on iteration 1 with a chatty model that never saw `PROMPT`. The new behavior tolerates one fence-less round (with a reminder appended), then falls back to a `RlmTermination::DirectAnswer` exit. `RlmTurnResult` now carries a `termination: RlmTermination` enum (`Final | DirectAnswer | Exhausted | Error`) so callers can tell what happened.
3798 - **Richer `Metadata(state)`.** The metadata message the root LLM sees now includes paper-required *access patterns* (`repl_get`, slicing, `splitlines`, `repl_set`, `llm_query`, `sub_rlm`, `FINAL`) and a live list of variable keys currently in the REPL state file — so the model can see what it's accumulated across rounds without us shipping the values themselves.
3799 - **Unicode-safe truncation.** `truncate_text` now counts Unicode codepoints (was mixing `text.len()` bytes with `chars().take(n)`), so multi-byte previews can no longer mis-count. Per-turn temp state files are cleaned up on completion. `ROOM_TEMPERATURE` typo → `ROOT_TEMPERATURE`.
3800 - **End-to-end smoke test.** `rlm::turn::tests::sidecar_url_is_exported_to_python_env` stands up a stand-in axum server that always replies `{"text":"pong-from-sidecar"}`, runs `print(llm_query('hello'))` in the real `PythonRuntime`, and asserts the reply round-trips. This catches future regressions in the sidecar URL passthrough.
3801
3802 ### Reference
3803 - Zhang, Kraska, Khattab. "Recursive Language Models." arXiv:2512.24601 (Algorithm 1).
3804
3805
3806 ### Added
3807 - **Sub-agents surface in the footer status strip.** When N > 0 sub-agents are in flight, the footer grows a "1 agent" / "N agents" chip in DeepSeek-sky color matching the model badge. Hides entirely at zero. (`footer_agents_chip` in `widgets/footer.rs`)
3808 - **`@`-mention popup is fully wired in the composer.** Previously only the App state fields existed (`mention_menu_selected`, `mention_menu_hidden`). The popup now renders below the input mirror-style with the slash menu, with `@`-prefixed entries; Up/Down navigates, Enter / Tab apply the selection, Esc hides until the next input edit. Mention takes precedence over slash because the positional check is stricter. (`visible_mention_menu_entries` + `apply_mention_menu_selection` in `file_mention.rs`)
3809
3810 ### Fixed
3811 - **Tool-call cells no longer flash `<command>` / `<file>` placeholders.** The engine used to emit `ToolCallStarted` from `ContentBlockStart` with `input: {}` — before any `InputJsonDelta` had streamed in — which baked the placeholder into the cell at creation time. The emission is now deferred to `ContentBlockStop` and routed through `final_tool_input`, so the cell is created with the parsed args already in hand. (engine.rs `final_tool_input`; engine/tests.rs `final_tool_input_*`)
3812 - **`parse_invocation_count` flake.** Two `markdown_render` tests both read the global PARSE_INVOCATIONS atomic and raced when other tests called `parse()` in parallel. Switched the counter to `thread_local!<Cell<u64>>`, so each test thread sees only its own invocations. Tested 8 sequential full-suite runs: 8/8 green (was ~40% green).
3813
3814 ### Changed
3815 - **System prompts redesigned with decomposition-first philosophy.** All four prompt tiers (base, agent, plan, yolo) now teach the model to decompose tasks before acting — `todo_write` first for granular task tracking, `update_plan` for high-level strategy, and sub-agents for parallelizable work. Inspired by the "mismanaged geniuses hypothesis" (Zhang et al., 2026): frontier LMs are already capable enough; the bottleneck is how we scaffold their self-management. The prompts now make work visible through the sidebar (Plan / Todos / Tasks / Agents) instead of letting the model work invisibly.
3816 - **Tool labels use progressive verbs.** "Read foo.rs" → "Reading foo.rs", "List X" → "Listing X", "Search pattern" → "Searching for `pattern`", "List files" → "Listing files". Past-tense labels read wrong while a tool is still in flight; the new forms match what the user actually sees.
3817 - **Long-running tools grow an elapsed badge.** From 3 s onward the `running` status segment becomes `running (3s)`, `running (4s)`, … so the user can tell a tool isn't stuck. The status-animation tick (360 ms) drives the redraw; below 3 s the badge stays hidden so quick reads/greps don't churn. (history.rs `running_status_label_with_elapsed`)
3818 - **Spinner pulse is twice as fast** — `TOOL_STATUS_SYMBOL_MS` 1800 ms → 720 ms per glyph (full 4-glyph heartbeat in ~2.88 s instead of ~7.2 s).
3819 - **`tools/subagent.rs` is now a folder module.** Tests live in `tools/subagent/tests.rs`; runtime + manager + tool implementations stay in `tools/subagent/mod.rs`. Public API unchanged. The runtime / tool-impl split was deferred — `SubAgentTask`, `run_subagent_task`, `build_allowed_tools`, the agent prompt constants, and `normalize_role_alias` are referenced from both layers and need a small API design pass before they cleanly separate.
3820
3821 ### Test hygiene
3822 - **5 regression tests pin auto-scroll churn contract.** `mark_history_updated` does not scroll; tool-cell handlers only `mark_history_updated`; `add_message` and `flush_active_cell` gate on `user_scrolled_during_stream`; the per-stream lock clears at TurnComplete and when the user returns to the live tail. (P2.4)
3823
3824 ## [0.6.1] - 2026-04-26
3825
3826 ### Changed
3827 - **V4 cache-hit input prices cut to 1/10th per DeepSeek's pricing update.** Pro promo 0.03625→0.003625, Pro base 0.145→0.0145, Flash 0.028→0.0028 per 1M tokens. Cache-miss and output rates unchanged.
3828 - **Removed the "light" theme option.** It was never tested, looked bad, and the dark/whale palettes are the supported targets. Theme validation now accepts only `default`, `dark`, and `whale`.
3829 - **System prompts redesigned with decomposition-first philosophy.** All five prompt tiers teach the model to `todo_write` before acting, `update_plan` for strategy, and sub-agents for parallel work. Inspired by the mismanaged-geniuses hypothesis (Zhang et al., 2026).
3830
3831 ## [0.6.0] - 2026-04-25
3832
3833 ### Added
3834 - **`rlm_query` tool — recursive language models as a first-class structured tool.** Inspired by [Alex Zhang's RLM work](https://github.com/alexzhang13/rlm) and Sakana AI's published novelty-search research, but trimmed to what an agent loop actually needs. The model calls `rlm_query` with one prompt or up to 16 concurrent prompts; children run on `deepseek-v4-flash` by default and can be promoted to Pro per-call. Children dispatch concurrently via `tokio::join_all` against the existing DeepSeek client — no external runtime, no fenced-block DSL, no Python sandbox. Returns plain text for one prompt, indexed `[0] ...\n\n---\n\n[1] ...` blocks for many. Available in Plan / Agent / YOLO. Cost is folded into the session's running total automatically.
3835
3836 ### Changed
3837 - **Scroll position survives content rewrites (#56).** `TranscriptScroll::resolve_top` and `scrolled_by` no longer teleport to bottom when the anchor cell vanishes. Three-level fallback chain: same line → same cell, line 0 → nearest surviving cell at-or-before. Previously, any rewrite of the assistant message (e.g. tool-result replacement) silently dropped the user back to the live tail mid-scroll.
3838 - **Looser command-safety chains (#57).** `cargo build && cargo test`, `git fetch && git rebase`, and similar chains of known-safe commands now escalate to `RequiresApproval` instead of being hard-blocked as `Dangerous`. Chains containing unknown commands still block.
3839 - **`GettingCrowded` no longer surfaces a footer chip.** The context-percent header already covers conversation pressure; the chip now only fires for active engine interventions (`refreshing context`, `verifying`, `resetting plan`).
3840
3841 ## [0.5.2] - 2026-04-25
3842
3843 ### Added
3844 - **`/model` opens a Pro/Flash + thinking-effort picker (#39).** Typing `/model` with no argument now pops a two-pane modal: model on the left (`deepseek-v4-pro` flagship, `deepseek-v4-flash` fast/cheap, plus a "current (custom)" row when the active id isn't one of the listed defaults), and thinking effort on the right. Tab/←/→ swaps panes, ↑/↓ moves within the focused pane, Enter applies both selections, Esc cancels. The effort pane intentionally exposes only **Off / High / Max** because [DeepSeek's Thinking Mode docs](https://api-docs.deepseek.com/guides/reasoning_model) state `low`/`medium` are mapped to `high` server-side and `xhigh` is mapped to `max` — the legacy variants stay valid in `~/.deepseek/settings.toml` for back-compat, the picker just doesn't surface them. Apply path persists `default_model` and `reasoning_effort` to settings, forwards `Op::SetModel` + `Op::SetCompaction` to the running engine so the next turn picks up the change without a restart, and resets the per-turn token gauges (cache, replay) so the footer numbers reflect the new model. `/model <id>` keeps working unchanged for power users.
3845
3846 ## [0.5.1] - 2026-04-25
3847
3848 ### Added
3849 - **`fetch_url` tool** for direct HTTP GET on a known URL — complements `web_search` for cases where the link is already known. Supports `format` (`markdown` / `text` / `raw`), `max_bytes` (default 1 MB, hard cap 10 MB), `timeout_ms` (default 15 s, max 60 s), redirect following, and structured `{url, status, content_type, content, truncated}` responses. 4xx/5xx bodies are returned (with `success: false`) so the caller can read JSON error envelopes. (#33)
3850 - **PDF support in `read_file`.** PDFs are auto-detected by extension or `%PDF-` magic bytes and extracted via `pdftotext -layout` (poppler) when available. New optional `pages` arg (`"5"` or `"1-10"`) reads page slices. Without `pdftotext`, returns a structured `{type: "binary_unavailable", kind: "pdf", reason, hint}` with install commands for macOS/Debian. (#34)
3851 - **Reasoning-content replay telemetry, end-to-end (#30).** The chat-completions sanitizer now estimates replayed `reasoning_content` tokens (~4 chars/token), threads the value through the streaming `Usage` payload, stores it on the App, and renders an `rsn N.Nk` chip in the footer next to the cache hit-rate. The chip turns warning-coloured when replay tokens exceed 50% of the input budget, so users on long thinking-mode loops can see at a glance how much of their context window is going to V4's "Interleaved Thinking" replay (paper §5.1.1). Logged at `RUST_LOG=deepseek_tui=info` for tail-friendly diagnosis.
3852 - **`@file` Tab-completion (#28).** Typing `@<partial>` and pressing Tab now resolves the mention against the workspace using the existing `ignore::WalkBuilder`. A unique match is spliced into the input; multiple matches with a longer common prefix extend the partial; remaining ambiguity is surfaced via the status line. The mention-expansion path that ships file contents to the model is unchanged — this is purely a discovery aid for typing the path. Inline-contents and a fuzzy popup picker are queued for v0.5.2.
3853 - **Per-workspace external trust list (#29).** `~/.deepseek/workspace-trust.json` now records, for each workspace, the absolute paths the user has opted into reading/writing from outside that workspace. The new `/trust` slash command supports `add <path>`, `remove <path>`, `list`, `on`, `off`, and a status read with no args; the engine consults the list when constructing every `ToolContext` so changes apply on the next tool call without restart. `/diagnostics` surfaces the list. The interactive "Allow once / Always allow / Deny" approval prompt is deferred — for now grant access ahead of the turn with `/trust add <path>`.
3854
3855 ### Fixed
3856 - **TUI sidebar gutter bleed regression test (#36).** Snapshot tests now lock in that long single-line tool results — including a `todo_write` echo of a multi-kilobyte JSON payload — never write any cells outside `chat_area` at the widths reported in the bug (80, 120, 165, 200 cols). A second test verifies the scrollbar coexists with content along the right edge instead of overdrawing the penultimate column.
3857 - **Version drift caught in CI.** New `versions` job in `.github/workflows/ci.yml` runs `scripts/release/check-versions.sh` on every push/PR, verifying every per-crate `Cargo.toml` inherits the workspace version, the npm wrapper matches the workspace version, and `Cargo.lock` is in sync. The release runbook now lists `check-versions.sh` as the first preflight step. (#31)
3858 - **Per-mode soft context budget for V4 compaction trigger** (#27).
3859 - **Phantom `web.run` references stripped** from prompts and the `web_search` tool surface (#25).
3860 - **Unused import + `cargo fmt` drift** that landed with `feat(#27)` and broke Build / Test / npm wrapper smoke under `-Dwarnings`.
3861
3862 ## [0.5.0] - 2026-04-25
3863
3864 ### Fixed
3865 - Multi-turn tool calls on thinking-mode models no longer return HTTP 400. Every assistant message in the conversation now carries `reasoning_content` when thinking is enabled — not just tool-call rounds — matching DeepSeek's actual API validation, which rejects any assistant message missing the field even though the docs describe non-tool-call reasoning as "ignored".
3866 - Added a final-pass wire-payload sanitizer in the chat-completions client that forces a non-empty `reasoning_content` placeholder onto any assistant message still missing one at request time. This is the last line of defense after engine-side and build-side substitution, so sessions restored from older checkpoints, sub-agents that append messages directly, and cached prefix mismatches all produce a valid request.
3867 - On a `reasoning_content`-related 400, the client now logs the offending message indices to make future regressions diagnosable.
3868 - Stripped phantom `web.run` references from prompts and the `web_search` tool surface ([#25](https://github.com/Hmbown/CodeWhale/issues/25)).
3869
3870 ### Changed
3871 - Header/UI widget refactor in the TUI (`crates/tui/src/tui/ui.rs`, `widgets/header.rs`) — internal cleanup, no user-visible behavior change.
3872
3873 ## [0.4.9] - 2026-04-27
3874
3875 ### Fixed
3876 - DeepSeek thinking-mode tool-call rounds now always replay `reasoning_content` in all subsequent requests (including across new user turns), matching DeepSeek's documented API contract that assistant messages with tool calls must retain their reasoning content forever.
3877 - Missing `reasoning_content` on a tool-call assistant message now substitutes a safe placeholder (`"(reasoning omitted)"`) instead of dropping the tool calls and their matching tool results, preventing orphaned conversation chains and API 400 errors.
3878 - Session checkpoint now persists a Thinking-block placeholder for tool-call turns that produced no streamed reasoning text, keeping on-disk sessions structurally correct so subsequent requests avoid HTTP 400 rejections.
3879 - Token estimation for compaction now counts thinking tokens across all tool-call rounds (not just the current user turn), aligning with the updated reasoning_content replay rule.
3880
3881 ## [0.4.8] - 2026-04-25
3882
3883 ### Fixed
3884 - DeepSeek V4 Pro cost estimates now use DeepSeek's current limited-time 75% discount until 2026-05-05 15:59 UTC, then automatically fall back to the base Pro rates.
3885
3886 ## [0.4.5] - 2026-04-24
3887
3888 ### Fixed
3889 - Alternate-screen TUI sessions now capture mouse input by default so wheel scrolling moves the transcript instead of exposing terminal scrollback from before the TUI started. Use `--no-mouse-capture` or `tui.mouse_capture = false` when terminal-native drag selection is preferred.
3890
3891 ## [0.4.2] - 2026-04-24
3892
3893 ### Fixed
3894 - DeepSeek V4 thinking-mode tool turns now checkpoint the engine's authoritative API transcript, including assistant `reasoning_content` on reasoning-to-tool-call turns with no visible assistant text.
3895 - Chat Completions request building now drops stale V4 tool-call rounds that are missing required `reasoning_content`, preventing old corrupted checkpoints from triggering DeepSeek HTTP 400 replay errors.
3896 - Web search now falls back to Bing HTML results when DuckDuckGo returns a bot challenge or otherwise yields no parseable results.
3897
3898 ## [0.4.1] - 2026-04-24
3899
3900 ### Fixed
3901 - DeepSeek V4 tool-result context now preserves large file reads and command outputs instead of compacting noisy tools to a 900-character snippet after 2k characters.
3902 - Capacity guardrail refresh no longer performs destructive summary compaction unless the normal model-aware compaction thresholds are actually crossed.
3903 - V4 compaction summaries retain larger tool-result excerpts and summary input when compaction is genuinely needed.
3904 - The transcript now follows the bottom again when sending a new message, shows an in-app scrollbar when internally scrolled, and leaves mouse capture off in `--no-alt-screen` mode so terminal-native scrolling can work.
3905
3906 ## [0.4.0] - 2026-04-23
3907
3908 ### Added
3909 - **DeepSeek V4 support**: `deepseek-v4-pro` (flagship) and `deepseek-v4-flash` (fast/cheap) are now first-class model IDs with 1M context windows.
3910 - **Reasoning-effort tier**: new `reasoning_effort` config field (`off | low | medium | high | max`) mapped to DeepSeek's `reasoning_effort` + `thinking` request fields. Defaults to `max`.
3911 - **Shift+Tab cycles reasoning-effort** through the three behaviorally distinct tiers (`off → high → max`). The current tier is shown as a ⚡ chip in the header.
3912 - Per-model pricing table: `deepseek-v4-pro` priced at $0.145/$1.74/$3.48 per 1M tokens (cache-hit/miss/output); `deepseek-v4-flash` and legacy aliases at $0.028/$0.14/$0.28.
3913
3914 ### Changed
3915 - **Default model flipped to `deepseek-v4-pro`** (from `deepseek-reasoner`).
3916 - `deepseek-chat` / `deepseek-reasoner` remain as silent aliases of `deepseek-v4-flash` for API compatibility; priced identically.
3917 - **Context compaction**: 1M-context V4 models now compact at 800k input tokens or 2,000 messages, so short/tool-heavy sessions do not compact as if they were 128k-context runs.
3918 - Cycling modes is now Tab-only; Shift+Tab is repurposed for reasoning-effort (reverse-mode cycle was low-value with only three modes).
3919 - Updated help/hint strings, validator error messages, and the model picker to reference V4 IDs.
3920
3921 ### Fixed
3922 - `requires_reasoning_content` now recognizes `deepseek-v4*` so thinking streams render correctly on V4 models.
3923 - DeepSeek V4 thinking-mode tool calls now preserve prior assistant `reasoning_content` whenever a tool call is replayed, matching DeepSeek's multi-turn contract and avoiding HTTP 400 rejections on later turns.
3924 - Raw Chat Completions requests now send DeepSeek's top-level `thinking` parameter instead of the OpenAI SDK-only `extra_body` wrapper.
3925 - Config, env, and UI model selection now normalize legacy DeepSeek aliases to `deepseek-v4-flash` instead of preserving old model labels.
3926 - npm wrapper first-run downloads now use process-unique temp files so concurrent `deepseek` / `deepseek-tui` invocations do not race on `*.download` files.
3927
3928 ## [0.3.33] - 2026-04-11
3929
3930 ### Changed
3931 - Footer polish: simplified footer rendering, removed footer clock label, updated status line layout
3932 - Palette cleanup: removed `FOOTER_HINT` color constant
3933
3934 ### Removed
3935 - `FOOTER_HINT` color constant from palette (use `TEXT_MUTED` or `TEXT_HINT` instead)
3936
3937 ### Fixed
3938 - Test updates to align with simplified footer logic
3939 - Empty state placeholder text removed for cleaner UI
3940
3941 ## [0.3.32] - 2026-04-11
3942
3943 ### Added
3944 - Finance tool: Yahoo Finance v8 quote endpoint with chart fallback, supporting stocks, ETFs, indices, forex, and crypto lookups.
3945 - Header widget redesign: proportional truncation, context-usage bar with gradient fill, streaming indicator, and graceful narrow-terminal degradation.
3946 - Expanded test coverage: 680+ tests including footer state, context spans, plan prompt lifecycle, workspace context refresh, header rendering, and finance tool integration tests with wiremock.
3947 - Workspace context refresh with configurable TTL and deferred initial fetch.
3948 - Config command additions for runtime settings management.
3949
3950 ### Changed
3951 - Redesigned footer status strip with mode/model/status layout, context bar, and narrow-terminal fallback.
3952 - Plan prompt now uses numeric selection (1-4) instead of keyword input; old aliases are sent as regular messages.
3953 - Archived outdated docs (`workspace_migration_status.md` -> `docs/archive/`).
3954 - Trimmed AGENTS.md boilerplate and updated task counts.
3955 - Clarified release-surface documentation: crates.io publication may lag the workspace/npm wrapper.
3956
3957 ### Fixed
3958 - Header `metadata_spans` now uses `saturating_sub` to prevent underflow on narrow terminals.
3959 - Finance tool reuses a single HTTP client instead of rebuilding per request.
3960 - Finance tool tests no longer leak temp directories.
3961
3962 ## [0.3.31] - 2026-03-08
3963
3964 ### Added
3965 - Replaced the finance tool backend with Yahoo Finance v8 + CoinGecko fallback for reliable real-time market data (stocks, ETFs, indices, forex, crypto).
3966 - Added compaction UX: status strip shows animated COMPACTING indicator during context summarization, footer reflects compaction state, and CompactionCompleted events now include message count statistics.
3967 - Added send flash: brief tinted background highlight on the last user message after sending.
3968 - Added braille typing indicator with smooth 10-frame animation cycle.
3969
3970 ### Changed
3971 - Redesigned the footer status strip with mode/model/token/cost layout, quadrant separators, and a context-usage bar.
3972 - Added Unicode prefix indicators (▸ You, ◆ Answer, ● System) to chat history cells for visual distinction.
3973 - Improved thinking token delineation with labeled delimiters in transcript rendering.
3974 - Refactored source code into workspace crates for better modularity and dependency management.
3975
3976 ### Fixed
3977 - Fixed Plan mode ESC key dismissing the prompt without clearing `plan_prompt_pending`, which prevented the prompt from reappearing on subsequent plan completions.
3978 - Fixed clippy lint (collapsible_if) in web browsing session management.
3979
3980 ## [0.3.30] - 2026-03-06
3981
3982 ### Added
3983 - Added a release-ready local npm smoke path that builds binaries, serves release assets locally, packs the wrapper, installs the tarball, and checks both entrypoints before publish.
3984 - Added an opt-in full-matrix local release-asset fixture so `npm run release:check` can be exercised before GitHub release assets exist.
3985
3986 ### Changed
3987 - Bumped the Rust workspace crates and npm wrapper to `0.3.30`.
3988 - Pointed the npm wrapper's default `deepseekBinaryVersion` at `0.3.30` for the next coordinated Rust + npm release.
3989 - Updated the crates dry-run helper to work from a dirty workspace and to preflight dependent workspace crates without requiring unpublished versions to already exist on crates.io.
3990
3991 ## [0.3.29] - 2026-03-03
3992
3993 ### Added
3994 - Added npm publish-time release asset verification for the `deepseek-tui` package to fail fast when expected GitHub binaries are missing.
3995 - Added checksum manifests to GitHub release assets and checksum verification in the npm installer.
3996 - Added `npm pack` install-and-smoke CI coverage for the `deepseek-tui` wrapper package.
3997 - Added an end-to-end release runbook covering crates.io, GitHub Releases, and npm publication.
3998
3999 ### Changed
4000 - Updated npm package documentation for clearer install modes, environment overrides, and release integrity behavior.
4001 - Improved installer support-matrix error messaging for unsupported platform/architecture combinations.
4002 - Decoupled npm package version from default binary artifact version via `deepseekBinaryVersion`, enabling packaging-only npm releases.
4003 - Moved the `deepseek-tui` binary target inside `crates/tui` so `cargo publish --dry-run -p deepseek-tui` works from the workspace package layout.
4004 - Replaced the root-level crates publish workflow with an ordered workspace publish flow.
4005 - Reworked first-run onboarding and README copy around primary workflows instead of shortcut memorization.
4006 - Relaxed onboarding API-key format heuristics so unusual keys warn instead of blocking setup.
4007
4008 ## [0.3.28] - 2026-03-02
4009
4010 ### Added
4011 - Converted the project to a modular Cargo workspace using a `crates/` layout.
4012 - Added new crate boundaries mirroring a deepseek architecture (`agent`, `config`, `core`, `execpolicy`, `hooks`, `mcp`, `protocol`, `state`, `tools`, `tui-core`, `tui`, and `app-server`).
4013
4014 ### Changed
4015 - Added parity CI coverage with protocol/state/snapshot checks.
4016 - Updated release workflow to build both `deepseek` and `deepseek-tui` binaries.
4017
4018 ## [0.3.26] - 2026-03-02
4019
4020 ### Fixed
4021 - Resolved SSE stream corruption caused by byte/string position mismatch in streaming parse flow.
4022 - Hardened base URL validation to reject non-HTTP/HTTPS schemes.
4023 - Prevented multi-byte UTF-8 truncation panics in common-prefix and runtime thread summary paths.
4024 - Corrected context usage alert thresholds by separating warning and critical trigger levels.
4025
4026 ### Changed
4027 - Removed non-code utility tools from the runtime tool registry (`calculator`, `weather`, `sports`, `finance`, `time`) and related wiring.
4028 - Consolidated duplicate URL encoding helpers by delegating to shared `crate::utils::url_encode`.
4029 - Replaced broad crate-level lint suppressions with targeted `#[allow(...)]` annotations where justified.
4030 - Cleaned up dead APIs, unused struct fields, unused builder helpers, and non-integrated modules.
4031 - Addressed clippy findings across the codebase (collapsible conditionals, defaults, indexing helpers, and API signature cleanup).
4032
4033 ## [0.3.24] - 2026-02-25
4034
4035 ### Fixed
4036 - Preserve reasoning-only assistant turns for DeepSeek reasoning models (`deepseek-reasoner`, R-series markers) when rebuilding chat history.
4037 - Align SSE tool streaming indices so each tool block start/delta/stop uses the same block index.
4038 - Prevent transcript auto-scroll-to-bottom when a non-empty transcript selection is active.
4039 - Allow session picker search mode to accept the current selection with a single `Enter` press.
4040 - Preserve tool output whitespace/indentation while still wrapping long unbroken tokens.
4041 - Make transcript selection copy/highlighting display-width aware (wide chars and tabs).
4042 - Gate execpolicy behavior on the `exec_policy` feature flag across CLI/tool execution paths.
4043 - Run doctor API connectivity checks using the effective loaded config/profile (instead of reloading defaults).
4044 - Parse DeepSeek model context-window suffix hints such as `-32k` and `-256k`.
4045 - Update README config docs with key environment overrides and a direct link to full configuration docs.
4046
4047 ## [0.3.23] - 2026-02-24
4048
4049 ### Changed
4050 - Updated project copy to describe the app as a terminal-native TUI/CLI for DeepSeek models (not pinned to a specific model generation).
4051
4052 ### Fixed
4053 - Model selection and config validation now accept any valid `deepseek-*` model ID (including future releases), while still normalizing common aliases like `deepseek-v3.2` and `deepseek-r1`.
4054 - Tool-call recovery now auto-loads deferred tools when the model requests them directly, instead of failing with manual `tool_search_*` instructions.
4055 - YOLO mode now preloads tools by default (including deferred MCP tools), so model tool calls can run immediately without discovery indirection.
4056 - Unknown tool-call failures now include discovery guidance and nearest tool-name suggestions instead of generic availability errors.
4057 - Slash-command errors now suggest the closest known command (for example `/modle` -> `/model`) instead of only returning a generic unknown-command message.
4058
4059 ## [0.3.22] - 2026-02-19
4060
4061 ### Added
4062 - Interactive `/config` editing modal for runtime settings updates.
4063
4064 ### Changed
4065 - Retired user-facing `/set` command path (no longer reachable/discoverable).
4066 - Replaced `/deepseek` command behavior with `/links` (aliases: `dashboard`, `api`).
4067
4068 ### Fixed
4069 - Legacy `/set` and `/deepseek` inputs now return migration guidance instead of generic unknown-command errors.
4070
4071 ## [0.3.21] - 2026-02-19
4072
4073 ### Added
4074 - Parallel tool execution in `multi_tool_use.parallel` for independent task workflows.
4075 - Session resume-thread coverage in tests.
4076
4077 ### Changed
4078 - Desktop and web parity polish across the TUI and runtime surfaces.
4079 - Onboarding and approval UX refinement from prior phase 3 iteration.
4080
4081 ### Fixed
4082 - Runtime pre-release startup issues and config-path edge cases.
4083 - Clippy lint regressions introduced by the last parity pass.
4084
4085 ### Security/Hardening
4086 - General pre-release hardening for runtime app behavior.
4087
4088 ## [0.3.17] - 2026-02-16
4089
4090 ### Fixed
4091 - Config loading now expands `~` in `DEEPSEEK_CONFIG_PATH` and `--config` paths.
4092 - When `DEEPSEEK_CONFIG_PATH` points to a missing file, config loading now falls back to `~/.deepseek/config.toml` if it exists.
4093
4094 ### Changed
4095 - Removed committed transient runtime artifacts (`session_*.json`, `.deepseek/trusted`) and added ignore rules to prevent re-commit.
4096
4097 ## [0.3.16] - 2026-02-15
4098
4099 ### Added
4100 - `deepseek models` CLI command to fetch and list models from the configured `/v1/models` endpoint (with `--json` output mode).
4101 - `/models` slash command to fetch and display live model IDs in the TUI.
4102 - Slash-command autocomplete hints in the composer plus `Tab` completion for `/` commands.
4103 - Command palette modal (`Ctrl+K`) for quick insertion of slash commands and skills.
4104 - Persistent right sidebar in wide terminals showing live plan/todo/sub-agent state.
4105 - Expandable tool payload views (`v` in transcript, `v` in approval modal) for full params/output inspection.
4106 - Runtime HTTP/SSE API (`deepseek serve --http`) with durable thread/turn/item lifecycle, interrupt/steer, and replayable event timeline.
4107 - Background task queue (`/task add|list|show|cancel` and `POST /v1/tasks`) with persistent storage, bounded worker pool, and timeline/artifact tracking.
4108
4109 ### Changed
4110 - Centralized the default text model (`DEFAULT_TEXT_MODEL`) and shared common model list to reduce drift across runtime/config paths.
4111 - `/model` now clarifies that any valid DeepSeek model ID is accepted (including future releases), while still showing common model IDs.
4112
4113 ### Fixed
4114 - Expanded reasoning-model detection for chat history reconstruction (supports R-series and reasoner-style naming without hardcoding single versions).
4115 - Aligned docs/config examples with the then-current runtime default model.
4116
4117 ## [0.3.14] - 2026-02-05
4118
4119 ### Added
4120 - `web.run` now supports `image_query` (DuckDuckGo image search)
4121 - `multi_tool_use.parallel` now supports safe MCP meta tools (`list_mcp_resources`, `mcp_read_resource`, etc.)
4122
4123 ### Fixed
4124 - Encode tool-call function names when rebuilding Chat Completions history (keeps dotted tool names API-safe)
4125
4126 ### Changed
4127 - Prompts: stronger `web.run` citation placement and quote-limit guidance
4128
4129 ## [0.3.13] - 2026-02-04
4130
4131 ### Fixed
4132 - Restore an in-app scrollbar for the transcript view
4133
4134 ## [0.3.12] - 2026-02-04
4135
4136 ### Fixed
4137 - Map dotted tool names to API-safe identifiers for DeepSeek tool calls
4138 - Encode any invalid tool names for API tool lists while preserving internal names
4139
4140 ## [0.3.11] - 2026-02-04
4141
4142 ### Fixed
4143 - Fix tool name mapping for DeepSeek API
4144
4145 ## [0.3.10] - 2026-02-04
4146
4147 ### Fixed
4148 - Always enable mouse wheel scrolling in the TUI (even without alt screen)
4149
4150 ## [0.3.9] - 2026-02-04
4151
4152 ### Removed
4153 - RLM mode, tools, and documentation pending a faithful implementation of the MIT RLM design
4154 - Duo mode tools and prompts pending a citable research spec
4155
4156 ### Fixed
4157 - Footer context usage bar remains visible while status toasts are shown
4158
4159 ### Changed
4160 - Updated prompts and docs to reflect the simplified mode/tool surface
4161
4162 ## [0.3.8] - 2026-02-03
4163
4164 ### Fixed
4165 - Resolve clippy warnings (CI `-D warnings`) in new tool implementations
4166
4167 ## [0.3.7] - 2026-02-03
4168
4169 ### Added
4170 - Tooling parity updates: `weather`, `finance`, `sports`, `time`, `calculator`, `request_user_input`, `multi_tool_use.parallel`, `web.run`
4171 - Shell streaming helpers: `exec_shell_wait` and `exec_shell_interact`
4172 - Sub-agent controls: `send_input` and `wait` (with aliases)
4173 - MCP resource helpers: `list_mcp_resources`, `list_mcp_resource_templates`, and `read_mcp_resource` alias
4174
4175 ### Changed
4176 - Skills directory selection now prefers workspace `.agents/skills`, then `./skills`, then global
4177 - Docs and prompts updated to reflect new tool surface and parity notes
4178
4179 ## [0.3.6] - 2026-02-02
4180
4181 ### Added
4182 - New welcome banner on startup showing "Welcome to DeepSeek TUI!" with directory, session ID, and model info
4183 - Visual context progress bar in footer showing usage with block characters [████░░░░░░] and percentage
4184
4185 ### Changed
4186 - Removed custom block-character scrollbar from chat area - now uses terminal's native scroll
4187 - Simplified header bar: removed context percentage indicator (moved to footer as progress bar)
4188
4189 ## [0.3.5] - 2026-01-30
4190
4191 ### Added
4192 - Intelligent context offloading: large tool results (>15k chars) are automatically moved to RLM memory to preserve the context window
4193 - Persistent history context: compacted messages are offloaded to RLM `history` variable for recall
4194 - Full MCP protocol support: SSE transport, Resources (`resources/list`, `resources/read`), and Prompts (`prompts/list`, `prompts/get`)
4195 - `mcp_read_resource` and `mcp_get_prompt` virtual tools exposed to the model
4196 - Dialectical Duo mode with specialized TUI rendering (`Player` / `Coach` history cells)
4197 - Dynamic system prompt refreshing at each turn for up-to-date RLM/Duo/working-set context
4198 - `project_map` tool for automatic codebase structure discovery
4199 - `delegate_to_agent` alias for streamlined sub-agent delegation
4200
4201 ### Changed
4202 - Default theme changed to 'Whale' with updated color palette
4203 - `with_agent_tools` now includes `project_map`, `test_runner`, and conditionally RLM tools for all agent modes
4204 - MCP `McpServerConfig.command` is now `Option<String>` to support URL-only (SSE) servers
4205
4206 ### Fixed
4207 - MCP test compilation errors for updated `McpServerConfig` struct shape
4208
4209 ## [0.3.4] - 2026-01-29
4210
4211 ### Changed
4212 - Updated Cargo.lock dependencies
4213
4214 ### Fixed
4215 - Compaction tool-call pairing: enforce bidirectional tool-call/tool-result integrity with fixpoint convergence
4216 - Safety net scanning to drop orphan tool results in the request builder
4217 - Double-dispatch race in parallel tool execution
4218
4219 ## [0.3.3] - 2026-01-28
4220
4221 ### Added
4222 - TUI polish: Kimi-style footer with mode/model/token display
4223 - Streaming thinking blocks with dedicated rendering
4224 - Loading animation improvements
4225
4226 ## [0.3.2] - 2026-01-28
4227
4228 ### Fixed
4229 - Preserve tool-call + tool-result pairing during compaction to avoid invalid tool message sequences
4230 - Drop orphan tool results in request builder as a safety net to prevent API 400s
4231
4232 ## [0.3.1] - 2026-01-27
4233
4234 ### Added
4235 - `deepseek setup` to bootstrap MCP config and skills directories
4236 - `deepseek mcp init` to generate a template `mcp.json` at the configured path
4237
4238 ### Changed
4239 - `deepseek doctor` now follows the resolved config path and config-derived MCP/skills locations
4240
4241 ### Fixed
4242 - Doctor no longer reports missing MCP/skills when paths are overridden via config or env
4243
4244 ## [0.3.0] - 2026-01-27
4245
4246 ### Added
4247 - Repo-aware working set tracking with prompt injection for active paths
4248 - Working set signals now pin relevant messages during auto-compaction
4249 - Offline eval harness (`deepseek eval`) with CI coverage in the test job
4250 - Shell tool now emits stdout/stderr summaries and truncation metadata
4251 - Dependency-aware `agent_swarm` tool for orchestrating multiple sub-agents
4252 - Expanded sub-agent tool access (apply_patch, web_search, file_search)
4253
4254 ### Changed
4255 - Auto-compaction now accounts for pinned budget and preserves working-set context
4256 - Apply patch tool validates patch shape, reports per-file summaries, and improves hunk mismatch diagnostics
4257 - Eval harness shell step now uses a Windows-safe default command
4258 - Increased `max_subagents` clamp to `1..=20`
4259
4260 ## [0.2.2] - 2026-01-22
4261
4262 ### Fixed
4263 - Session save no longer panics on serialization errors
4264 - Web search regex patterns are now cached for better performance
4265 - Improved panic messages for regex compilation failures
4266
4267 ## [0.2.1] - 2026-01-22
4268
4269 ### Fixed
4270 - Resolve clippy warnings for Rust 1.92
4271
4272 ## [0.2.0] - 2026-01-20
4273
4274 ### Changed
4275 - Removed npm package distribution; now Cargo-only
4276 - Clean up for public release
4277
4278 ### Fixed
4279 - Disabled automatic RLM mode switching; use /rlm or /aleph to enter RLM mode
4280 - Fixed cargo fmt formatting issues
4281
4282 ## [0.0.2] - 2026-01-20
4283
4284 ### Fixed
4285 - Disabled automatic RLM mode switching; use /rlm or /aleph to enter RLM mode.
4286
4287 ## [0.0.1] - 2026-01-19
4288
4289 ### Added
4290 - DeepSeek Responses API client with chat-completions fallback
4291 - CLI parity commands: login/logout, exec, review, apply, mcp, sandbox
4292 - Resume/fork session workflows with picker fallback
4293 - DeepSeek blue branding refresh + whale indicator
4294 - Responses API proxy subcommand for key-isolated forwarding
4295 - Execpolicy check tooling and feature flag CLI
4296 - Agentic exec mode (`deepseek exec --auto`) with auto-approvals
4297
4298 ### Changed
4299 - Removed multimedia tooling and aligned prompts/docs for text-only DeepSeek API
4300
4301 ## [0.1.9] - 2026-01-17
4302
4303 ### Added
4304 - API connectivity test in `deepseek doctor` command
4305 - Helpful error diagnostics for common API failures (invalid key, timeout, network issues)
4306
4307 ## [0.1.8] - 2026-01-16
4308
4309 ### Added
4310 - Renderable widget abstraction and modal view stack for TUI composition
4311 - Parallel tool execution with lock-aware scheduling
4312 - Interactive shell mode with terminal pause/resume handling
4313
4314 ### Changed
4315 - Tool approval requirements moved into tool specs
4316 - Tool results are recorded in original request order
4317
4318 ## [0.1.7] - 2026-01-15
4319
4320 ### Added
4321 - Duo mode (player-coach autocoding workflow)
4322 - Character-level transcript selection
4323
4324 ### Fixed
4325 - Approval flow tool use ID routing
4326 - Cursor position sync for transcript selection
4327
4328 ## [0.1.6] - 2026-01-14
4329
4330 ### Added
4331 - Auto-RLM for large pasted blocks with context auto-load
4332 - `chunk_auto` and `rlm_query` `auto_chunks` for quick document sweeps
4333 - RLM usage badge with budget warnings in the footer
4334
4335 ### Changed
4336 - Auto-RLM now honors explicit RLM file requests even for smaller files
4337
4338 ## [0.1.5] - 2026-01-14
4339
4340 ### Added
4341 - RLM prompt with external-context guidance and REPL tooling
4342 - RLM tools for context loading, execution, status, and sub-queries (rlm_load, rlm_exec, rlm_status, rlm_query)
4343 - RLM query usage tracking and variable buffers
4344 - Workspace-relative `@path` support for RLM loads
4345 - Auto-switch to RLM when users request large file analysis (or the largest file)
4346
4347 ### Changed
4348 - Removed Edit mode; RLM chat is default with /repl toggle
4349
4350 ## [0.1.0] - 2026-01-12
4351
4352 ### Added
4353 - Initial alpha release of DeepSeek TUI
4354 - Interactive TUI chat interface
4355 - DeepSeek API integration (OpenAI-compatible Responses API)
4356 - Tool execution (shell, file ops)
4357 - MCP (Model Context Protocol) support
4358 - Session management with history
4359 - Skills/plugin system
4360 - Cost tracking and estimation
4361 - Hooks system and config profiles
4362 - Example skills and launch assets
4363
4364 [0.8.39]: https://github.com/Hmbown/CodeWhale/compare/v0.8.38...v0.8.39
4365 [0.8.38]: https://github.com/Hmbown/CodeWhale/compare/v0.8.37...v0.8.38
4366 [0.8.37]: https://github.com/Hmbown/CodeWhale/compare/v0.8.36...v0.8.37
4367 [0.8.36]: https://github.com/Hmbown/CodeWhale/compare/v0.8.35...v0.8.36
4368 [0.8.35]: https://github.com/Hmbown/CodeWhale/compare/v0.8.34...v0.8.35
4369 [0.8.34]: https://github.com/Hmbown/CodeWhale/compare/v0.8.33...v0.8.34
4370 [0.8.33]: https://github.com/Hmbown/CodeWhale/compare/v0.8.32...v0.8.33
4371 [0.8.32]: https://github.com/Hmbown/CodeWhale/compare/v0.8.31...v0.8.32
4372 [0.8.31]: https://github.com/Hmbown/CodeWhale/compare/v0.8.30...v0.8.31
4373 [0.8.30]: https://github.com/Hmbown/CodeWhale/compare/v0.8.29...v0.8.30
4374 [0.8.29]: https://github.com/Hmbown/CodeWhale/compare/v0.8.28...v0.8.29
4375 [0.8.28]: https://github.com/Hmbown/CodeWhale/compare/v0.8.27...v0.8.28
4376 [0.8.27]: https://github.com/Hmbown/CodeWhale/compare/v0.8.26...v0.8.27
4377 [0.8.26]: https://github.com/Hmbown/CodeWhale/compare/v0.8.25...v0.8.26
4378 [0.8.25]: https://github.com/Hmbown/CodeWhale/compare/v0.8.24...v0.8.25
4379 [0.8.24]: https://github.com/Hmbown/CodeWhale/compare/v0.8.23...v0.8.24
4380 [0.8.23]: https://github.com/Hmbown/CodeWhale/compare/v0.8.22...v0.8.23
4381 [0.8.22]: https://github.com/Hmbown/CodeWhale/compare/v0.8.21...v0.8.22
4382 [0.8.21]: https://github.com/Hmbown/CodeWhale/compare/v0.8.20...v0.8.21
4383 [0.8.20]: https://github.com/Hmbown/CodeWhale/compare/v0.8.19...v0.8.20
4384 [0.8.19]: https://github.com/Hmbown/CodeWhale/compare/v0.8.18...v0.8.19
4385 [0.8.18]: https://github.com/Hmbown/CodeWhale/compare/v0.8.17...v0.8.18
4386 [0.8.17]: https://github.com/Hmbown/CodeWhale/compare/v0.8.16...v0.8.17
4387 [0.8.16]: https://github.com/Hmbown/CodeWhale/compare/v0.8.15...v0.8.16
4388 [0.8.15]: https://github.com/Hmbown/CodeWhale/compare/v0.8.13...v0.8.15
4389 [0.8.13]: https://github.com/Hmbown/CodeWhale/compare/v0.8.12...v0.8.13
4390 [0.8.12]: https://github.com/Hmbown/CodeWhale/compare/v0.8.11...v0.8.12
4391 [0.8.11]: https://github.com/Hmbown/CodeWhale/compare/v0.8.10...v0.8.11
4392 [0.8.10]: https://github.com/Hmbown/CodeWhale/compare/v0.8.8...v0.8.10
4393 [0.8.8]: https://github.com/Hmbown/CodeWhale/compare/v0.8.7...v0.8.8
4394 [0.8.7]: https://github.com/Hmbown/CodeWhale/compare/v0.8.6...v0.8.7
4395 [0.8.6]: https://github.com/Hmbown/CodeWhale/compare/v0.8.5...v0.8.6
4396 [0.8.5]: https://github.com/Hmbown/CodeWhale/compare/v0.8.4...v0.8.5
4397 [0.8.4]: https://github.com/Hmbown/CodeWhale/compare/v0.8.3...v0.8.4
4398 [0.8.3]: https://github.com/Hmbown/CodeWhale/compare/v0.8.2...v0.8.3
4399 [0.8.2]: https://github.com/Hmbown/CodeWhale/compare/v0.8.1...v0.8.2
4400 [0.8.1]: https://github.com/Hmbown/CodeWhale/compare/v0.8.0...v0.8.1
4401 [0.8.0]: https://github.com/Hmbown/CodeWhale/compare/v0.7.9...v0.8.0
4402 [0.7.9]: https://github.com/Hmbown/CodeWhale/compare/v0.7.8...v0.7.9
4403 [0.7.8]: https://github.com/Hmbown/CodeWhale/compare/v0.7.7...v0.7.8
4404 [0.7.7]: https://github.com/Hmbown/CodeWhale/compare/v0.7.6...v0.7.7
4405 [0.7.6]: https://github.com/Hmbown/CodeWhale/compare/v0.7.5...v0.7.6
4406 [0.6.1]: https://github.com/Hmbown/CodeWhale/compare/v0.6.0...v0.6.1
4407 [0.6.0]: https://github.com/Hmbown/CodeWhale/compare/v0.4.9...v0.6.0
4408 [0.4.9]: https://github.com/Hmbown/CodeWhale/compare/v0.4.8...v0.4.9
4409 [0.4.8]: https://github.com/Hmbown/CodeWhale/compare/v0.3.33...v0.4.8
4410 [0.3.33]: https://github.com/Hmbown/CodeWhale/compare/v0.3.32...v0.3.33
4411 [0.3.32]: https://github.com/Hmbown/CodeWhale/compare/v0.3.31...v0.3.32
4412 [0.3.31]: https://github.com/Hmbown/CodeWhale/compare/v0.3.28...v0.3.31
4413 [0.3.28]: https://github.com/Hmbown/CodeWhale/compare/v0.3.27...v0.3.28
4414 [0.3.23]: https://github.com/Hmbown/CodeWhale/compare/v0.3.22...v0.3.23
4415 [0.3.22]: https://github.com/Hmbown/CodeWhale/compare/v0.3.21...v0.3.22
4416 [0.3.21]: https://github.com/Hmbown/CodeWhale/compare/v0.3.17...v0.3.21
4417 [0.3.17]: https://github.com/Hmbown/CodeWhale/compare/v0.3.16...v0.3.17
4418 [0.3.16]: https://github.com/Hmbown/CodeWhale/compare/v0.3.14...v0.3.16
4419 [0.3.14]: https://github.com/Hmbown/CodeWhale/compare/v0.3.13...v0.3.14
4420 [0.3.13]: https://github.com/Hmbown/CodeWhale/compare/v0.3.12...v0.3.13
4421 [0.3.12]: https://github.com/Hmbown/CodeWhale/compare/v0.3.11...v0.3.12
4422 [0.3.11]: https://github.com/Hmbown/CodeWhale/compare/v0.3.10...v0.3.11
4423 [0.3.10]: https://github.com/Hmbown/CodeWhale/compare/v0.3.6...v0.3.10
4424 [0.3.6]: https://github.com/Hmbown/CodeWhale/compare/v0.3.5...v0.3.6
4425 [0.3.5]: https://github.com/Hmbown/CodeWhale/compare/v0.3.4...v0.3.5
4426 [0.3.4]: https://github.com/Hmbown/CodeWhale/compare/v0.3.3...v0.3.4
4427 [0.3.3]: https://github.com/Hmbown/CodeWhale/compare/v0.3.2...v0.3.3
4428 [0.3.2]: https://github.com/Hmbown/CodeWhale/compare/v0.3.1...v0.3.2
4429 [0.3.1]: https://github.com/Hmbown/CodeWhale/compare/v0.3.0...v0.3.1
4430 [0.3.0]: https://github.com/Hmbown/CodeWhale/compare/v0.2.2...v0.3.0
4431 [0.2.2]: https://github.com/Hmbown/CodeWhale/compare/v0.2.0...v0.2.2
4432 [0.2.0]: https://github.com/Hmbown/CodeWhale/releases/tag/v0.2.0
4433 [0.0.2]: https://github.com/Hmbown/CodeWhale/releases/tag/v0.0.2
4434 [0.0.1]: https://github.com/Hmbown/CodeWhale/releases/tag/v0.0.1
4435 [0.1.9]: https://github.com/Hmbown/CodeWhale/compare/v0.1.8...v0.1.9
4436 [0.1.8]: https://github.com/Hmbown/CodeWhale/compare/v0.1.7...v0.1.8
4437 [0.1.7]: https://github.com/Hmbown/CodeWhale/compare/v0.1.6...v0.1.7
4438 [0.1.6]: https://github.com/Hmbown/CodeWhale/compare/v0.1.5...v0.1.6
4439 [0.1.5]: https://github.com/Hmbown/CodeWhale/compare/v0.1.0...v0.1.5
4440 [0.1.0]: https://github.com/Hmbown/CodeWhale/releases/tag/v0.1.0
4441
4441 lines MARKDOWN