Prerequisites
From the root README.md and docs/development.md:
| Requirement | Value / note |
|---|---|
| Node.js | ^22.19.0 || >=24.0.0 (CI also covers 26) |
| pnpm | pinned 11.7.0; run corepack enable if pnpm --version doesn't resolve through Corepack |
| Git | 2.26+ |
| DeepSeek API key | needed for the Web/headless/ACP demos and real-API e2e tests (DEEPSEEK_API_KEY or a .env) |
You do not need TypeScript or a build tool to run dsh from npm — the published @deepseek-ai/dsh package ships built lib/*.js. You only need the build toolchain when running from source.
Installation & npm channels
dsh has no stable release yet — every published version is a prerelease, and experimental packages are never published. The launcher is published to npm as @deepseek-ai/dsh with three dist-tags:
| dist-tag | Carries | Currently |
|---|---|---|
alpha | alpha prereleases | 0.1.2-alpha.2 |
canary | canary builds | — |
next | all other prereleases (incl. rc) | 0.1.1-rc.2 |
Until 0.1.2-alpha.2, all prereleases went to next; the alpha tag now receives alpha prereleases. There is no stable on latest. Install a prerelease channel explicitly:
npm i -D @deepseek-ai/dsh@alpha # or: @deepseek-ai/dsh@nextRun from npm
Install Node.js, then:
npx @deepseek-ai/dsh webThe launcher boots the web profile and serves the Web UI at http://127.0.0.1:3080 by default (the port is decided by the web app's own flags, defaulting to 3080). The process uses your invoking directory as the default filesystem root, then the Web UI asks you to Choose workspace and to add a model in Settings → Models before a session becomes fully usable. See the user guide.
This same launcher handles every mode — apps/cli/src/bin.ts dynamically imports per mode, so --help/--version/a parse error print and exit, and only a valid mode reaches the real dispatch.
Run from source
Clone and build:
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh webpnpm installalso wires worktree-local Lefthook hooks and the translation-pairing Git merge driver (node scripts/install-lefthook.mjsif a cache-restored install skippedpostinstall).pnpm run buildbuilds the Host lib phase, the Client lib phase, and the Web frontend. Thedshroot script is defined asnode --import tsx/esm apps/cli/src/bin.ts, sopnpm dsh <args...>runs the TypeScript entry directly and forwards every argument.- Production runs from npm need no source checkout; the source path is for contributors.
Profiles: five templates
dsh is not a single program with modes baked in; it boots a profile, a named composition stored in the Harness home. Five are shipped as templates (PROFILE_TEMPLATES in packages/boot/app-boot/src/profile.ts) and auto-initialize on first use. Each template also fixes its patchReload — how a user cordis.patch.yml edit is applied: web uses live (hot reload), the other four use startup (applied at the next boot):
| Profile | What it brings | Typical invocation |
|---|---|---|
web | dsh-base + dsh-web-app: server, browser UI | dsh web or dsh --profile web |
headless | dsh-base + dsh-headless: one-shot runner, no server | dsh --profile headless "task" |
acp | dsh-base + dsh-acp-app: automation-only ACP stdio server | dsh --profile acp |
sdk | dsh-base + dsh-sdk-app: JSON-RPC SDK runtime over stdio | dsh --profile sdk |
sdk-minimal | dsh-sdk-minimal alone: a minimal two-tool coding agent without the shared base | dsh --profile sdk-minimal |
Any other profile name must be created first through the plugin subcommand:
dsh plugin --profile myname add <package>Useful commands
The launcher's command grammar lives in apps/cli/src/args.ts. It parses only its own flags and hands everything after them to the booted profile — so app flags (--port, --help) belong to that app, not the launcher:
| Command | Effect |
|---|---|
dsh web | boot the web profile (alias of --profile web) |
dsh --profile web | same, spelled out |
dsh --profile headless "task" | run one session on the task, print the answer, exit |
dsh --profile web --help | the web app's help text, not the launcher's |
dsh --help | the launcher's own help |
dsh --profile <name> --patch extra.yml | boot with one extra patch overlay (repeatable) |
dsh --profile web --dump-config | print the composed web tree and exit (with user layer + --patch) |
dsh --profile web --dump-default-config | print the bundle layers only (no user layer) |
dsh plugin --profile <name> add <pkg> | install a plugin into a profile (forwards to pnpm) |
Launcher flags are --profile, --patch, --dump-config, --dump-default-config, and --version. The config dumps are boot-free: renderConfigDump in app-boot composes the tree with the include's own applyEntryPatches, so the printed tree is exactly what would mount — a good way to see how plugins pile up before you write your own patch.
Where data lives
All user data lives under the Harness home, resolved by @deepseek-ai/dsh-home-paths:
resolveDshHome()→ an explicit configured path, else$DSH_HOME, else~/.dsh.- Profiles live at
$DSH_HOME/profiles/<name>(each a package.json manifest +cordis.patch.yml). - The home-level overlay is
$DSH_HOME/cordis.patch.yml; layered environment lives in$DSH_HOME/.env. - Managed credentials live separately in
$DSH_HOME/.credentials.yaml.
The invoking directory is the default workspace for a session; the Harness home is where profiles, credentials, and user patches are stored. Keeping the two distinct is important: home is machine-local state, workspace is what the agent works on.
Example overlays
After a source build, runnable demos live under apps/cli/config/examples/ as cordis.patch.yml overlays (the top-level examples/ tier was retired upstream — commit 4125514a08):
| Overlay | What it demonstrates |
|---|---|
cordis | a self-referential agent that inspects and edits its own live plugin tree |
github-review | a signed GitHub webhook → Session review rule |
mcp-memory | third-party memory servers via the generic MCP client (one overlay per server) |
schedule | durable reminders for a Web session |
Their tests live under apps/cli/tests/profiles/{acp,headless,sdk}. For the credentials-gated demos, set DEEPSEEK_API_KEY (optionally DEEPSEEK_BASE_URL) in the environment or a repo-root .env; without a key, the real-API suites self-skip.
Further reading
- What Is DeepSeek Harness? — the product you just launched.
- Anatomy of the Monorepo — which group owns the pieces you touch.
- Boot & CLI — profiles, bundles, and flags in depth.
docs/development.md— the contributor setup tutorial and daily commands.packages/boot/cmdline/README.md— how app flags reach the booted tree.