A practical guide to DeepSeek’s open-source agent harness. You will learn what the word “harness” means, how DeepSeek Harness differs from OpenCode and Pi, and how to install it, add useful plugins, and write your first one.
A language model does one thing: it takes text in and produces text out. It can’t open a file, run your tests, search the web, or remember what you asked yesterday. Everything that looks like “an AI agent working on my project” is something else wrapped around the model.
That something is called a harness.
In August 2026 DeepSeek open-sourced its own, DeepSeek Harness (dsh for short). Its tagline is “Everything is a plugin”: the tools, the model connection, the session log, even the main agent loop are plugins you can add, remove, or replace.
This guide covers:
- What a harness is and why it matters
- How DeepSeek Harness compares to OpenCode and Pi
- Installing it and sending your first message (about 10 minutes)
- A short list of plugins worth installing
- Reusing your OpenCode skills
- Writing your first plugin
- Safety rules and a troubleshooting list
One honest warning first: the project calls itself a developer preview, and its README says breaking changes are expected. If a command below stops working, the README is the source of truth.
What is a harness?
Think of the model as an engine. An engine alone doesn’t get you anywhere. You need a chassis, steering, brakes, and a dashboard. The harness is all of that.
In practice, a harness does six jobs:
- It builds the prompt. It collects your message, the conversation so far, project instructions, and the list of available tools, and sends them to the model.
- It gives the model tools. Reading files, editing files, running shell commands, searching the web. If a tool isn’t in the harness, the model can’t use it.
- It enforces the rules. Which commands need your approval, what runs in a sandbox, what is blocked entirely.
- It runs the loop. The model asks for a tool, the harness runs it, the result goes back to the model, and this repeats until the task is done.
- It manages memory. It decides what stays in the model’s limited context window and records everything in a session log you can inspect later.
- It gives you an interface. A terminal, a browser tab, an IDE panel, or an API for scripts.
Here is one turn of that loop:
- You: “Why is this test failing?”
- The harness sends your message plus its list of tools to the model.
- The model replies: “Run
npm test.” - The harness checks its rules, runs the command, and records the output.
- The output goes back to the model, which now explains the failure.
The model never touches your disk directly. Every action goes through the harness.
This is why the harness matters as much as the model. Put the same model in two different harnesses and you get two different products: different tools, different safety behavior, different memory, different speed. People increasingly call the work of tuning this layer “harness engineering”.
DeepSeek Harness, OpenCode, and Pi
All three tools sit in the same neighborhood, but they are built for different people. Here is how each one describes itself, based on its own docs and README.
OpenCode: a finished coding agent
OpenCode is an open-source AI coding agent. It comes as a terminal interface, a desktop app, or an IDE extension. It ships with two main agents, Build (full access to edit and run) and Plan (restricted, for analysis), plus sub-agents. You switch between the primary agents with the Tab key. It also has a permission system, skills, MCP servers, and plugins written in JavaScript or TypeScript that hook into events.
It contains a harness, but you rarely think about it. It is built to be a polished tool for editing code that you open and use.
Pi: the smallest harness
Pi uses the word on purpose. Its README says: “Pi is a minimal, extensible agent harness that you can make your own.” It “ships with powerful defaults but skips features like sub-agents and plan mode.” You are expected to add what you need, through extensions, skills, prompt templates, and themes, which you can bundle as packages and share through npm or git.
You can use it interactively, in print or JSON mode for scripts, over RPC, or through a TypeScript SDK.
DeepSeek Harness: a harness with the parts already mounted
DeepSeek Harness takes Pi’s idea (a harness you can reshape) and goes further on both ends. Out of the box you get file tools, a shell, web fetch, sub-agents, a to-do list, plan mode, and skills. The main interface is a browser UI, with a headless mode for scripts and a Python SDK. And the “everything is a plugin” design means that even the agent loop can be replaced.
Side by side
-
Mainly a…
- OpenCode: coding agent product
- Pi: minimal harness
- DeepSeek Harness: harness with a full default setup
-
Interface
- OpenCode: terminal, desktop app, IDE extension
- Pi: terminal, print/JSON, RPC, TypeScript SDK
- DeepSeek Harness: browser UI, headless CLI, Python SDK
-
Out of the box
- OpenCode: Build and Plan agents, sub-agents, permissions, skills, MCP
- Pi: a small set of defaults, no sub-agents or plan mode
- DeepSeek Harness: files, shell, web fetch, sub-agents, plan mode, to-dos, skills
-
How you extend it
- OpenCode: JS/TS plugins that hook into events, custom tools, skills, MCP servers
- Pi: TypeScript extensions, skills, prompt templates, themes, packages
- DeepSeek Harness: plugins for everything, including the core loop
-
Install
- OpenCode: install script, npm, Homebrew, and others
- Pi: install script or npm
- DeepSeek Harness:
npx @deepseek-ai/dsh web
-
License
- All three: MIT
Which one should you choose?
- OpenCode if the job is “edit this repository from my terminal, today.” It is the most complete daily coding tool of the three.
- Pi if you want the smallest possible loop and prefer building the rest yourself.
- DeepSeek Harness if you want a harness with the pieces already in place, and you are curious about changing the runtime itself.
They are not mutually exclusive. They can even share skills, which is covered further down.
Popularity, for scale: in early October 2026 GitHub showed roughly 245,000 stars for DeepSeek Harness, 212,000 for OpenCode, and 113,000 for Pi. Cursor and Claude Code belong in the same group as OpenCode: they are finished coding agents, not harnesses you assemble.
Set it up in 10 minutes
You need:
-
Node.js 22.19 or newer (24+ also works). Node 18 and 20 are rejected. Check with
node -v. - A DeepSeek API key from platform.deepseek.com. The model provider bills usage.
- A project folder you don’t mind being edited. Use a copy the first time.
1. Start it
From your project folder:
cd /path/to/your/project
export DEEPSEEK_API_KEY=sk-your-key-here
npx @deepseek-ai/dsh web
Your browser opens http://127.0.0.1:3080. Two flags go after web: --no-open skips opening the browser, and --port 3081 changes the port.
If the URL contains ?token=..., don’t share it. That token is your login to this session.
2. Add the key in the UI (if you didn’t export it)
Open Settings → Models, paste the key, and save. No restart is needed. The key is stored in ~/.dsh/.credentials.yaml and is never shown back to you.
The harness looks for a key in this order: your environment, ~/.dsh/.credentials.yaml, a .env file in the folder you started from, then ~/.dsh/.env. If it finds nothing, requests fail with MISSING_CREDENTIAL.
The default provider is deepseek-official with the model deepseek-v4-flash.
3. Pick a workspace and ask a question
A new session has no workspace, and the message box stays disabled until you choose one. Click Choose workspace, add your project folder, select it, and try:
Summarize this repository and identify its main packages.
You now have a working agent.
Want another model?
The same Settings page has Add model provider. Built-in providers include Anthropic, OpenAI, Kimi, and GLM. A company gateway or a self-hosted server works as a custom provider if it speaks one of three protocols: OpenAI Chat Completions, OpenAI Responses, or Anthropic Messages. See Configure models.
One question, no browser
npx @deepseek-ai/dsh --profile headless "summarize this workspace"
It runs one task, prints the answer, and exits. Handy in scripts.
What a session can do
Out of the box, a session can read and edit files, search the project, run shell commands, fetch public web pages, hand a sub-task to a child agent, keep a to-do list, and ask you a question when it is unsure. Depending on the approval policy, it asks before risky steps.
A few details help early:
-
Each shell command starts fresh. A
cddoesn’t carry over. The agent passes a working directory instead. Long jobs can run in the background. -
Web fetch only reaches public addresses. It refuses
localhostand private hosts. -
Project instructions load automatically. If your repo has an
AGENTS.mdorCLAUDE.md, the harness reads it (up to 65,536 bytes). - There is a trace view. When an answer looks wrong, open the trace before rewriting your prompt. It shows what the model saw, each tool call, the results, and the timing.
A good first real task is a code review:
Review the uncommitted diff. Group findings by severity.
For each one, name the file and the failure mode.
Do not edit files.
In the trace you should see a shell call for the diff, a few file reads, then the answer.
Plugins worth installing
Because everything is a plugin, the plugin ecosystem is large. A search for the dsh-plugin topic on GitHub returns thousands of repositories, and many of them have nothing to do with DeepSeek Harness. So here is a short list of community plugins that are real, installable, and useful. I picked them because each declares clear install steps, works with the standard dsh plugin add command, and has a published npm package that was updated in the last few weeks.
How to install any plugin
The easiest way is in the web UI: open the Add plugin wizard, type the plugin name, and click Install.
Or use the command line:
npx @deepseek-ai/dsh plugin --profile web add <package>
The commands in the list below are written as dsh plugin .... That works if you installed the CLI globally (npm install -g @deepseek-ai/dsh). If you only use npx, write npx @deepseek-ai/dsh plugin ... instead.
The command needs pnpm on your path. If pnpm complains with ERR_PNPM_ADDING_TO_ROOT, add -w before the package name. Restart dsh web afterwards if the plugin doesn’t show up, because a running session keeps the plugin set it started with.
The starter list
- dshmarket: a plugin store inside the UI. It adds Settings → Plugin Market, where you can browse, search, and install community plugins in one click, and switch themes. It requires dsh web 0.1.0-rc.6 or newer.
dsh plugin --profile web add dshmarket
-
dsh-context: see what fills your context window. A dashboard of context size, composition, and trend per session, a cross-session overview with token and cost charts, and a
/contextslash command. Useful when sessions get long and answers get worse.
dsh plugin --profile web add dsh-context
- dsh-usage-stats: know what you spend. Provider balances, subscription quotas, token usage by day, provider, and model, estimated cost, and CSV or JSON export. Its README says credentials stay on the server side and are never sent to the browser.
dsh plugin --profile web add "@ychris12138/dsh-usage-stats@0.3.5"
- dsh-univer-office: spreadsheets, documents, and slides. Lets the agent create and edit spreadsheets, documents, presentations, and tables, or work with existing Excel, Word, and PowerPoint files, and shows each change for you to approve or discard. Check its README for the list of supported DSH versions before installing, since it names specific releases.
dsh plugin --profile web add dsh-univer-office
- dsh-find-plugin: a plugin that finds plugins. Ask the agent “find me a plugin for X” and it searches GitHub, returning the top results with stars, a description, and an install command.
dsh plugin --profile web add dsh-find-plugin
For a bigger catalog, see the community list awesome-dsh-plugin. It only includes plugins that declare a dsh.bundle manifest and install with dsh plugin add.
Official features you can switch on later
Some capabilities ship with the harness but are off by default. In the web UI they are toggles in the plugin list.
- Terminal: a shell that keeps state between commands.
- Scheduled tasks: reminders inside a session. One-off delays, fixed intervals (at least 60 seconds), daily, weekly, and cron schedules. The session has to be alive to receive them, and after downtime a repeating reminder delivers only the latest missed one.
- Goals: one long objective a session keeps working toward over many turns. Only you can create, pause, or resume a goal.
- Workflow: run the same job across many files by spawning one sub-agent per item.
- LSP: go-to-definition and references (needs a language-server plugin too).
- Agent teams: marked experimental. Leave them off for now.
One rule for community plugins
A plugin is code that runs on your machine, inside preview software. I didn’t audit the plugins above, and you shouldn’t assume anyone else did. Before you install any plugin:
- Open its repository and read what it does.
- Check the license and when it was last updated.
- Try it in a copy of a project, not your main repo.
- Add one at a time, so you know which one changed behavior.
If you want a different interface
The official interface is the browser. Two community projects exist for people who want something else, both independent of DeepSeek:
-
dsh-TUI: a terminal UI (about 4,000 stars; a public beta published under
@deepseek-harness-tui, not DeepSeek’s npm scope). - DSH Desktop: a desktop app for Windows and macOS (about 30,000 stars). Its README states it is not affiliated with or endorsed by DeepSeek.
Read each README before you install either one.
Reuse your OpenCode skills
A skill is a markdown file with instructions the model loads only when it is relevant. Nothing needs installing: skills work out of the box.
If you already use OpenCode, here is the useful part: both tools can read the same folder, .agents/skills. Put a skill there once, and both find it.
~/.agents/skills/git-release/SKILL.md
---
name: git-release
description: Create consistent releases and changelogs from merged PRs. Use when preparing a tagged release.
---
Draft release notes from merged PRs.
Propose a version bump.
Give a `gh release create` command the user can run.
Ask if the versioning scheme is unclear.
To keep it visible in DeepSeek Harness:
- The
nameis lowercase with hyphens and matches the folder name. - Keep it one level deep.
skills/group/git-release/SKILL.mdwill not be found. - No restart is needed. New skills appear on their own.
DeepSeek Harness also reads .dsh/skills in your repo and ~/.dsh/skills in your home folder. It does not read OpenCode’s own folders (.opencode/skills, ~/.config/opencode/skills) or .claude/skills. If a skill lives only there, symlink that one skill folder into ~/.agents/skills/ instead of copying it.
Your first plugin in five minutes
This is where “everything is a plugin” becomes concrete. You need a source checkout, Git 2.26+, and pnpm 11.7.0 (Corepack can provide it):
corepack enable
corepack prepare pnpm@11.7.0 --activate
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
A plugin is a module that exports an apply function. This one gives the model a new tool called greet. Save it as scratch-plugin/src/my-plugin.ts:
import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'greet-tool'
export const inject = ['tools']
export function apply(ctx: Context) {
ctx.tools.register(defineTool({
name: 'greet',
description: 'Greet someone by name.',
parameters: {
name: { type: 'string', required: true, description: 'The name to greet' },
},
output: {
schema: { type: 'string' },
render: (_args, value) => [{ type: 'text', text: value }],
},
async execute(args) {
return `Hello, ${args.name}!`
},
}))
}
Then tell the harness to load it. Create scratch-plugin/cordis.yml, using the absolute path to your checkout:
- insert:
- id: hello
name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'
Start the web UI with that file:
pnpm dsh web --patch ./scratch-plugin/cordis.yml
Ask the session to greet Ada with the greet tool. It answers Hello, Ada!.
Two lines in that file do most of the work. inject = ['tools'] tells the loader to wait until the tool registry exists. And anything the plugin registers is removed automatically when the plugin unloads, so you write no cleanup code. That second idea comes from Cordis, the framework underneath the harness, described in the paper A Programming Paradigm for Spatiotemporal Composability.
The official tutorial continues with configuration and packaging: Your first plugin.
A shortcut: in the product UI, Creator mode can write a plugin for you from a chat message. DeepSeek’s own demo builds a Pomodoro timer this way. It works, but read the generated code before you keep it.
Safety: read this before your real repo
The project’s SAFETY.md is short and blunt. The software hasn’t had a security audit. It can run commands the model wrote, load plugins you installed, and reach any file, key, or network you gave it access to. Approval prompts and the sandbox help, but they can’t protect something you already allowed.
So:
- Run your first real sessions in a copy of the repo, a container, or a VM.
- Back up anything the workspace can write to.
- Read a plugin’s code before you install it.
- When the agent asks for wider shell access, read its reason before you say yes.
Troubleshooting
-
npxshows an engine error. Your Node is too old. Install 22.19+ or 24+ and open a new terminal. - The message box does nothing. Choose and select a workspace.
-
MISSING_CREDENTIAL. Add the key in Settings → Models, or exportDEEPSEEK_API_KEY. -
pnpm not found. Runcorepack enable, then activate pnpm 11.7.0. -
A plugin is installed but nothing changed. Restart. To see what loaded, run
npx @deepseek-ai/dsh --profile web --dump-config. -
It won’t start at all. Look in
~/.dsh/logs/for the startup report. - A command is blocked. That is the sandbox, not a broken tool. Approve a specific request, or narrow the task.
Final thoughts
DeepSeek Harness isn’t trying to replace your daily coding agent. If OpenCode already fits how you work, keep it. What DeepSeek Harness offers is a different starting point: an agent you can take apart and rebuild, with a sensible set of tools already in place.
A good first hour looks like this: run the ten-minute setup on a copy of a repo, install dshmarket and dsh-context, point your existing skills at ~/.agents/skills, and write the tiny greet plugin. After that you will know whether “everything is a plugin” is something you actually want.
Links
- Repository and README: github.com/deepseek-ai/deepseek-harness
- Documentation: deepseek-harness.github.io/deepseek-harness
- Web UI guide: Use the Web UI
- Models: Configure models
- Plugin tutorial: Your first plugin
- Python SDK: Get started with the Python SDK
- Safety notice: SAFETY.md
- Product page: deepseek.com/harness
- Community plugin list: awesome-dsh-plugin
- Cordis paper: arXiv:2608.25512
- OpenCode docs: opencode.ai/docs
- Pi: github.com/earendil-works/pi
- Community questions: GitHub Discussions
Top comments (0)