2nd dokployH
Find a file
Turtle f290a8b851 refactor(cli)!: one shared base config with per-surface overlays
`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.
2026-07-29 21:15:42 +08:00
.agents refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
.claude docs: accuracy sweep, architecture restructure, two ADRs, review skill 2026-06-13 22:05:34 +08:00
.github fix(ci): isolate pnpm setup per runner 2026-07-29 00:45:52 +08:00
apps refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
assets docs: make the top-level README product-first 2026-07-23 00:15:44 +08:00
bin feat(cli): launch dsh source through the tsx ESM hook 2026-07-29 13:15:24 +08:00
docs refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
examples refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
native docs(i18n): record proofread README pairs 2026-07-29 15:30:44 +08:00
packages refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
patches feat(tui): personal TUI rework, integrating upstream model reasoning-effort selection 2026-07-27 18:55:13 +08:00
python docs(i18n): address final line audit 2026-07-29 16:53:53 +08:00
scripts refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
skills Merge origin/master: web permission sandbox, default pi-ai providers 2026-07-29 21:15:34 +08:00
vendor refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
website docs(site): publish translated core data pages 2026-07-24 18:07:56 +08:00
.editorconfig Declare LF and final-newline conventions in .editorconfig 2026-07-15 16:09:12 +08:00
.gitattributes Pin LF working trees via .gitattributes 2026-07-15 16:09:12 +08:00
.gitignore Merge current master into codex/ignore-worktree-directories 2026-07-28 02:11:08 +08:00
.gitlab-ci.yml python: derive release version from repository 2026-07-13 17:49:01 +08:00
.jscpd.json chore(lint): bring .tsx files into the eslint, lefthook, and jscpd lanes 2026-07-27 21:42:08 +08:00
AGENTS.md Merge branch 'master' into xtr/dsh-source-launch-tsx-esm 2026-07-29 15:29:00 +08:00
CLAUDE.md Initialize repo with README, AGENTS.md, and CLAUDE.md symlink 2026-06-10 22:58:56 +08:00
eslint.config.mjs chore(lint): bring .tsx files into the eslint, lefthook, and jscpd lanes 2026-07-27 21:42:08 +08:00
knip.json refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
lefthook.yml Merge remote-tracking branch 'origin/master' into worktree/worktree-local-lefthook-20260727 2026-07-27 22:55:21 +08:00
LICENSE Initialize repo with README, AGENTS.md, and CLAUDE.md symlink 2026-06-10 22:58:56 +08:00
package.json feat(cli): launch dsh source through the tsx ESM hook 2026-07-29 13:15:24 +08:00
pnpm-lock.yaml refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
pnpm-workspace.yaml Merge branch 'master' into archive-agent-notes-sweep-2 2026-07-28 00:49:13 +08:00
pytest.ini Merge remote-tracking branch 'origin/master' into codex/trim-ai-prose 2026-07-14 00:40:36 +08:00
README.i18n.yaml feat(install): consolidate checkouts under ~/.dsh/source and route PATH through a stable current symlink 2026-07-27 19:08:26 +08:00
README.md feat(install): consolidate checkouts under ~/.dsh/source and route PATH through a stable current symlink 2026-07-27 19:08:26 +08:00
README.zh.md feat(install): consolidate checkouts under ~/.dsh/source and route PATH through a stable current symlink 2026-07-27 19:08:26 +08:00
tsconfig.base.client.json refactor(tsconfig): single root solution graph over host/client aggregates 2026-07-23 03:59:05 +08:00
tsconfig.base.json refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
tsconfig.client.json Merge remote-tracking branch 'origin/master' into web-permission-sandbox-merge-master 2026-07-29 11:16:49 +08:00
tsconfig.host.json refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
tsconfig.json refactor(tsconfig): single root solution graph over host/client aggregates 2026-07-23 03:59:05 +08:00
tsdown.config.ts refactor(tsconfig): single root solution graph over host/client aggregates 2026-07-23 03:59:05 +08:00
vitest.config.ts test: close the coverage gaps on the permission line 2026-07-29 00:06:19 +08:00
vitest.e2e.config.ts refactor(cli): unify the arg grammar — one program, --config flag, real web subcommand 2026-07-25 15:47:55 +08:00
vitest.snapshot.config.ts refactor(cli)!: one shared base config with per-surface overlays 2026-07-29 21:15:42 +08:00
vitest.web.config.ts Merge remote-tracking branch 'origin/master' into web-e2e-lane 2026-07-25 18:19:22 +08:00

DeepSeek Harness

English | 中文

DeepSeek Harness (dsh) is an open-source coding agent built on the DeepSeek Harness SDK.

It uses an architecture where everything is a plugin.

Install

Install dsh with one command:

curl -fsSL https://raw.githubusercontent.com/deepseek-harness/deepseek-harness/master/scripts/install.sh | sh

The installer requires git and Node ^22.19 || >=24, offers to install pnpm when it is missing, and prompts for a DeepSeek API key.

The installer keeps every checkout under ~/.dsh/source: the master clone at ~/.dsh/source/master and each install's staging checkout as a git worktree ~/.dsh/source/staging-<timestamp>. The stable symlink ~/.dsh/source/current points at the active staging worktree, and dsh in ~/.local/bin links to current/bin/dsh, so an upgrade repoints one symlink and the dsh on PATH never moves. Re-running the command adds a fresh staging worktree from an updated master and repoints current at it. See scripts/install.sh for alternate install locations and other options.

Use DeepSeek Harness

Web UI

For the recommended local interface, build the frontend after installation and after each update, then start the Web UI. Resolve the running checkout from the dsh launcher so the command holds regardless of which staging worktree is current (the launcher resolves through the stable current symlink):

dsh_bin=$(cd "$(dirname "$(command -v dsh)")" && pwd -P)/$(basename "$(command -v dsh)")
while [ -L "$dsh_bin" ]; do
  link=$(readlink "$dsh_bin")
  case $link in /*) dsh_bin=$link ;; *) dsh_bin=$(cd "$(dirname "$dsh_bin")" && cd "$(dirname "$link")" && pwd -P)/$(basename "$link") ;; esac
done
dsh_dir=$(cd "$(dirname "$dsh_bin")/.." && pwd -P)
pnpm --dir "$dsh_dir" run build && pnpm --dir "$dsh_dir" run build:web
dsh web

The Web UI is served at http://127.0.0.1:3080 by default.

TUI

Start the full-screen terminal interface:

dsh

Headless

Run one task, print the final answer, and exit:

dsh -p "summarize this workspace"

Why DeepSeek Harness

Built-in capabilities cover file reading, editing, and search; shell execution; reusable skills; task tracking; subagents and workflows; persistent sessions; and context compaction. The TUI also includes Plan Mode.

  • Everything is a plugin. Models, tools, policies, storage, context management, and interfaces are composable Cordis plugins, so deployments can extend or replace behavior without forking the agent loop. See the architecture for the underlying design.
  • Code Mode (opt-in). It exposes a run_code tool and a generated TypeScript SDK; only program output re-enters model context. See Code Mode.
  • Self-referential Cordis tools are opt-in. They let the agent inspect its live runtime and mount or unmount plugins while it runs. See the Cordis tools.

Community

Follow DeepSeek Harness on Twitter for project updates.

Development

pnpm install
pnpm run test:coverage

Start with the development guide and read the architecture before changing packages.

For agents, follow AGENTS.md.

DeepSeek Harness is currently pre-release.

License

BSD 3-Clause