DeepSeek Harness · guide
What dsh-why is, and when to use it
Two ways dsh fails, two commands that answer them, and one rule that governs every answer: a blind spot is never turned into a red card.
dsh 有两种挂法,两个命令分别回答,以及贯穿所有答案的一条原则:绝不把盲区变成红牌。
What dsh-why isdsh-why 是什么
dsh (DeepSeek Harness) has two ways to fail, and they leave completely different evidence behind. dsh-why answers both, from local files, read-only.
npx dsh-whydsh will not start. A plugin's client bundle calledrequire()on a module the shell does not provide, and the loader materialized the whole client plugin tree — so one plugin takes every plugin down. dsh-why reads your actual install and names the plugin, the module, and the fix.npx dsh-why rundsh starts fine, but a run died. The turn is over, you have a symptom, and nothing said why. dsh-why reads your own session logs and turnsturn/end.reasoninto a verdict — plus a health view that separates chronic noise from a real incident.
dsh(DeepSeek Harness)有两种挂法,留下的证据完全不同。dsh-why 两种都答,全部基于本地文件、只读。
npx dsh-whydsh 起不来。某个插件的 client bundlerequire()了 shell 不提供的模块,而加载器会物化整棵客户端插件树——所以一个插件能把所有插件一起拖下水。dsh-why 读取你真实的安装,点名是哪个插件、哪个模块、怎么修。npx dsh-why rundsh 起得来,但某次 run 挂了。turn 已经结束,你手上只有一个现象,没人告诉你为什么。dsh-why 读取你自己的会话日志,把turn/end.reason变成判定——再给一个健康视图,把长期噪声和真正的「事件」分开。
Which one do I run?我该跑哪一个?
| What you see | Run this |
|---|---|
| dsh shows a red screen, a blank page, or will not boot | npx dsh-why |
| A run stopped, errored, or never finished | npx dsh-why run |
| You want to know whether your failures are normal | npx dsh-why run --all |
| You are about to publish a plugin | npx dsh-why --package . |
| You have an error string and no install handy | paste it into the box on the home page |
| 你看到的现象 | 跑这个 |
|---|---|
| dsh 红屏、白屏,或者根本起不来 | npx dsh-why |
| 某次 run 停了、报错了,或者一直没结束 | npx dsh-why run |
| 想知道自己的失败率算不算正常 | npx dsh-why run --all |
| 马上要发布一个插件 | npx dsh-why --package . |
| 手上只有一句报错,机器上没装 dsh | 粘进首页的输入框 |
The verdicts, and why some of them are deliberately vague判定档位,以及为什么有些档位故意说得很含糊
A diagnostic that guesses is worse than one that admits it does not know. Every dsh-why verdict lands on one of these, and a blind spot is never turned into a red card:
| Verdict | Means |
|---|---|
| crash | The evidence is conclusive and something must change (exit 1). |
| conditional | The specifier is a built-in graph row: it usually resolves, the ordering is not guaranteed. Not a crash — declaring it in dsh.client.external makes it certain. |
| stopped by you | A deliberate abort. Never a failure, never a red card. |
| unclassified | dsh-why could not decide — the run was interrupted or the log is truncated, or a --package check read nothing. It says so, and never reports it as a pass (exit 3 for the gate). |
That last row is the reason to trust the other three.
一个会猜的诊断工具,比一个承认自己不知道的更糟。dsh-why 的每个判定都落在这几档上,而且绝不把盲区变成红牌:
| 判定 | 含义 |
|---|---|
| crash | 证据确凿,必须改点什么(退出码 1)。 |
| conditional | 该 specifier 是内置图行:通常能解析,但顺序不保证。不是崩溃——在 dsh.client.external 里声明它就变成确定的。 |
| 你主动停止 | 主动中断。永远不算故障,永远不给红牌。 |
| 无法定性 | dsh-why 判不出来——run 被中断、日志被截断,或者 --package 什么都没读到。它会明说,绝不当作通过(门禁场景退出码 3)。 |
最后这一档,才是另外三档可信的理由。
What it can name when a run diesrun 挂掉时,它能定性的东西
The failure vocabulary is closed, which is what makes attribution possible at all. Across a measured corpus of 2,006 turns every failure carried one of these, and they split into two families that need opposite advice — the network family usually clears on its own, the configuration family never does:
失败词汇表是封闭的,而这是「能归因」这件事成立的前提。在一份 2,006 个 turn 的实测语料里,每一次失败都落在这几类上,而且分成两个需要相反建议的族——网络族通常会自己恢复,配置族永远不会:
Loader failures — dsh will not start
client-modules: require("…") missed the module tableclient-modules: cannot resolve "…"client-modules: bundle script … failed to loadFailed to load plugins
Run failures — dsh started, a run died
DeepSeek API request to https://api.deepseek.com failedthe API call never completed401: The API Key appears to be invalid or may have expiredthe key was rejectedllm-deepseek: no API key for provider route "deepseek-official"no key for this routeInsufficient Balanceout of credit503 "pricing not configured for provider/model"no pricing for this model400 "unsupported model"the route cannot serve it502 status code (no body)a 5xx from the providerDeepSeek stream idle timeout after 300000msthe stream went idle
加载器失败 —— dsh 起不来
client-modules: require("…") missed the module tableclient-modules: cannot resolve "…"client-modules: bundle script … failed to loadFailed to load plugins
运行失败 —— dsh 起来了,某次 run 挂了
DeepSeek API request to https://api.deepseek.com failedAPI 请求根本没完成401: The API Key appears to be invalid or may have expiredkey 被拒绝llm-deepseek: no API key for provider route "deepseek-official"这条路由没配 keyInsufficient Balance余额不足503 "pricing not configured for provider/model"这个模型没配计价400 "unsupported model"路由不提供这个模型502 status code (no body)provider 返回 5xxDeepSeek stream idle timeout after 300000ms响应流空闲超时
If you publish a plugin如果你发布插件
dsh does not let your client bundle require() arbitrary npm packages — it resolves against a module table baked into each shell build. dsh ships several times a day. Nothing in your repo tells you when an upstream change would break yours, until your users do.
npx dsh-why --package . is that check, and it works as a CI gate:
npx dsh-why --package . && npm publish # any non-zero must block the releaseExit 1 is a real crash. Exit 3 means it could not check at all — almost always an unbuilt checkout, since the client bundle is a build artifact. It is deliberately not 0: a gate that passes when it verified nothing is worse than no gate.
Field-tested against 13 popular published plugins: zero false positives, and no plugin was found broken. This gate is quiet on healthy plugins — it is a regression guard against upstream, not a cleanup tool.
Full integration guide: CI recipes, exit codes, and the seed-safe fix pattern →
dsh 不允许你的 client bundle 任意 require() npm 包——它只对照烘焙进每个 shell 构建的模块表解析。而 dsh 每天要发好几次。你的仓库里没有任何东西会告诉你:上游的某次改动会不会打挂你的插件——直到你的用户先撞上。
npx dsh-why --package . 就是这个检查,而且可以直接当 CI 门禁:
npx dsh-why --package . && npm publish # 任何非 0 都必须拦住发版退出码 1 是真的崩溃。退出码 3 表示根本没检查成——几乎总是仓库还没构建,因为 client bundle 是构建产物。它故意不是 0:一个什么都没验证却给通过的门禁,比没有门禁更糟。
对 13 个热门已发布插件做过实测:零误报,且没有发现任何一个真的坏。这个门禁在健康插件上是安静的——它是防上游的回归护栏,不是清理工具。
What it will never do它永远不会做的事
- Never modifies a file.It diagnoses. Fixing is yours, or your agent's —
--promptproduces a paste-ready instruction. - Never uploads anything.No account, no telemetry, no session content leaves the machine.
--offlineskips even the read-only data fetches. - Never calls a model.Zero dependencies, no API key, no per-run cost. The whole rule base is local.
- Never turns "I could not tell" into a failure.It reports it as unclassified and gives it a distinct exit code.
- 永远不修改任何文件。它只做诊断。修是你的事,或者你的 agent 的事——
--prompt会产出一段可直接粘贴的指令。 - 永远不上传任何东西。没有账号、没有遥测,会话内容不离开本机。
--offline连只读的数据抓取都跳过。 - 永远不调用模型。零依赖、不需要 API key、没有按次成本。整套规则库都在本地。
- 永远不把「我判不出来」变成失败。它报成「无法定性」,并给出一个独立的退出码。
CLI referenceCLI 参考
| Command | What it does |
|---|---|
npx dsh-why | diagnose the current install (loader failures) |
npx dsh-why run | attribute your latest run from its session log |
npx dsh-why run --all | failure mix, your own baseline, and incident days |
npx dsh-why --package . | plugin-author pre-publish gate |
npx dsh-why --error "…" | diagnose a pasted error (or pipe via stdin) |
npx dsh-why --offline | bundled rule base only, zero network |
npx dsh-why --json | machine-readable report (CI / an LLM) |
| 命令 | 作用 |
|---|---|
npx dsh-why | 诊断当前安装(加载器失败) |
npx dsh-why run | 从会话日志给最近一次 run 定性 |
npx dsh-why run --all | 失败构成、你自己的基线、异常日 |
npx dsh-why --package . | 插件作者发版门禁 |
npx dsh-why --error "…" | 诊断粘贴的报错(或管道输入) |
npx dsh-why --offline | 仅用包内规则库,完全不联网 |
npx dsh-why --json | 机器可读输出(CI / 喂给 LLM) |
Exit codes退出码
| Code | Meaning |
|---|---|
0 | nothing crash-level was found; for a run, no failed run in scope |
1 | a crash-level finding — something will break |
3 | the check could not be performed (--package only) |
2 | usage error or an internal bug |
| 码 | 含义 |
|---|---|
0 | 没有崩溃级问题;run 场景下范围内无失败 |
1 | 崩溃级问题——有东西会坏 |
3 | 检查无法执行(仅 --package) |
2 | 用法错误或内部 bug |
Where to go next接下来去哪
the full error and module reference— every failure class, and every module with its per-shell historyrun failures, all of them— the eight classes dsh-why run can namethe plugin-author gate guide— CI recipes and the seed-safe fix pattern
the full error and module reference—— 全部失败类别,以及每个模块在各 shell 上的生命周期run failures, all of them—— dsh-why run 能定性的八个类别the plugin-author gate guide—— CI 写法与 seed-safe 修法