DeepSeek Harness 完全指南:从零到用好插件

工具选型与安装第 4 / 5 篇

基线:@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(当前 npm latest)上重跑,配置树与命令行逐字节未变 —— 详见下一节。 素材: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 跑的。 你不动它会得到四个后果:

  1. 成本对不上(flash 输出 4.5 元/百万 vs pro 13.5,看着“便宜”其实是换了模型)
  2. 效果对不上(那些「顶级」「可媲美 Opus 5」的评价全是 pro 跑的)
  3. 📼 第 4 期那套「角色专武」论断整个失效——91/98 那组数字讲的是 V4-Pro 对首轮工具结构敏感,flash 未必有同样特性
  4. 你复现不出素材里任何一条 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 天漂一版。