DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins

dsh-acp-server

Acp Server

Agent Client Protocol (ACP) server plugin for the DeepSeek Harness (dsh) — drive dsh agents from Zed and any ACP client

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add dsh-acp-server@0.14.4
READMECompatibilityVersions

Compatibility and provenance

Acp Server is published as dsh-acp-server and currently resolves to version 0.14.4. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
any
Release source
npm
Registry updated
11/4/2026

Versions

0.14.4stable
10/29/2026
0.14.3stable
10/28/2026
0.14.2stable
10/14/2026
Show 18 more versionsCollapse versions
0.14.1stable
10/14/2026
0.14.0stable
10/13/2026
0.12.0stable
9/18/2026
0.11.1stable
9/9/2026
0.11.0stable
9/9/2026
0.10.0stable
8/18/2026
0.9.0stable
8/18/2026
0.8.0stable
8/17/2026
0.7.0stable
8/17/2026
0.6.1stable
8/17/2026
0.6.0stable
8/17/2026
0.5.1stable
8/17/2026
0.5.0stable
8/17/2026
0.4.0stable
8/17/2026
0.3.0stable
8/17/2026
0.2.0stable
8/17/2026
0.1.1stable
8/17/2026
0.1.0stable
8/17/2026

Related plugins

Loading related plugins…

Latest
0.14.4
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
581.8 kB
Files
125
Surface
any
License
MIT
Source
npm
GitHub
★ 10
Weekly downloads
798
Last push
10/29/2026
View source ↗Project homepage ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in integrations-communication.

Im@xmanrui/dsh-im把微信、飞书、企微、钉钉、QQ、Telegram、WhatsApp、Slack、Discord、Matrix接入DSH。 Connect Telegram, WhatsApp, Slack, Discord, Matrix, WeChat, Feishu, WeCom, DingTalk, and QQ to DSH.Ds Botds-botDS Bot: a team of long-lived Bots for DeepSeek Harness, with Main Bots, Bot-to-Bot messages and group chatsFree Searchdsh-free-searchFree web search for DeepSeek Harness: 27 engines (Bing/DuckDuckGo/AnySearch/SearXNG/Exa/Tavily/Keenable/Firecrawl/Parallel/You.com keyless; Zhihu global/site via MCP and Perplexity/SerpBase/DeepSeek (official + native tools/search)/Baidu/Kimi/Aliyun/DoubaPocketdsh-pocketPut DeepSeek Harness in your pocket: one package, one settings page, and scan a QR code on your phone to access DSH on your computer in sync (LAN + public network, real-time screen mirroring).

README

dsh-acp-server

Agent Client Protocol (ACP) server for the DeepSeek Harness (dsh).

Drive a full dsh coding agent - streaming output, tool calls, permission prompts, durable sessions - from Zed or any ACP v1 client, exactly like opencode or Gemini CLI.

English | 中文

What it does

A dsh profile bundle that boots the entire DeepSeek Harness (agent loop, tools, sandbox, session persistence) with an ACP v1 JSON-RPC server instead of - or alongside - the web UI.

ACP methodStatus
initialize✅ full capability advertisement (loadSession, promptCapabilities.image, sessionCapabilities.list/resume/close/delete)
authenticate✅ no-op success (dsh credentials live outside ACP; empty authMethods)
session/new✅ durable dsh agent + modes + slash-command advertisement + initial configOptions
session/prompt✅ streaming agent_message_chunk / agent_thought_chunk (reasoning), plan updates, full tool-call lifecycle, {stopReason, usage}; failed turns reject with a JSON-RPC error carrying the cause; image blocks persist through the dsh attachments service; a single /command text block routes to the dsh command registry
session/set_config_option✅ per-session model (<provider>/<model>) and reasoning_effort overrides; live effect on the next step; unsupported knobs/values refuse with precise -32602; config_option_update pushed on change
usage_update / usage✅ context usage (used/size) pushed from token accounting; the prompt response sums the turn's tokens (experimental ACP field)
session/list✅ every persisted + live session (id, cwd, title)
session/resume✅ reopen a persisted session without replay (standard form of the vendor method)
session/load✅ reopen + replay the transcript as user_message_chunk / agent_message_chunk
session/set_mode✅ default ⇄ plan, bridged to dsh plan mode, with current_mode_update push
available_commands_update✅ the dsh command registry, advertised per session and refreshed each turn
session/request_permission✅ dsh's approval seam bridged to the client (allow once/always, reject once/always)
elicitation/create✅ form-mode dsh user questions for clients declaring elicitation.form; one single-select question falls back to permission buttons; richer questions fall through to the host's answerer
session/cancel✅ aborts the turn, prompt resolves cancelled
$/cancel_request✅ handled by the ACP SDK: the request's abort signal cancels the in-flight dsh turn
session/close✅ cancels, flushes, disposes the agent
session/delete✅ removes a persisted session's artifact; refuses open/live/foreign-claimed sessions with a clear error
fs/read_text_file, fs/write_text_file☑️ intentionally not called — dsh tools read/write the host filesystem in-process, so the server never round-trips file access through the client (clients that declare the fs capability will simply never see these requests)

Roadmap: session/fork (still UNSTABLE in the ACP SDK), URL-mode elicitation, audio, document sync (document/didOpen et al. — this server is deliberately single-conversation); the dsh↔dsh client half, discovery, and identity are planned as a separate package - see the design doc.

The two final forms

dsh-acp-server       # 1) standalone: ACP on stdio (editors), or `serve` for remote HTTP
dsh web              # 2) together: the GUI and ACP in one process on one port

Form 1 — standalone (dsh-acp-server)

After npm i -g dsh-acp-server (or via npx). The bin boots dsh --profile acp with the current stdio and passes every launcher flag through (serve --port 7800, --patch extra.yml). First use in a DSH home auto-bootstraps the acp profile with the official dsh plugin command - bootstrap output goes to stderr, so an editor's stdout only ever sees ACP frames.

Zed → Settings → agent_servers (full sample in examples/zed-settings.json):

{
  "agent_servers": {
    "dsh": { "type": "custom", "command": "dsh-acp-server", "args": [] }
  }
}

Form 2 — together (dsh web)

Install into the web profile once; every plain dsh web boot then serves the GUI and ACP on one port:

node bin/setup-webacp.mjs        # official `dsh plugin --profile web add` + the web-mounted row
dsh web                          # http://127.0.0.1:3080 = GUI, /acp = ACP
node bin/acp-chat.mjs --url http://127.0.0.1:3080

Prefer to keep web untouched? node bin/setup-webacp.mjs --clone webacp gives the same on dsh --profile webacp.

The script writes a row-level inject: [agents, agentDefaultModel, webServer] so Cordis starts the acp-server fiber only after the shared webServer service exists - the stdio transport can never race a web boot. A hand install without that row is safe too: the plugin web-mounts late via service provisioning (terminal boots skip stdio entirely; daemon boots get an EOF grace window). The full row is documented in examples/patches/web-mounted.yml.

Why a bin instead of the literal dsh acp-server: the dsh launcher hardcodes its app subcommands (web, plugin) and parses argv before any plugin loads, so a bundle cannot register one; the wrapper is the same single-command shape.

Drive dsh from a script (run)

dsh-acp-server run is a one-shot CLI for external agents and orchestrators: it spawns the real dsh --profile acp, speaks ACP to it through the same SDK every other client uses, prints the answer, and exits. No ACP client implementation required:

dsh-acp-server run "fix the failing tests and summarize the cause" \
  --cwd /path/to/workspace \
  --json                                  # one JSON object on stdout
  --session acp-69041a38-...              # resume a persisted session (no cold plugin-tree start)
  --model liepin/glm-5-3                  # temporary <provider>/<model> override
  --timeout 600                           # cancel the turn after 600s
  --permission-policy auto                # auto | ask | deny
  --attach /tmp/screenshot.png            # repeatable; images ride image blocks
  • Default output is the final assistant answer as plain text on stdout; progress (tool calls, permission notes) goes to stderr. --json prints exactly one object: {sessionId, stopReason, text, toolCalls: [{title, status}], usage?, error?}.
  • Exit codes: 0 done · 1 error · 2 timeout (the turn was cancelled) · 3 cancelled · 4 a permission request was denied. A script branches on the code, never on parsing prose.
  • --session <id> resumes a persisted session (dsh-acp-server run ... --session "$(cat last-session)" keeps one conversation across invocations); without it each run creates a fresh session.
  • --model <provider>/<model> maps to session/set_config_option and overrides the profile default for that session only; your profile's agent-default-model is untouched.
  • --permission-policy auto approves every permission request (allow once), deny rejects them (exit 4 if any was rejected), ask (default) prompts on the terminal — and fails closed (deny) when stdin is not a TTY.

Install

Requires Node.js ≥ 22 and the dsh CLI (npm i -g @deepseek-ai/dsh). The dsh-acp-server bin handles the profile itself; to manage it explicitly:

# prebuilt from npm (recommended - no build authorization needed)
dsh plugin --profile acp add dsh-acp-server

# or from a tarball
dsh plugin --profile acp add ./dsh-acp-server-0.7.0.tgz

# or from GitHub (source install; see note below)
dsh plugin --profile acp add github:dushaobindoudou/dsh-acp

GitHub installs pull source, not build output. The package's prepare script builds lib/ on install; pnpm ≥ 10 refuses to run it until you allow it in the profile's pnpm-workspace.yaml:

allowBuilds:
  dsh-acp-server: true

then re-run the add. Prefer locking a commit (github:…/dsh-acp#<sha>), or avoid the authorization entirely with a prebuilt npm package or tarball. Verify any time with dsh --profile acp --dump-config (a dsh-acp-server layer should appear). node bin/setup-profile.mjs --pkg <spec> is a thin wrapper over the same command.

Remote access (serve)

Editors get ACP over stdio; serve runs a long-lived HTTP+SSE endpoint for remote machines, shared agents, or curl - following the shape of the ACP streamable-HTTP RFD:

dsh --profile acp serve --port 7800            # bind 127.0.0.1 by default
dsh --profile acp serve --host 0.0.0.0 --port 7800 --token s3cret

The serve port also ships a built-in single-file web client at GET / - open http://127.0.0.1:7800 in any browser for a complete chat UI (streaming, thoughts, tool cards, plans, permission dialogs) driven purely by the ACP routes above. It is the reference proof that this surface can carry a web interface. The same routes are served in web-mounted mode (Form 2) on the GUI's port.

HTTP transport reference

Method + pathPurpose
POST /acpone JSON-RPC message per body (single JSON object or NDJSON lines); initialize → 200 + JSON body + Acp-Connection-Id header; everything else → 202, the response arrives on the SSE stream
GET /acp/streamlong-lived SSE stream for the connection (header Acp-Connection-Id, or ?connection=); : ping comment every 15 s
DELETE /acpclose the connection → 204
GET /acp/healthzliveness probe (no auth; serve mode also answers /healthz)

Errors: 401 bad/missing credentials · 404 unknown connection id or route · 400 unparseable body. Several clients can attach to one process (one ACP connection each).

dsh/* vendor extensions (host plane)

ACP v1 standardizes one conversation, not the host around it. Sessions history, jobs, goals, skills, and the live agent tree are exposed as vendor methods under the dsh/ namespace. Host writes and orchestration are described below:

MethodReturns
dsh/sessions/listevery persisted + live session (id, title, createdAt, cwd, parentSession, acp flag)
dsh/sessions/readone session's transcript as {seq, type, text} entries
dsh/sessions/searchfind sessions by ID, title, or cwd ({query, limit?})
dsh/sessions/resumereopen a persisted session as a live ACP session (full context)
dsh/jobs/listbackground jobs (id, kind, label, status, owner)
dsh/goals/listactive goal per live agent (objective, phase, rounds)
dsh/skills/listinstalled skills (name, description, provider)
dsh/agents/treelive agents with parent/model/cwd (the subagent tree)
dsh/sessions/watch / unwatchsubscribe to any session's translated live stream - dsh/session/update frames in the same SessionUpdate shapes the owner gets (orchestrators, dashboards, audit)

Orchestration and host control

Use session/list and dsh/sessions/search to locate work, then session/resume or session/load to switch to it. dsh/sessions/prompt queues or steers a turn and returns immediately; dsh/sessions/wait, read, and watch follow its outcome. dsh/sessions/cancel cancels a running turn, and configure sets its permission policy. session/new accepts _meta['dsh/agentPreset'] and _meta['dsh/permissionPolicy'] before the first turn.

dsh/remote/catalog exposes the live Typert method catalog, parameter schemas, and an available flag. dsh/remote/invoke calls a unary method with {endpoint, args}. dsh/remote/stream opens a stream that sends dsh/remote/item and dsh/remote/end; dsh/remote/cancel stops it. The standalone ACP profile mounts workspace, directory browser, workspace files, and settings controllers. When mounted into dsh web, the bridge also sees that composition's other host methods. For example, workspace/create takes {"endpoint":"workspace/create","args":{"request":{"path":"/absolute/project"}}}. Inspect settings/describe and the catalog schema before calling settings/update. These calls run as the local DSH operator. Web-mounted ACP accepts a DSH Web login cookie or a configured ACP bearer token for scripts; standalone serve takes --token.

The shell client uses the same ACP methods:

dsh-acp-server catalog workspace --url http://127.0.0.1:3080 --token "$DSH_ACP_TOKEN"
dsh-acp-server call workspace/create '{"request":{"path":"/absolute/project"}}' --url http://127.0.0.1:3080 --token "$DSH_ACP_TOKEN"
dsh-acp-server rpc dsh/sessions/search '{"query":"project"}' --url http://127.0.0.1:3080 --token "$DSH_ACP_TOKEN"
dsh-acp-server stream workspace/follow --limit 1 --url http://127.0.0.1:3080 --token "$DSH_ACP_TOKEN"
dsh-acp-server run "continue this task" --session <session-id> --json --url http://127.0.0.1:3080 --token "$DSH_ACP_TOKEN"
dsh-acp-server run "long task" --detach --permission-policy auto --url http://127.0.0.1:3080 --token "$DSH_ACP_TOKEN"

--url and --token also read DSH_ACP_URL and DSH_ACP_TOKEN. Without a URL the CLI starts a private stdio server. --detach requires a running server and prints the session ID immediately; use rpc dsh/sessions/wait '{"sessionId":"..."}' and rpc dsh/sessions/read to follow the result. --preset selects the agent preset when creating a session. call, stream, and rpc accept inline JSON, @file.json, or - for stdin. Stream item limits must be positive integers; timeout values must be positive finite seconds. Stream timeout exits with code 2.

The run client handles form questions: auto selects the first offered option, deny declines, and ask prompts in a terminal. With non-TTY stdin, ask answers questions with the first options; permission requests are denied. Detached tasks use the server's configured policy. The question tool must be present in the agent's composition.

Push: dsh/changed {topics} notifications fire on turn ends, session lifecycle, job changes, and agent-status transitions (throttled). Interop-safe by construction - they are sent only to connections that opted in via the schema-sanctioned extension point clientCapabilities._meta['dsh/extensions'] (the _meta record is official ACP schema); standard clients like Zed see a fully standard server and are never contacted with vendor traffic. Each method degrades to a clean -32601 in compositions that lack the underlying service.

A complete, runnable conversation with nothing but curl: examples/curl-conversation.sh.

./examples/curl-conversation.sh http://127.0.0.1:7800 [bearer-token]

Configuration

All knobs have schema defaults; override only the keys you want in your profile layer ($DSH_HOME/profiles/<name>/cordis.patch.yml). Full samples in examples/patches/.

KeyTypeDefaultDescription
agentNamestringdshinitialize.agentInfo.name shown to clients
providerstring-pin the model for ACP sessions (must be set with model)
modelstring-pin the model for ACP sessions (must be set with provider)
tokenstring-extra ACP bearer credential for web-mounted mode; otherwise DSH Web's login cookie is required. Standalone serve takes --token
offerAlwaysPermissionsbooleantrueinclude allow_always / reject_always options in permission requests
flushOnTurnEndbooleantrueflush session persistence after every completed turn
hostControlbooleantrueexpose dsh/remote/* host methods
hostControlDenystring[][]block endpoints such as settings/*, workspace/delete, or *
- id: acp-server
  config:
    agentName: my-dsh
    provider: liepin        # pin (or omit both to follow the live default)
    model: glm-5-3

Behavior follows the harness config conventions: the schema validates at plugin load (wrong types or a half-set provider/model pin fail loudly with the exact key), missing keys fall back to defaults (a patch layer replaces the whole config value, the schema refills the rest), and an unset provider/model follows the profile's agent-default-model - read per session, so in-GUI model switches apply to new ACP sessions too.

Model credentials come from the usual dsh places ($DSH_HOME settings / provider API-key envs), shared with the web UI - no second setup.

Try it without an editor

acp-chat is a zero-install interactive terminal client bundled in this repo (REPL with streaming, tool-call display, plan rendering, and inline permission prompts). It speaks both transports:

node bin/acp-chat.mjs                                   # spawns `dsh --profile acp` (stdio)
node bin/acp-chat.mjs --url http://127.0.0.1:7800 --token s3cret   # remote HTTP+SSE

Third-party ACP clients that work today:

ClientTypeTry it
Zededitor (reference client)agent_servers entry above
acpxCLInpx acpx@latest --agent 'dsh --profile acp' "hello"
ghost.nvim / acpear.nvimNeovimplugin config → command dsh-acp-server
acp.elEmacs(setq acp-agent-command '("dsh-acp-server"))
obsidian-agent-clientObsidianplugin settings
ACP-inspectorconformance/debugvalidates wire traffic

How it works

Transport choice is deterministic at mount: serve subcommand → standalone HTTP server; a webServer service present (or arriving late) → routes registered on the shared server; otherwise stdio.

ACP client (Zed / curl / acp-chat)
   │  stdio NDJSON JSON-RPC          │  HTTP POST + SSE (serve / web-mounted)
   ▼                                 ▼
  dsh-acp-server plugin ⇄ dsh services
      ├─ ctx.agents.create/dispose      (session/new, close)
      ├─ agent.followup/cancel/whenIdle (session/prompt, cancel)
      ├─ 'session/event'                (streaming session/update)
      ├─ 'approval/request'             (session/request_permission)
      └─ dsh-base: tools, sandbox, persistence, settings

Source layout: src/connection.ts (method handlers) · translate.ts / config-options.ts (pure wire mappings, unit-tested) · event-bridge.ts / perm-bridge.ts (dsh ⇄ ACP seams) · session-delete.ts (guarded persisted-session cleanup) · cli/run.ts (the one-shot CLI; cli/run-core.ts is its pure mapping layer) · http-transport.ts (shared HTTP router) · serve-startup.ts (the serve subcommand) · config.ts (schema) · table.ts (session registry).

Full research behind every mapping: research/ - ACP protocol, DSH architecture, prior art, design blueprint.

Development

pnpm install
pnpm run build     # tsc -> lib/
pnpm test          # unit tests (pure translation + config layers)

# end-to-end: boots the REAL dsh in a throwaway $DSH_HOME with a
# deterministic mock LLM, and asserts the full wire behavior:
pnpm run test:e2e  # stdio · run CLI · serve (HTTP+SSE) · web-mounted · bare-install grace

The e2e suites are the fastest way to iterate on protocol behavior - each drives a complete conversation (text prompt, tool-call lifecycle, teardown) over its transport. Set DSH_ACP_PKG (repo path by default, ./dsh-acp-server-*.tgz, or an npm spec) to pick the install source.

Contributing

PRs welcome - see CONTRIBUTING.md. The milestone plan lives in research/acp-dsh-design.md.

License

MIT