blue
Blue: a TUI is not a package, it is a Cordis plugin tree — a modern terminal UI for DeepSeek Harness with hot-swappable render, interaction, and command plugins.
- Stars
- 1
- Language
- TypeScript
- Created
- Aug 18, 2026
- Updated
- Aug 21, 2026
Introduction
Blue
English | 中文
Blue is an interactive terminal UI (TUI) plugin for DeepSeek Harness (dsh): a pi-tui renderer mounted as an out-of-tree Cordis plugin bundle on top of the dsh-base bundle. Its core claim: a TUI is not a package — it is a Cordis plugin tree. Every render component, interaction provider, command, and status entry is a separate plugin with its own fiber lifecycle, hot-swappable and omittable.
This repository is the standalone home of Blue's five workspace packages under the @dsh-blue scope, extracted from the deepseek-harness monorepo (packages/blue/* and packages/bundle/blue). They build and test against the published npm releases of the harness (0.1.1-rc.1 line) and vendored Cordis.
Contents
- Quick start
- Features — Key bindings · Slash commands
- Design philosophy
- Layered architecture
- The Editor seam, in brief
- Development
- Documentation
- Relationship to deepseek-harness
- License
Quick start
[!NOTE] Blue is not published to npm. The only supported install today is a local development install against a checkout of this repository.
Prerequisites: Node ^22.19 || >=24, pnpm 11, and a dsh CLI ≥ 0.1.1-rc.1 (npm i -g @deepseek-ai/dsh).
One-shot
script/install-dev.sh
# overrides: DSH_BIN=/path/to/dsh PROFILE=my-profile DSH_HOME=/custom/home script/install-dev.sh
The script builds the workspace and link-installs all five packages into the profile.
Manual, equivalent
pnpm install && pnpm run build # lib/ is the runtime entry of every package
# One-time profile setup:
dsh plugin --profile blue add \
link:/path/to/blue/packages/bundle/blue \
link:/path/to/blue/packages/core \
link:/path/to/blue/packages/interaction \
link:/path/to/blue/packages/transcript \
link:/path/to/blue/packages/app
dsh --profile blue [task] # run a task, or start interactive
dsh --profile blue --resume <id> # resume a persisted session
Why all five links: the four library packages are the bundle's workspace:^ dependencies, unresolvable outside this workspace. dsh plugin forwards verbatim to pnpm, whose link: protocol installs the checkout itself as a symlink; the linked bundle then resolves its siblings through the profile's own node_modules links. The four non-bundle links are plain dependencies — expect one declares no dsh.bundle warning each; they are libraries, not layers.
If your profile was linked before the package rename (when the packages were named @dsh-blue/blue*), those links are stale — delete the profile directory (~/.dsh/profiles/<name>) or dsh plugin --profile <name> remove the old entries, then re-run the script.
Iteration loop
edit src → pnpm run build → re-run dsh --profile blue. The links point at the package directories, so rebuilt lib/ takes effect with no reinstall; only a dependency-graph change (adding a package or changing dependencies) needs another dsh plugin --profile blue add/install.
Headless smoke check (pseudo-TTY via script(1)):
(sleep 10; printf '/quit\r'; sleep 3) \
| timeout 90 script -qec "dsh --profile blue" /tmp/blue-smoke.typescript
# Assert: bracketed-paste on (\x1b[?2004h) at boot, off (\x1b[?2004l) at exit, exit code 0.
Features
- Streaming transcript — user/assistant messages rendered as Markdown while they stream; tool calls as cards, generic by default with dedicated cards for diffs (
intent-diff) and terminal output (intent-terminal). - Input editor — rounded-box editor with fuzzy slash-command autocomplete, argument ghost hints,
!bash mode,@file completion,#skill completion, and Ctrl-V clipboard image paste. - Overlays — four-option approval panel (with session-level "always allow" inheritance) and tabbed user-questionnaire overlays.
- Two-row status footer — model name, session-mode badge, git branch, context occupancy
ctx N; entries are registry contributions, not hardcoded. - Bottom dock panes — activity spinner while the agent runs, queued inbox messages, todo list, a
/btwside-question pane that forks the live session, and the subagent-group pane. - Theming —
/themehot-switching acrossdark/light/auto(OSC 11 background detection) /custom(JSON palette). - Extensible by construction — commands, status entries, and editor enhancements register through the same seams downstream plugins use; the completion menu and
/helpreflect the live registry.
User-facing feature guides live on the documentation website: dsh-blue.dev/en/features (English) · dsh-blue.dev/features (中文).
Key bindings
The /help overlay lists every registered binding live — it is the authoritative source:
| Key | Action |
|---|---|
Shift+Tab | Cycle session mode: normal → plan → yolo (/yolo auto-approves tool calls; questions still pop) |
Ctrl-C | Clear the draft → interrupt the agent; a second press within 1 s exits |
Ctrl-S | Steer the running turn with the draft |
Ctrl-V | Paste a clipboard image as an [image #N] marker |
Ctrl-O | Expand/collapse the last 3 turns of tool output and thinking blocks |
Ctrl-T | Fold/unfold the todo pane |
↑ (empty editor) | Recall the most recent queued inbox message |
In the editor, the prefixes / ! @ # trigger command, bash, file, and skill completion respectively; a #name token anywhere in the line rewrites to the upstream /name skill gesture on submit.
Slash commands
All commands auto-list in the editor's completion menu; /help is the live truth:
| Command | Aliases | Description |
|---|---|---|
/quit | /q /exit | Exit Blue |
/new | /clear | Start a new session |
/fork | — | Fork the current session into a new one |
/sessions | /resume | List persisted sessions and switch; an id resumes directly |
/btw | — | Side question: fork the live session and ask |
/help | — | Show available commands and key bindings |
/model | — | Switch the session model (no argument opens the picker) |
/effort | /thinking | Switch the thinking effort of the current model |
/provider | — | List providers, switch the route, or add one |
/preset | — | List agent presets or switch (blank sessions only) |
/yolo | /yes | Toggle auto-approval of tool calls |
/tools | — | List the tools visible to the current session |
/mcp | — | Browse the MCP servers the host connects to (read-only) |
/skills | — | List available skills (the # prompt invokes one) |
/theme | — | Switch the color theme |
/init | — | Analyze the codebase and write AGENTS.md |
/status | — | Show the session header, model, and context status |
/context | — | Show token usage and the context window |
/version | — | Show the Blue and harness versions and the live model |
/export | — | Export the current session as a Markdown file |
/copy | — | Copy the last assistant message to the clipboard |
Design philosophy
A TUI is not a package; it is a Cordis plugin tree. pi's own coding agent collapsed its pi-tui UI into a 6.5k-line InteractiveMode god class. Blue's core claim is the opposite organization:
- Everything is a plugin — render components, interaction providers, commands, status entries are all separate plugins with their own fiber lifecycles.
- Registration is an effect — component mounts, provider registrations, keybindings bind through
ctx.effect/ctx.on, so plugin unload rolls everything back; HMR and session switching come free. - Seams with three roles — every capability is split into definition / provider / consumer. Blue consumes the harness's seams (
agents,sessions,commands,userQuestions, approval) and opens its own seams for downstream plugins (docs/blue-seams.md). - Dependency-derived loading — plugins
injectwhat they need and wait until the services exist; a provider hot-swap unloads and reloads its dependents automatically. - plain-first (ADR D21) — every non-trivial surface is a seam plus a plain default implementation. Blue's own enhancements register through the same seams as downstream plugins, and the bundle with every enhancement row removed still boots and works.
- One pi-tui import — only
packages/coreimports@earendil-works/pi-tui. Its breaking changes cannot propagate out of L0, and no contract mentions a pi-tui type.
The full architecture document is docs/blue-architecture.md (Chinese); decisions are recorded in docs/blue-decisions.md.
Layered architecture
flowchart TB
subgraph L4["L4 composition 组合层 — @dsh-blue/blue (bundle)"]
patch["cordis.patch.yml — inserts the Blue rows over dsh-base"]
app["blue-app · blue-startup — CLI startup + Agent driver"]
end
subgraph L3["L3 render 渲染插件 — @dsh-blue/blue-transcript · hot-swappable 可热替换、可省略"]
fold["event folds → streamed Markdown + tool cards"]
status["blueStatus registry + two-row footer shell"]
dock["dock panes — activity · todo · btw · subagents"]
end
subgraph L2["L2 interaction 交互插件 — @dsh-blue/blue-interaction · implements harness seams"]
input["blue-input — editor + completion"]
cmds["blue-commands — built-in commands"]
qa["blue-approval · blue-questions — overlays"]
enh2["enhancements — editor-plus · paste-image · attachments · pane-queue · mode-status"]
end
subgraph L1["L1 kernel services 内核服务 — @dsh-blue/blue-core"]
services["blueScreen · blueTheme · blueKeymap · blueComponents · blueTerminalInfo"]
end
subgraph L0["L0 pi-tui adapter 适配 — @dsh-blue/blue-core"]
adapter["terminal lifecycle ↔ fiber binding — the tree's only pi-tui import"]
end
subgraph BASE["dsh-base host bundle 宿主"]
seams["agents · sessions · commands · userQuestions · approval · agentPresets"]
end
pitui["pi-tui ^0.84.2 (npm)"]
L4 --> L3
L4 --> L2
L3 --> L1
L2 --> L1
L1 --> L0
L0 --> pitui
L2 -. implements interaction seams 实现交互缝 .-> BASE
L4 -. rides on 骑在 dsh-base 上 .-> BASE
Dependencies are strictly one-way: core ← transcript / interaction ← app ← bundle.
| Package | Layer | Role |
|---|---|---|
@dsh-blue/blue-core | L0 + L1 | The tree's only @earendil-works/pi-tui adapter: terminal lifecycle plus the blueScreen / blueTheme / blueKeymap / blueComponents / blueTerminalInfo services. |
@dsh-blue/blue-interaction | L2 | Input editor, slash commands, approval and user-question overlays, the queued-inbox pane, plus enhancement subpath plugins (bash mode, image paste, attachments). |
@dsh-blue/blue-transcript | L3 | Folds session events into transcript items and renders them (streamed Markdown, tool cards), the blueStatus registry with its footer shell, and the dock panes (activity, todo, /btw, subagent group). |
@dsh-blue/blue-app | L4 | Command-line startup ([task], --resume <id>) and the Agent driver publishing blueSession. |
@dsh-blue/blue | L4 | The installable bundle: cordis.patch.yml inserts the Blue plugin rows over dsh-base. |
Each entry point is a Cordis plugin (export const name, optional inject, apply(ctx)); Cordis and the dsh service packages are peerDependencies provided by the host dsh installation.
The same tree, seen from the bundle. cordis.patch.yml inserts 23 Blue rows in three segments. The plain baseline (baseline + assembly, 8 rows) boots and works alone; every enhancement row — the whole dashed segment — is individually deletable, which is plain-first (ADR D21) as a picture:
flowchart TB
subgraph bundle["cordis.patch.yml — the 22 Blue rows · 22 条 Blue 行"]
subgraph baseline["plain baseline 基线 — 8 rows, self-sufficient 自足"]
core["blue-core"]
theme["blue-theme-dark"]
banner["blue-banner"]
transcript["blue-transcript"]
sbasic["blue-status-basic"]
interaction["blue-interaction"]
startup["blue-startup"]
bapp["blue-app"]
end
subgraph enhancement["enhancement segment 增强段 — every row droppable 每行皆可删"]
editorPlus["blue-editor-plus"]
att["blue-attachments · blue-paste-image"]
statusEnh["blue-status-cwd · -git · -mode · -title · -context"]
intents["blue-intent-diff · -terminal"]
panes["blue-pane-activity · -queue · -todo · -btw · -agents"]
end
end
dshbase["dsh-base — agent-plane rows disabled, agents composed behind agent-presets"]
bundle -.-> dshbase
classDef optional stroke-dasharray: 4 4;
class editorPlus,att,statusEnh,intents,panes optional;
Dock order is plugin-row order — activity → queue → todo → btw → subagents, the editor mounting last. The host's agent plane (tools, plan mode, …) is disabled process-wide and re-composed per agent behind presets (ADR D37 thin host); /preset switches the composition.
The Editor seam, in brief
The input editor walks the whole philosophy in four roles, with no shortcuts between layers:
- Contract (L1) —
BlueEditoris an interface inpackages/core/src/types.tsthat mentions no pi-tui type and no harness type, on purpose. - Implementation (L0) — the only way to obtain one is
ctx.blueComponents.createEditor(); inside core, an adapter wraps the pi-tuiEditorand is the only code that knows pi-tui is involved. A future vim-mode editor could implement the same interface without any consumer noticing. - Consumer (L2) — the
blue-inputplugin creates the editor, mounts it, and publishes it through the shared-editor seam, so later plugins find it regardless of row order. - Enhancements (L2 subpath plugins) —
blue-editor-plus(bash mode, autocomplete providers) andblue-paste-image(Ctrl-V markers) are rows incordis.patch.yml: delete either and the plain editor keeps working.
Full walkthrough with code: docs/blue-editor-walkthrough.md (Chinese). The complete seam catalog — every seam Blue opens, its contract, its plain default: docs/blue-seams.md.
Development
pnpm run test # vitest: unit suites plus the bundle's whole-tree e2e
pnpm run test:coverage # per-file 100% gate on packages/*/src
pnpm run build # tsc -b emits lib/types, tsdown bundles lib/
pnpm run lint # oxlint
pnpm run typecheck # tsc -b
Tests run from source: specs import the package under test through relative ../src/*.ts paths, and every @deepseek-ai/* dependency resolves from node_modules.
Documentation
User-facing docs are on the website: https://dsh-blue.dev/ (中文) · https://dsh-blue.dev/en/ (English). The design documents below remain repo-internal.
Design documents (Chinese) live under docs/; the living/archived index is docs/README.md:
- docs/blue-architecture.md — architecture: philosophy, L0–L4 layers, stability rules.
- docs/blue-seams.md — the seam catalog: every seam Blue opens (contracts, plain defaults) and which Blue plugin implements each harness-side visual surface.
- docs/blue-editor-walkthrough.md — the Editor seam worked example: four roles, with code.
- docs/blue-decisions.md — decision records (ADR).
- docs/blue-roadmap.md and docs/blue-commands-plan.md — roadmap, and the built-in slash-command implementation checklist (four-harness reference merge, capability matrix, phasing).
- AGENTS.md plus each package's own
AGENTS.md— the authoritative description of the current code (repo-wide conventions at the root; per-package implementation detail inpackages/*/AGENTS.md).
Archived phase designs and surveys (MVP, P1, P2, pi-tui/harness selection) are under docs/history/.
Relationship to deepseek-harness
- Runtime and test dependencies (
@deepseek-ai/cordis4.0.1,@deepseek-ai/dsh-*0.1.1-rc.1,@earendil-works/pi-tui^0.84.2) come from the npm registry; Blue's own five packages are unpublished and stay workspace-linked here. - The harness's repository gates (documentation i18n pairing, README gates, snapshot/e2e lanes) do not apply here; this repo keeps the build, the full test suite, and the per-file 100% src coverage gate.
License
MIT. Every package under the @dsh-blue scope declares license: MIT.