资讯动态

open-code-review:嵌入 Git 流程的本地化 LLM 代码审查 CLI 工具

发布时间:2026/10/19 9:22:32 来源:尧图企业网站定制
1. 项目概述一个真正能落地的开源代码审查 CLI 工具“open-code-review”这个名字乍看平平无奇但拆开来看——open不是指“开源”这个老生常谈的标签而是指“开放上下文、开放规则、开放反馈路径”code review也不是 Pull Request 里点个 approve 那种形式主义流程而CLI这个后缀才是它真正扎根于工程师日常工作的锚点。我从去年开始在三个不同规模的团队里推动代码审查自动化实践试过 GitHub Copilot Reviews、SonarQube LLM 插件、自研 Web 端 Review Agent最后全砍掉就因为它们都卡在一个致命环节无法嵌入真实开发流。开发者不会为了“被审查”专门切窗口、填表单、等页面刷新。但如果你把open-code-review当成git commit的延伸——它就在你敲完git add .之后、git commit -m feat: add user auth之前自动跑一次本地扫描3 秒内返回带行号标注的建议、潜在边界条件遗漏、测试覆盖缺口甚至用自然语言解释“为什么这里建议用Optional.ofNullable()而不是直接判空”——那它就不再是工具而是你键盘边上的第三只手。核心关键词open-code-review、CLI、LLM、code review、Git不是并列关系而是层级依赖Git 是触发器CLI 是载体LLM 是引擎而 open-code-review 是整套机制的输出契约——它承诺不黑箱、不越权、不离线、不传源码。你执行ocr --diff它只读取git diff --cached的输出你加-v参数它会打印出每条建议对应的 prompt 模板和模型调用耗时你配置--rulesetsecuritytest它就只加载对应规则集的 prompt chain 和校验逻辑绝不加载无关的“可读性优化”模块。这不是一个“用 LLM 做 code review”的玩具项目而是一个把大模型能力压缩进 Git 钩子生命周期里的工程化接口。适合三类人一线写业务的前端/后端工程师想少点无效 CR、技术负责人需要可审计、可收敛的审查标准、以及正在做 DevOps 工具链整合的 SRE需要稳定、低侵入、可 pipeline 化的审查节点。它不替代人工 Review但能把 60% 的重复性问题空指针、硬编码密钥、未处理异常分支在提交前拦截让人的注意力真正聚焦在架构合理性、业务逻辑漏洞、跨服务契约一致性这些高价值判断上。2. 整体设计思路与架构选型逻辑2.1 为什么必须是 CLI而不是 Web UI 或 IDE 插件这个问题我踩过三次坑。第一次用 Web UI 方案团队要求“所有审查结论必须留痕”结果发现 UI 上的评论和 Git 提交记录完全脱钩——PR 合并后UI 里的讨论就变成孤岛数据没法追溯到具体哪一行代码、哪个 commit。第二次搞 VS Code 插件看似无缝但问题出在环境隔离插件运行在 Electron 渲染进程里访问不了用户.gitconfig里的 proxy 设置也拿不到~/.ssh/id_rsa的权限上下文导致对私有 Git 仓库的 diff 获取失败更麻烦的是不同团队用的 Node.js 版本从 16 到 20 不等插件编译产物兼容性一塌糊涂。第三次尝试 GitHub App倒是能深度集成但审批流完全受制于平台策略——比如某次安全合规要求“所有含process.env的文件必须由指定角色二次确认”App 却无法在 PR 创建瞬间触发该检查只能等 reviewer 主动点击按钮。所以open-code-review的 CLI 定位本质是向 Git 原生能力借力。Git 本身就是一个分布式状态机它的pre-commit、prepare-commit-msg、post-merge这些钩子天然具备原子性、可复现、环境一致三大特性。CLI 只需做一件事在pre-commit阶段调用git diff --cached --no-color获取待提交变更喂给本地 LLM 推理引擎再把结构化结果写回STDERR或生成临时 patch 文件。整个过程不依赖网络可选离线模型、不修改 Git 内部状态、不引入新进程生命周期管理——它就是 Git 的一个子命令像git stash那样可靠。实测下来在 M1 Mac 上ocr --diff --modelphi-3平均耗时 1.8 秒在 Windows WSL2Ubuntu 22.04下用 Ollama 加载codellama:7b耗时 2.3 秒。这个延迟远低于开发者等待git commit的心理阈值行业共识是 3 秒比等 CI 构建快一个数量级。2.2 LLM 引擎为何不直接调用 OpenAI 或 Claude API热词里反复出现llm、agent、embedding、prompt injection恰恰说明当前 LLM 应用最大的风险不在能力不足而在上下文失控。open-code-review的设计铁律是任何代码片段未经用户显式授权绝不离开本地机器。我们做过压力测试用包含 AWS Access Key、数据库连接串、内部 API Token 的测试文件触发ocr --diff抓包确认全程无 HTTP 请求发出用strace -e traceconnect,sendto监控进程系统调用也验证了零外连。这背后是三层隔离输入层隔离CLI 解析git diff输出时会主动过滤掉*.env、secrets.yml、application-prod.properties等敏感文件后缀可配置对匹配到的process.env.*、os.getenv(等模式自动添加// [OCR-SKIP] sensitive env usage detected注释并跳过分析。模型层隔离默认绑定 Ollama 作为本地推理服务支持llama3:8b、phi-3:mini、deepseek-coder:6.7b等轻量级代码模型。Ollama 的优势在于镜像体积小phi-3:mini仅 2.1GB、量化精度高Q4_K_M、CPU 推理足够快。不采用 vLLM 或 Text Generation Inference是因为它们需要独立部署服务、占用固定端口违背“即装即用”原则。输出层隔离所有 LLM 返回结果强制 JSON Schema 校验见后文--output-formatjson章节字段包括file_path、line_number、severitylow/medium/high、suggestion、explanation。禁止返回任意 HTML、Markdown 表格、代码块——这些富文本格式易被注入恶意 payload且难以审计。JSON 是唯一可编程解析、可管道传递、可存入 Git Notes 的格式。提示很多团队问“能不能接入企业微信或飞书通知”我们的答案是可以但必须通过--hookwebhook://your-company-webhook-url参数显式开启且 webhook payload 经过 SHA256 签名验证URL 必须是白名单域名。绝不允许在 config 文件里硬编码 token。2.3 “Open” 的真实含义规则可插拔、反馈可追溯、结果可验证“open” 在这里不是形容词而是动词。它意味着规则可插拔open-code-review自带三套规则集base基础语法/空指针/资源泄漏、securityCWE Top 25、硬编码密钥检测、testJUnit/TestNG 覆盖缺口、Mock 使用规范。每套规则对应一个 YAML 文件例如security.yaml里定义rules: - id: CWE-798 name: Use of Hard-coded Credentials pattern: password\s*\s*[\].*[\] severity: high suggestion: Move credential to environment variable or secret manager用户可随时新增规则只需ocr --ruleset./my-rules.yaml --diff。CLI 会动态加载并注入到 LLM prompt 中“请严格按以下规则检查代码...”。反馈可追溯每次运行生成唯一review_idUUIDv4记录在.ocr_history文件中。该文件是纯文本每行一个 JSON 对象包含review_id、commit_hash、timestamp、cli_args。你可以用ocr --history --since2024-06-01查看历史审查记录或用git notes append -m $(ocr --diff --json | jq -r .review_id) -f把 ID 关联到当前 commit。结果可验证提供--dry-run模式只输出将要执行的 LLM 调用命令如ollama run phi-3 Analyze this diff: ...不实际触发推理提供--debug-prompt参数打印最终发送给模型的完整 prompt方便调试规则冲突或模型幻觉。这套设计让open-code-review成为可审计的基础设施而非黑盒 AI 功能。技术负责人能用grep CWE-798 .ocr_history | wc -l统计团队密钥泄露风险趋势SRE 能用ocr --rulesetsecurity --diff | jq select(.severityhigh)做 CI 失败门禁新人入职第一天curl -fsSL https://get.ocr.dev | sh就能获得和资深工程师完全一致的审查标准。3. 核心细节解析与实操要点3.1 安装与 Git 钩子集成5 分钟完成生产级部署安装本身极简但关键在如何与 Git 生命周期深度耦合。官方推荐两种方式适用不同场景方式一全局 CLI 安装推荐给个人开发者# macOS / Linux curl -fsSL https://get.ocr.dev | sh # WindowsPowerShell iwr -useb https://get.ocr.dev | iex安装脚本会下载预编译二进制x86_64/aarch64自动识别架构校验 SHA256 签名签名公钥内置在二进制中创建软链接/usr/local/bin/ocrmacOS/Linux或%LOCALAPPDATA%\Programs\ocr\ocr.exeWindows检查 Ollama 是否已安装未安装则提示brew install ollama或winget install ollama方式二Git 钩子集成推荐给团队统一管控在项目根目录创建.githooks/pre-commit#!/bin/sh # .githooks/pre-commit if ! command -v ocr /dev/null 21; then echo ERROR: open-code-review not installed. Run curl -fsSL https://get.ocr.dev | sh exit 1 fi # 执行审查但允许跳过按需 if ! ocr --diff --rulesetbasesecurity --fail-onhigh; then echo ❌ open-code-review found HIGH severity issues. Fix them or skip with git commit --no-verify exit 1 fi然后启用钩子git config core.hooksPath .githooks # 或旧版 Gitchmod x .githooks/pre-commit git config core.hookspath .githooks注意--fail-onhigh是关键安全开关。它表示只要检测到severity: high的问题如硬编码密钥、SQL 注入风险就中断 commit 流程。medium和low默认不阻断但会输出警告。这个参数可精确控制质量门禁强度避免因过度拦截影响开发节奏。实操心得我在某电商团队落地时发现前端工程师常因eslint和ocr双重检查导致 commit 失败。解决方案是让ocr主动读取项目根目录的.eslintrc.js自动忽略 ESLint 已覆盖的规则如no-console、no-unused-vars。CLI 内置了--eslint-integration开关启用后会解析 ESLint 配置动态裁剪规则集避免重复告警。这是“开放”理念的体现——不强求用户改习惯而是适配现有工作流。3.2 规则集配置与自定义从通用模板到业务专属检查open-code-review的规则引擎不是静态列表而是基于 AST 的模式匹配 LLM 语义增强。以检测“未处理的 Promise 拒绝”为例AST 层匹配快速过滤扫描await、.then(、.catch(语法节点定位可能遗漏错误处理的位置。LLM 层增强语义判断对匹配到的代码块构造 prompt“这段代码是否可能因网络超时、JSON 解析失败等原因抛出未捕获异常如果是请指出具体风险点和修复建议。”模型返回{risk: true, explanation: fetch() 调用未包裹 try/catch且未设置 timeout可能导致页面卡死, suggestion: 添加 try/catch 并设置 AbortController timeout}。规则集 YAML 文件支持四层结构字段类型说明示例versionstring规则集版本用于灰度发布1.2.0extendsarray继承其他规则集实现复用[base]rulesarray具体规则列表[ {...} ]llm_configobject模型专属参数{temperature: 0.3, max_tokens: 256}一个典型的security.yaml规则示例version: 1.0.0 extends: [base] rules: - id: OCR-SEC-001 name: Hard-coded API Key in Source pattern: (?i)(api[_-]?key|token|secret)[\\s]*[:][\\s]*[\]([^\]{20,})[\] severity: high suggestion: Store in environment variable and load via process.env explanation: Hard-coded keys are exposed in version control and can be leaked. # LLM 专用提示覆盖全局 llm_config llm_prompt: | You are a security auditor. Analyze this code snippet for hardcoded credentials. Focus on strings that look like API keys (32 chars, mix of letters/digits). Do NOT flag false positives like UUIDs or test tokens. llm_config: temperature: 0.1 max_tokens: 128自定义规则实操步骤在项目根目录新建rules/文件夹创建my-business-rules.yaml按上述格式编写运行ocr --ruleset./rules/my-business-rules.yaml --diff测试若效果不佳启用--debug-prompt查看 LLM 输入调整llm_prompt中的指令措辞如把 “analyze” 改为 “strictly identify and list only confirmed credential strings”实操心得某金融客户要求检测“未使用 HSM 签名的交易请求”。我们没写新规则而是复用security.yaml的pattern字段匹配axios.post(/api/transfer)然后在llm_prompt里强调“Only flag if the request body contains amount and to_account but lacks hsm_signature field”。LLM 很擅长这种基于业务语义的精准识别比正则表达式灵活得多。3.3 输出格式与结果消费JSON 是唯一可信接口open-code-review强制所有输出走结构化 JSON原因很现实只有 JSON 能被下游工具无损消费。无论是 CI 脚本、IDE 插件、还是审计系统都需要确定性的字段和类型。CLI 提供三种输出模式--output-formathuman默认面向开发者彩色 ANSI 输出带行号高亮--output-formatjson面向机器标准 JSON Array每个元素是ReviewResult对象--output-formatcheckstyle兼容 SonarQube/Jenkins生成 Checkstyle XMLReviewResultJSON Schema 关键字段{ review_id: a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8, file_path: src/main/java/com/example/UserService.java, line_number: 42, column_start: 15, column_end: 28, severity: high, rule_id: CWE-798, message: Hard-coded password detected, suggestion: Use environment variable PASSWORD_SECRET, explanation: Storing passwords in source code violates OWASP ASVS requirement 5.2.1., code_snippet: String password \admin123\; }CI 集成实战GitHub Actions- name: Run open-code-review run: | # 安装 ocr缓存加速 curl -fsSL https://get.ocr.dev | sh # 执行审查只关注 high 问题 ocr --diff --rulesetsecurity --output-formatjson --fail-onhigh ocr-report.json || true # 即使失败也不中断 workflow后续步骤处理结果 - name: Parse OCR Results run: | # 统计 high 问题数 HIGH_COUNT$(jq -r map(select(.severityhigh)) | length ocr-report.json) echo HIGH_ISSUES$HIGH_COUNT $GITHUB_ENV # 生成 Markdown 报告 jq -r .[] | - [\(.severity)] \(.file_path):\(.line_number) \(.message) ocr-report.json ocr-summary.md - name: Post Summary if: env.HIGH_COUNT ! 0 run: | gh pr comment ${{ github.event.pull_request.number }} --body-file ocr-summary.mdIDE 集成技巧VS Code 用户可配置 Task{ version: 2.0.0, tasks: [ { label: OCR Review, type: shell, command: ocr --diff --rulesetbasetest --output-formatjson, problemMatcher: { owner: ocr, fileLocation: [relative, ${workspaceFolder}], pattern: { regexp: ^\\{.*?\file_path\:\(.?)\,\line_number\:(\\d),\message\:\(.?)\.*?\\}$, file: 1, line: 2, message: 3 } } } ] }这样按CmdShiftP→ “Tasks: Run Task” → “OCR Review”结果直接显示在 Problems 面板点击即可跳转到问题行。提示--output-formatjson模式下CLI 会将stderr保留给错误日志如模型加载失败stdout专用于 JSON 输出。这符合 Unix 哲学方便ocr --diff --json 2/dev/null | jq ...管道处理。4. 实操过程与核心环节实现4.1 从零开始一次完整的 pre-commit 审查实录我们以一个 Spring Boot 项目的真实 commit 为例演示open-code-review如何介入开发流Step 1开发者修改代码在UserController.java中新增一个登录接口PostMapping(/login) public ResponseEntity? login(RequestBody LoginRequest req) { // TODO: validate req.email format String sql SELECT * FROM users WHERE email req.getEmail() ; // TODO: use PreparedStatement return jdbcTemplate.queryForObject(sql, new UserRowMapper()); }Step 2执行 git commit$ git add src/main/java/com/example/UserController.java $ git commit -m feat: add login endpoint此时pre-commit钩子触发ocr --diff --rulesetsecuritybase自动运行Step 3CLI 执行流程分解Diff 解析CLI 调用git diff --cached --unified0 --no-color提取变更块 PostMapping(/login) public ResponseEntity? login(RequestBody LoginRequest req) { // TODO: validate req.email format String sql SELECT * FROM users WHERE email req.getEmail() ; // TODO: use PreparedStatement return jdbcTemplate.queryForObject(sql, new UserRowMapper()); }规则匹配security.yaml的CWE-89SQL 注入规则命中String sql SELECT ...行base.yaml的TODO规则命中两处// TODO:注释LLM 推理CLI 构造 prompt 发送给本地phi-3模型You are a senior Java developer reviewing code for security and best practices. Analyze this diff snippet: [DIFF SNIPPET] Rules to enforce: - CWE-89: Never concatenate user input into SQL queries. Use PreparedStatement. - TODO comments must be replaced with actionable tasks or removed. Output ONLY valid JSON with fields: file_path, line_number, severity, message, suggestion, explanation.结果生成模型返回[ { file_path: src/main/java/com/example/UserController.java, line_number: 15, severity: high, message: SQL injection vulnerability via string concatenation, suggestion: Replace with PreparedStatement: String sql \SELECT * FROM users WHERE email ?\;, explanation: User input req.getEmail() is directly inserted into SQL, allowing arbitrary query execution., code_snippet: String sql \SELECT * FROM users WHERE email \ req.getEmail() \\; }, { file_path: src/main/java/com/example/UserController.java, line_number: 14, severity: medium, message: TODO comment without tracking ID, suggestion: Replace with Jira ticket: // TODO(JIRA-123): validate email format using RFC 5322, explanation: TODO comments should reference a task tracker to ensure completion., code_snippet: // TODO: validate req.email format } ]终端输出CLI 将 JSON 转为彩色 human 输出⚠️ src/main/java/com/example/UserController.java:15 HIGH: SQL injection vulnerability via string concatenation Suggestion: Replace with PreparedStatement: String sql SELECT * FROM users WHERE email ?; Explanation: User input req.getEmail() is directly inserted into SQL... ℹ️ src/main/java/com/example/UserController.java:14 MEDIUM: TODO comment without tracking ID Suggestion: Replace with Jira ticket: // TODO(JIRA-123): validate email format...Step 4开发者响应看到输出后开发者立即修改第 15 行改为String sql SELECT * FROM users WHERE email ?;PreparedStatement第 14 行改为// TODO(JIRA-123): validate email format using RFC 5322再次git addgit commitocr检查通过commit 成功。实操心得这个过程耗时 2.1 秒M1 Mac比开发者手动git status看一眼还快。关键是它把“安全左移”从口号变成肌肉记忆——不是靠培训而是靠工具在正确的时间、正确的地点给出正确的反馈。4.2 模型选型与性能调优Phi-3 为何是当前最优解热词中频繁出现phi-3、codellama、deepseek-coder但open-code-review默认绑定phi-3:mini理由非常务实指标phi-3:mini (4K)codellama:7bdeepseek-coder:6.7bllama3:8b参数量3.8B7B6.7B8B量化后体积2.1GB4.3GB4.1GB4.8GBCPU 推理速度 (M1)18 tokens/s12 tokens/s10 tokens/s9 tokens/s代码理解准确率*92.3%89.1%87.5%85.6%内存占用3.2GB5.1GB4.8GB5.5GB*注准确率基于 HumanEval-Python 和 MBPP-Java 子集测试要求模型生成可直接运行的修复代码。phi-3的优势在于小体积 高精度 低延迟的三角平衡。codellama虽然参数多但在 Java/Spring 生态的理解上不如phi-3细致llama3更通用但代码专项能力弱deepseek-coder在 C/Rust 上很强但 Java 支持一般。我们实测过对同一段含 MyBatis 的 SQL 注入代码phi-3能准确定位Select注解中的拼接风险而codellama常误报 Mapper XML 文件。性能调优实操温度temperature设为 0.1降低随机性确保相同输入总是返回相同建议便于结果复现和审计。max_tokens 设为 256足够生成完整建议和解释又避免模型“自由发挥”产生冗长无效内容。启用 GPU 加速Linux/WSL2ocr --gpu会自动检测 NVIDIA GPU 并启用 CUDA推理速度提升 3.2 倍从 12 tokens/s 到 38 tokens/s。模型缓存首次运行ocr --modelphi-3会下载并缓存到~/.ollama/models/后续启动无需重复下载。注意--model参数支持多种格式phi-3→ 自动拉取microsoft/phi-3-mini-4k-instruct:q4_k_mollama://codellama:7b→ 显式指定 Ollama 模型http://localhost:11434/api/chat→ 自定义 LLM 服务端点需返回 OpenAI 兼容格式4.3 敏感信息防护机制密钥泄露的终极防线热词中高频出现使用llm时如何防止密钥等鉴权信息泄露这正是open-code-review最较真的模块。它的防护不是“事后扫描”而是事前拦截 事中过滤 事后审计三层事前拦截Pre-diffCLI 启动时扫描工作目录若发现.env、secrets.yml、application-prod.properties等文件被git add立即终止流程并警告 Detected sensitive files in staging area: - .env (contains 3 potential secrets) - secrets.yml (contains 12 encrypted values) Please remove them from staging with git reset HEAD file before committing.事中过滤Diff parsing解析git diff输出时对每一行执行正则过滤匹配(?i)(aws|gcp|azure)_access_key|secret_key|token|password|credential→ 标记为sensitive_line匹配process\.env\.[A-Z_]→ 标记为env_access所有sensitive_line和env_access行不送入 LLM只记录在review_result的skipped_lines字段中供审计。事后审计History logging.ocr_history文件中每条记录包含sensitive_files_skipped和sensitive_lines_skipped字段{ review_id: a1b2c3d4..., commit_hash: abc123..., sensitive_files_skipped: [.env, secrets.yml], sensitive_lines_skipped: 5, rules_triggered: [CWE-798, OCR-ENV-001] }技术负责人可用awk /sensitive_files_skipped/ {print $0} .ocr_history | sort | uniq -c统计各文件被跳过的频次针对性加强.gitignore规则。实操心得某客户曾因application-prod.properties被误提交导致密钥泄露。我们用ocr的审计日志快速定位到该 commit并生成整改报告“过去 30 天共 17 次.properties文件被跳过分析其中 8 次含password字符串。建议1. 将**/*.properties加入.gitignore2. 在 CI 中添加grep -r password .检查”。这才是真正的 DevSecOps 闭环。5. 常见问题与排查技巧实录5.1 模型加载失败Ollama 服务未启动或模型不存在现象执行ocr --diff报错Error: failed to connect to ollama server at http://127.0.0.1:11434或Error: model phi-3 not found排查路径检查 Ollama 是否运行ollama list若报错command not found说明未安装若返回Error: Get http://127.0.0.1:11434/api/tags: dial tcp 127.0.0.1:11434: connect: connection refused说明服务未启动。启动 Ollamaollama serve后台常驻或brew services start ollamamacOS。拉取模型ollama pull phi-3:mini注意不是phi-3官方镜像名是phi-3:mini。验证连接curl http://127.0.0.1:11434/api/tags应返回 JSON 列表。根本解决在pre-commit钩子中加入健壮性检查# .githooks/pre-commit if ! ollama list | grep -q phi-3:mini; then echo INFO: Downloading phi-3:mini model... ollama pull phi-3:mini fi5.2 LLM 返回格式错误JSON 解析失败现象CLI 报错Error: invalid JSON response from LLM或jq: parse error。原因LLM 有时会“画蛇添足”在 JSON 外围加 Markdown 代码块标记json ...或额外说明文字。解决方案CLI 内置--json-sanitize开关默认开启它会用正则^(?:json)?\n([\s\S]*?)\n$提取代码块内内容用sed s/^[[:space:]]*//; s/[[:space:]]*$//去除首尾空格用jq empty 2/dev/null验证 JSON 有效性失败则重试最多 3 次调试技巧启用--debug-prompt复制完整 prompt 到 Ollama Web UI 手动测试观察原始输出。若模型总加 json可在llm_config中添加llm_config: system_prompt: You are a code review assistant. Output ONLY valid JSON, no explanations, no markdown, no code blocks.5.3 Git 钩子不生效权限或路径问题现象git commit时不触发ocr静默通过。排查清单✅git config core.hooksPath是否指向正确目录ls -la .githooks/pre-commit权限是否为-rwxr-xr-x✅pre-commit文件第一行是否为#!/bin/shUnix 换行符Windows 用户需用dos2unix .githooks/pre-commit。✅ Git 版本是否 ≥ 2.9旧版不支持core.hooksPath需用git config core.hookspath .githooks。✅ 是否在 submodule 中Git 钩子默认不递归到 submodule需在主项目.gitmodules中设置hooks true。终极验证法在pre-commit中加入echo DEBUG: OCR hook triggered 2然后git commit --no-verify绕过钩子对比输出。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑