
1. 项目概述这不是又一个代码审查工具而是一次开发工作流的底层重定义“open-code-review”这个名称乍看平平无奇甚至有点像某个被遗忘在 GitHub 某个角落的冷门仓库名。但如果你最近刷过技术社区、看过几篇关于 LLM Agent 的实操笔记或者被团队里那个总在 Slack 里发“codex cli review --pr123”命令的人问得哑口无言那你大概率已经站在了这场静默变革的边缘——它不是把 AI 塞进 IDE 插件里再加个“智能”前缀而是把代码审查这件事从“人对人”的协作仪式彻底还原成“机器可理解、可调度、可验证”的原子操作。我从去年底开始在三个不同规模的项目中落地这套逻辑最深的体会是真正的 open不在于源码是否开源而在于审查意图能否被结构化表达、审查过程能否被 CLI 精确编排、审查结果能否被 Git diff 精准锚定。它直击现代工程中最顽固的断层PR 描述写得天花乱坠但 reviewer 看到的只是 47 行新增 12 行删除AI 模型能生成惊艳的函数却无法解释为什么不该用Array.prototype.flat()处理嵌套深度超过 3 层的数据飞书机器人推送了一条“安全风险提示”点进去却发现上下文缺失连哪行代码触发的都找不到。而 open-code-review 的核心价值就是用一套轻量但严丝合缝的 CLI 协议把“谁在什么上下文里基于什么规则对哪段 diff 做了什么判断”这件事变成可追溯、可复现、可自动化串联的工程事实。它适合两类人一类是正在被 PR 海啸淹没的 Tech Lead需要把 Code Review 从“靠经验、靠记忆、靠催促”的黑盒状态变成可度量、可拆解、可沉淀的团队能力另一类是刚接触 LLM Agent 概念的工程师想跳过那些堆砌术语的理论文章直接上手构建一个真正能嵌入日常开发节奏的 AI 协作节点——不是调用 API而是让 AI 成为git commit后自动触发的一个确定性环节。2. 核心设计思路为什么必须绕开 IDE 插件和 Web UI死磕 CLI 与 Git Diff2.1 选择 CLI 作为唯一入口不是为了复古而是为了“可编程性”很多人第一反应是“又要敲命令现在不是都流行点点点吗” 这恰恰是 open-code-review 最关键的设计分水岭。我试过把同类功能封装成 VS Code 插件也搭过简易 Web UI结果无一例外地卡死在三个地方上下文割裂、权限失控、流程不可控。举个真实例子某次紧急修复前端同学在本地改完utils/date.js顺手点了插件里的“提交审查”插件却只把当前文件发给了模型而完全没带上package.json里date-fns的版本号、也没带上src/api/index.ts里调用该工具函数的上下文。模型给出的建议是“使用Intl.DateTimeFormat替代”这在 v2.30 版本里完全正确但团队锁死的是 v2.16这个版本里Intl.DateTimeFormat缺少timeZoneName支持——插件无法感知这个约束因为它的“视野”被 IDE 的文件树框死了。而 CLI 方案完全不同open-code-review --diff $(git diff HEAD~1 -- utils/date.js)这条命令天然携带了完整的 Git 差异快照。我们可以在 CLI 内部做三件事第一解析 diff 元数据提取出变更涉及的文件、行号、前后内容第二根据预设规则比如.reviewrc配置自动拉取这些文件的依赖声明、CI 配置、甚至历史审查记录第三把这些结构化信息连同 diff 本身打包成一个严格定义的 JSON Schema 输入给 LLM Agent。这个过程没有“点击”带来的随意性只有命令参数决定的确定性输入。CLI 的本质是把审查行为降维成一个可脚本化的函数调用input → process → output的边界清晰到可以写进 CI 脚本里。你甚至可以用find . -name *.ts -mtime -1 | xargs -I {} open-code-review --file {}这样的管道命令批量审查昨天所有修改的 TypeScript 文件——这种灵活性任何图形界面都无法提供。2.2 Git Diff 是唯一可信的“事实锚点”而非文件路径或 PR ID另一个常被忽视的致命陷阱是把审查对象绑定在“文件”或“PR”上。open-code-review --pr123看起来很直观但它隐含了一个危险假设PR 123 的代码状态是静态且唯一的。现实是残酷的PR 可能被 rebase、force push、甚至被合并后又 revert。上周我就遇到一个 case一位同事在 PR 评论里写道“utils/date.js第 45 行的时区处理有 bug”但当我们去查时那行代码早已被后续提交覆盖原始 diff 记录也因 rebase 而丢失。而 Git Diff 不同它是时间切片的快照是 Git 世界里最基础、最不可篡改的“事实”。open-code-review的核心协议强制要求所有审查请求必须附带一个可解析的 diff 字符串支持标准git diff输出格式或一个指向 diff 的 URL如 GitHub/GitLab 的 patch 链接。这意味着无论代码库如何演进只要 diff 存在审查的上下文就永远可重现。我们内部有个小技巧在 CI 流程里每次git push后自动执行git diff HEAD~1 /tmp/review-$(git rev-parse --short HEAD).patch然后把这个 patch 文件上传到内部对象存储并生成一个带签名的短链接。open-code-review --diff-url https://review.internal/abc123.patch这样的命令就能确保审查永远基于那个精确的、不可变的变更快照。这背后是工程哲学的转变不再信任“当前状态”只信任“变更本身”。Diff 就是代码世界的“事件日志”而 open-code-review就是专门消费这种日志的处理器。2.3 LLM Agent 的角色定位不是“更聪明的 reviewer”而是“可配置的审查协作者”这里必须厘清一个高频混淆点open-code-review 里的 LLM Agent和你在 ChatGPT 里问“帮我 review 这段代码”有本质区别。前者是一个受控的、有明确输入输出契约、具备领域知识注入能力的专用协作者后者是一个通用对话引擎它的“review”行为是启发式的、不可预测的。我见过太多团队踩坑把 LLM 当成万能胶水直接把整个 PR 的 diff 文本塞给模型指望它自己总结问题。结果要么是泛泛而谈“代码可读性有待提升”要么是揪住一个微不足道的命名风格问题却漏掉了关键的并发安全漏洞。open-code-review 的 Agent 设计核心是“分治”与“引导”。它不负责端到端的审查结论而是被拆解为多个可插拔的“审查专家”security-expert专注识别硬编码密钥、SQL 注入模式perf-expert基于 AST 分析循环嵌套和内存分配i18n-expert检查字符串硬编码和日期格式化。每个专家都有自己的 prompt 模板、输入 schema例如只接收包含context: { file, line, code_snippet }的 JSON、输出 schema例如必须返回{ severity: high|medium|low, message: string, suggestion: string }。Agent 的“智能”体现在它能根据 diff 的特征比如检测到crypto相关 import就自动激活security-expert检测到for (let i 0; i arr.length; i)模式就调用perf-expert而不是凭空发挥。这就像一个经验丰富的 Tech Lead他不会在没看到具体代码前就下结论而是先快速扫描变更类型再调用自己脑子里对应的检查清单。LLM 在这里是执行这份清单的高效“手”而不是制定清单的“脑”。3. 核心实现细节从零搭建一个可运行的 open-code-review CLI3.1 架构全景三层分离各司其职要让 open-code-review 真正落地不能只停留在概念。我基于半年多的生产环境迭代提炼出一个稳定、易维护的三层架构它不依赖任何特定云服务纯本地可运行┌─────────────────────────────────────────────────────────────────────┐ │ CLI Interface Layer │ │ • 解析命令行参数--diff, --file, --config, --output-format │ │ • 验证输入合法性diff 格式校验、文件存在性检查 │ │ • 加载用户配置.reviewrc │ │ • 调用 Core Engine 并传递结构化输入 │ └─────────────────────────────────────────────────────────────────────┘ ↓ (JSON-RPC 或进程间通信) ┌─────────────────────────────────────────────────────────────────────┐ │ Core Engine Layer │ │ • Diff Parser将 git diff 文本解析为结构化变更列表 │ │ [ { file: src/utils/date.js, type: modified, │ │ additions: [{line: 45, content: return new Date(...)}, ...], │ │ deletions: [...] } ] │ │ • Context Loader根据变更文件自动收集关联上下文 │ │ - package.json 依赖版本 │ │ - tsconfig.json 类型检查配置 │ │ - .eslintrc.js 规则集 │ │ - 历史审查记录通过 git log -p 查找 │ │ • Agent Orchestrator根据变更特征路由到对应 Expert Agent │ │ • Result Aggregator合并各 Expert 输出生成统一报告 │ └─────────────────────────────────────────────────────────────────────┘ ↓ (HTTP API 或本地模型调用) ┌─────────────────────────────────────────────────────────────────────┐ │ Expert Agent Layer │ │ • 每个 Expert 是一个独立的、可热替换的模块 │ │ • 输入严格定义的 JSON Schema含 diff 片段 上下文 │ │ • 处理调用本地 LLMOllama或远程 APIOpenAI/Claude │ │ • 输出强制符合预定义 Schema 的 JSON含 severity/message/suggestion │ │ • 示例 Prompt 模板security-expert │ │ 你是一名资深安全工程师。请严格基于以下代码片段和上下文 │ │ 识别是否存在硬编码密钥、明文密码或敏感信息泄露风险。 │ │ 仅返回 JSON格式{severity: high|medium|low, │ │ message: 描述问题, suggestion: 具体修复建议}。 │ │ 不要添加任何额外解释或 markdown。 │ └─────────────────────────────────────────────────────────────────────┘这个架构的关键在于解耦。CLI 层只管“怎么用”Core Engine 层只管“怎么分析”Expert Agent 层只管“怎么判断”。当你要接入新的 LLM比如从 OpenAI 切换到 Claude只需修改 Agent 层的调用逻辑其他两层完全不动。当你要增加一个新的审查维度比如“无障碍访问合规性”只需编写一个新的a11y-expert模块注册到 Orchestrator 即可。这种设计让 open-code-review 从一个“工具”变成了一个可生长的“审查平台”。3.2 Diff Parser 的实现超越正则拥抱 Git 的原生语义很多人以为解析git diff就是写几个正则表达式匹配和-行。这在简单场景下可行但在真实工程中会迅速崩溃。比如一个 diff 可能包含二进制文件Binary files a/src/logo.png and b/src/logo.png differ可能包含重命名rename from src/old.js\nrename to src/new.js可能包含大段的 -1,5 1,8 头信息。我们最初用正则结果在处理一个包含 200 行的 CSS 文件 diff 时把/* comment */里的符号也当成了新增行导致整个审查错乱。后来我们彻底转向 Git 的原生能力直接调用git apply --stat --summary和git diff --no-color --unified0。--unified0参数是关键它让 diff 输出只显示变更的行号和内容不显示无关的上下文极大简化了解析逻辑。我们的 Parser 核心代码Python如下import subprocess import re from typing import List, Dict, Any def parse_git_diff(diff_text: str) - List[Dict[str, Any]]: 解析 git diff 输出返回结构化变更列表。 使用 --unified0 格式确保每行变更都带有精确的文件名和行号。 changes [] current_file None # 匹配 diff 头diff --git a/src/utils/date.js b/src/utils/date.js file_pattern rdiff --git a/(.*) b/(.*) # 匹配行号信息 -12,5 15,8 hunk_pattern r -(\d),?(\d)? \(\d),?(\d)? lines diff_text.split(\n) for line in lines: # 处理文件头 if line.startswith(diff --git): match re.search(file_pattern, line) if match: # 取 b/ 后面的路径即新文件路径 current_file match.group(2) continue # 处理变更块头 elif line.startswith(): match re.search(hunk_pattern, line) if match and current_file: # 新增行起始行号 new_start int(match.group(3)) # 新增行数如果未指定默认为1 new_count int(match.group(4)) if match.group(4) else 1 # 下一行就是实际的新增内容 # 我们在这里只记录起始位置具体内容在后续循环中捕获 # 实际生产代码中会维护一个 buffer 来收集接下来的 行 pass # 处理新增行 elif line.startswith() and not line.startswith(): if current_file and not line.startswith() and not line.startswith(import): # 过滤掉 git 添加的文件头 b/src/utils/date.js和 import 语句 # 提取实际代码内容去掉 号 content line[1:].strip() if content and not content.startswith(//) and not content.startswith(/*): # 只处理非注释的代码行 changes.append({ file: current_file, type: addition, line: new_start, # 这里需要更复杂的逻辑来跟踪行号简化示意 content: content }) return changes这段代码的核心思想是不试图用正则“理解” diff而是利用 Git 自己生成的、语义明确的格式做精准的字符串匹配和提取。它牺牲了一点通用性强依赖git diff --unified0的输出但换来了 99.9% 场景下的绝对可靠性。这也是 open-code-review “务实”哲学的体现不追求理论上的完美只解决工程师每天真实面对的问题。3.3 Context Loader 的实战技巧让 AI 看懂你的项目LLM 的幻觉hallucination问题在代码审查中尤为致命。它可能“自信满满”地告诉你Array.from({length: 10}, (_, i) i)是低效的却不知道你的项目里babel-preset-env已经将此语法转译为高效的 for 循环。Context Loader 的使命就是喂给 AI 它真正需要的、项目专属的“常识”。我们不搞大而全的信息轰炸而是聚焦三个黄金上下文源依赖图谱Dependency Graph通过npm ls --json或pipdeptree --json-tree获取解析出utils/date.js所依赖的date-fns版本如date-fns: ^2.16.1并将其作为context.dependencies字段注入。这样security-expert在看到require(crypto)时就能结合node版本从engines字段获取判断是否应推荐webcryptoAPI。构建与测试配置Build Test Config自动读取tsconfig.json、.eslintrc.js、jest.config.js。例如如果tsconfig.json中strict为true那么perf-expert在发现any类型时就会将 severity 提升为high因为这直接违反了项目的核心类型策略。历史审查知识库Historical Review Knowledge这是最具巧思的一环。我们用git log -p -S new Date( --since3 months ago src/utils/date.js命令搜索过去三个月内所有对date.js中new Date(的修改。然后用一个轻量级的 embedding 模型如all-MiniLM-L6-v2对这些历史 diff 的摘要进行向量化并存入本地 SQLite 数据库。当新的 diff 提交时CLI 会计算其摘要的 embedding查询数据库中相似度最高的 3 条历史记录并将它们的审查结论如“此处时区处理需兼容 IE11”作为context.history注入。这相当于给 AI 配备了一个“团队记忆”让它能从过往的集体经验中学习而不是每次都从零开始“发明轮子”。提示Context Loader 的性能至关重要。我们采用“懒加载”策略只在某个 Expert Agent 明确声明需要某类上下文如security-expert需要dependencies时才去执行相应的加载逻辑。避免为一次审查请求无谓地扫描整个node_modules。3.4 Agent Orchestrator 的路由逻辑让审查像流水线一样精准Orchestrator 是 open-code-review 的“大脑”它的核心任务不是思考而是决策针对当前 diff应该启动哪些 Expert以什么顺序用什么参数。我们摒弃了简单的“if-else”链采用一种基于“变更指纹Change Fingerprint”的动态路由机制。指纹由三部分组成语言指纹Language Fingerprint通过文件扩展名和 shebang 行如#!/usr/bin/env node确定。date.js→javascriptDockerfile→dockerfilepyproject.toml→python。变更模式指纹Pattern Fingerprint对 diff 内容进行轻量级 NLP 分析。我们维护一个小型的关键词-专家映射表[crypto, AES, RSA, secret]→security-expert[for, while, map, filter, reduce]→perf-expert[t(, i18n.t, useTranslation]→i18n-expert[test(, it(, describe(]→test-expert影响范围指纹Scope Fingerprint根据 diff 修改的文件路径和数量判断。如果只修改了src/utils/date.js属于“局部变更”如果同时修改了src/utils/date.js,src/api/index.ts,tests/date.test.ts则标记为“跨域变更”Orchestrator 会强制启用cross-domain-expert专门检查接口契约一致性。路由算法伪代码如下def route_experts(diff_changes: List[Dict]) - List[str]: fingerprints { language: detect_language(diff_changes), patterns: detect_patterns(diff_changes), scope: calculate_scope(diff_changes) } # 初始化专家列表 experts set() # 语言是基础必须启用 experts.add(f{fingerprints[language]}-expert) # 根据模式添加 for pattern in fingerprints[patterns]: if pattern in PATTERN_TO_EXPERT_MAP: experts.add(PATTERN_TO_EXPERT_MAP[pattern]) # 根据范围添加 if fingerprints[scope] cross-domain: experts.add(cross-domain-expert) # 强制启用核心专家 experts.add(core-style-expert) # 检查基础代码风格 return list(experts) # 示例一个修改了 date.js含 crypto和 Dockerfile 的 diff # fingerprints {language: javascript, patterns: [crypto], scope: local} # 返回: [javascript-expert, security-expert, core-style-expert]这种设计让审查过程变得极其透明。你可以通过open-code-review --debug --diff my.patch命令看到详细的路由日志“[ROUTER] Detected language: javascript → loading javascript-expert”, “[ROUTER] Detected pattern: crypto → loading security-expert”。这不仅是调试利器更是团队建立审查共识的基础——每个人都能看到AI 的“判断”并非玄学而是基于可审计、可复现的规则。4. 实操全流程从安装到嵌入 CI一次完整的审查闭环4.1 五分钟快速上手本地 CLI 安装与首次运行别被前面的架构吓到open-code-review 的设计哲学是“开箱即用渐进增强”。你不需要成为 LLM 专家也能在五分钟内跑通第一个审查。以下是我在 macOS 和 Ubuntu 上验证过的、最简路径第一步安装 CLI无需 Node.js 或 Python 环境我们提供了预编译的二进制文件直接下载即可# 创建安装目录 mkdir -p ~/bin cd ~/bin # 下载macOS ARM64 curl -L https://github.com/open-code-review/releases/download/v0.3.1/ocr-darwin-arm64 -o ocr # 或下载Ubuntu x64 # curl -L https://github.com/open-code-review/releases/download/v0.3.1/ocr-linux-amd64 -o ocr # 赋予执行权限 chmod x ocr # 添加到 PATH写入 ~/.zshrc 或 ~/.bashrc echo export PATH$HOME/bin:$PATH ~/.zshrc source ~/.zshrc第二步准备一个测试 diff找一个你本地项目中最近的一次小修改生成一个干净的 patch# 假设你刚改了 src/utils/date.js git diff HEAD~1 -- src/utils/date.js test.patch第三步运行第一次审查# 最简命令使用默认配置和内置的 Ollama 模型需提前安装 Ollama ocr --diff test.patch # 如果你更习惯用 OpenAI可以这样 ocr --diff test.patch --model openai:gpt-4-turbo --api-key sk-xxx # 输出会是结构化的 JSON但为了可读CLI 默认格式化为 Markdown 报告 # ┌───────────────────────────────────────────────────────────────────┐ # │ open-code-review Report │ # │ Commit: abc123 (HEAD~1) │ # │ File: src/utils/date.js │ # ├───────────────────────────────────────────────────────────────────┤ # │ [HIGH] Security Risk │ # │ Message: Hardcoded API key found in environment variable access. │ # │ Suggestion: Use a secrets manager or environment-specific config. │ # │ Line: 45 │ # │ │ # │ [MEDIUM] Performance │ # │ Message: new Date().getTime() is less efficient than Date.now().│ # │ Suggestion: Replace with Date.now(). │ # │ Line: 22 │ # └───────────────────────────────────────────────────────────────────┘这就是全部。你不需要配置任何东西CLI 会自动为你加载package.json、tsconfig.json并调用一个轻量级的本地模型Ollama 的phi3:mini完成审查。整个过程耗时通常在 3-8 秒取决于 diff 大小和模型响应速度。4.2 配置驱动用.reviewrc文件定制你的审查规则CLI 的默认行为是“安全第一”但每个团队都有自己的“代码宪法”。.reviewrc就是你的宪法起草委员会。它是一个 YAML 文件放在项目根目录下ocr会自动加载。下面是一个典型配置展示了如何精细控制# .reviewrc # 全局设置 global: # 审查超时时间秒 timeout: 30 # 是否启用历史知识库 enable_history: true # 默认使用的 LLM 模型 default_model: ollama:phi3:mini # 专家Expert配置 experts: # 安全专家 security-expert: # 启用的检查项 enabled_checks: - hardcoded_secrets - sql_injection - xss_vulnerability # 禁用的检查项例如团队已决定不检查 XSS disabled_checks: - xss_vulnerability # 性能专家 perf-expert: # 对于大型数组操作阈值设为 1000 array_size_threshold: 1000 # 禁用对 map 的审查团队认为其可读性优先 disable_map_check: true # 风格专家 core-style-expert: # 严格遵循 ESLint 规则 eslint_config: .eslintrc.js # 忽略某些文件 ignore_files: - **/node_modules/** - **/dist/** # 自定义规则Custom Rules custom_rules: # 规则ID - id: no-console-in-prod # 触发条件在非测试文件中出现 console.log condition: | file !~ /test\.js$/ content ~ /console\.log\(/ # 违反时的严重等级 severity: high # 建议 suggestion: Use a logging library like winston or pino with environment-aware levels.这个配置文件的强大之处在于它把原本分散在不同地方的规则ESLint、团队 Wiki、Code Review Checklist统一到了一个地方。当你运行ocr --diff test.patch时CLI 会读取这个文件动态调整所有 Expert 的行为。更重要的是这个文件本身就是代码的一部分会被 Git 跟踪、Code Review、版本管理。新成员加入时git clone下来ocr就自动拥有了团队的全部审查智慧无需任何口头传授。4.3 深度集成将 open-code-review 嵌入你的 CI/CD 流水线CLI 的终极形态是成为 CI 流水线中一个沉默而可靠的守门人。我们以 GitHub Actions 为例展示如何实现“无人值守的自动化审查”。这个方案不替代人工 Review而是把重复、机械、高风险的检查前置让人 Review 的精力聚焦在更高阶的设计和权衡上。第一步创建.github/workflows/code-review.ymlname: Open Code Review on: pull_request: types: [opened, synchronize, reopened] # 只对特定分支触发 branches: [main, develop] jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 with: # 必须获取完整的历史以便 Context Loader 查询历史 fetch-depth: 0 - name: Setup Node.js uses: actions/setup-nodev4 with: node-version: 18 - name: Install open-code-review CLI run: | curl -L https://github.com/open-code-review/releases/download/v0.3.1/ocr-linux-amd64 -o ocr chmod x ocr sudo mv ocr /usr/local/bin/ - name: Run open-code-review on PR diff # 关键使用 GitHub 提供的 PR diff URL run: | # 获取 PR 的 patch URL PATCH_URLhttps://github.com/${{ github.repository }}/pull/${{ github.event.number }}.patch # 执行审查输出为 JSON便于后续解析 ocr --diff-url $PATCH_URL --output-format json review-report.json 2 review-error.log || true - name: Post review comments to PR # 使用一个轻量级的 Action 来解析 JSON 并发布评论 # 这里用一个自研的 action也可以用社区的 peter-evans/create-or-update-comment uses: ./actions/post-review-comments with: # 传入生成的报告 report-path: review-report.json # GitHub Token用于发布评论 token: ${{ secrets.GITHUB_TOKEN }}第二步理解审查报告的结构与 CI 反馈ocr生成的review-report.json是一个标准的 JSON 数组每个元素代表一个发现的问题[ { id: security-hardcoded-secret, file: src/utils/auth.js, line: 32, severity: high, message: Hardcoded API key detected., suggestion: Move to environment variable and use process.env.API_KEY., expert: security-expert }, { id: perf-array-map, file: src/components/List.jsx, line: 88, severity: medium, message: Using map() on large arrays may cause performance issues., suggestion: Consider using a for loop or virtualized list., expert: perf-expert } ]我们的post-review-commentsAction 会遍历这个数组为每个high级别的问题在对应的文件和行号上发布一条 GitHub 评论。效果如下Comment onsrc/utils/auth.jsline 32open-code-review (security-expert)Hardcoded API key detected. Move to environment variable and use process.env.API_KEY.这个评论不是来自某个机器人账号而是由ocr生成、由 CI 流水线自动发布的它带着精确的上下文和可操作的建议。最关键的是它不会阻断 CI。我们刻意设计为|| true即审查失败也不让 CI 失败。因为 open-code-review 的定位是“辅助”不是“裁判”。它的价值在于把问题暴露出来把讨论引向正确的方向而不是用一个exit 1去制造冲突。真正的“门禁”依然由人工 Reviewer 和合并策略如 require 2 approvals来把守。4.4 高级技巧与飞书、钉钉等 IM 工具联动让审查触手可及审查的最终目的是“发现问题”而问题最有效的传播渠道往往是工程师最常驻留的地方——即时通讯工具。我们实现了与飞书Feishu的深度集成让审查报告不再是埋在 CI 日志里的几行文字而是主动推送到你的飞书群聊中。实现原理很简单在飞书开发者后台创建一个 Bot获取App ID和App Secret。在你的 CI 流水线中ocr审查完成后调用飞书开放平台的send_messageAPI。将review-report.json中的high和medium级别问题格式化为飞书富文本卡片Card发送到指定群组。飞书卡片的核心代码Pythonimport requests import json def send_feishu_card(webhook_url: str, report: List[Dict]): # 过滤出 high/medium 问题 issues [issue for issue in report if issue[severity] in [high, medium]] if not issues: return # 构建飞书卡片消息体 card { msg_type: interactive, card: { elements: [ { tag: div, text: { content: f **open-code-review 发现 {len(issues)} 个待关注问题**\n\n, tag: lark_md } } ], header: { title: { content: 代码审查警报, tag: plain_text } } } } # 为每个问题添加一个 div 元素 for issue in issues[:5]: # 最多显示前5个 card[card][elements].append({ tag: div, fields: [ { is_short: True, text: { content: f**文件:** {issue[file]}, tag: lark_md } }, { is_short: True, text: { content: f**行号:** {issue[line]}, tag: lark_md } } ] }) card[card][elements].append({ tag: div, text: { content: f {issue[message]}\n *建议:* {issue[suggestion]}, tag: lark_md } }) # 发送请求 requests.post(webhook_url, jsoncard) # 在 CI 脚本中调用 # send_feishu_card(https://open.feishu.cn/open-apis/bot/v2/hook/xxx, report_data)效果是震撼的当一个 PR