DeepSeek Harness 完全指南:从零到用好插件
基线:
@deepseek-ai/dsh@0.1.0-rc.7· Node v22.22.3 · macOS 26.5.2 arm64 · 实测日期 2026-08-20 复核:2026-08-27 在0.1.1-rc.2(当前 npmlatest)上重跑,配置树与命令行逐字节未变 —— 详见下一节。 素材:5 篇视频笔记(2026-08-13 ~ 08-15 录制,全部基于 rc.6)+ 本机实测 实测环境:~/dsh-lab/(smoke / ss-cs / plugins 三个工作区)+ 一个 Unity 大仓的 sparse worktree
📌 标题说的是「用好插件」而不是「写插件」:第 7 章(挑 / 装 / 验 / 卸)是完整实测过的, 而「自己写插件」是第 9 章,至今仍是 ⏳ 待补。标题不该承诺正文没有的东西。
⚠️ 先看这个:这是一个 5 天漂一个版本的项目
包创建 2026-08-10 19:41 (比公开发布早 3 天)
rc.6 2026-08-13 20:35 ← 五篇素材全部基于它
rc.7 2026-08-17 19:50 ← 本文基线
rc.8 2026-08-19 23:41
0.1.1-rc.1 2026-08-21 06:49
0.1.1-rc.2 2026-08-21 12:42 ← 当前 latest(latest 与 next 现在是同一个)
README 用全大写写着 THERE WILL BE COMPATIBILITY-BREAKING CHANGES。本文所有结论都带版本号,看到没标版本的说法请当作已过期。
🔔 什么时候该重新验证这篇(一条可执行的判据)
别靠「感觉过了挺久」,跑这一条:
npm view @deepseek-ai/dsh dist-tags.latest
- 输出仍是
0.1.1-rc.2→ 本文基线未变,✅ 标记的结论仍然成立 - 输出变了 → 本文所有 ✅ 需要复验,尤其是命令行参数、profile 结构、插件机制
📌 为什么要写下这条:这类文档最危险的失效方式不是「过期」, 而是你以为它还准。把「什么时候该怀疑它」变成一条能跑的命令, 就不必依赖记性,也不必每次都从头核一遍。
✅ 2026-08-27 执行过一次,结果:全部仍成立
判据触发了(0.1.0-rc.7 → 0.1.1-rc.2),于是把两个版本并排装下来逐条比:
| 比什么 | 结果 |
|---|---|
--profile web --dump-config |
⭐ 两版逐字节完全相同(都是 503 行 / 135 条目 / 25 disabled / 31 个 ui-* / 79 个启用中的非 UI,末条目都是 agent-presets) |
顶层 --help |
逐字相同;子命令仍只有 web 与 plugin |
dsh run / dsh bench |
仍不存在(都报 --profile <name> is required),坑 10 成立 |
--profile headless 的 usage |
逐字相同 |
plugin 透传 |
仍是 pnpm 透传,两版都是 pnpm 11.10.0 |
| 默认模型 / 三档权限 / 平台裁剪表达式 | 全部一字未改 |
⭐ 所以升了两个小版本,本文的 ✅ 结论一条都没坏。
判据的基线号已更新为 0.1.1-rc.2,可以继续用。
⚠️ 但正文里的命令仍然钉在 @0.1.0-rc.7,这是有意的:本次复核比的是配置树、命令行参数与插件机制,没有重跑成本实测(第 5 章)与真实项目分析(第 6 章)。把命令改成 rc.2 等于替没做过的验证背书。两个版本在已核对的部分行为相同,想用新版直接把命令里的版本号换掉即可。
⚠️ 但有两处描述确实过期了,已在上面的表里改掉:
① rc.8 当时「挂在 next 标签、非 latest」——现在 next 与 latest 是同一个版本;
② 「两天一个版本」是 08-13 ~ 08-21 那一段的节奏,08-21 之后已经 6 天没有新版。
📌 节奏本身也是会变的量 —— 别把它当成常数去推算下次该复查的时间。
🚨 复现这些数字要用干净的 $DSH_HOME
复核时先量到 136 个条目而不是 135,多出来的一条是 dream-skin ——
因为本机 ~/.dsh/profiles/web/ 里装着 dsh-dream-skin(第 7 章装的)。
⭐ --dump-config 的输出包含你已装的插件,所以上面那些计数只在干净环境下成立:
DSH_HOME=$(mktemp -d) npx -y @deepseek-ai/dsh@0.1.1-rc.2 --profile web --dump-config
📌 这也顺带说明第 7.2 节「装 2 个 → 137、卸 1 个 → 136」为什么是有效的验证手段: 条目数就是装了什么的直接读数。
本文的标注约定
| 标记 | 含义 |
|---|---|
| ✅ | 本机实测,有命令、有输出、可复现 |
| 📼 | 素材转述(哪一期、哪个画面),我没有独立验证 |
| 💭 | 我的推断,标注了推理依据 |
| 🚨 | 坑,会让你白花时间或得到错误结论 |
| ⚠️ | 口径提醒,两个数字看着像但不是一回事 |
一页速查
这一节是「一屏解决 80% 的查询」,每一条在正文里都有展开与实测过程。
30 秒跑起来
mkdir -p ~/dsh-lab/.npmcache # ← 不加这步可能被本机 npm 缓存卡死 8 分钟(坑 1)
export npm_config_cache=~/dsh-lab/.npmcache
npx -y @deepseek-ai/dsh@0.1.0-rc.7 web # → http://127.0.0.1:3080
npx -y @deepseek-ai/dsh@0.1.0-rc.7 web --no-open # 不自动开浏览器
浏览器里填 API Key → 选工作区 → 开跑。
六个必须知道的默认值
「后果」这一列比「在哪改」更要紧 —— 它回答的是「不改会怎样」:
| 项 | 默认 | 不改的后果 | 在哪改 |
|---|---|---|---|
| 模型 | deepseek-v4-flash |
不是 Pro。网上所有演示都是手动切 Pro 跑的,不改复现不出任何数据 | UI 输入框右下角 / --patch |
| 推理等级 | high |
— | 同上 |
| 权限 | workspace-write |
装插件不够用(要 full access),在真项目上又太大 | UI 左下角 / DSH_PERMISSION_MODE |
| 端口 | 3080 |
官网示意图上的 3000 是错的,照它连不上 |
--port |
| 遥测 | DISABLED |
默认就是关的,可放心 | DSH_TELEMETRY_MODE |
| 沙箱根 | process.cwd() |
跟着 cd 走,换目录等于换沙箱根 |
— |
四种模式怎么选
| 模式 | 什么时候用 |
|---|---|
| 标准 | 日常就用它 |
| PTC | 批量、多步、标准化任务(模型写一段 TS 一次跑完,不用来回调工具) |
| 极简 | 别用 —— 官方拿来跑基准的,只有 bash + 编辑器 |
| 创造 | 写插件 / 做自定义 preset 时用 |
三档权限
read-only sandbox: read-only approval: ask
workspace-write sandbox: workspace-write approval: ask ← 默认
danger-full-access sandbox: danger-full-access approval: never ← 注意是「全程无弹窗」
命令行里用环境变量:DSH_PERMISSION_MODE=read-only
⭐ 分目录用权限:装插件开一个独立目录给 full access,干活的目录给最小权限。 别在真实项目仓库里开 full access。
最有用的四条命令
# 1. 看真实配置树(零 API 成本,验证任何改动是否生效都靠它)
npx -y @deepseek-ai/dsh@0.1.0-rc.7 --profile web --dump-config
# 2. 一次性任务,不开界面
cd <工作目录>
DSH_PERMISSION_MODE=read-only \
npx -y @deepseek-ai/dsh@0.1.0-rc.7 --profile headless "你的任务"
# 3. 插件(就是 pnpm 透传,5 秒,零 API 花费)
npx -y @deepseek-ai/dsh@0.1.0-rc.7 plugin --profile web add <包名>
npx -y @deepseek-ai/dsh@0.1.0-rc.7 plugin --profile web remove <包名>
npx -y @deepseek-ai/dsh@0.1.0-rc.7 plugin --profile web list
# 4. 换模型(写 patch 文件,然后用第 1 条验证它真的生效了)
cat > use-pro.yml <<'YAML'
- id: agent-default-model
config: { provider: deepseek-official, model: deepseek-v4-pro }
YAML
npx -y @deepseek-ai/dsh@0.1.0-rc.7 --profile headless --patch ./use-pro.yml "任务"
关键文件
~/.dsh/.credentials.yaml API Key,权限 0600,注意文件名有前导点
~/.dsh/settings.yaml UI 设置
~/.dsh/profiles/web/package.json 装了哪些插件(dependencies + dsh.profile.bundles 两处)
~/.dsh/profiles/web/cordis.patch.yml 你自己的配置覆盖层(默认空)
~/.dsh/sessions/<工作区>/<会话>/session.jsonl.zstd 完整轨迹与精确 token
算成本
总输入 = inputTokens + cacheReadTokens ← 是相加,不是包含!
成本 = inputTokens×未命中价 + cacheReadTokens×缓存价 + outputTokens×输出价
高峰时段 9:00–12:00、14:00–18:00,空闲价减半。v4-pro 高峰 0.30 / 9.0 / 27.0(元/百万)。
实测量级:一次真实代码库的程序集依赖分析(v4-pro、高峰、2 分钟)= ¥0.48。
⭐ 一条最重要的使用原则
agent 的「我是如何确定的」不能当证据。
实测里它给出的分析结论方向正确、方法正确,但漏了 16% 的结果, 并且在过程说明里声称做过一步它根本没做的检查。
所以:只信产物,不信过程叙述。 任何要拿去做决策的分析,配一个独立校验脚本。
入门篇
第 0 章:Harness 是什么 📼
Agent = Model + Harness
负责思考 负责接入现实环境(文件系统 / 终端 / 网页 / 工具链)
DeepSeek 之前只开源了 Model 这一半,2026-08-13 晚把另一半也开了(MIT)。
官方口号是**「一切皆插件」**:模型、工具、技能、会话、沙箱、文件系统、循环、编排、UI 全部是插件,可自由组合替换。底层框架叫 Cordis(vendor 进来的独立包,版本已到 4.x,比 dsh 自己的 0.1.0-rc.x 成熟得多)。
📼 素材里最扎实的一条论证(第 3 期,有一手报道):LangChain 把编码 agent deepagents-cli 在 Terminal Bench 2.0 上从 52.8% 提到 66.5%,模型全程锁定 GPT-5.2 不变,全部提升来自「工具工程」——改系统提示词、工具和中间件。这是「同一个模型换 Harness 效果差很多」的实证。
⚠️ 它不是开箱即用的产品,是个 Agent 平台。 五位 UP 的共同判断。如果你只是想要个能写代码的 agent,DSH 停在这一层对你几乎没有增量;它的价值在插件系统。
第 1 章:装机 ✅
1.1 前置
📼 素材里五位 UP 全用 Node 24。
✅ 实测 Node v22.22.3 可以跑 rc.7——包的 engines 字段根本不存在,npm 不会拦你。不用为了 DSH 升 Node。
1.2 一条命令
npx -y @deepseek-ai/dsh@0.1.0-rc.7 web
✅ 成功后输出:
npm warn deprecated node-domexception@1.0.0: Use your platform's native DOMException instead
dsh web: http://127.0.0.1:3080
dsh web: opening the default browser; pass --no-open to disable
✅ 服务健康:HTTP 200 / 3.9ms,常驻内存 47MB。
⚠️ --no-open 这个参数素材里没人提,但你多半用得上——它默认会抢你的浏览器焦点。
1.3 🚨 坑 1:npm 缓存里的 root 文件会卡死安装,而报错完全不指向 DSH
✅ 我第一次装失败,跑了 8 分 06 秒:
npm error code EEXIST
npm error syscall rename
EACCES: permission denied, rename '~/.npm/_cacache/tmp/xxx' -> '~/.npm/_cacache/content-v2/sha512/...'
npm error File exists
根因:~/.npm/_cacache 里混有 root 属主的文件(抽样 2000 个中 9 个,来自过去某次 sudo npm)。这不是 DSH 的问题,是任何拉新包的操作都会撞上的既存问题,但报错信息会让你以为是这个包装不上。
解法(副作用最小)——用独立缓存目录,不动你现有的缓存:
mkdir -p ~/dsh-lab/.npmcache
npm_config_cache=~/dsh-lab/.npmcache npx -y @deepseek-ai/dsh@0.1.0-rc.7 web
✅ 这条路一次成功。独立缓存占 444MB。
不推荐
npm cache clean --force(会清掉你 2.8G 的共享缓存)或chown(改共享状态)。
1.4 填 API Key
浏览器打开 http://127.0.0.1:3080 → 弹窗「添加一个 API Key 开始使用」→ 填 → 保存并继续。
Key 在 DeepSeek 开放平台建(📼 单账号上限 100 个)。
1.5 🚨 坑 2:凭据文件名带前导点
✅ 实际路径是 ~/.dsh/.credentials.yaml(有点),素材和很多笔记记成了 credentials.yaml(无点)。
~/.dsh/.credentials.yaml 54 字节 权限 -rw------- (0600)
内容形如:DEEPSEEK_API_KEY: <你的key>
✅ 权限是 0600,这点 DSH 做得对。 📼 但注意第 5 期实测里 AI 自己从这个文件读到了 Key——你给 agent 高权限时,它能读到自己的凭据。
1.6 阶段结业验证 ✅
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3080/ # 应为 200
ls -l ~/.dsh/.credentials.yaml # 应存在,权限 0600
ls ~/.dsh/profiles/ # 应有 web
第 2 章:Web UI 主路径 ✅
本章全部由 agent-browser 驱动实测,截图在
~/dsh-lab/_shots/。
2.1 首屏
标语「探索未至之境」+ 预览版 徽标。左侧栏:新会话 / 工作区树 / 设置。
⚠️ 首屏只有两个控件:选择工作区、标准模式。没有模型下拉、没有权限下拉——它们要等你选了工作区才出现。
2.2 🚨 坑 3:选工作区会挂住服务端
✅ 点「添加工作区」时,前端调的是 POST /api/host.pickDirectory,这是一个服务端原生目录选择器,会阻塞等待。我用 curl 直接打它,60 秒超时也没返回。
这意味着:
- 浏览器自动化点不动它(原生窗口不在浏览器里)
- 无头/远程场景下这条路走不通
✅ 绕开的办法(素材里完全没有,见第 8 章):直接调 API 建工作区。
curl -s -X POST http://127.0.0.1:3080/api/workspace.create \
-H 'Content-Type: application/json' \
-d '{"type":"client-request","rpcId":"r1","method":"workspace.create","payload":{"path":"/绝对/路径"}}'
返回:
{"result":{"ok":true,"value":{"workspace":{"workspaceId":"...","path":"...","title":"smoke"},"created":true}}}
刷新页面就能在左侧栏看到。
2.3 选完工作区后的四个控件
✅ 布局是上二下二(📼 素材第 5 期说「输入框上有三组控制」,不准确):
上排(输入框外): [📁 ss-cs ▾] [🎛 标准模式 ▾]
下排(输入框内): [+] [🛡 Workspace Write ▾] ............ [DeepSeek-V4-Flash High ▾] [↑]
2.4 🚨 坑 4:默认模型是 Flash,不是 Pro
✅ UI 上默认显示 DeepSeek-V4-Flash,模型下拉里只有两项:
● DeepSeek-V4-Flash ← 默认选中
○ DeepSeek-V4-Pro
✅ --dump-config 也印证了:agent-default-model.config.model = deepseek-v4-flash,web 和 headless 两个 profile 都是它。
📼 五位 UP 的所有演示都是手动切到 V4-Pro 跑的。 你不动它会得到四个后果:
- 成本对不上(flash 输出 4.5 元/百万 vs pro 13.5,看着“便宜”其实是换了模型)
- 效果对不上(那些「顶级」「可媲美 Opus 5」的评价全是 pro 跑的)
- 📼 第 4 期那套「角色专武」论断整个失效——91/98 那组数字讲的是 V4-Pro 对首轮工具结构敏感,flash 未必有同样特性
- 你复现不出素材里任何一条 token / 耗时数据,却会以为是自己做错了
2.5 设置页
✅ 侧栏 4 项:通用设置 / 模型 / 插件 / Agent 预设,外加一个 打开配置文件 按钮。
⚠️ 📼 素材第 1 期说中文界面有 5 项(多一个「文件提及」)。rc.7 只有 4 项。我没有 rc.6 的界面可比对,不确定是版本变化还是当时记错。
通用设置里可见:默认模式、默认权限、语言(中文)、主题(浅色/深色/跟随系统)、排队发送。
2.6 ⚠️ 插件计数有两个口径,别混用
| 口径 | rc.7 实测(干净基线) | 装 1 个第三方插件后 | 📼 rc.6 素材 |
|---|---|---|---|
| UI「插件列表」页显示 | 165 | 166 | 159(第 5 期)/ 160(第 2 期) |
--dump-config 顶层条目 |
135 | 136 | 素材没这个数 |
两者差 30,是不同东西。看到「159 个插件」这类说法,先问是哪个口径。
⭐ 顺带:插件列表里能直接看到 directory-picker-native——就是 2.2 节那个会阻塞的原生目录选择器的实体。
第 3 章:四种模式 ✅
3.1 界面原文(rc.7 与 rc.6 逐字一致)
✅ 下拉里的顺序是 标准 → PTC → 极简 → 创造:
| 模式 | 官方描述(界面原文) |
|---|---|
| 标准模式 | 功能完整的编码 Agent,支持文件编辑、Shell、文件与网页检索、Skills、计划、目标、子代理和工作流。 |
| PTC 模式 | 具备标准模式的全部能力,并通过 Code Mode SDK 呈现工具,让模型用一个 TypeScript 程序组合多步操作。 |
| 极简模式 | 仅提供持久 bash 与 str_replace_editor 的双工具编码 Agent。 |
| 创造模式 | 用于创建自定义 Agent preset:具备标准模式的全部能力,并提供运行时检查、插件实验和 preset 创作指导。 |
⚠️ 同一个模式两套叫法:中文界面叫「PTC 模式」,英文界面叫 Code mode。跨视频比对时别当成两个东西。
3.2 ⭐ 机制:工具默认全是关的
✅ 这是本文最有价值的一条架构发现,五篇素材都没讲。--dump-config 导出 503 行、135 个顶层条目:
135 个条目
├ 25 个 disabled: true ← 包括 tool-bash / tool-str-replace-editor / tool-web
│ / tool-subagent / tool-skill / tool-todo / plan-mode …
├ 31 个 ui-* ← 连轨迹面板 ui-trajectory 都是插件
└ 79 个启用中的非 UI 条目
最后一个条目:
- id: agent-presets
name: '@deepseek-ai/dsh-agent-presets'
config:
default: standard ← 它在运行时按模式把工具打开
也就是说 tool-bash 这种核心工具在组合树里是「挂载但禁用」的,由 agent-presets 按你选的模式动态启用。
💭 这直接解释了 📼 第 4 期那个 dsh-anchored-standard 插件(首轮伪装成极简、第一次工具调用后再把 23 个工具还回去)——它不是 hack,是顺着架构本来的设计做的。原视频只说「发现 V4-Pro 对首轮工具结构敏感」,没人解释为什么这种插件写得出来。
3.3 平台裁剪是配置里的 JS 表达式
✅ 📼 素材第 1 期观察到「pwsh-sandbox 在 Mac 上显示已停用」,说法是「默认状态按平台裁剪过」。实际配置写的是:
bash-sandbox: disabled: !!js process.platform === 'win32'
pwsh-sandbox: disabled: !!js process.platform !== 'win32'
⭐ Cordis 的配置支持 !!js 内联 JS 表达式——这条素材没提,但写插件时会用到。
3.4 该选哪个(我的建议)
- 日常就用标准模式。
- 极简模式不是给你用的。 📼 官方定位是跑基准测试(「V4-Pro 使用 DeepSeek Harness 极简模式作为框架进行测试」是官方文字)。📼 第 4 期实测它确实快 10~21 分钟,但 代价是少干活(不做无头浏览器验证、不做联网搜索),且关键交付能力(自己找到本机 API Key)失败。
- PTC 适合批量、多步、标准化的任务(📼 例:批量重命名 128 张图,普通模式要来回 128 次,PTC 生成一个
for循环一次跑完)。 - 创造模式是写插件时用的,见第 9 章。
第 4 章:权限与沙箱 ✅
4.1 三档的确切定义
✅ 从 --dump-config 里读到的原始配置:
presets:
read-only: { sandbox: read-only, approval: ask }
workspace-write: { sandbox: workspace-write, approval: ask }
danger-full-access: { sandbox: danger-full-access, approval: never }
⭐ 注意 danger-full-access 会把审批策略直接设成 never——不是“少几次确认”,是全程无弹窗。📼 第 2 期在轨迹里看到的 The approval policy changed from "ask" to "never" 就是这个。
4.2 ⭐ 权限可以用环境变量设(素材没有)
mode: !!js process.env.DSH_PERMISSION_MODE ?? 'workspace-write'
workspaceRoot: !!js process.cwd()
✅ 所以 headless / 脚本场景下:
DSH_PERMISSION_MODE=read-only npx ... --profile headless "只读分析任务"
合法值就是那三个:read-only / workspace-write / danger-full-access。
4.3 ✅ read-only 是真的只读
S1 那次分析里,agent 调用了 5 次 bash,全程 git status 干净,工作区无任何改动。只读档下 bash 仍可用,但写操作被沙箱挡住。
4.4 建议的权限策略
| 场景 | 权限 | 理由 |
|---|---|---|
| 分析代码、出报告 | read-only |
零风险,而且这类任务本来就不需要写 |
| 在玩具目录里做东西 | workspace-write |
默认值,够用 |
| 装插件 | danger-full-access |
必须——插件要写 ~/.dsh/profiles/,在 workspace 之外 |
| 在真实项目仓库里 | 别用 full access | 见下 |
🚨 📼 第 5 期原话是「想省事的话,可以先把权限改为全放开」——他是在自己的玩具目录里说这句话的。 你在一个 147G 的公司仓上照做,等于给 agent 开了整机写权限。
正确做法是分目录:装插件用一个独立目录开 full access,干活用另一个目录给最小权限。
第 5 章:成本怎么算准 ✅
5.1 会话日志在哪
✅ 每次会话都会落盘:
~/.dsh/sessions/--<工作区路径转义>--/session-<uuid>/session.jsonl.zstd
zstd 压缩的 jsonl。解开就有精确到每一步的 usage,比界面统计条硬:
zstd -dc ~/.dsh/sessions/*/*/session.jsonl.zstd > /tmp/s.jsonl
事件类型包括 request/header、assistant/chunk(含 usage)、tool/call、tool/result、step/start、step/end、turn/start、turn/end、permission/preset、sandbox/mode、approval/policy……
5.2 🚨 坑 5:inputTokens 和 cacheReadTokens 是相加关系
✅ 这条我自己算错过一次,成本差了 8 倍。判据在逐步数据里:
step1: input=8848 cacheRead=0
step2: input=1478 cacheRead=8960 ← input 小于 cacheRead
若 input 包含 cache,不可能小于 cache。所以:总输入 = inputTokens + cacheReadTokens,其中 inputTokens 就是未命中部分。
正确公式:
成本 = inputTokens × 未命中价 + cacheReadTokens × 缓存价 + outputTokens × 输出价
5.3 价格表(2026-08-17 起生效,峰谷定价)
高峰 = 北京时间 9:00–12:00、14:00–18:00,其余空闲,空闲价 = 高峰价的一半。单位:元/百万 token。
| 模型 | 时段 | 输入(缓存命中) | 输入(未命中) | 输出 |
|---|---|---|---|---|
| v4-flash | 空闲 | 0.05 | 1.5 | 4.5 |
| v4-flash | 高峰 | 0.10 | 3.0 | 9.0 |
| v4-pro | 空闲 | 0.15 | 4.5 | 13.5 |
| v4-pro | 高峰 | 0.30 | 9.0 | 27.0 |
🚨 涨价里涨得最狠的是缓存命中价(v4-pro 高峰 ×12),而真实用法的缓存命中率普遍在 84%~100%。📼 素材里「¥4.60 跑完四个任务」是旧价 + 99% 命中率的产物,不可复制。
5.4 ✅ 本次实测的真实花费
| 任务 | 模型/时段 | 未命中输入 | 缓存读 | 输出 | 花费 |
|---|---|---|---|---|---|
| S0 冒烟(建个文件) | flash / 空闲 | 8,975 | 8,832 | 245 | ¥0.0150 |
| S1 程序集依赖分析 | pro / 高峰 | 28,172 | 150,400 | 6,721 | ¥0.4801 |
| S2 装/卸插件 | — | — | — | — | ¥0(纯 CLI) |
跑完一个真实的代码库分析 = 5 毛钱。
⚠️ 口径提醒:session/title-llm-request 是一次额外的模型调用(生成会话标题),它的用量不在上面那两条 usage 记录里,所以真实花费略高于这个数。
实战篇
第 6 章:在真实项目上跑第一个分析 ✅
实测对象:某 Unity 大仓(Unity 2022.3 / C# / 147GB 的公司仓)
📌 下文用
ModA/ModB代指其中两个模块,Shared.Runtime代指一个跨模块程序集。 真实名称见本地_MyDoc/的层级审计报告 —— 本篇的结论(坑 6、坑 7) 不依赖真实模块名也完全成立。
6.1 ⭐ 别把 147G 的仓直接给它——用 sparse worktree
✅ 实测三档成本差异:
完整 clone 147 GB
Orca 式全量 worktree 8.2 GB / 7 分钟 (📼 来自我此前的 Orca 实测)
sparse worktree 只签 .cs 156 MB / 2.4 秒 ← 本次用的
REPO=/path/to/big-unity-repo
WT=~/dsh-lab/ss-cs
git -C $REPO worktree add --no-checkout --detach $WT <commit>
cd $WT
git sparse-checkout init --no-cone # --no-cone 才能按文件类型过滤
git sparse-checkout set '*.cs' '*.asmdef' '*.asmdef.meta' '*.asmref' '*.md'
git checkout
✅ 结果:156MB / 16557 个文件(16229 .cs + 154 .asmdef + 154 .asmdef.meta + 140 .md),skip-worktree 86094 条。
6.2 🚨 坑 6:少签一类文件,会让整个分析静默失效
✅ 我第一版故意没签 .meta,理由是「省得给它制造可以改的错觉」。结果:
asmdef 引用总边 655,其中 GUID 形式 464(71%)
Unity 的 .asmdef 里 71% 的引用写的是 GUID 而不是程序集名,而 GUID→名字的映射在 .asmdef.meta 里。不签 meta,依赖图根本解不出来——而且失败方式很隐蔽:agent 会照样输出一份“结果”,里面全是 ModB.Main -> 6de90ce572153b748af42cf0485c51ac。
教训:sparse checkout 的文件类型清单,要按分析需要什么来定,不是按改动风险来定。只读模式下“制造可以改的错觉”这个顾虑根本不存在。
6.3 ⭐ 先自己算标准答案,再让 agent 跑
否则它给什么你都没法判对错。我用 python 建了 GUID→名字映射,得到跨层依赖的 ground truth,然后才把同一个问题(不提示 GUID 这件事)交给 DSH。
6.4 🚨 坑 7:我的第一版标准答案自己就是错的
✅ 我第一版用 assembly_name.startswith('ModA') 判归属,得到 1 条跨层边。DSH 报 16 条。
差点写成「DSH 大幅误报」——实际是我错了。 DSH 用的是文件路径(Assets/ModA/ vs Assets/ModB/),而像 Shared.Runtime 这种住在 Assets/ModA/Scripts/ 但名字不以 ModA 开头的程序集,我的判据整个漏掉了。
按路径重算:
| ModA→ModB | ModB→ModA | 合计 | |
|---|---|---|---|
| 真实(路径判据) | 18 | 1 | 19 |
| DSH | 15 | 1 | 16 |
| 我的第一版(名字前缀) | 1 | 0 | 1 ❌ |
判据错比没判据更危险——没判据你会说“不确定”,判据错你会说“已确认”,而且方向可能完全相反。
6.5 DSH 的实际表现
做对的:
- ✅ 自己发现了 GUID→meta 这层间接(我没提示)。这是这次测试的真正考点。
- ✅ 主动处理了
Easy Save 3、Odin Inspector这类带空格的路径 - ✅ 枚举数完全正确(
ModA下 34 个、ModB下 24 个,与我逐字一致) - ✅ 定性结论正确(
ModB是被依赖方,ModA大量反向依赖) - ✅
read-only守住了,调了 5 次 bash 全是只读
做错的:
- ❌ 漏 16%(19 → 16),漏的是某个测试程序集的 3 条边。文件它扫到了,交叉比对时漏的。
- 🚨 过程自述里有一句是假的。它写「并额外检查了
ModA/ModB下没有使用非 GUID 形式的引用」——实测有 61 条非 GUID 引用(Unity.TextMeshPro、Unity.InputSystem…)。这 61 条恰好都不跨层,所以结论没错,但它声称做过的那步检查没做。
⭐ 本章最该带走的一条:agent 的「我是如何确定的」不能当证据。 结论可能对、过程可能是编的——而这种组合最危险,因为它让你以为已经验过了。
6.6 结论:它能用在你的项目里吗
能做第一遍粗筛,不能当唯一来源。 2 分钟、5 毛钱给出程序集级依赖分析,方法对、定性对,但漏 16%,且过程自述会撒谎。必须配一个独立校验(一个 30 行的 python 脚本就够)。
第 7 章:插件——挑 / 装 / 验 / 卸 ✅
7.1 机制
✅ dsh plugin 就是 pnpm 的透传(pnpm 11.10.0)。dsh plugin --profile web --help 直接吐出 pnpm --help。
装一个插件 = 改 ~/.dsh/profiles/web/package.json 两处:
{
"dependencies": { "dsh-dream-skin": "^0.3.0" }, // ← 一处
"dsh": { "profile": { "bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-dream-skin" // ← 另一处,少了这条不会被加载
]}}
}
7.2 ⭐ 零成本验证插件是否真的挂上了
npx ... --profile web --dump-config | grep -c '^- id:'
✅ 实测:原始 135 → 装 2 个 137 → 卸 1 个 136。不用重启、不用看界面、不花一分钱。
7.3 ✅ 用 CLI 装,别让 agent 装
| 方式 | 耗时 | 花费 |
|---|---|---|
| CLI(本次实测) | 5 秒 | ¥0 |
| 📼 让 AI 装(第 5 期实测) | 2 分 20 秒 | 60 万 token |
7.4 🚨 坑 8:24 小时内发布的版本装不到,且提示是「Already up to date」
✅ 实测:
dsh-dream-skin
0.4.1 发布于 14 小时前 ← npm 上的 latest
0.4.0 发布于 15 小时前
0.3.0 发布于 2 天 19 小时前 ← 实际装到的是这个
对照:dsh-find-plugin 0.3.7 发布于 27 小时前 → 装到了
即使显式写 @latest 也没用,它回 Already up to date。
根因:pnpm 11 的供应链保护 minimumReleaseAge = 24 小时。报错信息里的 cutoff 时间戳恰好是 24 小时前,实锤:
[ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION]
dsh-dream-skin@0.4.1 was published at 2026-08-19T18:23:26Z,
within the minimumReleaseAge cutoff (2026-08-19T08:38:10Z)
在一个 7 天大、插件一天发好几版的生态里,这意味着你默认永远拿不到最新版。
7.5 🚨 坑 9:绕过它的代价比问题本身大
✅ 加 --config.minimumReleaseAge=0 确实能装到 0.4.1,但 lockfile 从此违规,profile 里所有后续 pnpm 操作全部被拦死——我下一步想卸载另一个插件就失败了。
正解:要么等满 24 小时,要么此后每条命令都带这个 flag,别只在装的时候带一次。
# 要么全程带
npx ... plugin --profile web add <pkg>@<ver> --config.minimumReleaseAge=0
npx ... plugin --profile web remove <pkg> --config.minimumReleaseAge=0
# 要么退回合规版本,让 profile 干净
npx ... plugin --profile web add <pkg>@<24小时前的版本> --config.minimumReleaseAge=0
7.5b 🚨 坑 9b:装完必须重启,agent 不会替你重启
✅ 实测确认(这条 📼 素材第 5 期说过,本次独立验证):
重启前 UI 插件列表 165 搜不到 dream-skin
重启后 UI 插件列表 166 dream-skin 已启用
运行中的 dsh 是启动那一刻组装好的插件树,之后装的插件不会热加载。
# 在跑 dsh web 的终端里 Ctrl-C,然后重开
npx -y @deepseek-ai/dsh@0.1.0-rc.7 web --no-open # ✅ --no-open 实测有效,不抢浏览器
📼 第 5 期里 AI 装完插件后自己说明了「我不会去重启它(会中断咱们当前这个会话)」——这一步永远要你自己做。
7.6 挑插件的五条判据 ✅
生态规模:npm 上带 dsh-plugin 关键字的包 2072 个(2026-08-20 实查;📼 素材里 08-15 时 dsh-store 声称「550+」,5 天翻了近 4 倍)。⏱️ 2026-08-27 复查为 3100 个,7 天又涨 50% —— 增速在放缓但仍然很快。自己查一条:npm search --json 'keywords:dsh-plugin',或直接读 registry 的 /-/v1/search?text=keywords:dsh-plugin 返回里的 total。这个生态里已经出现了 @shaoshi/dshscan——一个 DSH 插件安全扫描器。这本身就说明问题。
| 看什么 | 怎么看 | 反面例子 |
|---|---|---|
有没有 repository 字段 |
npm view <pkg> repository |
create-dsh-plugin 没有——无法审代码,419 周下载也别装 |
有没有 postinstall/preinstall |
npm view <pkg> scripts |
这是唯一的任意代码执行入口,装之前必查 |
| 周下载量 | api.npmjs.org/downloads/point/last-week/<pkg> |
dream-skin 4475 / find-plugin 5892 |
| 版本节奏 | npm view <pkg> time |
2 天发 13 版 = 还在剧烈变;发完停更 = 可能弃坑 |
| license | npm view <pkg> license |
📼 素材里那个鲸鱼娘皮肤是 CC BY-NC-SA 4.0,禁商用 |
7.7 ⚠️ 一条素材的坑在你机器上可能不成立
📼 第 5 期:「本机 pnpm 不在 PATH,要先 corepack enable pnpm」。
✅ 本机不成立——~/.hermes/node/bin/pnpm 早就有了(装 Hermes 时带的)。这是环境差异,不是官方修了。 你换台机器可能还会撞上。
第 8 章:命令行与 HTTP API ✅
本章内容素材里完全没有,而且素材里那两条被当作真命令引用的东西是错的。
8.1 🚨 坑 10:dsh run 和 dsh bench 不存在
✅ rc.7 的真实子命令只有两个:
Commands:
web [options] [args...] boot the web profile
plugin [options] [args...] manage a profile's plugins (forwards to pnpm)
试着跑素材里那两条:
dsh run "echo hi" → exit=1 error: --profile <name> is required
dsh bench --mode minimal → exit=1 error: --profile <name> is required
✅ 我装了 rc.6 对比,--help 与 rc.7 逐字一致,bench 同样不存在。 所以不是“被删了”,是从来没有过。
📼 那两条的出处:第 5 期「四项进阶玩法」的 dsh run ... --dir ... --yes 是作者自制的幻灯片示意图;第 4 期的 dsh bench --mode minimal 那一屏同样是幻灯片。
🚨 这条也打我自己:我在
260818-4那篇笔记里写过「『官方用来跑基准测试』不是作者的推测,dsh bench --mode minimal这条命令就在画面上」。这个断言错了——我把“画面上有个终端样式的框”当成了硬证据。 注意区分:「极简模式是官方拿来跑基准的」这个结论很可能仍然成立(官方文字里写了「V4-Pro 使用 DeepSeek Harness 极简模式作为框架进行测试」),但我给它找的那个证据是假的。结论对、证据错,是最危险的一种,因为它让人以为已经验过了。
8.2 一次性任务的正确写法
cd <工作目录>
npx ... --profile headless "你的任务"
Usage: dsh --profile headless [options] [task...]
Answer one task, print the final assistant message, and exit.
✅ headless profile 是随发行版交付的模板——~/.dsh/profiles/ 下本来没有它,第一次用 --profile headless 时会自动生成。
8.3 ⭐ 用 --patch 换模型(并零成本验证)
# ~/dsh-lab/patches/use-pro.yml
- id: agent-default-model
config:
provider: deepseek-official
model: deepseek-v4-pro
npx ... --profile headless --patch ~/dsh-lab/patches/use-pro.yml "任务"
✅ 改完必须用 --dump-config 做 A/B 验证,别问模型「你是谁」:
npx ... --profile headless --patch <patch> --dump-config | grep -A4 agent-default-model # → v4-pro
npx ... --profile headless --dump-config | grep -A4 agent-default-model # → v4-flash
为什么不能问模型:✅ S0 那次它答「我是 v4-flash」是对的,但它的 reasoning 里写着 “per system prompt ‘You are a coding agent powered by the deepseek-v4-flash model’”——它是在读自己的系统提示词,不是内省。如果系统提示词写错,它会同样自信地答错。
8.4 ⭐ 完整的本地 HTTP RPC API
✅ 端点是 POST /api/<方法名>,信封格式:
{"type":"client-request","rpcId":"<任意字符串>","method":"<方法名>","payload":{...}}
已确认可用的方法(从前端网络请求里抓的):
workspace.list workspace.create {path: string}
host.describe host.pickDirectory ← ⚠️ 会阻塞
settings.describe credentials.describe
agentPreset.list llm.providers
session.list dynamicCordisRunner/inventory
dynamicCordisRunner/syncInspectManifest
例:
curl -s -X POST http://127.0.0.1:3080/api/workspace.create \
-H 'Content-Type: application/json' \
-d '{"type":"client-request","rpcId":"r1","method":"workspace.create","payload":{"path":"/abs/path"}}'
⭐ 好用之处:发错请求时,它会把完整的 schema 校验错误吐回来,等于自带 API 文档。
🚨 安全提醒:--help 里提到 /api 有 “browser-trust fence”,但 ✅ 实测普通 curl 没有被拦(返回的是 schema 错误,不是 403)。也就是说,任何能访问 3080 端口的进程都能驱动你的 agent。📼 第 2 期那位 UP 用 ngrok 把 3080 裸暴露到公网且无认证——按这个实测结果看,那等于把一台能读写你磁盘的 agent 开放给了互联网。
进阶篇
第 9 章:自己写插件 ⏳ 待补
本章尚未实测。已知的骨架(📼 素材第 3 期的官方文档截图):
import type { Context } from '@deepseek-ai/cordis'
export const name = 'my-plugin'
export function apply(ctx: Context) {
// 在这里注册能力
}
✅ 从两个真实插件的 package.json 里读到的声明格式:
{
"dsh": {
"bundle": { "patch": "./cordis.patch.yml" },
"client": {
"inject": ["@deepseek-ai/dsh-client-runtime", "@deepseek-ai/dsh-client-ui-theme", "..."],
"platform": "web",
"immediately": true
}
}
}
dsh.bundle.patch→ 服务端能力(工具、模型适配器等)dsh.client.inject→ 客户端 UI 注入
✅ npm 上有 create-dsh-plugin 脚手架(但没有 repository 字段,按第 7.6 节的判据,不建议直接用)。
计划做的:一个「Unity 程序集依赖检查」插件,把第 6 章手写的 GUID→meta 解析逻辑封成工具,有第 6 章的标准答案可以直接验准确率。
第 10 章:能用到 Unity 项目吗 ⏳ 待补
已有的证据见 6.6。完整评估要等第 9 章做完。
坑总表
| # | 坑 | 症状 | 解法 |
|---|---|---|---|
| 1 | npm 缓存混有 root 文件 | EEXIST/EACCES,报错不指向 DSH,8 分钟后失败 |
npm_config_cache=<独立目录> |
| 2 | 凭据文件名带前导点 | 找不到 ~/.dsh/credentials.yaml |
是 ~/.dsh/.credentials.yaml |
| 3 | host.pickDirectory 阻塞 |
点「添加工作区」没反应,自动化点不动 | 走 workspace.create API |
| 4 | 默认模型是 Flash 不是 Pro | 复现不出素材的任何数据 | UI 下拉切 / --patch |
| 5 | token 口径 | input 与 cacheRead 是相加不是包含 |
总输入 = 两者之和 |
| 6 | sparse 少签一类文件 | 分析静默失效,输出一堆 GUID | 按分析需要定文件清单 |
| 7 | 判据用名字前缀而非路径 | 结论差 19 倍且方向相反 | 用路径判归属 |
| 8 | pnpm minimumReleaseAge=24h |
装不到 24 小时内的新版,提示 Already up to date |
等满 24h 或全程带 flag |
| 9 | 绕过策略污染 lockfile | 此后所有 pnpm 操作被拦死 | 每条命令都带 flag,或退回合规版 |
| 10 | dsh run/dsh bench 不存在 |
照素材敲命令报 --profile is required |
用 --profile headless "任务" |
| 11 | --help 示例引用已删除的 tui profile |
照着敲会失败 | 只有 web 和 headless |
| 12 | 插件计数两个口径 | UI 165 vs 组合树 135 | 别混用 |
| 12b | 装完插件不重启不生效 | 装了但列表里没有、功能不出现 | Ctrl-C 重开 dsh web --no-open;agent 不会替你重启 |
| 13 | agent 的过程自述会撒谎 | 「我已检查过 X」实际没查 | 只信产物,不信过程叙述 |
| 14 | /api 无认证 |
任何本机进程可驱动你的 agent | 别把 3080 暴露到公网 |
附录 A:传闻 vs 实测
| 说法 | 出处 | 实测 |
|---|---|---|
| 「官方跑分只差 0.1」 | 📼 第 5 期 08:34 | 只在 Terminal Bench 2.1 一项成立;HLE 差 10.6 分。且作者的对比图比官方原表少了 GLM-5.2 和 Kimi-K3 两列,而 Kimi-K3 恰是该基准全表第一(88.3) |
| 「不到 5 块跑完四个任务」 | 📼 第 5 期 | 旧价 + 99% 缓存命中的产物。涨价后缓存命中价涨得最狠(v4-pro 高峰 ×12),不可复制 |
| 「极简模式性能暴增,对标 Fable 5」 | 📼 B 站评论 → 第 4 期验证 | 快 10~21 分钟属实,但主要因为少干活(不做浏览器验证、不联网);关键交付能力失败 |
| 「91 vs 98 证明角色专武」 | 📼 第 4 期 | 那组数字被贴了两套互斥标签;按 README 原始出处,91 来自 DeepSeek 自家 Standard preset,不是「别家 Harness」。片中没有任何跨 Harness 横评数据 |
dsh bench --mode minimal |
📼 第 4 期画面 | ✅ rc.6 和 rc.7 都不存在这条命令,那一屏是幻灯片 |
dsh run ... --dir ... --yes |
📼 第 5 期画面 | ✅ 同上,不存在 |
| 「pnpm 不在 PATH 要先 corepack」 | 📼 第 5 期 | 本机不成立(Hermes 带了 pnpm)。环境差异,不是官方修了 |
| 「输入框上有三组控制」 | 📼 第 5 期 | ✅ 实际是上二下二,共四个 |
| 「设置侧栏 5 项」 | 📼 第 1 期 | ✅ rc.7 只有 4 项(无「文件提及」)。⚠️ 无法区分是版本变化还是当时记错 |
| 「插件 159/160 个」 | 📼 第 5/2 期 | ✅ rc.7 UI 显示 165;⚠️ 但 --dump-config 口径是 135,两者不是一回事 |
附录 B:本文没做的 / 未验证的
明确没做:
- 第 9 章(自己写插件)、第 10 章(Unity 项目评估结论)
- PTC 模式、创造模式的实操(只读了界面文案和配置)
- 多模型提供商接入(📼 第 2 期实测过 OpenRouter 可用,我没验)
- ngrok 内网穿透(📼 第 2 期有,且有明显安全问题)
- rc.7 → rc.8 跨版本复验
方法论上的坦白:
- 本文的 Web UI 部分由 agent-browser 驱动,没有人眼逐屏核对;截图在
~/dsh-lab/_shots/(12 张) - 成本数字全部来自
session.jsonl.zstd的 usage 字段,没有与 DeepSeek 用量页对账 - 第 6 章的「真实答案 19 条」是我自己写的 python 脚本算的,它本身已经错过一次(见坑 7)。它可能还有别的错。
开工/收工对账(在真实公司仓上作业的必要动作):
开工 2026-08-20 11:12 HEAD 76cbf10bc3 (dev) 132 条未提交改动(今晨 10:30 的配置导表产物,非本次作业造成)
10 条 stash 1 个 worktree
本次新增 1 个 detached sparse worktree → ~/dsh-lab/ss-cs
本次对仓库的写操作 0(S1 全程 read-only,git status 无变化)
本文的每一条 ✅ 都对应一条可重跑的命令。如果你重跑得到不同结果,先看版本号——这个项目 5 天漂一版。