Third-party, complete DeepSeek Harness agent over the Agent Client Protocol (ACP) — a superset of the official automation-only @deepseek-ai/dsh-acp: streaming, tool calls, sessions, slash commands, agent presets, config options. npx one-command, offline archive, works with Zed / VS Code ACP / Claude Code.
An independent, third-party DeepSeek Harness agent over the Agent Client
Protocol (ACP v1) — a complete ACP agent over stdio that any ACP-compatible
client (Zed, VS Code ACP, Claude Code, ...) can launch directly. It is a
superset of the official automation-only
@deepseek-ai/dsh-acp:
every ACP session is a real DSH agent with the same tool access, presets,
sessions, and settings as the Web GUI.
# One command — the package brings the full @deepseek-ai/dsh runtime, so no
# separate server, no global install. First launch downloads ~330 MB once.
npx -y dsh-acp-gateway
First boot takes ~15-20s (a full DSH instance boots); each agent window is its
own process that exits with the window. Sessions persist in ~/.dsh
(DSH_ACP_HOME isolates), so session/load resumes them later. Set the model
provider's API key env var (e.g. OPENCODE_GO_API_KEY or DEEPSEEK_API_KEY).
available_commands_update + /cmd execution (incl. /plan, /plan off — the same channel the web GUI's Plan chip uses)
✅ Session modes
the agent presets (the web GUI's modes: Standard / Code(PTC) / Minimal / Creator / your custom presets), session/set_mode re-composes the agent, current_mode_update
✅ user_message_chunk
echo accepted prompts
✅ Embedded resource content
resource blocks expand into prompt text
✅ Session config options
ACP v1 configOptions (select) for mode (the agent presets), model (provider/model), thought_level, permission (read-only / workspace-write / danger-full-access)
✅ Permission approval flow
workspace-write asks the client through session/request_permission for mutating tools (edit/delete/move/execute)
✅ Elicitation
DSH ask_user_question surfaces as an ACP elicitation/create form; answers feed back as the tool result
✅ Thinking stream
agent_thought_chunk from DSH reasoning chunks
✅ Agent plan
exit_plan_mode markdown → ACP plan notification (entries)
✅ Session info
session_info_update on title changes
Architecture
ACP client (Zed / VS Code ACP / ...)
│ stdio (launches `dsh-acp-gateway` / `dsh-acp-agent` / `dsh-acp-server`)
▼
dsh-acp-gateway process (full DSH instance)
│ agents.create() → real DSH agent (selected preset, full tools)
▼
DSH agent engine (same as the Web GUI)
Direct mode (default for editors): the client launches the server itself
over stdio — stdio is the ACP channel, and the process exits when the client
closes (1:1 lifecycle, no orphans).
Bridge mode: dsh-acp-agent is a thin stdio bridge to a long-running
dsh-acp-server (endpoint discovery: DSH_ACP_URL → ~/.dsh/acp/endpoint
→ http://127.0.0.1:3080); one server can serve many clients/sessions.
Each ACP session maps to a real DSH agent/session (durable, resumable via
session/load).
Installation
1. Zero-install: npx (recommended for editors)
See Quick Start. The package depends on the full
@deepseek-ai/dsh runtime, so it is self-contained — no globally installed
dsh app, no separate server process, no manual lifecycle.
2. Offline archive (no npm, no network)
Build a self-contained tarball with the full dependency closure, the shipped
presets, and a portable vendor anchor. It expects a system node >= 20
(--embed-node bundles a Node binary instead):
bash scripts/package-offline.sh # → dist-offline/dsh-acp-gateway-.tar.gz
bash scripts/package-offline.sh out --embed-node # embed a Node runtime (~156 MB)
Extract anywhere and point an ACP client at the bundled launcher:
Requires the standard host services (agents, webServer, fs, shell,
agentDefaultModel, approval, agentPresets, commands, attachments,
sessionQuery). On start the plugin writes the stdio bridge to
~/.dsh/acp/dsh-acp-agent.js (endpoint embedded).
Any other ACP client — point it at npx -y dsh-acp-gateway, or at a
local install (npm i -g ./dsh-acp-gateway-.tgz then
dsh-acp-gateway), or at the extracted offline launcher
(/path/to/dsh-acp).
Usage
Commands
Command
Purpose
dsh-acp-gateway
the ACP agent itself (stdio direct mode)
dsh-acp-server
alias of the above
dsh-acp-agent
stdio bridge to a long-running server (bridge mode)
By default the server shares your deployment home (~/.dsh): presets
(including locally authored ones like anchored-standard), settings (default
model, default preset, permission), sessions, and credentials are exactly the
ones the web GUI uses. Set DSH_ACP_HOME (e.g. ~/.dsh-acp) for a fully
isolated instance.
Session modes = agent presets
ACP session modes are the agent presets — the same "modes" the web GUI
offers (Standard / Code / Minimal / Creator, plus your custom presets). The
current mode follows the deployment default (agent-presets.default in
settings); session/set_mode or the mode config option switches the preset,
re-composing the agent at the next prompt. Plan mode is not a mode: it is
toggled through the /plan and /plan off slash commands, exactly like the
web GUI's Plan chip.
Test client
npx dsh-acp-client # interactive, via the bridge
npx dsh-acp-client --endpoint http://127.0.0.1:56045
echo 'init
new /tmp
prompt 运行 pwd 并报告' | npx dsh-acp-client # scripted
Commands: init, new [cwd], prompt , mode ,
set (mode/provider/model/thought_level/permission),
cancel, list, load , delete .
Session config options: mode (the agent presets — standard / code(PTC) / minimal / creation / your custom presets), model (provider/model — one selector across every provider), thought_level (minimal/low/medium/high/max), permission (sandbox file access: read-only / workspace-write / danger-full-access). Changing mode, model, or thought_level rebuilds the live agent from its persisted session; permission applies immediately and sets the approval policy (workspace-write asks the client via session/request_permission for mutating tools). Both configOptions and the modes field are returned (transition period per the spec).
Notifications additionally include agent_thought_chunk (reasoning stream), plan (from exit_plan_mode), and session_info_update (title changes). DSH ask_user_question maps to an ACP elicitation/create form.
Not implemented (by design): client-cooperative capabilities (fs/*, terminal/*, elicitation/*), MCP server connection, HTTP transport.
Troubleshooting
Symptom
Cause / fix
Editor stuck on "loading"
The bridge could not reach any endpoint. Check ~/.dsh/acp/endpoint points at a live server (DSH_ACP_URL overrides), or use direct mode (npx -y dsh-acp-gateway). The bridge now answers with a JSON-RPC error and re-reads the endpoint file instead of hanging
Typing / shows no slash commands
Zed drops available_commands_update sent before the session/new response (zed#60199); this gateway holds notifications until after the response — restart the agent and create a fresh session
session/delete leaves sessions behind
Fixed: persisted session dirs are removed with direct fs
Multiple ACP instances
Multiple clients can share one server (bridge mode); each direct-mode process is its own full DSH instance (~30-60 MB RSS each, 15-20s boot)
Plan mode does nothing
Plan is toggled via /plan / /plan off slash commands, not a session mode
Development
The package is TypeScript compiled to ESM in dist/ (NodeNext). Logic lives
in src/*.ts; bin/ artifacts are emitted to dist/src/bin/.
npm run check # tsc --noEmit (type-check)
npm run build # tsc (emit dist/)
npm test # build + run unit tests against the build
Publishing
The package is self-contained for npx: it depends on @deepseek-ai/dsh
(which brings the whole runtime closure), ships the preset roster in
config/agent-presets, and carries the portable vendor anchor in vendor/
(regenerate after any dependency change):
npm install # fetch the closure
npm run vendor # regenerate vendor/dsh-app/package.json
npm run build
npm test
npm publish
Offline archive (for machines without npm/Node):
npm run pack-offline # → dist-offline/dsh-acp-gateway-.tar.gz (~119 MB)
The runtime depends on the dsh installation's packages (resolved through the
@deepseek-ai/* symlink farm in node_modules/). After any npm install,
restore the links with: