dsh-ccTUI
August 19, 2026 · View on GitHub
Goal: port the clawcodex ui-tui TypeScript terminal UI (Claude-Code-style look, feel, and
interactions) to a deepseek-harness plugin, using dsh-TUI as the packaging/integration
skeleton reference.
Reference material (gitignored, vendored locally under reference_projects/):
| Project | Role |
|---|---|
reference_projects/clawcodex/ui-tui | The TUI to port: ~41k LOC React app + ~29k LOC forked Ink renderer (packages/dsh-cctui-ink). MIT. |
reference_projects/dsh-TUI | A proven claude-code-style TUI plugin for deepseek-harness; we borrow its packaging skeleton and integration patterns. MIT. |
reference_projects/deepseek-harness | The harness itself (docs + source). Published on npm as @deepseek-ai/*@0.1.0-rc.7. |
Core architectural insight
The clawcodex TUI has exactly one backend seam: src/gatewayClient.ts (~2.9k LOC). It spawns
the Python backend as a subprocess and translates NDJSON into an app-facing contract:
- an
EventEmitteremitting a 44-memberGatewayEventunion (message.delta,tool.start,approval.request, …) defined insrc/gatewayTypes.ts, and - a
request(method, params)promise RPC surface (~75 dotted methods:prompt.submit,session.list,approval.respond, …) where unhandled methods gracefully resolve{}.
Everything above that seam (157 non-test files) is backend-agnostic. Therefore the port is:
- Copy the app + the Ink fork wholesale (preserving look/feel/interactions by construction).
- Replace only the gateway client internals with an in-process implementation over
deepseek-harness services (
ctx.agents,session/event,approval/requestwaterfall,ctx.userQuestions,ctx.commands,ctx.sessionPersistence, …). The graceful-degradation design means the TUI runs early and features light up RPC-by-RPC. - Package as a cordis bundle plugin (
package.json→"dsh": {"bundle": {"patch": "./cordis.patch.yml"}}), installable withdsh plugin --profile <p> add <pkg>and launched withdsh --profile <p>, following dsh-TUI's proven skeleton (peerDeps on@deepseek-ai/*, adapter boundary, exit funnel,NODE_ENV=productionfor React).
The full event/RPC mapping is in ARCHITECTURE.md.
Working agreements
- Each stage: implement → test → PR → merge → next stage. Branch names
stage-N-<slug>. - English is the project language (code, docs, commits, UI strings).
- Tests per stage:
tsc --noEmit+vitest run(ported suites) and, from Stage 4 on, scripted end-to-end boots of the real harness (@deepseek-ai/dshrc.7) with a scripted LLM plugin (no API key exists in dev/CI; the mock replays canned deltas/tool calls). - Features whose backend doesn't exist in the harness stay as gracefully-degrading stubs:
billing/credits, voice, pets, browser progress, worktree exit flow, rollback. The UI code
remains; the RPCs resolve
{}/ events never fire. - Provenance: clawcodex and dsh-TUI are MIT; attribution kept in
NOTICE.md.
Stages
Stage 1 — Plan & scaffolding (this PR)
Deliverables: docs/PLAN.md, docs/ARCHITECTURE.md, README.md, LICENSE, NOTICE.md,
.gitignore.
Acceptance: docs merged to main.
Stage 2 — Toolchain + vendored Ink fork
- Root
package.json(dsh-cctui, ESM, React 19,file:dep on the fork),tsconfig.json,vitest.config.ts, CI workflow (typecheck + vitest). - Vendor
packages/dsh-cctui-inkunchanged (esbuild build, rootindex.jsshims). - Acceptance: fork builds; its own unit tests pass; a headless
renderSyncsmoke test renders Box/Text into a fake stdout; CI green.
Stage 3 — App source copy compiles; unit suite green (null gateway)
- Copy
src/app + tests from ui-tui. KeepgatewayTypes.tsverbatim (it is the contract). - Replace
gatewayClient.tswith the same class surface backed by a null backend (no subprocess; RPCs resolve{}), keepingSLASHEScatalog and pure helpers. - Adapt/skip subprocess-specific tests with a documented list; everything else must pass.
- Acceptance:
tsc --noEmitgreen;vitest rungreen; headless mount ofAppLayoutrenders the banner/composer.
Stage 4 — Harness plugin boots; core conversation loop works
src/harness/adapter (the only dir importing@deepseek-ai/*): plugin entry (name/inject/Config/apply), TTY guard, exit funnel, React mount;cordis.patch.yml+ devcordis.yml;HarnessGatewayClientv1:- boot: agent create/resume →
gateway.ready+session.info; prompt.submit→agent.followup()/ busy →agent.steer();session.interrupt→agent.cancel({kind:'user'});session/event→message.delta(assistant/chunk text),thinking.delta(reasoning chunks),tool.start(tool/call),tool.complete(tool/result),message.complete(assistant/message + turn/end), busy state fromagent/status.
- boot: agent create/resume →
- Scripted-LLM e2e: a tiny test-only cordis plugin registering a canned LLM adapter; PTY/headless boot asserts prompt→stream→tool→result renders in the transcript.
- Acceptance:
dsh --profile cc(dev profile) shows the clawcodex UI and completes a scripted turn end-to-end.
Stage 5 — Interaction gates
approval/requestwaterfall →approval.request→ ApprovalPrompt → outcomes (allowed-once/rejected); pairing with streamedtool/callviacallId.ctx.userQuestions.registerProvider→question.request→ AskUserQuestion panel; plan-review intent → PlanApprovalPrompt; plan mode viactx.planMode.- Permission modes: map clawcodex
default/plan/acceptEdits/bypassPermissionsonto harness approval policy + permission presets + plan mode; Shift+Tab cycle; footer badges. - Acceptance: e2e scripts covering approve/deny, question answer/cancel, mode cycling.
Stage 6 — Sessions
session.list/active_list/resume/create/close/delete/title/statsoverctx.agents,ctx.sessionPersistence,ctx.sessionProjections; transcript rehydration from the session event log on resume; Ctrl+X switcher;/clear,/new,/rename,/resume.- Acceptance: e2e resume of a prior scripted session shows the replayed transcript.
Stage 7 — Slash commands, completions, model picker, config
- Merge local registry +
ctx.commandscatalog (commands.catalog,slash.exec,command.dispatch,commands/changerefresh);complete.slash+complete.path. /modelviactx.llmcatalog +installModelSelection+ctx.agentDefaultModel;/compactviactx.compaction;/status,/help,/usage;config.get/setover adsh-cctuisettings namespace.- Acceptance: e2e slash dispatch of a harness-registered command; model switch reflected in
session.info.
Stage 8 — Rich rendering & telemetry
- Structured diffs: tool
presentCall/presentResultDiff views →StructuredDiffPayload(colorDiff pipeline); terminal views → tool trail output;todo/write→ TodoPanel; token usage/context bar viactx.tokenMeter+resolveModelInfo; subagent progress (ctx.subagents→subagent.*); goal indicator (ctx.goals); notices. - Acceptance: e2e scripted Edit tool shows the diff card; todos render; context % moves.
Stage 9 — Packaging, launcher, final QA
bin/dsh-cctui.jslauncher (profile bootstrap viadsh plugin add, version-skew guard,NODE_ENV=production),install.sh, packagedfileslist, README usage docs.- Fresh-
DSH_HOMEinstall e2e from a local checkout; tagv0.1.0. - Acceptance:
./install.shon a clean profile launches the TUI.
Status log
- 2026-08-18: Stage 1 merged (#1). Stage 2 merged (#2) — fork vendored, 129 fork tests green.
- 2026-08-18: Stage 3 merged (#3) — verbatim app copy, 1879 tests green, AppLayout mounts headless.
- 2026-08-18: Stage 4 merged (#4) — harness gateway: real dsh boots the TUI as a cordis plugin; scripted end-to-end turn passes in a PTY e2e (also in CI).
- 2026-08-18: Stage 5 merged (#5) — gates: approvals (sandbox escalation e2e round-trip), user questions, plan review, permission-mode cycle.
- 2026-08-18: Stage 6 merged (#6) — sessions: live-agent registry, resume/activate with transcript rehydration, session list/close/title; two-phase resume e2e.
- 2026-08-18: Stage 7 merged (#7) — command bridge, /model + effort via llm catalog with persisted selection, token-meter usage/context bar.
- 2026-08-18: Stage 8 merged (#8) — presentation views (diff cards via structuredPatch, terminal/search views), todos rider, tool.generating, resume stats.
- 2026-08-18: Stage 9 merged (#9) — packaging: install.sh + bin launcher, installed-path
e2e via real
dsh plugin add(in CI), README. - 2026-08-18: v0.1.0 tagged — all nine stages complete. The clawcodex TUI runs as a deepseek-harness plugin: conversation loop, tool trail + diff cards, approvals, questions, plan review, permission modes, sessions/resume, command bridge, model picker, usage metering, checkout-based install. Remaining ideas live in PORTING-NOTES (skipped upstream test skew, features with no harness backend).
- 2026-08-18: v0.2.1 — ocean-blue brand ramp + DeepSeek-blue theme hue; the app owns
~/.dsh-cctui(no longer reads clawcodex's config);/logopersistence implemented; banner colors now regression-tested.