dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
把同一个 diff 同时交给多个评审者——已安装的 CLI 编程智能体(codex、claude 等)或 DSH 子智能体——各自成节,合并为一份报告;评审者与命名评审模式在设置界面里配置。
English | 中文
Code review as a tool, not a single vendor. Hand your diff to a CLI coding agent, or to a subagent running a model from your DSH configuration — then read one merged report.
codex / claude / gemini / opencode /cursor / any CLI you template yourself, or a DSH subagent running a model from your DSH configuration.
order they were selected.
quick, balanced, deep, …) and reuseit, instead of retyping review instructions every time.
stays collapsed under advanced settings. Edits are written about half a second after you stop typing — a status line at the top says where they stand, and a Save now button remains as a manual retry.
composer says whether this session has reviewed, which round is running, how many rounds finished, and who reviewed. Expand it for each round's time, scope, and outcome. It stays hidden while the conversation is empty or when the current turn changed no files. The data is session-scoped and persists across reloads.
only asks for what is already there.
Clone it somewhere permanent, then install it into a profile:
git clone git@github.com:yutingzhao1991/dsh-review.git ~/code/github/dsh-review
dsh plugin --profile web add ~/code/github/dsh-review # web → your profile nameOr ask your agent to run plugin_manager → install_bundle with that absolute path.
Restart the host afterwards. Updating works the same way: git pull, then restart.
Requires DSH 0.2.1 or newer. The plugin declares this as engines.dsh in its manifest, so an older host refuses to install or activate it instead of failing later inside a review.
review() // the reviewers you enabled, uncommitted changes
review({ reviewers: ["codex", "deep-dive"] }) // pick reviewers for this call
review({ mode: "deep" }) // deep strength, several reviewers
review({ base: "main" }) // working tree vs a branch
review({ commit: "abc1234" }) // one commit
review({ instructions: "only concurrency and error handling" })Reviewing takes minutes, so the call waits a little and then hands back a job id: read the result with job_output, stop it with job_kill, or just wait — you are notified when it settles.
Reviewers are opt-in: if nothing is enabled, a call with no reviewers fails and says so rather than quietly running everything.
A slim status line sits between the conversation and the composer, no panel required:
State · What it shows Nothing reviewed · Review · Not reviewed yet Running · Review · Round 2 in progress · 1m 05s + the running reviewers Finished · Review · 3 round(s) reviewed + reviewer chips Last round failed/interrupted · Review · Round 3 failed / Round 3 interrupted
Click the line for the last 30 finished rounds (plus any still running): round number, time, scope (uncommitted changes / a base branch / a commit), reviewers, and outcome. The round count is not limited by the retained history.
The data is a session projection: each review job writes once on registration and once on settlement, and the value is checkpointed with the session. Switching sessions, reloading, or restarting the host keeps the history. A round left running by a previous host process is shown as interrupted instead of ticking forever.
When it stays hidden:
@deepseek-ai/dsh-workspace-changes plugin: its workspace/changes event is normally only appended for a turn that actually changed files, so the status line does not run its own git status. It remains visible while a turn is in progress or a review is running, so triggering a review does not make it vanish.
workspace-changes, only the empty-conversation rule applies; amissing capability never hides the line. Subagent sessions are exempt from the no-change rule too, because the upstream plugin deliberately does not record them.
upstream plugin's snapshot coverage, are not counted — that boundary belongs to workspace-changes, not to a second heuristic here.
Kind · What runs · Reads the code itself · Needs cli · a coding agent you already trust · depends on the preset (codex reads the repo) · that CLI installed subagent · a DSH child agent · yes, it has tools · a subagent service (default spawn)
CLI presets: codex, claude, gemini, opencode, cursor, or custom with your own command template.
Where the CLI lives. The plugin looks, in order, at: executable (a PATH name or a path) → ~/.local/bin, ~/.bun/bin, /opt/homebrew/bin, /usr/local/bin → the current profile's dependencies (node_modules/.bin/, plus the package's own bin entry when the preset declares one, e.g. @openai/codex's bin/codex.js).
That last step is the recommended setup: install the CLI as a direct dependency of the profile (dsh plugin --profile add ). Do not keep pinning an absolute path in your patch — that is the trap we hit locally: a dependency reinstall pruned node_modules/@openai/codex, the pinned path silently went stale, and the tool description still advertised the reviewer as usable while every call burned a full run. Absolute paths still work (highest priority), but their lifetime is tied to the dependency graph.
When the configuration looks wrong, run the self-check instead of a real review:
review({ doctor: true })It checks, per reviewer, whether the executable resolves, which candidate found it, whether --version runs, whether the subagent provider is registered, and whether the host exposes the startActivation() interface this plugin uses. It also reports whether the GUI config schema resolved (@deepseek-ai/schemastery) and where it came from. It reviews nothing, starts no reviewer, and does not need a git repository. Model connectivity for subagents is out of scope — that would need a real request.
One thing worth knowing: a subagent inherits the parent session's model unless you set agentModel, so it is not automatically a second opinion — name the model explicitly if you want one.
Subagents get a 30-minute wall-clock ceiling by default (timeoutMs per reviewer; hardTimeoutMs still caps the whole call). Recursion is bounded by the host's delegation-depth budget (default 1), so a reviewer normally cannot start another subagent. Progress is reported while they run, so a long review does not look stuck.
DSH 0.2.1 moved persona and tool restrictions out of the subagent start request: configure them in an Agent Preset and select it with agentPreset. The old persona / toolFilter keys are ignored with a migration warning instead of silently doing nothing.
There is deliberately no "send the diff to a bare model" kind: a reviewer that can open the repository itself is worth more than one that only sees what it was handed.
- id: review
name: dsh-review
config:
agents:
- preset: codex
model: gpt-5.6-sol
- preset: claude
reviewers:
- id: deep-dive
kind: subagent
provider: spawn # subagent service, `spawn` by default
agentProvider: bailian # any provider from your DSH config
agentModel: deepseek-v4.1-flashA subagent's model comes from your DSH configuration (provider, key, context window), and the GUI combines provider and model into one grouped picker — choosing an entry writes both agentProvider and agentModel, and nothing is duplicated in this plugin.
provider is the subagent service implementation (default spawn), not the model provider. The GUI hides it unless it is set to something other than spawn.
Add agentPreset: to run that reviewer under a specific Agent Preset. The preset owns its persona and tool set; spawn supports an independent preset, while fork inherits the parent's composition.
A mode bundles how hard to look, what to say, and who to use.
Field · Meaning strength · light / standard / deep — built-in review framing prompt · extra instructions for this mode reviewers · which reviewers this mode uses when · always / complex / never — a review policy for the agent to follow
config:
defaultMode: balanced
modes:
balanced:
strength: standard
reviewers: [ codex ]
deep:
strength: deep
reviewers: [ codex, deep-dive ]With no modes configured the plugin adds no constraints at all — you keep steering the agent with your own prompt. when only takes effect if you also set injectPolicy: true, and it is stated in the system prompt, not enforced as a gate.
Everything can be set in the GUI; these are the same knobs in YAML. Only the ones worth knowing:
Key · Default · Meaning defaultReviewers · none · reviewers used when a call omits reviewers; empty means none are enabled defaultMode · none · mode applied when a call omits mode language · auto · zh / en / auto report language (auto follows your instructions) injectPolicy · false · state each mode's when rule in the system prompt agents / reviewers · [] · define CLI and subagent reviewers (agents is the preset shorthand, reviewers the full form) modes · {} · named review modes waitMs · 0 · how long a call blocks before handing back a job id. 0 returns immediately (reviews take minutes, so waiting rarely pays) hardTimeoutMs · 0 · wall-clock ceiling; 0 = no limit — you decide when to stop it maxResultChars · 80000 · report cap; longer reports are truncated with a path to the full file maxDiffChars · 160000 · diff cap for reviewers that receive the diff
CLIs. base and commit are mutually exclusive. A range plus instructions works for subagents but not for the codex CLI (its range flag and PROMPT exclude each other): if every selected reviewer is such a CLI the call is rejected up front, otherwise the CLI ones are named in the report footnotes. To keep both the range and the focus, add a subagent reviewer; putting the focus in a mode's prompt does not help, since a mode prompt is skipped as well whenever a range is given (next bullet).
range is always honoured, and the report says when the prompt was skipped.
~/.codex/config.toml).base/commit fails before any reviewer starts, instead of running for minutes andreporting a batch that reviewed nothing.
language only controls thereviewers' own instructions.
$TMPDIR/dsh-review-*/report.md; other runs clean up afterthemselves.
reload plugin code when the profile's dependencies change (measured: patchReload: live only reloads the patch layer), so the description can lag behind disk. Use review({ doctor: true }) for the current truth. For the same reason, plugin code changes need a host restart.
collectMaxBytes), thereport footnote says the tail may be missing and gives the spill path. When no executable can be found, every candidate path and its failure reason is listed.
node selftest.mjs # drives the plugin with a fake host: no DSH, no codex, no model calls