xinyangGL/dsh-open-code-review ↗★ 0

dsh-open-code-review

把阿里 OpenCodeReview(ocr) 接进 DSH:模型可调用的 ocr_review/ocr_status 工具、/ocr-review 命令、按需评审(回合尾部的「启动代码审核」按钮 + 运行时 skill,出厂默认不自动评审)、评审先于测试(preTest=remind/gate 把评审接进「跑测试之前」)、三档引擎(ocr 流水线 / delegate 委派 / 独立的只读评审子 agent),结果按文件逐条列出「文件:行 [严重程度] 问题」,每次评审都有实时进度(Jobs 面板 + 会话内进度行、可停止)。 适合需要在测试前自动或手动进行代码质量审查、逐行输出问题的开发任务。

パッケージ
dsh-open-code-review
互換性
未検証
バージョン
0.5.7
ライセンス
MIT
最終更新
2026/10/10

同名パッケージの別リポジトリ

インストール

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:xinyangGL/dsh-open-code-review

ドキュメント

README 全文を読む ↗

Configuration

Settings page

Two entries lead to the same form:

  • Settings → Code review — the plugin’s own settings page (the nav title is 「代码评审」).
  • Settings → Plugins → dsh-open-code-review — the plugin card shows a read-only summary plus a pointer to the settings page; values are edited on the settings page, not on the card.

Layout of the page:

  • Basics — 6 rows, expanded: enabled (master switch), engine, autoReview, reviewerAgent, llmMode, llmModel.
  • Dependent rows appear with their parent: reviewerProvider / reviewerModel / reviewerRounds when reviewerAgent = spawn; llmBaseUrl / llmProtocol / llmApiKeyRef when llmMode = endpoint; llmProvider (an advanced row) only in dsh mode.
  • 「Advanced settings」— 13 items, folded by default. Tuning: autoScope, autoMaxPerSession, autoMinReviewableFiles, autoMinIntervalMs, autoSkipSubagents, autoIncludeDiff, preTest. Runtime & diagnostics: audience, ocrPath, timeoutMinutes, progress, llmProvider, verbose. The fold title reads 「高级设置(13 项)」; if it holds edited-but-unsaved rows it also shows 「N 项待保存」.
  • autoMinIntervalMs is a preset dropdown (30 seconds / 1 minute / 5 minutes / 10 minutes / Custom…) but is stored in milliseconds — pick 「自定义…」 to type a millisecond value (default 60000).
  • Rows the settings page has touched carry a 「设置页已改」 badge.
  • Values are stored per profile (they do not follow you to another profile or machine). ocr_status shows where each key actually came from.

Settings page — basics

Settings page — advanced section expanded

Real screenshots (DSH on Windows, sidebar cropped out): the basics group, and the advanced section after expanding it.

Config sources

resolveConfigFile() (lib/config.js) reads one file — the first that exists:

  1. the path in DSH_OPEN_CODE_REVIEW_CONFIG;
  2. /dsh-open-code-review.json — recommended (DSH_HOME defaults to ~/.dsh);
  3. /config.json — only meaningful for a source / local checkout: a GitHub (git) install lives under node_modules and is overwritten on upgrade.

That file layer holds the keys the settings page does not have (ocrCandidates, extraArgs, env, llm.apiKey, a larger maxTimeoutMinutes, …). Precedence is settings page > config file > factory defaults, and ocr_status.fileValues lists the keys the file actually provided.

ocr’s own configuration (~/.opencodereview/config.json) is separate; ocr_status.ocrHomeConfig reports what was found there.

Key reference

Where says which settings-page row exposes the key (or file only). Defaults are the factory values in lib/config.js.

KeyDefaultWhereNotes
enabledtrueBasicsMaster switch. false stops automatic review and makes ocr_review / /ocr-review refuse to run (ocr_status still works).
engine"auto"BasicsDefault engine: auto / ocr / delegate. A tool call can override it.
auto"off"Basics (autoReview)Settings-page key autoReview writes here. off (the default since 0.5.0) / adaptive / inject / followup.
onDemandtrueBasics (onDemand)On-demand review: a Start code review button at the end of every completed turn, plus the runtime skill ocr-on-demand-review (so the model itself can start a review when you ask it to verify something).
reviewer.agent"off"Basics (reviewerAgent)off / spawn — run reviews through an independent read-only reviewer subagent.
llm.mode"dsh"Basics (llmMode)dsh / endpoint — see LLM routing.
llm.model""Basics (llmModel)→ OCR_LLM_MODEL; empty = follow DSH’s default model.
reviewer.provider"spawn"dependent (spawn)Subagent provider. A wrong name fails with OCR_REVIEWER_UNAVAILABLE and lists the available ones.
reviewer.model""dependent (spawn)Empty = that provider’s default model.
reviewer.rounds3dependent (spawn)1–10 round trips before automatic re-review stops.
llm.baseUrl"https://api.commandcode.ai/provider/v1"dependent (endpoint)→ OCR_LLM_URL.
llm.protocol"openai"dependent (endpoint)openai / anthropic → OCR_LLM_PROTOCOL.
llm.apiKeyRef"COMMANDCODE_API_KEY"dependent (endpoint)→ OCR_LLM_TOKEN, resolved from the DSH credential store (no plaintext on disk).
autoScope"workspace"Advanced · tuningScope used by automatic reviews: workspace / range / commit / scan.
autoMaxPerSession3Advanced · tuningMax automatic reviews per session (0 = none; manual reviews still work).
autoMinReviewableFiles1Advanced · tuningSkip the automatic review when fewer files are reviewable.
autoMinIntervalMs60000Advanced · tuningCooldown between two automatic reviews, in ms.
autoSkipSubagentstrueAdvanced · tuningTurns of subagents (delegationDepth > 0) do not trigger automatic review.
autoIncludeDifftrueAdvanced · tuningInclude the unified diff when an automatic review falls back to delegate.
preTest"off"Advanced · tuningReview before tests: off / remind / gate — see Review before tests.
audience"agent"Advanced · runtime→ ocr --audience; agent = summary only, human = the fuller report.
ocrPath""Advanced · runtimeAbsolute path to the real ocr executable; empty = auto-discovery.
timeoutMinutes15Advanced · runtime→ ocr --timeout and the plugin-side hard timeout. The settings page caps it at the factory 60.
progresstrueAdvanced · runtimeRegister each review as a background job (Jobs panel) and show the in-session progress row.
llm.provider""Advanced · runtime (dsh)Provider id the bridge forwards to; empty = follow DSH’s default model.
verbosefalseAdvanced · runtimeLog the ocr command line, env and timings to the DSH log.
autoEngine""file onlyEngine used by automatic reviews; empty = follow engine.
ocrCandidates[]file onlyExtra candidate paths tried after ocrPath ([] clears the layer).
extraArgs[]file onlyRaw extra arguments appended to the ocr command line.
env{}file onlyExtra environment variables for the ocr child process ("" deletes one).
includeDiffMaxBytes120000file onlyCap (characters) on the diff embedded in the generated spec.
maxIssuesInText40file onlyMax issues listed in the text summary (the full data stays in issues / rawJson).
maxTimeoutMinutes60file onlyHard upper bound for timeoutMinutes; itself clamped to 24 h (1440 min) in code.
llm.apiKey""file onlyLiteral key for the endpoint route. Prefer llm.apiKeyRef: a literal ends up on disk in a config file — and keep that file out of any repository (this repo ships only config.example.json).
reviewer.persona""file onlyExtra persona / instructions for the reviewer subagent.

Choosing an engine

The spec always comes from ocr, so all three engines review against the same rules; you can switch per call.

EngineWhat actually runsCostPick it when
ocrocr’s own pipeline: deterministic engineering + its LLM reviewer, parsed back into issuesNeeds an LLM for ocr — with llm.mode = dsh that is DSH’s model, key and quotaYou want the most hands-off setup and OCR’s own review pipeline.
delegateNo LLM call inside ocr: the plugin returns the ocr-parsed rules + file list + unified diff, and the current model reviews by those rulesUses the current session’s model/quota onlyYou have no LLM key/quota to spare, or ocr’s LLM is not configured. engine = auto falls back to this automatically.
reviewer.agent = spawnEach round spawns an independent read-only subagent (own context + model, tools limited to read/grep/glob) that returns structured findings; the coding agent fixes them or explains why not, then the next round starts automatically until clean or the round limitThe most expensive, and the closest to a human reviewHigh-risk changes where “the author reviews their own work” is not enough.

Which one? Start with ocr (or delegate if you want reviews without spending anything extra), and switch on reviewer.agent = spawn for the changes that really matter.

LLM routing

ModeBehaviour
dsh (default, recommended)ocr is a separate subprocess and cannot reach cordis, so the plugin starts a small OpenAI-compatible bridge on 127.0.0.1 that accepts only a random per-run token and forwards requests to DSH’s ctx.llm.stream. Models, provider, keys, account rotation and quota stay inside DSH — nothing to configure beyond optionally pinning llm.provider / llm.model.
endpointocr talks straight to a static endpoint: llm.baseUrl + llm.protocol (openai / anthropic) + a key — llm.apiKeyRef names a DSH credential (recommended), or llm.apiKey holds a literal key in the config file.

The plugin maps these onto the environment ocr understands: OCR_LLM_URL, OCR_LLM_PROTOCOL, OCR_LLM_TOKEN, OCR_LLM_MODEL (config.env can override or add more).

ocr_status.bridge shows the dsh bridge live: url, the masked token, requests, failed, retries, retrySkips + retrySkipReason (why a request was not retried automatically), cumulative tokens (prompt_tokens, completion_tokens, total_tokens, cache_read_tokens, cache_write_tokens, partial), lastError, lastProvider, lastModel, inflight and uptimeMs. If the host has no llm service, the plugin still works and the dsh route falls back to the static endpoint.

Usage

Tool ocr_review

ParameterTypeMeaning
scopeworkspace | range | commit | scanworkspace (default) = uncommitted changes, equivalent to ocr review; range uses from/to; commit uses commit; scan scans paths and needs no diff.
from / tostringStart / end ref of scope = range, e.g. main, feature-x (to omitted = up to the working tree).
commitstringCommit hash or tag for scope = commit.
pathsstring[]Files/directories to scan for scope = scan; also filters the git diff in delegate mode.
engineauto | ocr | delegateDefaults to the configured engine. auto = try ocr, fall back to delegate when ocr has no LLM.
reviewerbooleantrue = force the independent reviewer subagent (fails with OCR_REVIEWER_UNAVAILABLE instead of falling back); false = force ocr/delegate; omitted = follow reviewer.agent.
previewbooleanOnly list the files that would be reviewed and the exclusions; no LLM call (like ocr review -p).
effortlow | medium | highReview effort preset (ocr’s --effort).
model / providerstringOverride the model / provider for this run.
excludestring[]gitignore-style exclusion patterns (joined with commas for --exclude).
rulePathstringPath to a custom system-rule JSON file (ocr’s --rule).
timeoutMinutesnumberTimeout for this run; defaults to the plugin config.
repostringGit repository root; defaults to the session working directory.
includeDiffbooleandelegate mode only: embed the unified diff in the spec (default true).
extraArgsstring[]Raw extra arguments for ocr (advanced).

Unknown parameters are rejected (additionalProperties: false), so a typo fails loudly instead of silently doing nothing.

The result carries: ok, code (empty on success), engine (the one that actually ran: ocr / delegate / agent), reviewer (provider, model, round, rounds, childId, stopReason, verdict = clean / issues / uncertain), scope, repository, command (the ocr command line that ran), exitCode, durationMs, reviewableFiles[] (path, status, insertions, deletions), excludedFiles[], issues[] (file, line, severity, message), summary, reviewSpec (the delegate payload), configHint, notes[], rawJson (ocr’s stdout, up to 100 000 characters), stderr, lostOutput, spillPath, llmMissing, usage (prompt_tokens, completion_tokens, total_tokens, cache_read_tokens, cache_write_tokens, partial, requests — accumulated through the bridge on the dsh route), timedOut, aborted.

Tool ocr_status

Diagnostics for one call: resolved executable + version, configPath / configSource / fileValues[], installHint, settingsPage, the effective enabled / engine / auto / llmMode / llmRoute / llmEndpoint, the bridge counters (above), reviewer availability (providers[], ready, error), credentialRef / credentialSource, ocrHomeConfig, llmEnv[], a minimal llmTest, and notes[]. Start here whenever a review fails.

Command /ocr-review

Runs a review from the input box: it injects a follow-up instruction into the current session, which then calls ocr_review (default scope = workspace) and works through the findings one by one. It accepts optional free text after the command — extra requirements such as “only review changes under src/, focus on concurrency and error handling”. If the plugin is switched off (enabled = false), the command returns an error pointing at the settings page; ocr_status still works.

On-demand review (the default since 0.5.0)

Nothing runs on its own. Two ways to start a review when you decide the change is ready:

  1. The button at the end of a turn. Every completed turn gets a Start code review button in the conversation tail. One click runs the same thing as /ocr-review for that session; while a review for that session is running the button turns into Reviewing… and is disabled (so double-clicking cannot stack two reviews), and a failure shows the reason inline and can be retried. It is rendered by lib/client.js (conversation.chat.turnTail); if the host does not expose the remote-command service the button simply is not there, and everything else keeps working.
  2. The runtime skill ocr-on-demand-review. With onDemand = true the plugin registers it with the host, so when you say “review this”, “verify the change” or “跑一次评审” the model can call ocr_review itself and report file-by-file findings. ocr_status reports onDemand and skill.registered, which is how you confirm the registration.

The button and a typed /ocr-review both execute the same slash command on the host, so ocr_status also reports command: { name: "ocr-review", registered, reason } (added in 0.5.4). If registered is false the host refused the registration — the button and the command cannot work, and the status note says so instead of failing silently.

Turn both off (onDemand = false, or enabled = false) and the plugin is reduced to the tools plus the /ocr-review command — nothing is ever injected or auto-started. onDemand = false also removes the skill registration; the tail button disappears with it.

Review before tests (preTest, since 0.5.7)

“Can the review be wired into the standard flow — start it before the agent runs unit tests?” Yes, and it is off by default. Three modes (preTest, settings page → Advanced → Tuning → Review before tests, or preTest in the config file):

ModeWhat happens when a shell tool looks like a test command
off (default)Nothing. Test commands are untouched.
remindT