本地安装与使用 DeepSeek Harness

前言

DeepSeek Harness(命令行 dsh)是 DeepSeek 开源的 Agent 运行时:模型、工具、会话与界面以插件方式挂接,适合在本地目录里读代码、改文件、跑命令。
它目前是 developer preview,可能有破坏性变更。
本文只介绍一种本机用法:用 npm 全局安装 后,在任意目录直接执行 dsh web。
版本与界面以你安装到的包为准。

依赖

需要 Node.js(建议 ^22.19 或 >=24,过低可能装不上或启动失败)。
在终端确认:

1
2
node --version
npm --version

若版本不够,到 Node.js 官网 安装后再重开终端。

装插件时 dsh plugin 会调用 pnpm ,PATH 里没有就会报 pnpm not found on PATH 。
Node 自带 Corepack 时,执行下面命令启用即可:

1
2
corepack enable pnpm
pnpm --version

若 Corepack 不可用,也可全局安装:

1
npm install -g pnpm

模型侧准备 DeepSeek API Key(在 开放平台 创建),勿写入仓库。
也可启动 Web UI 后在页面里填写。

实现

全局安装

希望在任意目录都能直接使用 dsh 时,执行:

1
npm install -g @deepseek-ai/dsh

安装完成后确认命令可用:

1
dsh --version

升级同一全局包时,重新执行上面的 npm install -g 即可。
如需钉住具体版本,可执行:

1
npm install -g @deepseek-ai/dsh@0.1.0-rc.7

版本号按 npm 上实际版本调整。

启动 Web UI

任意目录下运行:

1
dsh web

看到类似 dsh web: http://127.0.0.1:3080 后,用浏览器打开该地址。
停止服务:在运行 dsh 的终端按 Ctrl+C。

会话与凭据等数据默认在用户目录下的 ~/.dsh(Windows 多为 %USERPROFILE%\.dsh),与全局命令安装位置分开。

配置模型

打开 Web UI → 设置 → 模型。

在 DeepSeek 卡片填入 API Key 并保存。
密钥一般为只写字段;保存后界面只显示脱敏信息。

若使用 OpenAI 兼容网关,可按界面添加自定义提供方:填写 Provider ID、基础 URL、协议、凭据与至少一个模型 id,保存后在模型选择器中选用。

火山方舟 Coding Plan 把基础 URL 填成下面即可,模型名一般不用改。

1
https://ark.cn-beijing.volces.com/api/coding/v3

选择工作区

必须先选择工作区,否则会话输入区常常不可用。
在界面中点「选择工作区」,指定本机项目目录后再新建会话发任务。

插件

dsh-routing-suite

dsh-routing-suite 分两步:装配注入器,再安装路由预设。
注入器用 dsh-super-injector Release 的预编译包。
Windows 装到 %USERPROFILE%\.dsh\plugins\dsh-super-injector ,macOS 装到 ~/.dsh/plugins/dsh-super-injector 。
下面以 0.3.3 为例,版本以 Release 页面为准。

Windows

先下载并解压注入器,再登记到 web 配置:

1
2
3
4
5
6
7
8
9
10
$ver = "0.3.3"
$pluginRoot = Join-Path $env:USERPROFILE ".dsh/plugins"
$pkgDir = Join-Path $pluginRoot "dsh-super-injector"
$tgz = Join-Path $pluginRoot "dsh-external-dsh-super-injector-$ver.tgz"
New-Item -ItemType Directory -Force -Path $pluginRoot | Out-Null
Invoke-WebRequest -Uri "https://github.com/yjh051108/dsh-super-injector/releases/download/v$ver/dsh-external-dsh-super-injector-$ver.tgz" -OutFile $tgz
if (Test-Path $pkgDir) { Remove-Item $pkgDir -Recurse -Force }
New-Item -ItemType Directory -Force -Path $pkgDir | Out-Null
tar -xzf $tgz -C $pkgDir --strip-components=1
dsh plugin --profile web add $pkgDir

再克隆套装并复制两个预设目录。
目标路径是 .dsh/.agent-presets/router-standard 与 router-spec ,目录内直接包含 agent.cordis.yml 。

1
2
3
4
5
6
git clone --recurse-submodules https://github.com/yjh051108/dsh-routing-suite.git
cd dsh-routing-suite
$presetHome = Join-Path $env:USERPROFILE ".dsh/.agent-presets"
New-Item -ItemType Directory -Force -Path $presetHome | Out-Null
Copy-Item -Recurse .\preset\preset\router-standard (Join-Path $presetHome "router-standard")
Copy-Item -Recurse .\preset\preset\router-spec (Join-Path $presetHome "router-spec")

macOS

macOS 用系统自带的 curl 与 tar 即可,路径写到 ~/.dsh 。
先下载并解压注入器,再登记到 web 配置:

1
2
3
4
5
6
7
8
9
10
ver="0.3.3"
pluginRoot="$HOME/.dsh/plugins"
pkgDir="$pluginRoot/dsh-super-injector"
tgz="$pluginRoot/dsh-external-dsh-super-injector-$ver.tgz"
mkdir -p "$pluginRoot"
curl -L "https://github.com/yjh051108/dsh-super-injector/releases/download/v${ver}/dsh-external-dsh-super-injector-${ver}.tgz" -o "$tgz"
rm -rf "$pkgDir"
mkdir -p "$pkgDir"
tar -xzf "$tgz" -C "$pkgDir" --strip-components=1
dsh plugin --profile web add "$pkgDir"

再克隆套装,把两个预设目录复制到 ~/.dsh/.agent-presets 。
目录内同样要直接包含 agent.cordis.yml 。

1
2
3
4
5
6
git clone --recurse-submodules https://github.com/yjh051108/dsh-routing-suite.git
cd dsh-routing-suite
presetHome="$HOME/.dsh/.agent-presets"
mkdir -p "$presetHome"
cp -R preset/preset/router-standard "$presetHome/router-standard"
cp -R preset/preset/router-spec "$presetHome/router-spec"

然后按上文「启动 Web UI」的方式启动 dsh web 。
浏览器打开 http://127.0.0.1:3080 。
新建会话,在预设列表中选择 Router Standard 或 Router Spec 。

端口被占用时

若端口被占用,先结束占用 3080 端口的进程,再重新启动。

Windows 可按监听端口找到进程并结束:

1
2
3
4
Get-NetTCPConnection -LocalPort 3080 -State Listen -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty OwningProcess -Unique |
Where-Object { $_ -gt 0 } |
ForEach-Object { Stop-Process -Id $_ -Force }

macOS 可用 lsof 查出占用 3080 的进程并结束:

1
lsof -ti :3080 | xargs kill

注意:这会终止正在运行的旧会话,操作前请先保存需要保留的内容。