Back to home@dsh-blue

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

CI Node pnpm License: MIT Docs

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

[!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 /btw side-question pane that forks the live session, and the subagent-group pane.
  • Theming/theme hot-switching across dark / 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 /help reflect 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:

KeyAction
Shift+TabCycle session mode: normal → plan → yolo (/yolo auto-approves tool calls; questions still pop)
Ctrl-CClear the draft → interrupt the agent; a second press within 1 s exits
Ctrl-SSteer the running turn with the draft
Ctrl-VPaste a clipboard image as an [image #N] marker
Ctrl-OExpand/collapse the last 3 turns of tool output and thinking blocks
Ctrl-TFold/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:

CommandAliasesDescription
/quit/q /exitExit Blue
/new/clearStart a new session
/forkFork the current session into a new one
/sessions/resumeList persisted sessions and switch; an id resumes directly
/btwSide question: fork the live session and ask
/helpShow available commands and key bindings
/modelSwitch the session model (no argument opens the picker)
/effort/thinkingSwitch the thinking effort of the current model
/providerList providers, switch the route, or add one
/presetList agent presets or switch (blank sessions only)
/yolo/yesToggle auto-approval of tool calls
/toolsList the tools visible to the current session
/mcpBrowse the MCP servers the host connects to (read-only)
/skillsList available skills (the # prompt invokes one)
/themeSwitch the color theme
/initAnalyze the codebase and write AGENTS.md
/statusShow the session header, model, and context status
/contextShow token usage and the context window
/versionShow the Blue and harness versions and the live model
/exportExport the current session as a Markdown file
/copyCopy 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 inject what 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/core imports @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.

PackageLayerRole
@dsh-blue/blue-coreL0 + L1The tree's only @earendil-works/pi-tui adapter: terminal lifecycle plus the blueScreen / blueTheme / blueKeymap / blueComponents / blueTerminalInfo services.
@dsh-blue/blue-interactionL2Input editor, slash commands, approval and user-question overlays, the queued-inbox pane, plus enhancement subpath plugins (bash mode, image paste, attachments).
@dsh-blue/blue-transcriptL3Folds 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-appL4Command-line startup ([task], --resume <id>) and the Agent driver publishing blueSession.
@dsh-blue/blueL4The 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)BlueEditor is an interface in packages/core/src/types.ts that 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-tui Editor and 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-input plugin 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) and blue-paste-image (Ctrl-V markers) are rows in cordis.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 in packages/*/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/cordis 4.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.