`dsh` shipped two config trees that were 43 rows the same: apps/cli/cordis.yml composed web as 74 flat rows, while the TUI booted examples/tui-agent/cordis.yml whose single `@deepseek-ai/dsh-tui-demo` row mounted twelve plugins behind a twenty-key pass-through Config. Neither file was what its location claimed — apps/cli hardcoded the "example" as the product default and the "demo" bundle was the application — and every capability change had to be made twice. - apps/cli/base.cordis.yml holds the 43 shared rows; tui.cordis.yml and web.cordis.yml are patch lists stating only what differs per surface - overlays apply as SIBLING patch lists at one include level, because include patches never cross an include boundary. Precedence: base < surface < (--config | personal ~/.dsh/config.yaml) < launcher flag/profile patches - `--config` now applies an overlay INSTEAD OF the personal one, so a demo or test tree never inherits the user's route; new `--config-replace` boots a file as the entire tree (the old `--config` behaviour). Both survive /resume - vendor/include: index each `insert`ed row as it is added so a later patch can configure or disable it. Upstream built the id index once before the patch loop, leaving every surface-only row — the whole TUI front door — silently unpatchable from user config. Logged as local modification 8 - session identity moves to dsh-agent-loop's CONFIGURED_AGENT_IDENTITIES_KEY; dsh-tui's MAIN_SESSION_ID_KEY is deleted (only the bundle read it) - delete examples/tui-agent, examples/cordis-agent, packages/examples/tui-demo; TUI tests → apps/cli/tests, cordis e2e → packages/cordis/tool-cordis/tests, examples/code-mode survives as an overlay leaf - `dsh web` gains --config, threaded into AppCLIEntry as an extra overlay Three latent defects surfaced and are fixed here: the TUI captured the optional sessionQuery service once at construction and could permanently disable /resume when it won the mount race; the session-store root silently reverted to a project-local ./.sessions; --config-replace was dropped by the resume handoff. Verified by booting each tree through the real Loader (TUI 55 entries, web 75, zero unsettled) rather than reading YAML. All eight terminal snapshots replay byte-identically; 14/14 PTY smoke, 112/112 snapshots, 25/25 doc-sync, hygiene and lint clean.
code-mode
English | 中文
Code Mode over the shipped TUI: the model stops calling one tool per turn and instead writes TypeScript programs for a single run_code tool, executed in a worker thread.
This leaf is an overlay, not a tree. dsh --config includes the shared apps/cli/base.cordis.yml, applies the tui.cordis.yml surface overlay, then applies this file — all as sibling patch lists at one include level.
Run it
# repo root .env (gitignored) or exported env:
# DEEPSEEK_API_KEY=sk-…
# DEEPSEEK_BASE_URL=https://… # optional; defaults to the public API
pnpm run demo:code-mode
pnpm run demo:code-mode acp boots the same idea over the ACP transport from examples/acp-agent/code-mode.cordis.yml.
What the overlay changes
| Row | Change |
|---|---|
tools |
mode: code — the wire registry collapses to run_code plus its generated TypeScript SDK prompt section |
system-prompt |
a persona telling the model to batch tool work into one program |
tui |
a Code Mode welcome line |
code-runtime |
inserted: @deepseek-ai/dsh-code-runtime-worker, the worker thread run_code executes in |
Everything else — the model backend, executors, filesystem tools, persistence, delegation, and the front door — comes from the base and the TUI overlay.
A patch replaces a row's whole config rather than merging into it, so each row above restates every key it owns. A patch whose id matches no row is skipped with a Loader warning, so renaming a row in the base or the surface overlay requires updating this file.
Model Experience
The model sees one tool instead of the full native registry. Its request carries the run_code schema and a generated TypeScript SDK section describing the callable surface, which costs more prompt tokens up front but replaces many single-call turns with one program — fewer round trips and fewer intermediate tool results in the transcript. Because the tool catalog is part of the cached request prefix, switching modes invalidates the KV cache for the session.