离线诊断工具:环境/Profile/会话共 19 项检查,带设置「诊断」面板与只读 JSON API。
安装
# npm 包(预构建)
dsh plugin --profile web add @moonquake2004/dsh-doctor
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:moonquake2004/dsh-doctor#path:/plugin
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
Offline diagnostic for DeepSeek Harness — run it before boot or before installing plugins, and it tells you which of the failure classes this community has been reporting will bite.
Zero npm dependencies. One file. Runs anywhere node exists (zstd needed only for .zstd session logs; E1 checks for it).
Why
dsh's plugin tree is "fragile by install": a dangling reference, a broken file: link, a duplicate entry id, or a corrupted session log can brick the profile at boot or stall the whole web server — and --dump-config never mounts the loader, so it passes on broken setups. This class of failure was consolidated in dsh discussion #1496 (Advisory: plugin-install path needs guardrails). dsh-doctor is the offline check that advisory calls for — 19 built-in checks mapped to 18 community reports, each verified with synthetic negative fixtures, plus a self-updating remote catalog of declarative pattern checks (v0.2.0).
Usage
node dsh-doctor.mjs # everything (env + profile + session)
node dsh-doctor.mjs --profile web # profile checks only
node dsh-doctor.mjs --session <path> # session checks (default: latest session)
node dsh-doctor.mjs --env # env checks
node dsh-doctor.mjs --json # machine-readable output
node dsh-doctor.mjs --no-catalog # skip remote catalog fetch (bundled copy only)
Exit codes: 0 = all pass · 1 = problems found (built-in checks + catalog severity: error) · warn-level catalog failures don't flip the exit code.
Checks (19)
env
| ID | Checks | Discussion |
|---|---|---|
| E1 | node/pnpm/zstd on PATH |
#1270 |
| E2 | .env is a file, not a directory |
#71 |
| E3 | node version / --expose-internals reachability |
#113, #1313 |
| E4 | node-pty native binary present (prebuilds/<platform>-<arch>/pty.node) |
#1219 |
| E5 | storage JSON files valid (strict UTF-8 + parse) | #1357 |
| E6 | anchor tripwire: our S6/S7/S10 contracts still in installed dsh-session |
anti-rot idea |
profile
| ID | Checks | Discussion |
|---|---|---|
| P2 | bundle-layer vs user-patch insert id collisions (boot crash) | #1404 |
| P3 | user-patch insert name: resolvable from the profile anchor |
#1197, #880 |
| P4 | file: dependencies intact |
#1197 |
| P5 | no top-level @deepseek-ai/* duplication (dual module instances) |
#1486 |
session
| ID | Checks | Discussion |
|---|---|---|
| S1 | orphan tool_call (no matching tool result) |
#1363, #1544 |
| S2 | unclosed turns (session stuck "running") | #466, #1265 |
| S6 | seq == index contiguity (official semantics, chunk rows expanded like expandRow) |
#1333, #1452, #1469 |
| S7 | post-end-seed replay (replayed committed tail) |
#1497 |
| S8 | unknown event types without ignorable (wholesale refusal) |
#1538 |
| S9 | zstd container frame count (single-frame logs → session.list 500) |
#1043 |
| S10 | sourceEventSeqs referencing non-earlier events |
#1469 |
| S11 | whole-session scan: corrupt → quarantine suggestion; oversized / workspace estimated-heap (max(events×600B, bytes×6), default 1GiB, DSH_DOCTOR_HEAP_MB) → cold-start stall risk |
#1550 |
Notes
- The S-class checks replicate the harness's own validation (e.g.
SessionLogScanner'sseq == events.lengthwithexpandRowchunk expansion), so offline verdicts match what boot/resume would do. $DSH_HOMEis honored (default~/.dsh), so you can dry-run against a temp home without touching your real data.- In-flight tool calls in the current active turn are reported as warnings, not errors, so scanning a live session never false-positives.
- Sibling implementation with the same scope: boyin111-1/dsh-doctor — the two tools cross-verified against the same broken fixtures.
Self-update check (v0.2.1, Layer B)
The tool also watches its own npm version: each run compares the installed version against dist-tags.latest (same 6h TTL cache + offline fallback as the catalog). When a newer release exists it prints a notice and reports update: { current, latest, available } in JSON — it never touches your install without being asked.
--update— apply the update now: runspnpm installin the profile that hosts the plugin (orDSH_DOCTOR_UPDATE_CMDto override), then tells you to restartdsh web.DSH_DOCTOR_AUTO_UPDATE=1— apply updates automatically when one is available.- Honest boundary: cordis loads plugins at boot, so the new engine only activates after a restart — Layer B replaces files and reminds you to restart, it doesn't hot-swap the running plugin.
--no-catalogalso disables the update check (pure offline mode).
Remote check catalog (v0.2.0)
The built-in 19 checks are compiled into the tool. The catalog is a second, self-updating layer: plugin/checks.json in this repo holds declarative rules (data, not code), and every installed instance picks up new rules automatically — no reinstall needed.
- How it works: each run tries to fetch
plugin/checks.jsonfrom GitHub (3s timeout) → on success it's cached to$DSH_HOME/.cache/dsh-doctor/checks.json(TTL 6h) → on failure it falls back to the last-known-good cache, then to the bundled copy. New checks therefore arrive within ≤6h of being committed upstream. - Safety: rules are read-only probes executed by the built-in engine (
command-exists,path-*,json-valid,text-contains/text-not-contains,file-size-above,glob-count). The remote payload can never run code — it can only add pattern checks. - Severity:
error(default, flips exit code) orwarn(reported, exit code unaffected). Disable remote fetch with--no-catalog. - Adding a check (that's the whole point — no plugin release needed): append an entry to
plugin/checks.jsonand commit. Catalog checks shipped so far:
| ID | Probe | Checks | Discussion |
|---|---|---|---|
| E7 | command-exists |
dsh on PATH |
#1270 family |
| E8 | text-contains (warn) |
ignore-workspace-root-check=true present in profile .npmrc |
dsh-market #20 |
| E9 | json-valid |
config/workspace.json parses |
#1357 family |
| P6 | text-not-contains |
patch insert name: with spaces (Windows spawn lint) |
#1420 |
Catalog check results are marked src: "catalog" in JSON output and [目录] in CLI output.
Also installable as a dsh plugin
The tool ships as a proper dsh bundle (plugin/), so you can run the same checks (19 built-in + catalog rules) from inside the web UI:
# install into a profile (works from a checkout or a published path)
dsh plugin --profile web add file:/path/to/dsh-doctor/plugin
What you get:
- Settings → Doctor panel: one click runs all checks and renders results grouped by env / profile / session, with per-check fixes and quarantine suggestions (suggestions are shown, never auto-executed);
- HTTP API:
GET /dsh-doctor/runreturns the same checks as JSON (optional?profile=/?session=to narrow scope).
Architecture: the plugin's server route shells out to the bundled plugin/dsh-doctor.mjs --json — the same single source of truth as the CLI (the checks are offline/filesystem-based by design, so they don't need harness internals). The repo-root dsh-doctor.mjs is a thin wrapper for node dsh-doctor.mjs compatibility.
License
MIT
链接
同类插件
strukto-ai/mirage#dsh★ 3416
把文件系统与 bash 提供者换成 mirage 虚拟工作区:文件工具与 shell 命令作用于挂载的资源(RAM、S3、Redis、Slack、Gmail、Notion、Postgres)而非宿主磁盘,支持按挂载点设置读/写/执行模式、按命令选择沙箱(进程内 monty、pyodide、quickjs;远程 docker、e2b、daytona),并可在虚拟终端中安装 CLI(git、gh、slack、linear、ntn、gws,或自行注册的程序树)作为命令头词。
hust-open-atom-club/oh-dsh★ 171
社区发行版:TUI、桌面端与 Web UI 统一体验,分层安装、一步到位。
Jayden-X-L/forkprobe★ 65
同一任务并行试跑多个技能,对比结果选出最优。
vlln/plugin-registry★ 37
插件生态基建:浏览器面板管理官方 repository 插件(0 patch)+ make-dsh-plugin 插件开发引导技能。
forrestchang/dsh-multica-runtime★ 32
让 dsh 运行时跑在 Multica 上。
DietCokewithSugar/dsh-user-experience★ 18
帮你发现项目中可能存在的用户体验问题:自动走查 React/TypeScript 源码,定位问题并给出具体优化建议。