Guide
DeepSeek Harness: Install, Configure and Troubleshoot
DeepSeek open-sourced its agent harness on 13 August 2026, hours after the DeepSeek V4 Pro release. It is MIT-licensed, it runs from a single npx command, and it is a developer preview that says so in the README. This guide is written from the repository rather than the launch coverage — including the parts the coverage got wrong.
Looking for a desktop download? Start with our DeepSeek Harness Desktop guide for the official browser interface and community wrapper options.
What DeepSeek Harness Actually Is
DeepSeek Harness (the command is dsh) is not a model and not an API client. It is an agent harness: the layer that connects a model to a filesystem, a shell, a code editor, the web and other agents, then records what it did and constrains what it may do. The repository describes its own architecture in four words — everything is a plugin — and it means it literally. The agent loop itself is a plugin.
It is built on Cordis, a microkernel whose design is published as a paper, A Programming Paradigm for Spatiotemporal Composability. A running harness is a Cordis context; packages register services, events and capabilities into it, and a configuration file decides which of them a given agent gets.
The practical consequence is that the shipped coding agent is the framework's first customer rather than its point. Filesystem, terminal, subprocess, PTY, language servers, web access, skills, subagents, workflows, plan mode, session persistence, settings, credentials and telemetry each live in their own package, behind their own interface.
Install DeepSeek Harness with npx
Install Node.js, open a terminal in your project directory, and check that node --version and npm --version work. Then run the command from the official README:
npx @deepseek-ai/dsh webThat starts the Web UI, served at http://127.0.0.1:3080 by default. The directory you ran it from becomes the default workspace root, but a fresh Web UI has no workspace selected — the session composer stays unavailable until you click Choose workspace and add one. That trips people up on first launch.
Keep that terminal running while using the browser. Running with npx does not install a permanent global dsh command; use the same npx command when you launch it again. This starts a local web application, so no separate desktop wrapper is required.
To run from a checkout instead:
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh webAdd a DeepSeek API Key and Choose a Workspace
Open Settings → Models and enter a DeepSeek API key. The route becomes usable immediately — no restart. Keys are write-only from the UI's point of view: after saving, the page only ever receives a redacted descriptor. The secret is stored in $DSH_HOME/.credentials.yaml, and your settings keep nothing but a reference to it.
Credentials resolve in a fixed order: the inherited environment, then $DSH_HOME/.credentials.yaml, then the invoking directory's .env, then $DSH_HOME/.env. The managed credentials document is never materialized into process.env.
Other providers work through Add provider (Anthropic, OpenAI and the rest of the installed catalog) or Add a custom provider for a company gateway or self-hosted endpoint, where you supply a provider ID, base URL, protocol, credential and at least one model. Two things worth knowing before you fight them:
- The provider ID is permanent. Requests, saved sessions, model defaults and credential references all key off it. Renaming means adding a new provider and deleting the old one.
- A hand-entered model is text-only until it says otherwise. Nothing can ask an endpoint which modalities it accepts, so attaching an image is refused before it is sent. Give the model
input: [text, image]in$DSH_HOME/settings.yaml— the form has no field for it.
llm-pi-ai:
providers:
my-gateway:
apiKeyEnv: GATEWAY_API_KEY
api: openai-completions
baseURL: https://gateway.example/v1
models:
- id: legacy-chat
- id: vision-preview
input: [text, image]DeepSeek's own chat-completions route is text-only and cannot be configured otherwise.
DeepSeek Harness Setup Troubleshooting
- npx is not found or is not recognized
- Install Node.js with npm, reopen your terminal, and check
npm --versionbefore retrying. - dsh: command not found
- Use
npx @deepseek-ai/dsh web. A previous npx launch does not put dsh on your global PATH. - The browser cannot connect to localhost
- Check the terminal for a startup error and open the URL it actually prints. For an SSH launch, localhost in your laptop browser points to your laptop; use your SSH client or editor's port forwarding to reach the remote server.
- The page opens but the message composer is disabled
- Click Choose workspace, add your project directory and select it. Starting the server from that directory alone does not select a workspace.
- The model is unavailable or authentication fails
- Open Settings → Models, check the provider and save its API key. A DeepSeek website login is separate from an API credential; see our API key guide.
Setup checked against the upstream Web UI guide on 5 September 2026. This preview changes quickly; use the URL and error printed by your installed version when diagnosing a failure.
The Four Agent Presets
The Web UI ships four presets. They are not four separate agents and not four prompt styles — they are four compositions mounted on one shared host, so the model route, session persistence, sandbox and approval stack stay identical while the tools and prompt sections change.
| Preset ID | Label in the UI | Name in preset.yml | What it composes |
|---|---|---|---|
standard | Standard mode | 标准模式 | The full coding agent: file editing, shell, file and web search, skills, plan, goals, subagents and workflows. |
code | PTC mode | PTC 模式 | Everything in standard, but tools are presented through the Code Mode SDK so the model writes one TypeScript program instead of many round-trips. |
minimal | Minimal mode | 极简模式 | Two tools only — persistent bash and str_replace_editor — with a fixed one-line system prompt and no context compaction. |
cordis | Creator mode | 创造模式 | Standard plus runtime inspection, temporary plugin experiments and preset-authoring guidance. The agent can reshape its own runtime, so it is a high-trust mode. |
The two label columns differ, and it trips people up. The shipped descriptors at config/agent-presets/<id>/preset.yml really do carry Chinese names, but the Web UI localizes them, so an English install reads “Standard mode”, “PTC mode”, “Minimal mode” and “Creator mode” — Settings carries an explicit Language control that drives this. Note that cordis surfaces as “Creator mode”, not “Cordis mode”. Either way the directory names — standard, code, minimal, cordis — are what the code actually keys on.
Corrected 20 August 2026. An earlier version of this guide said the Chinese names were what you would see in the UI, and that hunting for “Standard” there would come up empty. That was wrong: we checked it against a running 0.1.0-rc.7 install rather than against the repository alone, and the UI shows the English labels.
The minimal preset is the clearest illustration of the architecture. Its whole system prompt is the single sentence You are a helpful software engineer assistant., runtime context snapshots are suppressed, context compaction is absent, and the model gets exactly two tools: a persistent bash and str_replace_editor. Everything else in the harness is still running — it is simply not composed into that agent.
Profiles: How Configuration Actually Layers
Most launch write-ups describe a single cordis.yml. The shipped CLI is more specific than that. dsh is a launcher for profiles: ordered stacks of plugin-bundle patch layers with your own overrides on top.
| Command | What it does |
|---|---|
dsh web | Alias of --profile web. Starts the Web UI on http://127.0.0.1:3080. Auto-initializes on first use. |
dsh --profile headless "run the tests" | One fresh persisted session. Prints the final assistant message and exits 0 on completion, 1 otherwise. Opens no port. Built for CI. |
dsh --profile <name> | Boot any profile under $DSH_HOME/profiles/<name>. Anything other than web and headless must be created first. |
dsh plugin --profile <name> add <pkg> | Install an out-of-tree plugin bundle into a profile by forwarding to pnpm in that profile directory. |
The effective tree composes over an empty root in this order:
- each bundle patch named in the profile manifest's
dsh.profile.bundleslist - the profile's own
cordis.patch.yml - the home-level
$DSH_HOME/cordis.patch.yml, which outranks the per-profile layer - each
--patch <path>overlay, in argv order
config value rather than deep-merging keys. Write one new field and the API key, base URL and everything else on that row disappear with it. It is consistent, and it is not what most people expect on their first patch.A related trap: some shipped rows read runtime services through expressions, such as port: !!js ctx.webStartup.port ?? 3080. Replace that whole config with literals and you have quietly removed the runtime read, so the command-line flag stops beating the file. Use --dump-default-config and --dump-config to inspect the composed tree without booting it.
Bundle names resolve from the dsh installation first — @deepseek-ai/dsh-base, @deepseek-ai/dsh-web-app, @deepseek-ai/dsh-headless — then from the profile's own pnpm-managed node_modules.
The TUI Is Not Bundled
Coverage of the launch tends to list “Web, TUI, headless and SDK” as four shipped front doors. Three of those are in the box. The terminal UI is an out-of-tree plugin you install into a profile you create yourself:
dsh plugin --profile tui add github:deepseek-harness/turtle-ui
dsh --profile tuiOnly web and headless auto-initialize from shipped templates on first use. Any other profile name fails loudly with a hint to install a bundle into it first.
Sandbox and Approvals
A coding agent with shell and filesystem access can modify code, install dependencies and start processes. DeepSeek Harness treats that as an architecture problem rather than a confirmation dialog. Filesystem effects are governed by a sandbox mode:
| Mode | Effect |
|---|---|
read-only | The backend denies writes. POSIX runners still grant the /dev/null sink their shells need. |
workspace-write | Writes permitted under the workspace root and the backend’s promised temp area. This is the default, paired with the ask approval policy. |
danger-full-access | Confinement bypassed entirely, paired with the never approval policy. The deployment has to choose it explicitly. |
Enforcement is platform-specific: bwrap and Landlock on Linux, Seatbelt on macOS, and an ACL restricted-token backend on Windows. It is also a reported fact rather than an assumption — a backend reports full or partial enforcement, and older Landlock ABIs and the Windows ACL runner's boundaries are current partial cases. The seam is fail-closed by design: a runner must return enforcing arguments or fail, and silently passing an unconfined command through is forbidden.
The permission selector you see in the UI bundles two independent knobs — sandbox mode and approval policy — into named presets. The default table ships workspace-write (workspace-write + ask) and danger-full-access (danger-full-access + never).
One security decision deserves a callout because it runs against the industry default: no MCP server is enabled out of the box. The MCP client ships as a dependency for patch layers, but each server command is trusted executable code living outside the agent sandbox, so enabling one is your explicit act. Compare that to how most agent runtimes ship MCP.
The Session Log Is the Source of Truth
The rule the project sets itself is that anything the model saw must be reconstructable from the log. User messages, runtime context, model request metadata, streaming chunks, tool calls and results, compaction events, permission switches and cancellation reasons all append to one event stream. The UI, persistence, resume, fork, telemetry and replay all derive from that single source instead of each keeping its own approximately-correct copy.
This answers a question most agent stacks answer badly: when a run goes wrong, what did the model actually see? If a system stores only the final chat text, the workspace snapshot injected before the request, the truncated tool result, the silent model reroute and the mid-stream steering message are all gone. Persistence is itself a plugin, with JSONL and SQLite backends; resume continues the original session, and fork branches from a definite historical boundary.
Automation: Headless, ACP, JSON-RPC and Python
For CI, dsh --profile headless "run the tests" runs one task, waits for the agent to fully settle, prints the last non-empty assistant message on stdout and exits — 0 when the turn completed, 1 otherwise. The headless profile mounts no HTTP server, no web runtime and no browser client, and a clean run opens no listening port.
For programs that need structured events and continuous control, there is an ACP service and a JSON-RPC entry point. The Python SDK drives the bundled JSON-RPC runtime, so a Python application can start sessions, send tasks and receive notifications without embedding the Node core:
python -m pip install deepseek-harness-sdk
export DEEPSEEK_API_KEY=sk-your-key-here
# export DEEPSEEK_BASE_URL=http://127.0.0.1:8000/v1 # OpenAI-compatible proxy
# export DSH_MODEL=deepseek-v4-flashThe SDK needs Python 3.10+ and ships its own same-version runtime, so no system Node.js is required. Supported platforms are Linux x64, Linux arm64, and macOS 14+ on arm64.
What It Does Not Do
DeepSeek Harness is a coding harness that runs on the machine you are sitting at. That framing explains its gaps honestly:
- No messaging channels. There is no Telegram, Discord, WhatsApp or WeChat surface. You talk to it through a local Web UI, a terminal, or code.
- It is not always on. Close the laptop and the agent stops. Nothing is waiting to answer a message at 3am or run a scheduled job. This one is a property of where you run it rather than of the harness: put the same
dshin a hosted box built for coding harnesses and the box outlives the laptop. - It is a developer preview. The README promises breaking changes, and the repository is moving fast enough that config shapes will drift.
- It expects a workspace. The whole design assumes a checked-out project directory to read, edit and run commands in.
None of those are criticisms — they are the shape of the thing. They just describe a different job from an always-on personal agent.
DeepSeek Harness vs. a Hosted Agent
These are complements, not competitors. Use dsh when you want a model refactoring a repository you have open. Use a hosted agent when you want something that answers you on Telegram while your laptop is shut.
| Aspect | DeepSeek Harness | OpenClaw Launch |
|---|---|---|
| What it is | An SDK and app framework for building agents | A hosted, always-on personal agent |
| Where it runs | Your machine — or a hosted Coding Workspace | A dedicated container, 24/7 |
| Interface | Local Web UI, terminal, headless, ACP/JSON-RPC | Telegram, Discord, WhatsApp, WeChat, web chat |
| Setup | One npx command, then a config file per profile | A visual form, then Deploy |
| Model choice | DeepSeek by default; any OpenAI-compatible endpoint | Model picker, BYOK, or OpenRouter |
| Best at | Coding in a repository you have checked out | Answering you wherever you already chat |
| Maturity | Developer preview — breaking changes promised | Production |
The models are the same either way. If you liked what V4 Pro or V4 Flash did inside dsh, you can point a hosted OpenClaw agent at the same models — from the model picker, with your own DeepSeek API key, or through OpenRouter. See running DeepSeek V4 Pro on OpenClaw and V4 Flash on OpenClaw.
Or Run dsh Itself, Hosted
The table above is the honest comparison between two different jobs. There is now a third option that is neither: you can run dsh — the actual harness, not a lookalike — in a Coding Workspace. It is pre-installed in the box alongside Claude Code, Codex, OpenCode, Aider, OpenClaude, Zero and Pi, so a browser terminal gives you the same dsh you would get from npx, on a machine that stays up when your laptop does not.
export DEEPSEEK_API_KEY=sk-...
dsh --profile headless "run the tests"Three notes on those two lines. --profile has no default, hosted or not, so a bare dsh stops with error: --profile <name> is required rather than opening anything — name the profile, or use the dsh web alias. A run needs a credential within reach and a fresh workspace has none, because the key saved on your account funds the API route below rather than the terminal: export one, or store it through the credentials service described above, before the first run, or dsh exits at once with MISSING_CREDENTIAL. And the Web UI starts fine but binds inside the container, which publishes no ports — so in a hosted box the terminal and the API are the two routes that actually reach you.
You can also drive it without a terminal at all. The workspace API takes a prompt and runs the harness unattended, which is the headless mode above with the container, the workspace and the polling already built:
curl -X POST https://openclawlaunch.com/api/v1/coding-workspaces \
-H "Authorization: Bearer $OPENCLAW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"harness":"dsh","prompt":"run the tests and fix what fails","use_saved_key":true}'use_saved_key is what funds the run from the DeepSeek key on your account. Leave it out and the run uses whatever credential already lives inside that box — which in a fresh workspace is nothing, so dsh stops immediately and tells you it has no key. It is a per-request flag rather than an account setting on purpose: the agent runs with approvals bypassed and can read the key while it works, which is fine when the prompt is yours and not fine when it came from someone else.
The key itself is your own DeepSeek API key, saved on your account — there is no key of ours behind it. And the version is pinned: the box ships one exact dsh release rather than whatever npx resolves today, which for a package promising breaking changes is the difference between a workspace that behaves the same on Tuesday and one that does not.
Frequently Asked Questions
Is DeepSeek Harness free?
The harness is free and open source under the MIT license. Model inference is not — you supply an API key, and you pay whichever provider serves the model.
Is DeepSeek Harness a model?
No. It is the runtime around a model. It ships with a native DeepSeek adapter and connects to Anthropic, OpenAI and any OpenAI-compatible endpoint through its provider catalog or a custom provider.
How do I install DeepSeek Harness?
Install Node.js and run npx @deepseek-ai/dsh web. The Web UI serves at http://127.0.0.1:3080. Then open Settings → Models, add an API key, and select a workspace before starting a session.
Does DeepSeek Harness support MCP servers?
Yes, but none is enabled by default. The MCP client ships as a dependency for patch layers; you enable a server deliberately, because each server command is trusted executable code that runs outside the agent sandbox.
Can DeepSeek Harness reply on Telegram or WhatsApp?
No. It has no messaging-channel surface. It is reached through its local Web UI, an installable terminal UI, a headless one-shot command, or the ACP / JSON-RPC / Python interfaces. A hosted agent is the right tool for chat platforms.
Is it production-ready?
Not yet, by its own account. The README labels it a developer preview and states in capitals that there will be compatibility-breaking changes.
What's Next?
- What an agent harness is — the general concept
- DeepSeek V4 Pro on OpenClaw
- Get a DeepSeek API key
- Deploy an always-on agent — live in 30 seconds