动手:跑起来 + 写插件
前九章是「想清楚」,这一章是「做出来」。装好环境,亲手摸一遍从启动到改装的整条链路。
费曼学习法讲究「查漏补缺」:讲一遍、动手做一遍,卡住的地方就是没懂的地方。这一章就是你的「动手卡点探测器」——每一步失败都会告诉你,前面哪一章还没吃透。翻译成人话:报错了别慌,那是教程在给你划重点。
另外友情提示:装环境是程序员三大幻觉之一(另外两个是「这次一定能跑通」和「再改一行就好了」)。跟着步骤走,遇到幻觉直接翻到下面「新手常见坑」。
npx @deepseek-ai/dsh web → 配模型密钥 → 选工作区 →
发任务;进阶:从源码构建、headless 跑批、写自己的组合包并用 --dump-config 验证。
第 1 步:装环境(一次就好)
需要 Node.js ^22.19 或 >= 24(推荐用 nvm 或官网安装包),包管理器 pnpm(当前锁定 11.7.0)。 然后:
node -v # 确认版本
npm i -g pnpm # 装 pnpm(可选,只用 npx 可以跳过)
第 2 步:一条命令启动 Web UI(最快路径)
npx @deepseek-ai/dsh web
# 浏览器打开 http://127.0.0.1:3080
然后按界面提示走三步:
- 设置 → 模型:输入 DeepSeek API 密钥并保存(密钥只写不读,存在
$DSH_HOME/.credentials.yaml,配置里只有凭据引用); - 选择工作区:添加你启动 dsh 时所在的项目目录并选中(不选工作区,输入框不可用);
- 发一个任务:例如 「Summarize this repository and identify its main packages.」 —— 观察它读文件、跑命令、需要审批时弹出确认。
第 3 步:从源码跑(探索源码的姿势)
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build # 生产运行必须先 build
pnpm dsh web # 等价于 node --import tsx/esm apps/cli/src/bin.ts web
真实模型演示需要 DEEPSEEK_API_KEY(根目录 .env 或环境变量)。
不带密钥也能启动 —— 只是模型调用会失败。
第 4 步:headless —— 命令行一次性跑任务
pnpm dsh --profile headless "统计一下这个仓库的 packages 数量"
# 常用调试命令:
pnpm dsh --profile web --dump-config # 打印实际拼出的插件树(标注每行来源)
pnpm dsh --profile headless --dump-config
headless profile 新建一个持久化会话、跑完任务、打印最终答案后退出(成功=0,失败=1),
完全不带服务器。配合 --dump-config,你可以亲手验证第 02 章的「层叠顺序」。
第 5 步:写第一个组合包(bundle)
理论(第 02 章)说:组合包 = 一个 npm 包 + 一份 cordis.patch.yml。
现在就做一个。新建一个目录:
mkdir my-bundle && cd my-bundle && pnpm init -y
在 package.json 里声明 bundle 身份:
{
"name": "my-bundle",
"version": "0.1.0",
"dsh": {
"bundle": {
"patch": "./cordis.patch.yml"
}
}
}
在同目录写 cordis.patch.yml —— 给插件树插入一行新插件:
- insert:
- id: my-plugin
name: my-plugin-package # 换成真实存在的插件包名
把它装进一个 profile 并验证:
dsh plugin --profile my-profile add my-bundle # 转调 pnpm 安装,自动进 dsh.profile.bundles
dsh --profile my-profile --dump-config # 能看到 my-plugin 那一行
读一个真实 cordis.yml
仓库里 examples/headless-agent/cordis.yml 是教科书式的装配清单,
摘录并注释如下(密钥经 credentials 逐请求解析,文件里不内联任何 key):
# 每行 = 一个插件实例:id 唯一标识,name 是包名,config 是它的参数
- id: settings # 用户设置:读 $DSH_HOME/settings.yaml,热重载
name: '@deepseek-ai/dsh-settings-file'
- id: credentials # 凭据:环境变量 > $DSH_HOME/.credentials.yaml
name: '@deepseek-ai/dsh-credentials-local'
- id: llm-deepseek # DeepSeek 模型适配器
name: '@deepseek-ai/dsh-llm-deepseek'
config:
thinking: enabled
reasoningEffort: max
models:
- id: deepseek-v4-pro
contextWindow: 128000
- id: bash # bash 执行器(60s 超时)
name: '@deepseek-ai/dsh-bash-local'
config: { timeoutMs: 60000 }
- id: agent-spine # 预建 main agent:provider / model / cwd / persona
name: '@deepseek-ai/dsh-agent-spine-demo'
config:
agents:
- id: main
provider: deepseek-official
model: deepseek-v4-flash
cwd: !!js process.cwd()
- id: persistence # JSONL 会话落盘到 ./.sessions
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config: { root: './.sessions' }
- id: compaction-basic # 上下文逼近阈值时自动压缩(thresholdRatio 0.8)
name: '@deepseek-ai/dsh-compaction-basic'
① Node 版本不够(< 22.19)—— 装新版本;② 忘记配 API Key —— 模型调用会 401;
③ 从源码跑但没 pnpm run build —— 生产入口找不到构建产物;
④ patch 想「改一个字段」却整块替换了 config —— 记住 patch 是整块替换不深合并;
⑤ --patch 是启动参数,要放在命令靠前位置。