CLI 参考
命令、参数、输出与退出码。
ocra review
审查当前 Git 仓库里的代码改动。
ocra review [options]| 参数 | 含义 |
|---|---|
| (不带参数) | 审查未提交的改动:已暂存、未暂存和未跟踪的文件 |
--from <ref> | 审查 --to 从 <ref> 分叉以来的改动(基于 merge base) |
--to <ref> | 区间终点,默认 HEAD,必须配合 --from 使用 |
--commit <sha> | 审查单个 commit 相对其父 commit 的改动 |
--format text|json|sarif | 输出格式,默认 text。sarif 输出 SARIF 2.1.0 |
--output <file> | 把结果写入文件,而不是输出到 stdout |
--pr <number> | 审查一个 GitHub PR,见 GitHub Pull Request |
--repo <owner/name> | --pr 所在的仓库(默认取 GITHUB_REPOSITORY 或 origin) |
--mr <iid> | 审查一个 GitLab Merge Request,见 GitLab Merge Request |
--project <id|路径> | --mr 所在的项目(默认取 CI_PROJECT_ID 或 origin) |
--publish | 配合 --pr 或 --mr:把评审发布到 PR 或 Merge Request |
--full | 配合 --pr 或 --mr:审查所有文件,而不是只审查上次评审之后改动过的文件 |
--max-cost-usd <n> | 本次运行的花费上限。花费达到上限的 80% 时审查任务停止:不再启动新任务,正在运行的任务也会被停下,已经找到的问题保留;这些任务的文件算作未审查,所以退出码为 3。剩下的部分留给核查和裁决。如果这部分也用完,剩余的问题会标为未核查,不会拦下改动,报告里也会写明。运行中的任务大约每 10 秒报告一次花费,所以一次运行最多会超出上限:每个任务在这段时间里的花费,加上它正在进行的那一步。任务按分组逐个运行,所以受上限约束的运行会审完一部分文件,而不是每个文件都只开个头;使用 --pr 时,下一次审查会接着审剩下的文件 |
--plan | 不调用任何模型(免费),显示会审查和排除的文件、分组、审查任务以及每个任务首轮提示词的大小,包括 --ultra 下或 5 个文件以上的分组在审查前的那一次规划调用。由于跳过了 light 模型分组,需要分组的较大改动会按每个文件一组显示(超过 20 个文件时按目录分组)。和 --pr 一起用时按全量审查来规划,而不是只看上次审查以来的改动;不会写会话日志 |
--import-sarif <文件> | 把分析工具(Semgrep、CodeQL 等)写出的 SARIF 2.1.0 日志里的结果加入审查,可以重复使用。只保留落在改动行上的结果,它们和审查员的问题一样经过核查和裁决。见 SARIF 输入。不能和 --plan 一起用 |
--ultra | 以成本换召回率,见模式 |
--reviewers <ids> | 只运行这些审查员,用逗号分隔(例如 security) |
--temperature <n> | 每次模型调用的采样温度,0 到 2;覆盖配置里的 sampling.temperature。不设置时用各供应商的默认值 |
--seed <n> | 每次模型调用的采样种子,运行时和供应商支持时才生效;覆盖 sampling.seed。opencode 运行时没有种子设置,会报告为未应用 |
--config <文件> | 读取这个配置文件,而不是仓库的 .ocra/config.json(与 --pr 或 --mr 一起用时,代替 base 分支的那份)。文件是你自己的,所以和 --no-repo-config 一起用也生效;它列出的插件从文件所在目录解析,审查 PR 和 Merge Request 时照样不加载。见配置 |
--no-repo-config | 忽略 .ocra/config.json 及其中列出的插件(与 --pr 一起用时,base 分支的也忽略),模型改从 OCRA_MODEL_* 或 --config 读取;memory、rules 和 AGENTS.md 从 --from 所在的提交读取,否则不使用。审查不信任的代码时使用 |
-h, --help | 显示帮助 |
--commit 不能和 --from、--to 同时使用。
进度
进度输出到 stderr,所以用 --format json 时 stdout 上的内容仍然可以直接给程序解析:
[ocra] Reviewing: Working tree changes
[ocra] 4 file(s) selected, 1 excluded · risk tier: lite
[ocra] 2 bundle(s) (grouped)
[ocra] 2 review task(s)
[ocra] correctness-1 started: auth session handling (2 file(s))
[ocra] correctness-1 reviewing with google/gemini-3.5-flash
[ocra] correctness-1 google/gemini-3.5-flash: 3 step(s), 3 tool call(s) (read_file 2, task_done 1), 19558 in / 118 out / 0 reasoning tokens, $0.0062
[ocra] correctness-1 completed in 5.9s · 0 finding(s)模型超过 30 秒没有新输出时,ocra 会打印 Model is thinking...,让长时间的审查不会看起来像卡住了。
退出码
| 退出码 | 含义 |
|---|---|
0 | 审查完成,结论为 approved、approved_with_comments 或 minor_issues |
1 | 结论为 significant_concerns:至少有一个经核查确认的 critical 问题。未经确认的 critical 只会得到 minor_issues,退出码为 0。结论只是参考意见,可能受被审查改动的影响,见工作原理。配合 --pr 时,维护者针对 head commit 的 /ocra override 会把它变成 0(见 GitHub) |
2 | 参数、Git 或配置错误,或者没有任何审查任务完成。错误行会写出错误代码,例如 ocra [VCS_REF_UNKNOWN]: Unknown commit: nope(代码列表) |
3 | 审查不完整:有选中的文件没有被审查(任务失败、超时、触及花费上限或任务数上限,或者没有审查员覆盖它),或者有 critical 因核查失败、预算不足而没能核查。它优先于 1:不完整的审查不会只报告为阻塞,CI 不会因此放行 |
130 | 被 Ctrl-C 或 SIGTERM 中断;仍会打印部分报告,不会发布任何内容 |
JSON 输出
--format json 会输出完整报告:变更信息、风险档位、结论和总结、每个改动文件的覆盖情况(已审查、失败、未审查(没有为它启动任何任务)、自上次评审后未改动,或被排除及原因)、审查 PR 时本次是增量还是全量审查及原因(scope)、分组、各任务结果、被 Matrix 跳过的(审查员,分组)组合、被核查丢弃的问题(refuted,附原因)、核查没能检查的 critical 数量(unverifiedCriticals)、Judge 合并、丢弃或重新定级的记录(judgement)、问题列表、与上次审查的对比(rereview:已修复、未再报告、未重新检查、未改动和已驳回的旧问题)、被仓库 memory 接受的问题(remembered)、维护者的放行(changeRequest.override)、token 用量与花费,设置了花费上限时还有上限本身以及本次运行是否达到了它(spendLimit:审查任务因此停止时 reached 为 review,整个上限用完时为 total),以及警告信息。会话里的 report.json 格式相同。
这个格式带版本号("version": 1),是一份约定:后续版本只会新增可选字段,否则就会改版本号。每条问题包含 fingerprint(多次运行间保持稳定;ocra memory add 接受它的前缀)、reviewer、category、severity、verification(confirmed、uncertain 或 unchecked)、file、lines({ start, end },问题没能对应到具体行时不存在)、inDiff、status(new,或者之前的审查也报过时为 unfixed)、title、body、可选的 suggestion、evidence、code(引用的代码)、--ultra 下的 lowConfidence,以及 provenance:报告它的那个任务在 tasks 里的 task,运行时能说出时还有 model。tasks 里的每个任务带有自己的 usage(token 和花费;一条问题的花费就是它所属任务的花费)。报告的 provenance 说明这次审查是用什么做的:ocraVersion;promptHash(这份配置会发出的系统提示词的哈希:每个启用的审查员和每个辅助阶段的,从不包含改动本身);configHash(实际生效的配置,加上会改变审查的参数 --reviewers、--ultra 和 --max-cost-usd 的哈希;不含采样设置和密钥,key 只以变量名出现,从不保存);以及 sampling:运行时实际应用的 temperature 和 seed,notApplied 列出要求了却没法传下去的设置;以及 agents:每个启用的审查员和 verifier、judge、helper 三个角色各自的模型层级 tier、设置了时的推理强度 effort、是否已应用 applied(这个 agent 没有发出调用时不存在),以及 notApplied:它的调用没有发送的采样设置。报告的 JSON Schema(draft 2020-12)由代码生成并经测试核对;@open-cr-agent/core 的 reportJsonSchema() 返回同一份 schema。--plan 输出的 JSON 同样带版本号("version": 1):变更信息、风险档位、选中和排除的文件、分组、各任务及其估算的提示词大小和设置了时的推理强度 effort、被跳过的(审查员,分组)组合、是否跳过了模型分组(groupingSkipped)、首轮提示词的估算总大小(promptTokens),以及警告信息。
SARIF 输出
--format sarif 把审查结果写成 SARIF 2.1.0 日志,代码扫描和安全看板读取的就是这种格式。上传到 GitHub 的方法见代码扫描。
- 规则和结果。 每个审查员类别(
correctness、security等)一条规则,每个问题一条结果:- 级别来自严重程度:
critical为error,warning为warning,suggestion为note; - 消息是标题、正文和修改建议;
- 区域是问题所在的行;
partialFingerprints里是它的指纹(ocra/v1);- 审查员、严重程度、核查结果、状态、任务,以及已知时的模型放在属性里。
- 级别来自严重程度:
- 没有行号的问题。 ocra 没能定位到行的问题作用于整个文件:它没有区域。
- 沿用的问题。 审查 PR 时,之前的审查报告过、仍然打开、而且所在文件这次没有重新审查的问题,也会作为结果写出。它们归在规则
ocra-carried-over下,标为unchanged,没有行号:审查状态里没有保存它们的行。 - 不完整的审查。 退出码为
3的审查会标为执行不成功。没审到的文件数和警告写成通知。结论、风险档位、没审到的文件和花费写在这次运行的属性里。
来自改动和模型的文字只作为文字:方括号和反斜杠会被转义,因此拼不出内嵌链接;花括号按 SARIF 的要求写成两个;网址会被插入一个零宽空格,和 PR 评论里一样。--plan 没有问题可写,所以不能输出 SARIF。
SARIF 输入
ocra 不运行任何分析工具。你自己运行 Semgrep、CodeQL 或其他工具,再用 --import-sarif <文件> 把它写出的 SARIF 2.1.0 日志交给 ocra(可以重复使用,每个文件最大 20 MB)。日志里的每个 run 在报告里都是一个独立的任务 sarif-<工具>-<n>:审查员是工具名,没有花费,文件是它报告过的文件;它的问题在 provenance.task 里指向这个任务。
- 只保留落在改动上的结果:文件在本次审查范围内,行号落在 diff 的某个 hunk 里。整仓库扫描的其余结果会被留下并计入一条警告;没有文件和行号、路径在仓库之外、没有消息的结果也一样。每个 run 最多取 200 条。
- 严重程度来自结果的 level,没有时来自规则的默认值:
error为critical,warning为warning,note和none为suggestion,正好是 SARIF 输出的反向映射。标题是规则的简短描述、名字或 id;正文是消息、规则的说明,以及一行写明工具、版本、规则和帮助链接。 - 引用的代码决定行号。 结果里的代码片段(没有时取文件对应的行)和审查员引用的代码走同一套定位;对不上的引用会让问题变成文件级。
- 之后它就是一条普通的问题:memory 和驳回照样生效,核查会对照 diff 检查它,Judge 会把它和审查员的问题放在一起裁决(工具和审查员重复报告的问题在这里合并),它也计入结论。
已用 Semgrep 1.178.0 写出的日志测试过;其他工具的日志遵循同一标准。
会话记录
每次审查(--plan 除外)都会写入 .ocra/sessions/<id>/events.jsonl(运行过程中逐行追加事件)和 report.json。这个 <id> 就是运行 id:第一行进度输出会写出它,JSON 报告以 runId 携带它,摘要评论在"覆盖范围和花费"里显示它,SARIF 日志以 automationDetails.id(ocra/<id>)携带它,因此从任何一处都能找回同一次运行。这个目录自带 .gitignore,日志既不会被提交,也不会在下一次审查时被当成改动。
ocra metrics
对 .ocra/sessions/ 下已完成的审查做统计,数据来自每个会话的 report.json,不调用任何模型:
ocra metrics # 文本表格
ocra metrics --format json # 给看板或脚本用;带 "version": 1
ocra metrics --since 2026-10-01 # 只统计在该日期及之后开始的运行
ocra metrics --sessions /srv/ocra # 另一个会话目录,比如 CI runner 上的它报告运行次数(按结论分、有多少次留下未审查的文件、有多少个会话没有可读的报告)、花费(总计和每次运行、token 数)、问题数(报告条数、按指纹去重数、按严重程度和核查状态分)、早先报告的问题后来的去向(fixed:后一次审查里代码已不在;dismissed:被审查者驳回;两者之比即接受率),以及每个审查员各自的任务数、失败任务数、花费和同样的去向统计。一条问题归于最先报告该指纹的审查员。只统计版本 1 的报告;JSON 输出和报告一样是契约,同样按版本管理。
ocra --version
打印版本号。
ocra memory
有些问题本身没错,但已被接受:风险在别处处理了,或者团队决定接受它。把它们记下来,ocra 就不会再报告:
ocra review # 每条问题都会显示一个 id,例如 #1a2b3c4d
ocra memory add 1a2b3c4d --reason "重试次数由网关限制。"
ocra memory listocra memory add 会在 .ocra/sessions/ 下最新的会话里查找这个 id;用 --session <dir> 可以指定别的会话。条目写入 .ocra/memory.json,提交这个文件即可与团队共享。被记住的问题(审查员、文件和引用的代码都相同)不会出现在报告里,只会计数;审查员也会看到自己所审文件里已被接受的问题,不会再提。审查 PR 时,这个文件从 base 提交读取,因此 PR 无法借此压掉针对自己的问题。.ocra/memory.json 无效时审查会报错停止,和 .ocra/rules.json 无效时一样。
ocra login、ocra logout、ocra whoami
开发中。 ocra Cloud(ADR-0024)的地址是 https://app.ocracloud.com;`OCRA_CLOUD_URL` 可以指定其他服务器。ocra 的其他功能都不依赖这几个命令:不登录时审查行为与以前完全相同;设置 OCRA_CLOUD=off 后这几个命令拒绝运行。
ocra login # 显示一个验证码,并打开浏览器确认
ocra whoami # 当前登录的 GitHub 账号
ocra logout # 在服务器上结束会话,并删除本地保存的会话ocra login 使用 OAuth 设备授权流程(RFC 8628):它打印一个验证码(如 BCDF-GHJK),打开服务器上的确认页(加 --no-browser 则只打印链接),然后等待你在已用 GitHub 登录的浏览器里批准。只批准你自己刚刚发起的验证码。之后这个终端持有一个会话:可以用服务器上保存的 key 调用模型、上传审查结果,但不能读取这些 key,也不能修改账号;它会显示在服务器的会话页面上,可以在那里撤销。
会话保存在 ~/.config/ocra/credentials.json(或 $XDG_CONFIG_HOME/ocra/,Windows 上为 %APPDATA%\ocra\),只有你本人可读。访问令牌有效期一小时,用刷新令牌续期,刷新令牌每次使用后都会更换。登录后,名为 ocra-<provider>/<model> 的模型会经由 ocra Cloud、使用服务器上为 <provider> 保存的 key 调用(走服务器列出的 OpenAI 兼容对话接口),例如:
{ "runtime": "direct", "models": { "standard": "ocra-openrouter/qwen/qwen3.8-27b:free" } }这类模型没有价格:报告中的费用和 --max-cost-usd 不计入它们,ocra 会给出警告。此时提示词及其中引用的代码会经过 ocra Cloud 再到达模型服务商;ocra Cloud 只记录每次调用的模型、状态码、token 数和耗时,从不记录请求和回答内容。没有使用 ocra- 模型的审查不会读取会话,也不会连接 ocra Cloud;配置中自己以 ocra- 名称声明的 provider 保持原有声明。
已登录且仓库没有配置任何模型(配置中没有 models,也没有 OCRA_MODEL_*)时,ocra review 会使用你在服务器“默认模型”页面选择的模型,并给出提示。
每次审查结束后,已登录的 CLI 会把审查的统计数据发送给 ocra Cloud:结论、是否审完所有文件、各级别问题数、文件和任务数、token、费用和耗时、来源(本地、GitHub、GitLab)以及 ocra 版本。它从不发送路径、标题、问题描述或代码。仓库以其 origin 地址(去掉其中的凭据)的 SHA-256 发送,并加入一个只保存在本机的随机盐(位于凭据旁的 upload-salt),因此服务器可以把同一仓库的审查归在一起,却无法知道是哪个仓库;同一仓库在另一台机器上会得到不同的哈希。--no-upload 跳过单次上传,OCRA_CLOUD=off 关闭全部上传;上传失败只会给出警告。