[{"data":1,"prerenderedAt":13626},["ShallowReactive",2],{"header-counts":3,"playbook-onboarding\u002Fterminal-agent-stack-2026":6,"footer-counts":757,"playbook-tools-onboarding\u002Fterminal-agent-stack-2026":758,"pb-all":4335},{"tools":4,"reviews":5},67,7,{"id":7,"title":8,"body":9,"category":740,"cover":741,"description":742,"extension":242,"meta":743,"navigation":259,"path":744,"published":745,"relatedTools":746,"seo":751,"stem":752,"tags":753,"updated":745,"__hash__":756},"playbook\u002Fplaybook\u002Fonboarding\u002Fterminal-agent-stack-2026.md","2026 终端 AI Agent 怎么选：Claude Code \u002F Codex \u002F Gemini CLI \u002F Aider 工作流",{"type":10,"value":11,"toc":724},"minimark",[12,16,20,36,39,144,150,161,165,168,235,238,398,401,405,410,413,434,437,441,444,450,453,457,460,466,469,473,476,521,524,528,531,552,555,569,573,576,582,585,589,595,598,657,660,663,705,708,711,717,720],[13,14,15],"h2",{"id":15},"适用场景",[17,18,19],"p",{},"这篇不是「哪个 Agent 最强」的排行榜，而是一套现实可用的终端 AI Agent 工作流。适合：",[21,22,23,27,30,33],"ul",{},[24,25,26],"li",{},"已经会用 Cursor \u002F Copilot，但想把 AI 编程搬到终端的人",[24,28,29],{},"需要在服务器、SSH、容器、Windows 原生环境里跑 Agent 的开发者",[24,31,32],{},"团队想把 AI Agent 接入 repo 规范、MCP 工具、测试闭环",[24,34,35],{},"预算有限，想混用免费额度、订阅额度和 BYOK 模型的人",[13,37,38],{"id":38},"结论先行",[40,41,42,61],"table",{},[43,44,45],"thead",{},[46,47,48,52,55,58],"tr",{},[49,50,51],"th",{},"任务",[49,53,54],{},"首选",[49,56,57],{},"备选",[49,59,60],{},"原因",[62,63,64,79,91,105,118,131],"tbody",{},[46,65,66,70,73,76],{},[67,68,69],"td",{},"长时间重构 \u002F 多文件改造",[67,71,72],{},"Claude Code",[67,74,75],{},"Codex CLI",[67,77,78],{},"长任务规划和上下文连续性强",[46,80,81,84,86,88],{},[67,82,83],{},"已订阅 ChatGPT Plus\u002FPro",[67,85,75],{},[67,87,72],{},[67,89,90],{},"额度打包，Windows 原生体验好",[46,92,93,96,99,102],{},[67,94,95],{},"大仓库阅读 \u002F 查新资料",[67,97,98],{},"Gemini CLI",[67,100,101],{},"Aider",[67,103,104],{},"1M 上下文 + Google Search grounding",[46,106,107,110,112,115],{},[67,108,109],{},"接国产模型 \u002F 私有 endpoint",[67,111,101],{},[67,113,114],{},"Cline \u002F Continue",[67,116,117],{},"OpenAI-compatible endpoint 最灵活",[46,119,120,123,125,128],{},[67,121,122],{},"低成本 issue triage",[67,124,98],{},[67,126,127],{},"Codex mini",[67,129,130],{},"免费额度大，headless 脚本友好",[46,132,133,136,139,141],{},[67,134,135],{},"生产仓库改代码",[67,137,138],{},"Claude Code \u002F Codex",[67,140,101],{},[67,142,143],{},"沙箱、权限、工具链更完整",[17,145,146],{},[147,148,149],"strong",{},"AIHO 推荐默认组合：",[151,152,158],"pre",{"className":153,"code":155,"language":156,"meta":157},[154],"language-text","Claude Code \u002F Codex CLI：主力改代码\nGemini CLI：查新资料 + 大上下文阅读 + 第二意见\nAider：接国内模型 \u002F 私有模型 \u002F 成本兜底\nMCP：统一接 GitHub、数据库、内部工具\n","text","",[159,160,155],"code",{"__ignoreMap":157},[13,162,164],{"id":163},"第一步先给项目写-agent-记忆","第一步：先给项目写 Agent 记忆",[17,166,167],{},"不同工具的项目记忆文件不同，但内容应该一致：",[40,169,170,180],{},[43,171,172],{},[46,173,174,177],{},[49,175,176],{},"工具",[49,178,179],{},"项目记忆文件",[62,181,182,191,200,214,224],{},[46,183,184,186],{},[67,185,72],{},[67,187,188],{},[159,189,190],{},"CLAUDE.md",[46,192,193,195],{},[67,194,98],{},[67,196,197],{},[159,198,199],{},"GEMINI.md",[46,201,202,205],{},[67,203,204],{},"GitHub Copilot",[67,206,207,210,211],{},[159,208,209],{},"AGENTS.md"," \u002F ",[159,212,213],{},".github\u002Fcopilot-instructions.md",[46,215,216,218],{},[67,217,75],{},[67,219,220,223],{},[159,221,222],{},".codex\u002F"," \u002F team config",[46,225,226,229],{},[67,227,228],{},"Cursor",[67,230,231,234],{},[159,232,233],{},".cursorrules"," \u002F project rules",[17,236,237],{},"建议模板：",[151,239,243],{"className":240,"code":241,"language":242,"meta":157,"style":157},"language-md shiki shiki-themes github-light github-dark","# Project Guide for AI Agents\n\n## Tech stack\n- Nuxt 4 + Vue 3 + TypeScript\n- pnpm workspace\n- @nuxt\u002Fcontent for markdown content\n\n## Commands\n- Install: pnpm install\n- Typecheck: pnpm run typecheck\n- Build: pnpm run build\n\n## Conventions\n- Do not commit automatically.\n- Keep frontmatter schema consistent with content.config.ts.\n- Before changing many files, explain the plan first.\n- After editing, run the smallest relevant verification command.\n\n## Pitfalls\n- Do not run build while dev server is running on Windows.\n- Do not edit generated .output or .nuxt files.\n","md",[159,244,245,254,261,267,278,286,294,298,304,312,320,328,333,339,347,355,363,371,376,382,390],{"__ignoreMap":157},[246,247,250],"span",{"class":248,"line":249},"line",1,[246,251,253],{"class":252},"sq-ep","# Project Guide for AI Agents\n",[246,255,257],{"class":248,"line":256},2,[246,258,260],{"emptyLinePlaceholder":259},true,"\n",[246,262,264],{"class":248,"line":263},3,[246,265,266],{"class":252},"## Tech stack\n",[246,268,270,274],{"class":248,"line":269},4,[246,271,273],{"class":272},"s4XuR","-",[246,275,277],{"class":276},"sVt8B"," Nuxt 4 + Vue 3 + TypeScript\n",[246,279,281,283],{"class":248,"line":280},5,[246,282,273],{"class":272},[246,284,285],{"class":276}," pnpm workspace\n",[246,287,289,291],{"class":248,"line":288},6,[246,290,273],{"class":272},[246,292,293],{"class":276}," @nuxt\u002Fcontent for markdown content\n",[246,295,296],{"class":248,"line":5},[246,297,260],{"emptyLinePlaceholder":259},[246,299,301],{"class":248,"line":300},8,[246,302,303],{"class":252},"## Commands\n",[246,305,307,309],{"class":248,"line":306},9,[246,308,273],{"class":272},[246,310,311],{"class":276}," Install: pnpm install\n",[246,313,315,317],{"class":248,"line":314},10,[246,316,273],{"class":272},[246,318,319],{"class":276}," Typecheck: pnpm run typecheck\n",[246,321,323,325],{"class":248,"line":322},11,[246,324,273],{"class":272},[246,326,327],{"class":276}," Build: pnpm run build\n",[246,329,331],{"class":248,"line":330},12,[246,332,260],{"emptyLinePlaceholder":259},[246,334,336],{"class":248,"line":335},13,[246,337,338],{"class":252},"## Conventions\n",[246,340,342,344],{"class":248,"line":341},14,[246,343,273],{"class":272},[246,345,346],{"class":276}," Do not commit automatically.\n",[246,348,350,352],{"class":248,"line":349},15,[246,351,273],{"class":272},[246,353,354],{"class":276}," Keep frontmatter schema consistent with content.config.ts.\n",[246,356,358,360],{"class":248,"line":357},16,[246,359,273],{"class":272},[246,361,362],{"class":276}," Before changing many files, explain the plan first.\n",[246,364,366,368],{"class":248,"line":365},17,[246,367,273],{"class":272},[246,369,370],{"class":276}," After editing, run the smallest relevant verification command.\n",[246,372,374],{"class":248,"line":373},18,[246,375,260],{"emptyLinePlaceholder":259},[246,377,379],{"class":248,"line":378},19,[246,380,381],{"class":252},"## Pitfalls\n",[246,383,385,387],{"class":248,"line":384},20,[246,386,273],{"class":272},[246,388,389],{"class":276}," Do not run build while dev server is running on Windows.\n",[246,391,393,395],{"class":248,"line":392},21,[246,394,273],{"class":272},[246,396,397],{"class":276}," Do not edit generated .output or .nuxt files.\n",[17,399,400],{},"别把临时需求写进这些文件。项目记忆应该只放稳定事实：技术栈、命令、目录约定、不可踩的坑。",[13,402,404],{"id":403},"第二步按风险分级使用-agent","第二步：按风险分级使用 Agent",[406,407,409],"h3",{"id":408},"level-1只读分析","Level 1：只读分析",[17,411,412],{},"适合 Gemini CLI \u002F Aider \u002F 任意模型：",[151,414,418],{"className":415,"code":416,"language":417,"meta":157,"style":157},"language-bash shiki shiki-themes github-light github-dark","gemini -p \"读 README、package.json 和 src 目录，解释这个项目架构，不要改文件\"\n","bash",[159,419,420],{"__ignoreMap":157},[246,421,422,426,430],{"class":248,"line":249},[246,423,425],{"class":424},"sScJk","gemini",[246,427,429],{"class":428},"sj4cs"," -p",[246,431,433],{"class":432},"sZZnC"," \"读 README、package.json 和 src 目录，解释这个项目架构，不要改文件\"\n",[17,435,436],{},"用于：接手新项目、审计依赖、理解错误日志、生成迁移计划。",[406,438,440],{"id":439},"level-2小范围修改","Level 2：小范围修改",[17,442,443],{},"适合 Claude Code \u002F Codex CLI：",[151,445,448],{"className":446,"code":447,"language":156,"meta":157},[154],"只修改 src\u002Fauth 目录，修复 refresh token 过期判断。先列计划，我确认后再动手。改完跑 pnpm test auth。\n",[159,449,447],{"__ignoreMap":157},[17,451,452],{},"关键是限制范围、写清验收命令。",[406,454,456],{"id":455},"level-3多文件重构","Level 3：多文件重构",[17,458,459],{},"只建议用 Claude Code \u002F Codex CLI，且必须分阶段：",[151,461,464],{"className":462,"code":463,"language":156,"meta":157},[154],"目标：把旧的 REST client 迁移到 typed SDK。\n阶段 1：只做调用点清单，不改代码。\n阶段 2：先迁移一个模块，跑测试。\n阶段 3：确认模式后批量迁移。\n",[159,465,463],{"__ignoreMap":157},[17,467,468],{},"不要一上来就说「帮我重构整个项目」。Agent 会为了完成任务而扩大改动面。",[406,470,472],{"id":471},"level-4自动化-ci","Level 4：自动化 \u002F CI",[17,474,475],{},"用 headless 模式：",[151,477,479],{"className":415,"code":478,"language":417,"meta":157,"style":157},"gemini -p \"根据这些 issue 标题，按复杂度和风险排序，输出 JSON\" --output-format json\ncodex exec \"review this diff for security issues\"\naider --yes --message \"fix lint errors in changed files only\"\n",[159,480,481,496,507],{"__ignoreMap":157},[246,482,483,485,487,490,493],{"class":248,"line":249},[246,484,425],{"class":424},[246,486,429],{"class":428},[246,488,489],{"class":432}," \"根据这些 issue 标题，按复杂度和风险排序，输出 JSON\"",[246,491,492],{"class":428}," --output-format",[246,494,495],{"class":432}," json\n",[246,497,498,501,504],{"class":248,"line":256},[246,499,500],{"class":424},"codex",[246,502,503],{"class":432}," exec",[246,505,506],{"class":432}," \"review this diff for security issues\"\n",[246,508,509,512,515,518],{"class":248,"line":263},[246,510,511],{"class":424},"aider",[246,513,514],{"class":428}," --yes",[246,516,517],{"class":428}," --message",[246,519,520],{"class":432}," \"fix lint errors in changed files only\"\n",[17,522,523],{},"CI 中要注意：只读审查可以自动跑；自动改代码应该进入 PR，不要直接 push 到 main。",[13,525,527],{"id":526},"第三步mcp-只接必要工具","第三步：MCP 只接必要工具",[17,529,530],{},"MCP 很强，但也最容易失控。推荐从低风险工具开始：",[532,533,534,537,540,543,546,549],"ol",{},[24,535,536],{},"Filesystem（限定目录）",[24,538,539],{},"GitHub（限定 repo 权限）",[24,541,542],{},"Search \u002F docs",[24,544,545],{},"Database read-only",[24,547,548],{},"Slack \u002F Linear \u002F Jira",[24,550,551],{},"Production write tools（最后再考虑）",[17,553,554],{},"原则：",[21,556,557,560,563,566],{},[24,558,559],{},"能只读就不要给写权限。",[24,561,562],{},"能限定 repo \u002F schema \u002F directory 就不要给全局权限。",[24,564,565],{},"第三方 MCP server 先看源码和权限，再接入团队环境。",[24,567,568],{},"生产数据库必须 read-only replica，不能让 Agent 直连主库写入。",[13,570,572],{"id":571},"第四步每次任务都要有验证闭环","第四步：每次任务都要有验证闭环",[17,574,575],{},"好 prompt 不是「请帮我修好」，而是包含验证命令：",[151,577,580],{"className":578,"code":579,"language":156,"meta":157},[154],"修复这个 bug。限制：不要改 public API。完成后运行：\n1. pnpm run typecheck\n2. pnpm test auth\n3. pnpm run build\n如果任一失败，继续修到通过；如果是环境问题，说明具体报错。\n",[159,581,579],{"__ignoreMap":157},[17,583,584],{},"Agent 质量差距的一半来自模型，另一半来自你有没有给它可执行的验收标准。",[13,586,588],{"id":587},"推荐工作流双-agent-交叉检查","推荐工作流：双 Agent 交叉检查",[151,590,593],{"className":591,"code":592,"language":156,"meta":157},[154],"Claude Code \u002F Codex CLI 负责改代码\nGemini CLI 负责读 diff + 查新资料 + 第二意见\n人工负责最终 review 和 merge\n",[159,594,592],{"__ignoreMap":157},[17,596,597],{},"示例：",[151,599,601],{"className":415,"code":600,"language":417,"meta":157,"style":157},"# 1. 主 Agent 改代码后生成 diff\ngit diff > \u002Ftmp\u002Fchange.diff\n\n# 2. 第二 Agent 审查\ngemini -p \"Review this diff for hidden risk and missing tests:\\n$(cat \u002Ftmp\u002Fchange.diff)\"\n\n# 3. 人看两个结果再决定是否合并\n",[159,602,603,609,624,628,633,648,652],{"__ignoreMap":157},[246,604,605],{"class":248,"line":249},[246,606,608],{"class":607},"sJ8bj","# 1. 主 Agent 改代码后生成 diff\n",[246,610,611,614,617,621],{"class":248,"line":256},[246,612,613],{"class":424},"git",[246,615,616],{"class":432}," diff",[246,618,620],{"class":619},"szBVR"," >",[246,622,623],{"class":432}," \u002Ftmp\u002Fchange.diff\n",[246,625,626],{"class":248,"line":263},[246,627,260],{"emptyLinePlaceholder":259},[246,629,630],{"class":248,"line":269},[246,631,632],{"class":607},"# 2. 第二 Agent 审查\n",[246,634,635,637,639,642,645],{"class":248,"line":280},[246,636,425],{"class":424},[246,638,429],{"class":428},[246,640,641],{"class":432}," \"Review this diff for hidden risk and missing tests:\\n$(",[246,643,644],{"class":424},"cat",[246,646,647],{"class":432}," \u002Ftmp\u002Fchange.diff)\"\n",[246,649,650],{"class":248,"line":288},[246,651,260],{"emptyLinePlaceholder":259},[246,653,654],{"class":248,"line":5},[246,655,656],{"class":607},"# 3. 人看两个结果再决定是否合并\n",[17,658,659],{},"这种「一个写、一个审」比让同一个 Agent 自夸自审更可靠。",[13,661,662],{"id":662},"常见踩坑",[532,664,665,671,677,683,689,699],{},[24,666,667,670],{},[147,668,669],{},"不给边界","：让 Agent 改「整个项目」，它就真的会碰一堆文件。",[24,672,673,676],{},[147,674,675],{},"不给验证命令","：Agent 会用自然语言说完成，但没跑过测试。",[24,678,679,682],{},[147,680,681],{},"项目记忆太长","：几千行规则会稀释重点，保留最关键 20 条。",[24,684,685,688],{},[147,686,687],{},"MCP 权限过大","：一开始就接生产数据库、Slack 写权限、GitHub admin token。",[24,690,691,694,695,698],{},[147,692,693],{},"长会话不清理","：任务切换时 ",[159,696,697],{},"\u002Fclear"," 或新开会话，避免旧上下文污染。",[24,700,701,704],{},[147,702,703],{},"把 Agent 当 CI","：CI 是确定性验证，Agent 是概率性执行，两者不能互相替代。",[13,706,707],{"id":707},"一句话总结",[17,709,710],{},"2026 年终端 Agent 的正确姿势不是押注一个工具，而是建立一套可验证的流水线：",[151,712,715],{"className":713,"code":714,"language":156,"meta":157},[154],"项目记忆 → 小任务边界 → MCP 最小权限 → 自动验证 → 第二 Agent 审查 → 人工 merge\n",[159,716,714],{"__ignoreMap":157},[17,718,719],{},"工具会换，但这套工作流不会过时。",[721,722,723],"style",{},"html pre.shiki code .sq-ep, html code.shiki .sq-ep{--shiki-default:#005CC5;--shiki-default-font-weight:bold;--shiki-dark:#79B8FF;--shiki-dark-font-weight:bold}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":157,"searchDepth":263,"depth":263,"links":725},[726,727,728,729,735,736,737,738,739],{"id":15,"depth":256,"text":15},{"id":38,"depth":256,"text":38},{"id":163,"depth":256,"text":164},{"id":403,"depth":256,"text":404,"children":730},[731,732,733,734],{"id":408,"depth":263,"text":409},{"id":439,"depth":263,"text":440},{"id":455,"depth":263,"text":456},{"id":471,"depth":263,"text":472},{"id":526,"depth":256,"text":527},{"id":571,"depth":256,"text":572},{"id":587,"depth":256,"text":588},{"id":662,"depth":256,"text":662},{"id":707,"depth":256,"text":707},"onboarding","\u002Fog\u002Fplaybook\u002Fterminal-agent-stack-2026.png","一套面向 2026 年的终端 AI Agent 选型与落地指南：Claude Code、Codex CLI、Gemini CLI、Aider 各自适合什么任务，如何配置项目记忆、MCP、权限与验证闭环。",{},"\u002Fplaybook\u002Fonboarding\u002Fterminal-agent-stack-2026","2026-06-25",[747,748,749,750],"coding\u002Fcli\u002Fclaude-code","coding\u002Fcli\u002Fcodex","coding\u002Fcli\u002Fgemini-cli","coding\u002Fcli\u002Faider",{"title":8,"description":742},"playbook\u002Fonboarding\u002Fterminal-agent-stack-2026",[754,72,75,98,101,755],"CLI Agent","MCP","G9emZG5RHrZptWZrdwHuEDlxgV3g1Re9AgNyx5umrZA",{"tools":4,"reviews":5,"playbooks":330,"news":314},[759,1772,2974,3705],{"id":760,"title":101,"alternatives":761,"api_compatible":763,"body":764,"category":1731,"chinese_friendly":263,"cover":1732,"description":1733,"domestic":1734,"extension":242,"faq":763,"free":1734,"github":1208,"languages":1735,"meta":1738,"models":763,"navigation":259,"notSuitable":763,"opensource":259,"path":1739,"pillar":1740,"platforms":1741,"priceTable":763,"pricing":1745,"published":1746,"relatedPlaybooks":763,"relatedReviews":763,"score":1747,"self_host":259,"seo":1748,"slug":750,"sources":1749,"stem":1762,"suitable":763,"tagline":1763,"tags":1764,"updated":1769,"verdict":1770,"website":1663,"__hash__":1771},"tools\u002Ftools\u002Fcoding\u002Fcli\u002Faider.md",[747,748,762],"coding\u002Fcli\u002Fcline",null,{"type":10,"value":765,"toc":1714},[766,770,799,805,808,812,815,851,855,865,885,888,931,936,939,947,1023,1026,1030,1033,1037,1195,1198,1243,1255,1258,1296,1299,1435,1440,1462,1465,1563,1567,1570,1596,1599,1613,1616,1653,1656,1704,1711],[13,767,769],{"id":768},"tldr","TL;DR",[771,772,777,787],"div",{"className":773},[774,775,776],"card","p-5","my-4",[17,778,779,782,783,786],{},[147,780,781],{},"一句话："," Aider 把 \"AI 编辑代码\" 这件事拆成了 git 操作——每次对话结束自动 commit，回滚一行 ",[159,784,785],{},"git reset --hard HEAD~1"," 就行。没有 GUI、没有 IDE 插件、没有 Composer 那种漂亮 diff 面板，但你能拿到对开源项目最友好的工作流：bring your own key、bring your own model、bring your own editor。",[17,788,789,790,793,794,798],{},"代价是",[147,791,792],{},"学习曲线最陡","。第一次跑起来要花 10 分钟读文档，但跑顺了之后 ",[795,796,72],"a",{"href":797},"\u002Fcoding\u002Fcli\u002Fclaude-code.html"," 用户都觉得\"为啥不直接 aider\"。",[800,801,802],"blockquote",{},[17,803,804],{},"来源说明：本文事实点基于 aider.chat 官方文档（modes.html \u002F llms.html \u002F HISTORY.html）和 GitHub 仓库归纳，命令、参数、模型列表以官方为准。",[13,806,807],{"id":807},"核心特性",[406,809,811],{"id":810},"git-原生每次改动-一次-commit","Git 原生：每次改动 = 一次 commit",[17,813,814],{},"这是 Aider 与所有竞品的最大区别。其他 AI 编程工具改完文件丢给你看 diff，让你手动 stage \u002F commit；Aider 把 git 集成到工作流里：",[21,816,817,828,838,848],{},[24,818,819,820,823,824,827],{},"每次对话改完代码，自动 ",[159,821,822],{},"git add"," + ",[159,825,826],{},"git commit","，commit message 由 weak-model 生成",[24,829,830,831,834,835],{},"想撤回上一步：",[159,832,833],{},"\u002Fundo"," 或者直接 ",[159,836,837],{},"git reset",[24,839,840,841,844,845,847],{},"改坏了想从分叉点重来：",[159,842,843],{},"git checkout \u003Chash>"," 后继续 ",[159,846,511],{},"，对话上下文还在",[24,849,850],{},"这也是为什么官方推荐 Aider 用在 git 仓库里——非 git 目录功能受限",[406,852,854],{"id":853},"architect-模式两个模型分工","Architect 模式：两个模型分工",[17,856,857,858,864],{},"Architect 模式把\"想方案\"和\"写代码\"拆给两个模型——根据 ",[795,859,863],{"href":860,"rel":861},"https:\u002F\u002Faider.chat\u002Fdocs\u002Fusage\u002Fmodes.html",[862],"nofollow","官方 modes 文档","：",[21,866,867,873,879],{},[24,868,869,872],{},[159,870,871],{},"--model","（architect）：负责高层方案推理。适合 o1 \u002F o3 \u002F DeepSeek R1 \u002F Claude Opus 这类强推理模型",[24,874,875,878],{},[159,876,877],{},"--editor-model","：负责把方案落地成具体文件 diff。适合 GPT-4o \u002F Claude Sonnet 这类编辑能力强但推理一般的模型",[24,880,881,884],{},[159,882,883],{},"--weak-model","（可选）：用来生成 commit message \u002F 简单重构。可以指定便宜模型省钱",[17,886,887],{},"启动示例：",[151,889,891],{"className":415,"code":890,"language":417,"meta":157,"style":157},"aider --architect \\\n  --model deepseek\u002Fdeepseek-reasoner \\\n  --editor-model claude-3-5-sonnet-20241022 \\\n  --weak-model gpt-4o-mini\n",[159,892,893,903,913,923],{"__ignoreMap":157},[246,894,895,897,900],{"class":248,"line":249},[246,896,511],{"class":424},[246,898,899],{"class":428}," --architect",[246,901,902],{"class":428}," \\\n",[246,904,905,908,911],{"class":248,"line":256},[246,906,907],{"class":428},"  --model",[246,909,910],{"class":432}," deepseek\u002Fdeepseek-reasoner",[246,912,902],{"class":428},[246,914,915,918,921],{"class":248,"line":263},[246,916,917],{"class":428},"  --editor-model",[246,919,920],{"class":432}," claude-3-5-sonnet-20241022",[246,922,902],{"class":428},[246,924,925,928],{"class":248,"line":269},[246,926,927],{"class":428},"  --weak-model",[246,929,930],{"class":432}," gpt-4o-mini\n",[800,932,933],{},[17,934,935],{},"据 Aider 官方 benchmark，DeepSeek R1（架构师）+ Claude 3.5 Sonnet（编辑器）的 Architect 组合，比任一模型单跑高约 10%。本数据来自 aider.chat\u002FHISTORY.html 与 pixelsham.com 的 2025-07 评测笔记。",[406,937,938],{"id":938},"几乎能接所有模型",[17,940,941,946],{},[795,942,945],{"href":943,"rel":944},"https:\u002F\u002Faider.chat\u002Fdocs\u002Fllms.html",[862],"Aider 官方推荐"," 的\"最佳模型清单\"：",[40,948,949,962],{},[43,950,951],{},[46,952,953,956,959],{},[49,954,955],{},"厂商",[49,957,958],{},"推荐模型",[49,960,961],{},"备注",[62,963,964,975,986,997,1012],{},[46,965,966,969,972],{},[67,967,968],{},"Anthropic",[67,970,971],{},"Claude Sonnet 4 \u002F 3.7 Sonnet",[67,973,974],{},"编辑能力最稳",[46,976,977,980,983],{},[67,978,979],{},"Google",[67,981,982],{},"Gemini 2.5 Pro",[67,984,985],{},"超长上下文",[46,987,988,991,994],{},[67,989,990],{},"DeepSeek",[67,992,993],{},"R1 + V3",[67,995,996],{},"性价比之王",[46,998,999,1002,1009],{},[67,1000,1001],{},"OpenAI",[67,1003,1004,1005],{},"o3 \u002F o4-mini \u002F GPT-4.1 \u002F ",[795,1006,1008],{"href":1007},"\u002Fmodels\u002Fgpt-5.html","GPT-5",[67,1010,1011],{},"reasoning 路径",[46,1013,1014,1017,1020],{},[67,1015,1016],{},"本地",[67,1018,1019],{},"Ollama \u002F LM Studio 兼容 OpenAI API",[67,1021,1022],{},"完全离线",[17,1024,1025],{},"接入方式靠 LiteLLM 适配层，OpenRouter \u002F Bedrock \u002F Vertex \u002F xAI \u002F Groq \u002F Cohere \u002F Azure \u002F 私有 OpenAI 兼容端点 都支持——你能想到的 base_url，基本都行。",[406,1027,1029],{"id":1028},"repo-map上下文召回的核心机制","Repo map：上下文召回的核心机制",[17,1031,1032],{},"Aider 用 tree-sitter 解析整个 git 仓库，生成一份压缩版的 \"repo map\"——把符号定义、函数签名、类层级提取出来塞进 prompt。模型不需要看到所有源代码就能理解项目结构。这是 Aider 在 polyglot benchmark 上能打过很多带 Composer 的工具的关键原因。",[13,1034,1036],{"id":1035},"上手-5-分钟","上手 5 分钟",[151,1038,1040],{"className":415,"code":1039,"language":417,"meta":157,"style":157},"# 1. 安装（要 Python 3.9+）\npython -m pip install -U --upgrade-strategy only-if-needed aider-chat\n\n# 2. 进入 git 仓库\ncd your-project\n\n# 3. 设置 API key（任选其一）\nexport ANTHROPIC_API_KEY=sk-ant-...\nexport DEEPSEEK_API_KEY=sk-...\nexport OPENAI_API_KEY=sk-...\n\n# 4. 启动（默认会用环境变量里第一个能识别的 key）\naider\n\n# 或指定模型\naider --model deepseek\u002Fdeepseek-chat\naider --model claude-3-5-sonnet-20241022\n\n# 5. 在 aider 里直接用自然语言下指令\n> 把 server\u002Fapi\u002Fuser.ts 里的 getUserById 改成支持批量查询\n",[159,1041,1042,1047,1073,1077,1082,1090,1094,1099,1113,1125,1136,1140,1145,1150,1154,1159,1169,1178,1182,1187],{"__ignoreMap":157},[246,1043,1044],{"class":248,"line":249},[246,1045,1046],{"class":607},"# 1. 安装（要 Python 3.9+）\n",[246,1048,1049,1052,1055,1058,1061,1064,1067,1070],{"class":248,"line":256},[246,1050,1051],{"class":424},"python",[246,1053,1054],{"class":428}," -m",[246,1056,1057],{"class":432}," pip",[246,1059,1060],{"class":432}," install",[246,1062,1063],{"class":428}," -U",[246,1065,1066],{"class":428}," --upgrade-strategy",[246,1068,1069],{"class":432}," only-if-needed",[246,1071,1072],{"class":432}," aider-chat\n",[246,1074,1075],{"class":248,"line":263},[246,1076,260],{"emptyLinePlaceholder":259},[246,1078,1079],{"class":248,"line":269},[246,1080,1081],{"class":607},"# 2. 进入 git 仓库\n",[246,1083,1084,1087],{"class":248,"line":280},[246,1085,1086],{"class":428},"cd",[246,1088,1089],{"class":432}," your-project\n",[246,1091,1092],{"class":248,"line":288},[246,1093,260],{"emptyLinePlaceholder":259},[246,1095,1096],{"class":248,"line":5},[246,1097,1098],{"class":607},"# 3. 设置 API key（任选其一）\n",[246,1100,1101,1104,1107,1110],{"class":248,"line":300},[246,1102,1103],{"class":619},"export",[246,1105,1106],{"class":276}," ANTHROPIC_API_KEY",[246,1108,1109],{"class":619},"=",[246,1111,1112],{"class":276},"sk-ant-...\n",[246,1114,1115,1117,1120,1122],{"class":248,"line":306},[246,1116,1103],{"class":619},[246,1118,1119],{"class":276}," DEEPSEEK_API_KEY",[246,1121,1109],{"class":619},[246,1123,1124],{"class":276},"sk-...\n",[246,1126,1127,1129,1132,1134],{"class":248,"line":314},[246,1128,1103],{"class":619},[246,1130,1131],{"class":276}," OPENAI_API_KEY",[246,1133,1109],{"class":619},[246,1135,1124],{"class":276},[246,1137,1138],{"class":248,"line":322},[246,1139,260],{"emptyLinePlaceholder":259},[246,1141,1142],{"class":248,"line":330},[246,1143,1144],{"class":607},"# 4. 启动（默认会用环境变量里第一个能识别的 key）\n",[246,1146,1147],{"class":248,"line":335},[246,1148,1149],{"class":424},"aider\n",[246,1151,1152],{"class":248,"line":341},[246,1153,260],{"emptyLinePlaceholder":259},[246,1155,1156],{"class":248,"line":349},[246,1157,1158],{"class":607},"# 或指定模型\n",[246,1160,1161,1163,1166],{"class":248,"line":357},[246,1162,511],{"class":424},[246,1164,1165],{"class":428}," --model",[246,1167,1168],{"class":432}," deepseek\u002Fdeepseek-chat\n",[246,1170,1171,1173,1175],{"class":248,"line":365},[246,1172,511],{"class":424},[246,1174,1165],{"class":428},[246,1176,1177],{"class":432}," claude-3-5-sonnet-20241022\n",[246,1179,1180],{"class":248,"line":373},[246,1181,260],{"emptyLinePlaceholder":259},[246,1183,1184],{"class":248,"line":378},[246,1185,1186],{"class":607},"# 5. 在 aider 里直接用自然语言下指令\n",[246,1188,1189,1192],{"class":248,"line":384},[246,1190,1191],{"class":619},">",[246,1193,1194],{"class":276}," 把 server\u002Fapi\u002Fuser.ts 里的 getUserById 改成支持批量查询\n",[13,1196,1197],{"id":1197},"价格与运行成本",[21,1199,1200,1212,1226],{},[24,1201,1202,1205,1206,1211],{},[147,1203,1204],{},"Aider 本体","：开源免费（",[795,1207,1210],{"href":1208,"rel":1209},"https:\u002F\u002Fgithub.com\u002FAider-AI\u002Faider",[862],"Apache 2.0 协议","，根据官方 GitHub 仓库 LICENSE）",[24,1213,1214,1217,1218,210,1221,1225],{},[147,1215,1216],{},"真正的成本是模型 API key","：100% 自带——这是 Aider 与 ",[795,1219,228],{"href":1220},"\u002Fcoding\u002Fide\u002Fcursor.html",[795,1222,1224],{"href":1223},"\u002Fcoding\u002Fide\u002Fwindsurf.html","Windsurf"," 最大的商业模式差异",[24,1227,1228,1229],{},"单次会话典型消耗：\n",[21,1230,1231,1234,1237],{},[24,1232,1233],{},"用 Sonnet 4 改 1 个中型 PR（10-15 文件）：约 $0.5-2 美元",[24,1235,1236],{},"用 DeepSeek-V3 同等任务：约 $0.05-0.2 美元",[24,1238,1239,1240,1242],{},"用 ",[795,1241,1008],{"href":1007}," reasoning：根据推理深度，可能到 $3-8",[17,1244,1245,1246,823,1250,1254],{},"走 ",[795,1247,1249],{"href":1248},"\u002Fmodels\u002Fdeepseek-v3.html","DeepSeek-V3",[795,1251,1253],{"href":860,"rel":1252},[862],"Architect 模式"," 是当前性价比最高的组合，国内付款也直接。",[13,1256,1257],{"id":1257},"国内使用注意事项",[532,1259,1260,1269,1275,1290],{},[24,1261,1262,1265,1266],{},[147,1263,1264],{},"直连 OpenAI \u002F Anthropic 需要代理","——Aider 没有内置代理设置，靠环境变量 ",[159,1267,1268],{},"HTTPS_PROXY",[24,1270,1271,1274],{},[147,1272,1273],{},"DeepSeek \u002F Qwen \u002F GLM 直连无障碍","——国内付款，国内带宽，体验最好",[24,1276,1277,1280,1281,1284,1285,1289],{},[147,1278,1279],{},"支持自定义 base_url","：通过 ",[159,1282,1283],{},"OPENAI_API_BASE"," 环境变量接 ",[795,1286,1288],{"href":1287},"\u002Fcoding\u002Fapi\u002Fone-api.html","国内中转 \u002F 硅基流动 \u002F OneAPI"," 都行",[24,1291,1292,1295],{},[147,1293,1294],{},"Ollama 本地模型零网络依赖","——隐私场景首选，模型质量取决于本机",[13,1297,1298],{"id":1298},"与同类怎么选",[40,1300,1301,1325],{},[43,1302,1303],{},[46,1304,1305,1308,1310,1314,1319],{},[49,1306,1307],{},"维度",[49,1309,101],{},[49,1311,1312],{},[795,1313,72],{"href":797},[49,1315,1316],{},[795,1317,75],{"href":1318},"\u002Fcoding\u002Fcli\u002Fcodex.html",[49,1320,1321],{},[795,1322,1324],{"href":1323},"\u002Fcoding\u002Fcli\u002Fcline.html","Cline",[62,1326,1327,1342,1358,1374,1390,1404,1418],{},[46,1328,1329,1332,1335,1338,1340],{},[67,1330,1331],{},"开源",[67,1333,1334],{},"✅",[67,1336,1337],{},"❌",[67,1339,1337],{},[67,1341,1334],{},[46,1343,1344,1347,1350,1353,1356],{},[67,1345,1346],{},"模型选择",[67,1348,1349],{},"任意",[67,1351,1352],{},"仅 Anthropic",[67,1354,1355],{},"仅 OpenAI",[67,1357,1349],{},[46,1359,1360,1363,1366,1369,1372],{},[67,1361,1362],{},"自带 API key",[67,1364,1365],{},"✅ 必须",[67,1367,1368],{},"可选（订阅替代）",[67,1370,1371],{},"可选",[67,1373,1365],{},[46,1375,1376,1379,1382,1385,1388],{},[67,1377,1378],{},"Git 集成",[67,1380,1381],{},"★★★★★",[67,1383,1384],{},"★★★☆☆",[67,1386,1387],{},"★★☆☆☆",[67,1389,1384],{},[46,1391,1392,1395,1398,1400,1402],{},[67,1393,1394],{},"学习曲线",[67,1396,1397],{},"★★★★☆ 陡",[67,1399,1387],{},[67,1401,1387],{},[67,1403,1384],{},[46,1405,1406,1409,1412,1414,1416],{},[67,1407,1408],{},"Architect 双模型",[67,1410,1411],{},"✅ 原生",[67,1413,1337],{},[67,1415,1337],{},[67,1417,1337],{},[46,1419,1420,1423,1426,1429,1432],{},[67,1421,1422],{},"VS Code 集成",[67,1424,1425],{},"通过第三方插件",[67,1427,1428],{},"通过 Cursor 等",[67,1430,1431],{},"仅 CLI",[67,1433,1434],{},"★★★★★ 原生",[17,1436,1437,864],{},[147,1438,1439],{},"怎么选",[21,1441,1442,1445,1450,1455],{},[24,1443,1444],{},"不想被锁在某家厂商，要随时切换 DeepSeek \u002F Claude \u002F GPT → Aider",[24,1446,1447,1448],{},"已经买 Claude Pro \u002F Max 订阅 → ",[795,1449,72],{"href":797},[24,1451,1452,1453],{},"已经买 ChatGPT Plus \u002F Pro → ",[795,1454,75],{"href":1318},[24,1456,1457,1458,210,1460],{},"习惯 VS Code 不想离开 GUI → ",[795,1459,1324],{"href":1323},[795,1461,228],{"href":1220},[13,1463,1464],{"id":1464},"避坑清单",[21,1466,1467,1480,1497,1516,1525,1541,1549],{},[24,1468,1469,1472,1473,1476,1477,1479],{},[147,1470,1471],{},"没在 git 仓库里跑会被警告","：Aider 强烈建议你 ",[159,1474,1475],{},"git init"," 后再用，否则 ",[159,1478,833],{}," 不能用，自动 commit 也无意义。",[24,1481,1482,1488,1489,1492,1493,1496],{},[147,1483,1484,1487],{},[159,1485,1486],{},"\u002Fadd"," 之前的文件不会被 Aider 看见","：和 Cursor ",[159,1490,1491],{},"@codebase"," 不同，Aider 默认只看 repo map，需要修改的文件要 ",[159,1494,1495],{},"\u002Fadd path\u002Fto\u002Ffile"," 显式加入对话。这是新手最容易卡住的地方。",[24,1498,1499,1502,1503,1508,1509,1512,1513,1515],{},[147,1500,1501],{},"Architect 模式有 prompt injection 风险","：根据 GitHub issue ",[795,1504,1507],{"href":1505,"rel":1506},"https:\u002F\u002Fgithub.com\u002FAider-AI\u002Faider\u002Fissues\u002F5058",[862],"#5058","（2026 年 4 月报告），如果让 architect 读取 untrusted 仓库（如 README 被人塞了攻击指令），可能被诱导让 editor 生成后门代码。建议：在 ",[159,1510,1511],{},"--yes"," 自动接受前确认 architect 输出；不要在不可信项目上开 architect mode + ",[159,1514,1511],{}," 组合。",[24,1517,1518,1524],{},[147,1519,1520,1523],{},[159,1521,1522],{},"--yes-always"," 太激进","：会跳过所有确认，包括\"是否要把这个文件加入 chat\"——容易让 Aider 偷偷读你不想给模型看的文件。生产环境慎用。",[24,1526,1527,1530,1531,1534,1535,1540],{},[147,1528,1529],{},"token 限制错误的判断不可靠","：Ollama 本地模型超 context 不会报错而是静默截断，会让你以为\"模型忘了我加的文件\"。明确配置 ",[159,1532,1533],{},"num_ctx","（见 ",[795,1536,1539],{"href":1537,"rel":1538},"https:\u002F\u002Faider.chat\u002F2025\u002F01\u002F28\u002Fdeepseek-down.html",[862],"DeepSeek alternative providers 一文","）。",[24,1542,1543,1548],{},[147,1544,1545,1547],{},[159,1546,877],{}," 比想象重要","：架构师推理再强，editor 写不出合法 diff 一样白搭。优先选 Claude Sonnet 系列做 editor，不要让推理模型自己做 editor。",[24,1550,1551,1554,1555,1558,1559,1562],{},[147,1552,1553],{},"中文 commit message 默认不开","：可以 ",[159,1556,1557],{},"aider --commit-prompt \"...中文....\""," 或 ",[159,1560,1561],{},".aider.conf.yml"," 配置中改。",[13,1564,1566],{"id":1565},"适合-不适合","适合 \u002F 不适合",[17,1568,1569],{},"✅ 适合：",[21,1571,1572,1575,1578,1581,1584,1587],{},[24,1573,1574],{},"命令行重度用户、tmux \u002F Neovim 工作流",[24,1576,1577],{},"多模型试用 \u002F 比价场景（一行命令切换）",[24,1579,1580],{},"开源项目维护者（git 工作流原生融入）",[24,1582,1583],{},"想要完全离线（Ollama + 本地模型）",[24,1585,1586],{},"对 token 成本敏感（DeepSeek + Aider 组合极便宜）",[24,1588,1589,1590,1595],{},"跨语言项目（",[795,1591,1594],{"href":1592,"rel":1593},"https:\u002F\u002Faider.chat\u002Fdocs\u002Flanguages.html",[862],"官方支持 100+ 语言","）",[17,1597,1598],{},"❌ 不适合：",[21,1600,1601,1604,1607,1610],{},[24,1602,1603],{},"习惯 GUI \u002F 不愿读命令行文档的人",[24,1605,1606],{},"想\"一键智能\"、不愿配置环境变量",[24,1608,1609],{},"团队协作场景（没有共享 sessions \u002F 协作 UI）",[24,1611,1612],{},"Windows 纯小白（虽然能跑，但 Python 环境 + git CLI 双依赖门槛高）",[13,1614,1615],{"id":1615},"相关阅读",[21,1617,1618,1627,1636,1646],{},[24,1619,1620,1621,210,1623,210,1625],{},"同类对比：",[795,1622,72],{"href":797},[795,1624,75],{"href":1318},[795,1626,1324],{"href":1323},[24,1628,1629,1630,210,1634],{},"推理模型选择：",[795,1631,1633],{"href":1632},"\u002Fmodels\u002Fdeepseek-r1.html","DeepSeek R1",[795,1635,1008],{"href":1007},[24,1637,1638,1639,210,1642],{},"协议生态：",[795,1640,755],{"href":1641},"\u002Fwiki\u002Fmcp.html",[795,1643,1645],{"href":1644},"\u002Fwiki\u002Ffunction-calling.html","Function Calling",[24,1647,1648,1649],{},"工作流：",[795,1650,1652],{"href":1651},"\u002Fwiki\u002Fcontext-engineering.html","Context Engineering",[13,1654,1655],{"id":1655},"来源",[21,1657,1658,1665,1672,1678,1684,1690,1697],{},[24,1659,1660,1661],{},"官网：",[795,1662,1663],{"href":1663,"rel":1664},"https:\u002F\u002Faider.chat",[862],[24,1666,1667,1668],{},"官方文档：",[795,1669,1670],{"href":1670,"rel":1671},"https:\u002F\u002Faider.chat\u002Fdocs\u002F",[862],[24,1673,1674,1675],{},"Chat Modes 文档：",[795,1676,860],{"href":860,"rel":1677},[862],[24,1679,1680,1681],{},"LLM 兼容列表：",[795,1682,943],{"href":943,"rel":1683},[862],[24,1685,1686,1687],{},"GitHub：",[795,1688,1208],{"href":1208,"rel":1689},[862],[24,1691,1692,1693],{},"发布历史：",[795,1694,1695],{"href":1695,"rel":1696},"https:\u002F\u002Faider.chat\u002FHISTORY.html",[862],[24,1698,1699,1700],{},"PyPI：",[795,1701,1702],{"href":1702,"rel":1703},"https:\u002F\u002Fpypi.org\u002Fproject\u002Faider-chat",[862],[17,1705,1706,1707,1710],{},"本卡片由 AIHO 编辑部根据官方公开资料整理。如有更新请通过 ",[795,1708,1709],{"href":1709},"\u002Fsubmit"," 反馈。",[721,1712,1713],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":157,"searchDepth":263,"depth":263,"links":1715},[1716,1717,1723,1724,1725,1726,1727,1728,1729,1730],{"id":768,"depth":256,"text":769},{"id":807,"depth":256,"text":807,"children":1718},[1719,1720,1721,1722],{"id":810,"depth":263,"text":811},{"id":853,"depth":263,"text":854},{"id":938,"depth":263,"text":938},{"id":1028,"depth":263,"text":1029},{"id":1035,"depth":256,"text":1036},{"id":1197,"depth":256,"text":1197},{"id":1257,"depth":256,"text":1257},{"id":1298,"depth":256,"text":1298},{"id":1464,"depth":256,"text":1464},{"id":1565,"depth":256,"text":1566},{"id":1615,"depth":256,"text":1615},{"id":1655,"depth":256,"text":1655},"cli","\u002Fimg\u002Ftools\u002Faider.webp","Aider 真实评测：Git 原生 AI 编程 CLI，每次改动自动 commit、回滚成本极低。AIHO 编辑部基于官方文档与社区资料整理，含 Architect 双模型模式、支持模型清单、安装与配置实操。",false,[1736,1737],"zh","en",{},"\u002Ftools\u002Fcoding\u002Fcli\u002Faider","coding",[1742,1743,1744],"windows","macos","linux","开源免费 \u002F 自带 API key","2026-06-18",{"power":269,"ux":263,"price":280,"cn_support":263,"stability":280},{"title":101,"description":1733},[1750,1752,1754,1756,1758,1760],{"title":1751,"url":1670},"Aider 官方文档",{"title":1753,"url":860},"Aider Chat Modes 文档",{"title":1755,"url":943},"Aider 支持的 LLM 列表",{"title":1757,"url":1208},"Aider GitHub 仓库",{"title":1759,"url":1695},"Aider Release History",{"title":1761,"url":1702},"PyPI: aider-chat","tools\u002Fcoding\u002Fcli\u002Faider","Git 原生 AI 编程 CLI，commit 即动作",[1731,1765,1766,1767,1768],"agent","opensource","git-native","architect-mode","2026-06-24","极客派最爱。每次改动自动 commit、回滚成本极低。学习曲线最陡。","GFtIV9h15OvUqrrlQPTHmZR9x9n38Nl0gELROjfspIU",{"id":1773,"title":72,"alternatives":1774,"api_compatible":1775,"body":1777,"category":1731,"chinese_friendly":263,"cover":2912,"description":2913,"domestic":1734,"extension":242,"faq":763,"free":1734,"github":2869,"languages":2914,"meta":2915,"models":2916,"navigation":259,"notSuitable":2920,"opensource":1734,"path":2924,"pillar":1740,"platforms":2925,"priceTable":2926,"pricing":2946,"published":1746,"relatedPlaybooks":763,"relatedReviews":763,"score":2947,"self_host":1734,"seo":2948,"slug":747,"sources":2949,"stem":2960,"suitable":2961,"tagline":2967,"tags":2968,"updated":1769,"verdict":2972,"website":2857,"__hash__":2973},"tools\u002Ftools\u002Fcoding\u002Fcli\u002Fclaude-code.md",[748,750,762],[1776],"anthropic",{"type":10,"value":1778,"toc":2895},[1779,1781,1804,1809,1811,1815,1825,1850,1853,1857,1865,1894,1903,1907,1910,2063,2081,2085,2094,2170,2173,2177,2191,2193,2208,2289,2292,2303,2311,2313,2460,2462,2501,2503,2654,2659,2673,2678,2697,2699,2795,2797,2849,2851,2887,2892],[13,1780,769],{"id":768},[771,1782,1784,1793],{"className":1783},[774,775,776],[17,1785,1786,1788,1789,1792],{},[147,1787,781],{}," Anthropic 官方 CLI Agent，终端原生，长任务执行能力是目前体感最稳的一档。装好后在任何项目根目录跑 ",[159,1790,1791],{},"claude","，用自然语言让它读代码、改文件、跑测试、提交 commit——全自动。",[17,1794,1795,1796,1799,1800,1803],{},"最大价值是 ",[147,1797,1798],{},"不绑死 IDE","——VS Code、JetBrains、Vim、Emacs、Neovim 全能用，远程 SSH 也行。代价是 ",[147,1801,1802],{},"国内三大门槛","：账号要海外手机、支付要海外卡、网络要稳定代理。",[800,1805,1806],{},[17,1807,1808],{},"来源说明：本文基于 code.claude.com 官方文档、Anthropic 定价页面、第三方独立评测（laozhang.ai \u002F explainx.ai \u002F computingforgeeks.com）综合整理。Anthropic 模型版本迭代快，命令和价格请以最新官方文档为准。",[13,1810,807],{"id":807},[406,1812,1814],{"id":1813},"终端原生的-agent-体验","终端原生的 Agent 体验",[17,1816,1817,1818,1821,1822,1824],{},"不像 Cursor \u002F Windsurf 那种\"AI IDE\"，Claude Code 是个 ",[147,1819,1820],{},"CLI 工具","——在任何编辑器旁边开个终端，跑 ",[159,1823,1791],{},"，就进入了一个能读你整个 codebase 的对话环境。",[151,1826,1828],{"className":415,"code":1827,"language":417,"meta":157,"style":157},"cd your-project\nclaude                          # 进入交互模式\n> 帮我把这个 Express 项目迁移到 Fastify，写完之后跑测试确认通过\n",[159,1829,1830,1836,1843],{"__ignoreMap":157},[246,1831,1832,1834],{"class":248,"line":249},[246,1833,1086],{"class":428},[246,1835,1089],{"class":432},[246,1837,1838,1840],{"class":248,"line":256},[246,1839,1791],{"class":424},[246,1841,1842],{"class":607},"                          # 进入交互模式\n",[246,1844,1845,1847],{"class":248,"line":263},[246,1846,1191],{"class":619},[246,1848,1849],{"class":276}," 帮我把这个 Express 项目迁移到 Fastify，写完之后跑测试确认通过\n",[17,1851,1852],{},"它会自动：列出相关文件 → 给出计划 → 等你按回车确认 → 一次改多个文件 → 跑测试 → 报告结果。整个过程你可以在另一个窗口干别的，Claude Code 不抢编辑器焦点。",[406,1854,1856],{"id":1855},"子代理sub-agents-并行任务","子代理（Sub-agents）+ 并行任务",[17,1858,1859,1860,1864],{},"Claude Code 2.x 引入了 ",[795,1861,1863],{"href":1862},"\u002Fwiki\u002Fai-agent.html","子代理"," 机制：主对话可以派发独立的子任务到隔离 context 中跑，结果摘要返回主线。典型场景：",[151,1866,1868],{"className":415,"code":1867,"language":417,"meta":157,"style":157},"\u002Fagents              # 管理子代理\n\u002Fbatch              # 把大改动拆成独立单元，每个跑在自己的 git worktree\n\u002Ftasks              # 列出后台运行的子代理\n",[159,1869,1870,1878,1886],{"__ignoreMap":157},[246,1871,1872,1875],{"class":248,"line":249},[246,1873,1874],{"class":424},"\u002Fagents",[246,1876,1877],{"class":607},"              # 管理子代理\n",[246,1879,1880,1883],{"class":248,"line":256},[246,1881,1882],{"class":424},"\u002Fbatch",[246,1884,1885],{"class":607},"              # 把大改动拆成独立单元，每个跑在自己的 git worktree\n",[246,1887,1888,1891],{"class":248,"line":263},[246,1889,1890],{"class":424},"\u002Ftasks",[246,1892,1893],{"class":607},"              # 列出后台运行的子代理\n",[17,1895,1896,1897,1902],{},"据 ",[795,1898,1901],{"href":1899,"rel":1900},"https:\u002F\u002Fcomputingforgeeks.com\u002Fclaude-code-cheat-sheet",[862],"computingforgeeks.com 2026 cheat sheet"," 整理，子代理让\"一边改前端，一边改后端\"这种并行操作不会污染主对话上下文。",[406,1904,1906],{"id":1905},"slash-命令生产力关键","Slash 命令（生产力关键）",[17,1908,1909],{},"Claude Code 内置了一套 slash 命令，是日常使用的核心：",[40,1911,1912,1922],{},[43,1913,1914],{},[46,1915,1916,1919],{},[49,1917,1918],{},"命令",[49,1920,1921],{},"用途",[62,1923,1924,1937,1947,1959,1969,1979,1989,1999,2009,2019,2029,2039,2049],{},[46,1925,1926,1931],{},[67,1927,1928],{},[159,1929,1930],{},"\u002Finit",[67,1932,1933,1934,1936],{},"第一次进入仓库时跑，生成 ",[159,1935,190],{},"（项目记忆）",[46,1938,1939,1944],{},[67,1940,1941],{},[159,1942,1943],{},"\u002Fmemory",[67,1945,1946],{},"编辑长期记忆",[46,1948,1949,1953],{},[67,1950,1951],{},[159,1952,697],{},[67,1954,1955,1956,1595],{},"清空当前对话，重新开始（",[147,1957,1958],{},"最被低估的命令",[46,1960,1961,1966],{},[67,1962,1963],{},[159,1964,1965],{},"\u002Fcompact",[67,1967,1968],{},"长对话压缩，挽救快爆炸的 context window",[46,1970,1971,1976],{},[67,1972,1973],{},[159,1974,1975],{},"\u002Fcontext",[67,1977,1978],{},"显示当前 context 用量",[46,1980,1981,1986],{},[67,1982,1983],{},[159,1984,1985],{},"\u002Fplan",[67,1987,1988],{},"切到 plan 模式（只规划不执行）",[46,1990,1991,1996],{},[67,1992,1993],{},[159,1994,1995],{},"\u002Fmodel",[67,1997,1998],{},"切换模型（Opus \u002F Sonnet \u002F Haiku）",[46,2000,2001,2006],{},[67,2002,2003],{},[159,2004,2005],{},"\u002Fdiff",[67,2007,2008],{},"看本轮所有改动",[46,2010,2011,2016],{},[67,2012,2013],{},[159,2014,2015],{},"\u002Fcode-review",[67,2017,2018],{},"对 diff 跑代码审查",[46,2020,2021,2026],{},[67,2022,2023],{},[159,2024,2025],{},"\u002Frewind",[67,2027,2028],{},"回滚到任意 checkpoint（代码 + 对话）",[46,2030,2031,2036],{},[67,2032,2033],{},[159,2034,2035],{},"\u002Fmcp",[67,2037,2038],{},"管理 MCP 服务器",[46,2040,2041,2046],{},[67,2042,2043],{},[159,2044,2045],{},"\u002Fdoctor",[67,2047,2048],{},"排查环境问题",[46,2050,2051,2060],{},[67,2052,2053,2056,2057],{},[159,2054,2055],{},"\u002Fresume"," ",[159,2058,2059],{},"\u002Fbranch",[67,2061,2062],{},"回到 \u002F fork 历史对话",[17,2064,2065,2070,2071,2073,2074,2076,2077,2080],{},[795,2066,2069],{"href":2067,"rel":2068},"https:\u002F\u002Flearn-prompting.fr\u002Fblog\u002Fclaude-code-slash-commands-reference",[862],"learn-prompting.fr 2026-04 总结","：成熟团队最常用的三个是 ",[159,2072,1965],{},"（每 20-30 分钟一次防止 context drift）、",[159,2075,697],{},"（新任务开新会话）、自定义命令（写在 ",[159,2078,2079],{},".claude\u002Fcommands\u002F"," 提交进 git）。",[406,2082,2084],{"id":2083},"mcp-集成一等公民","MCP 集成（一等公民）",[17,2086,2087,2089,2090,2093],{},[795,2088,755],{"href":1641}," 是 Anthropic 自家协议，Claude Code 是 MCP 支持最完整的客户端。配置一次 ",[159,2091,2092],{},".mcp.json","，Claude Code 就能在对话里调任意 MCP server 暴露的 tool：",[151,2095,2099],{"className":2096,"code":2097,"language":2098,"meta":157,"style":157},"language-json shiki shiki-themes github-light github-dark","{\n  \"mcpServers\": {\n    \"postgres\": {\n      \"command\": \"npx\",\n      \"args\": [\"@modelcontextprotocol\u002Fserver-postgres\", \"postgresql:\u002F\u002F...\"]\n    }\n  }\n}\n","json",[159,2100,2101,2106,2114,2121,2135,2155,2160,2165],{"__ignoreMap":157},[246,2102,2103],{"class":248,"line":249},[246,2104,2105],{"class":276},"{\n",[246,2107,2108,2111],{"class":248,"line":256},[246,2109,2110],{"class":428},"  \"mcpServers\"",[246,2112,2113],{"class":276},": {\n",[246,2115,2116,2119],{"class":248,"line":263},[246,2117,2118],{"class":428},"    \"postgres\"",[246,2120,2113],{"class":276},[246,2122,2123,2126,2129,2132],{"class":248,"line":269},[246,2124,2125],{"class":428},"      \"command\"",[246,2127,2128],{"class":276},": ",[246,2130,2131],{"class":432},"\"npx\"",[246,2133,2134],{"class":276},",\n",[246,2136,2137,2140,2143,2146,2149,2152],{"class":248,"line":280},[246,2138,2139],{"class":428},"      \"args\"",[246,2141,2142],{"class":276},": [",[246,2144,2145],{"class":432},"\"@modelcontextprotocol\u002Fserver-postgres\"",[246,2147,2148],{"class":276},", ",[246,2150,2151],{"class":432},"\"postgresql:\u002F\u002F...\"",[246,2153,2154],{"class":276},"]\n",[246,2156,2157],{"class":248,"line":288},[246,2158,2159],{"class":276},"    }\n",[246,2161,2162],{"class":248,"line":5},[246,2163,2164],{"class":276},"  }\n",[246,2166,2167],{"class":248,"line":300},[246,2168,2169],{"class":276},"}\n",[17,2171,2172],{},"之后你就能直接说\"查一下 users 表里最近 7 天注册的人数\"——Claude Code 自动通过 MCP 跑 SQL，结果返回对话里继续讨论。",[406,2174,2176],{"id":2175},"后台-远程模式","后台 \u002F 远程模式",[17,2178,2179,2182,2183,2186,2187,2190],{},[159,2180,2181],{},"\u002Fbackground"," 让当前会话脱离终端，作为后台 agent 继续跑；",[159,2184,2185],{},"\u002Fteleport"," 把网页端会话拉到本地终端继续；",[159,2188,2189],{},"\u002Fremote-control"," 从手机或另一台机器接管这台机器的 Claude Code 会话。这套体系是面向\"agent 长时间跑\"设计的，区别于 Cursor 的\"实时交互\"。",[13,2192,1197],{"id":1197},[17,2194,2195,2196,2201,2202,2207],{},"根据 ",[795,2197,2200],{"href":2198,"rel":2199},"https:\u002F\u002Fwww.explainx.ai\u002Fblog\u002Fclaude-code-pricing-guide-2026",[862],"explainx.ai 2026-06 评测"," 和 ",[795,2203,2206],{"href":2204,"rel":2205},"https:\u002F\u002Fclaude.com\u002Fpricing",[862],"Anthropic 官方定价"," 整理：",[40,2209,2210,2222],{},[43,2211,2212],{},[46,2213,2214,2217,2220],{},[49,2215,2216],{},"路径",[49,2218,2219],{},"价格",[49,2221,15],{},[62,2223,2224,2237,2250,2263,2276],{},[46,2225,2226,2231,2234],{},[67,2227,2228],{},[147,2229,2230],{},"BYOK（自带 API key）",[67,2232,2233],{},"按 token 计费",[67,2235,2236],{},"全自由，但单月烧到 $500+ 也常见",[46,2238,2239,2244,2247],{},[67,2240,2241],{},[147,2242,2243],{},"Pro",[67,2245,2246],{},"$20\u002F月（年付 ~$17）",[67,2248,2249],{},"个人开发者，每天 1-4 小时",[46,2251,2252,2257,2260],{},[67,2253,2254],{},[147,2255,2256],{},"Max 5x",[67,2258,2259],{},"$100\u002F月",[67,2261,2262],{},"重度用户 + Opus 模型访问",[46,2264,2265,2270,2273],{},[67,2266,2267],{},[147,2268,2269],{},"Max 20x",[67,2271,2272],{},"$200\u002F月",[67,2274,2275],{},"8h+ agentic 工作流 \u002F 团队共享",[46,2277,2278,2283,2286],{},[67,2279,2280],{},[147,2281,2282],{},"Team Premium",[67,2284,2285],{},"$100\u002Fseat 年付 \u002F $125 月付",[67,2287,2288],{},"团队，含管理",[17,2290,2291],{},"API token 价格（2026 Q2 公开数据）：",[21,2293,2294,2297,2300],{},[24,2295,2296],{},"Sonnet 4.x：input $3 \u002F output $15 per 1M token",[24,2298,2299],{},"Opus 4.x：input $15 \u002F output $75 per 1M token",[24,2301,2302],{},"Haiku 4.x：input $1 \u002F output $5 per 1M token",[17,2304,2305,2310],{},[795,2306,2309],{"href":2307,"rel":2308},"https:\u002F\u002Fwww.ksred.com\u002Fclaude-code-pricing-guide-which-plan-actually-saves-you-money",[862],"ksred 博客真实使用日志","：作者 8 个月用 ~100 亿 token，API 价折合 $15,000+，订阅实际只花 $800——订阅模式对重度用户极度划算，但前提是能搞定支付。",[13,2312,1036],{"id":1035},[151,2314,2316],{"className":415,"code":2315,"language":417,"meta":157,"style":157},"# macOS \u002F Linux \u002F Windows (WSL)\ncurl -fsSL https:\u002F\u002Fclaude.ai\u002Finstall.sh | bash\n\n# macOS 用 Homebrew\nbrew install --cask claude-code\n\n# Windows PowerShell\nirm https:\u002F\u002Fclaude.ai\u002Finstall.ps1 | iex\n\n# 验证 + 登录\nclaude --version\nclaude auth login          # 走浏览器 OAuth，绑定 Pro \u002F Max 订阅\n# 或用 API key\nexport ANTHROPIC_API_KEY=sk-ant-...\n\n# 进项目，启动\ncd your-project\nclaude \u002Finit               # 生成 CLAUDE.md\nclaude                     # 进入交互模式\n",[159,2317,2318,2323,2340,2344,2349,2362,2366,2371,2384,2388,2393,2400,2413,2418,2428,2432,2437,2443,2453],{"__ignoreMap":157},[246,2319,2320],{"class":248,"line":249},[246,2321,2322],{"class":607},"# macOS \u002F Linux \u002F Windows (WSL)\n",[246,2324,2325,2328,2331,2334,2337],{"class":248,"line":256},[246,2326,2327],{"class":424},"curl",[246,2329,2330],{"class":428}," -fsSL",[246,2332,2333],{"class":432}," https:\u002F\u002Fclaude.ai\u002Finstall.sh",[246,2335,2336],{"class":619}," |",[246,2338,2339],{"class":424}," bash\n",[246,2341,2342],{"class":248,"line":263},[246,2343,260],{"emptyLinePlaceholder":259},[246,2345,2346],{"class":248,"line":269},[246,2347,2348],{"class":607},"# macOS 用 Homebrew\n",[246,2350,2351,2354,2356,2359],{"class":248,"line":280},[246,2352,2353],{"class":424},"brew",[246,2355,1060],{"class":432},[246,2357,2358],{"class":428}," --cask",[246,2360,2361],{"class":432}," claude-code\n",[246,2363,2364],{"class":248,"line":288},[246,2365,260],{"emptyLinePlaceholder":259},[246,2367,2368],{"class":248,"line":5},[246,2369,2370],{"class":607},"# Windows PowerShell\n",[246,2372,2373,2376,2379,2381],{"class":248,"line":300},[246,2374,2375],{"class":424},"irm",[246,2377,2378],{"class":432}," https:\u002F\u002Fclaude.ai\u002Finstall.ps1",[246,2380,2336],{"class":619},[246,2382,2383],{"class":424}," iex\n",[246,2385,2386],{"class":248,"line":306},[246,2387,260],{"emptyLinePlaceholder":259},[246,2389,2390],{"class":248,"line":314},[246,2391,2392],{"class":607},"# 验证 + 登录\n",[246,2394,2395,2397],{"class":248,"line":322},[246,2396,1791],{"class":424},[246,2398,2399],{"class":428}," --version\n",[246,2401,2402,2404,2407,2410],{"class":248,"line":330},[246,2403,1791],{"class":424},[246,2405,2406],{"class":432}," auth",[246,2408,2409],{"class":432}," login",[246,2411,2412],{"class":607},"          # 走浏览器 OAuth，绑定 Pro \u002F Max 订阅\n",[246,2414,2415],{"class":248,"line":335},[246,2416,2417],{"class":607},"# 或用 API key\n",[246,2419,2420,2422,2424,2426],{"class":248,"line":341},[246,2421,1103],{"class":619},[246,2423,1106],{"class":276},[246,2425,1109],{"class":619},[246,2427,1112],{"class":276},[246,2429,2430],{"class":248,"line":349},[246,2431,260],{"emptyLinePlaceholder":259},[246,2433,2434],{"class":248,"line":357},[246,2435,2436],{"class":607},"# 进项目，启动\n",[246,2438,2439,2441],{"class":248,"line":365},[246,2440,1086],{"class":428},[246,2442,1089],{"class":432},[246,2444,2445,2447,2450],{"class":248,"line":373},[246,2446,1791],{"class":424},[246,2448,2449],{"class":432}," \u002Finit",[246,2451,2452],{"class":607},"               # 生成 CLAUDE.md\n",[246,2454,2455,2457],{"class":248,"line":378},[246,2456,1791],{"class":424},[246,2458,2459],{"class":607},"                     # 进入交互模式\n",[13,2461,1257],{"id":1257},[532,2463,2464,2470,2476,2482],{},[24,2465,2466,2469],{},[147,2467,2468],{},"账号","：注册 claude.ai 需要海外手机号（Google Voice \u002F Twilio 可，国内号被封死）",[24,2471,2472,2475],{},[147,2473,2474],{},"支付","：Pro \u002F Max 订阅只收海外信用卡（MasterCard \u002F Visa）+ 海外账单地址。第三方平台（如老张 \u002F DMXAPI）可用支付宝走 API 代理，但是 BYOK 模式",[24,2477,2478,2481],{},[147,2479,2480],{},"网络","：终端 OAuth 流程对代理稳定性要求高，掉线会反复弹浏览器",[24,2483,2484,2487,2488,1558,2491,2493,2494,210,2496,2500],{},[147,2485,2486],{},"替代路径","：用 ",[795,2489,101],{"href":2490},"\u002Fcoding\u002Fcli\u002Faider.html",[795,2492,1324],{"href":1323}," 接 ",[795,2495,1249],{"href":1248},[795,2497,2499],{"href":2498},"\u002Fmodels\u002Fglm-5.2.html","GLM-5.2"," 是国内最经济的\"Claude Code 平替\"思路",[13,2502,1298],{"id":1298},[40,2504,2505,2525],{},[43,2506,2507],{},[46,2508,2509,2511,2513,2517,2521],{},[49,2510,1307],{},[49,2512,72],{},[49,2514,2515],{},[795,2516,228],{"href":1220},[49,2518,2519],{},[795,2520,75],{"href":1318},[49,2522,2523],{},[795,2524,101],{"href":2490},[62,2526,2527,2543,2557,2575,2595,2609,2622,2639],{},[46,2528,2529,2532,2535,2538,2541],{},[67,2530,2531],{},"形态",[67,2533,2534],{},"CLI（IDE 无关）",[67,2536,2537],{},"AI-first IDE",[67,2539,2540],{},"CLI",[67,2542,2540],{},[46,2544,2545,2548,2550,2553,2555],{},[67,2546,2547],{},"长任务能力",[67,2549,1381],{},[67,2551,2552],{},"★★★★☆",[67,2554,2552],{},[67,2556,1384],{},[46,2558,2559,2562,2569,2571,2573],{},[67,2560,2561],{},"上下文管理",[67,2563,2564,2565,2056,2567],{},"★★★★★ ",[159,2566,1965],{},[159,2568,697],{},[67,2570,2552],{},[67,2572,2552],{},[67,2574,1384],{},[46,2576,2577,2580,2587,2590,2593],{},[67,2578,2579],{},"子代理 \u002F 并行",[67,2581,2582,2583,2056,2585,1595],{},"✅（",[159,2584,1874],{},[159,2586,1882],{},[67,2588,2589],{},"部分（Bug bot）",[67,2591,2592],{},"⚠️ 有限",[67,2594,1337],{},[46,2596,2597,2600,2603,2605,2607],{},[67,2598,2599],{},"MCP 支持",[67,2601,2602],{},"★★★★★ 一等公民",[67,2604,2552],{},[67,2606,1384],{},[67,2608,1337],{},[46,2610,2611,2613,2615,2617,2619],{},[67,2612,1378],{},[67,2614,2552],{},[67,2616,1384],{},[67,2618,1384],{},[67,2620,2621],{},"★★★★★ 每改即 commit",[46,2623,2624,2627,2630,2633,2636],{},[67,2625,2626],{},"国内门槛",[67,2628,2629],{},"高（账号+支付+网络）",[67,2631,2632],{},"高（账号+支付）",[67,2634,2635],{},"高",[67,2637,2638],{},"低（BYOK 国产模型）",[46,2640,2641,2643,2646,2649,2651],{},[67,2642,2219],{},[67,2644,2645],{},"$20-$200\u002F月",[67,2647,2648],{},"$20\u002F月",[67,2650,2645],{},[67,2652,2653],{},"仅 API 成本",[17,2655,2656,864],{},[147,2657,2658],{},"选 Claude Code 如果你",[21,2660,2661,2664,2667,2670],{},[24,2662,2663],{},"重视长任务自主性 + 上下文管理",[24,2665,2666],{},"JetBrains \u002F Vim 用户，不想换 IDE",[24,2668,2669],{},"团队需要 SSH 远程 \u002F 后台 agent 模式",[24,2671,2672],{},"已经在用 Claude Pro\u002FMax，加 Code 是边际成本",[17,2674,2675,864],{},[147,2676,2677],{},"别选 Claude Code 如果你",[21,2679,2680,2686,2691],{},[24,2681,2682,2683,2685],{},"国内、个人、预算紧（去 ",[795,2684,101],{"href":2490}," + DeepSeek）",[24,2687,2688,2689,1595],{},"想要纯 IDE 内 inline 体验（",[795,2690,228],{"href":1220},[24,2692,2693,2694,1595],{},"主要写补全而非 agent 任务（",[795,2695,204],{"href":2696},"\u002Fcoding\u002Fcopilot\u002Fgithub-copilot.html",[13,2698,1464],{"id":1464},[21,2700,2701,2714,2729,2743,2751,2769,2783,2789],{},[24,2702,2703,2709,2710,2713],{},[147,2704,2705,2708],{},[159,2706,2707],{},"ANTHROPIC_API_KEY"," 优先级最高","：你以为在用 Pro 订阅，但 env 里有 key 时实际走 API 计费——卡崩之前先 ",[159,2711,2712],{},"env | grep ANTHROPIC"," 检查",[24,2715,2716,2722,2723,2725,2726,2728],{},[147,2717,2718,2719,2721],{},"长会话不 ",[159,2720,1965],{}," 会越来越笨","：context 接近上限时，模型会开始忘记前面约定。社区共识：每 20-30 分钟 ",[159,2724,1965],{}," 一次或 ",[159,2727,697],{}," 开新会话",[24,2730,2731,2736,2737,2742],{},[147,2732,2733,2735],{},[159,2734,1995],{}," 切换是个坑","：跨模型切会丢部分 context ",[795,2738,2741],{"href":2739,"rel":2740},"https:\u002F\u002Fwww.reddit.com\u002Fr\u002FClaudeAI\u002F",[862],"据 r\u002FClaudeAI 反馈","；建议起新会话指定模型",[24,2744,2745,2750],{},[147,2746,2747,2749],{},[159,2748,1930],{}," 生成的 CLAUDE.md 要 review","：自动生成的会有冗余\u002F错误，第一次进项目花 5 分钟整理",[24,2752,2753,2758,2759,2056,2762,2056,2765,2768],{},[147,2754,2755,2757],{},[159,2756,2079],{}," 自定义命令是放大器","：把团队最常用的工作流写成 ",[159,2760,2761],{},"\u002Fdeploy",[159,2763,2764],{},"\u002Fmigrate",[159,2766,2767],{},"\u002Freview-pr","，提交进 git",[24,2770,2771,2774,2775,2778,2779,2782],{},[147,2772,2773],{},"后台 agent + 重写大量文件 = 危险组合","：长任务跑通常加 ",[159,2776,2777],{},"--permission-mode plan"," 或开 ",[159,2780,2781],{},"acceptEdits"," 但配合 git worktree",[24,2784,2785,2788],{},[147,2786,2787],{},"Windows 原生支持有限","：官方推荐 WSL，PowerShell 安装路径有时跑不通",[24,2790,2791,2794],{},[147,2792,2793],{},"API token 烧钱速度","：BYOK 模式下，复杂 refactor 单次任务可能消耗几百万 token",[13,2796,1615],{"id":1615},[21,2798,2799,2811,2823,2838],{},[24,2800,1620,2801,210,2803,210,2805,210,2807,210,2809],{},[795,2802,228],{"href":1220},[795,2804,1224],{"href":1223},[795,2806,75],{"href":1318},[795,2808,101],{"href":2490},[795,2810,1324],{"href":1323},[24,2812,2813,2814,210,2817,210,2819,210,2821],{},"概念：",[795,2815,2816],{"href":1862},"AI Agent",[795,2818,1645],{"href":1644},[795,2820,755],{"href":1641},[795,2822,1652],{"href":1651},[24,2824,2825,2826,210,2830,210,2834],{},"模型：",[795,2827,2829],{"href":2828},"\u002Fmodels\u002Fclaude-opus-4.html","Claude Opus 4",[795,2831,2833],{"href":2832},"\u002Fmodels\u002Fclaude-sonnet-4.html","Claude Sonnet 4",[795,2835,2837],{"href":2836},"\u002Fmodels\u002Fclaude-haiku-4.html","Claude Haiku 4",[24,2839,2840,2841,210,2845],{},"进阶：",[795,2842,2844],{"href":2843},"\u002Fwiki\u002Fvibe-coding.html","Vibe Coding",[795,2846,2848],{"href":2847},"\u002Fwiki\u002Fprompt-engineering.html","Prompt Engineering",[13,2850,1655],{"id":1655},[21,2852,2853,2859,2865,2871,2878,2884],{},[24,2854,1660,2855],{},[795,2856,2857],{"href":2857,"rel":2858},"https:\u002F\u002Fclaude.com\u002Fclaude-code",[862],[24,2860,1667,2861],{},[795,2862,2863],{"href":2863,"rel":2864},"https:\u002F\u002Fcode.claude.com\u002Fdocs\u002Fen\u002Foverview",[862],[24,2866,1686,2867],{},[795,2868,2869],{"href":2869,"rel":2870},"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fclaude-code",[862],[24,2872,2873,2874],{},"CLI Reference：",[795,2875,2876],{"href":2876,"rel":2877},"https:\u002F\u002Fcode.claude.com\u002Fdocs\u002Fen\u002Fcli-reference",[862],[24,2879,2880,2881],{},"官方定价：",[795,2882,2204],{"href":2204,"rel":2883},[862],[24,2885,2886],{},"第三方评测：laozhang.ai \u002F explainx.ai \u002F computingforgeeks.com \u002F ksred.com \u002F learn-prompting.fr",[17,2888,2889,2890,1710],{},"本卡片由 AIHO 编辑部根据官方公开资料与第三方评测整理。所有事实点均标注来源；如发现价格 \u002F 命令 \u002F 功能与最新官方信息不一致，请通过 ",[795,2891,1709],{"href":1709},[721,2893,2894],{},"html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":157,"searchDepth":263,"depth":263,"links":2896},[2897,2898,2905,2906,2907,2908,2909,2910,2911],{"id":768,"depth":256,"text":769},{"id":807,"depth":256,"text":807,"children":2899},[2900,2901,2902,2903,2904],{"id":1813,"depth":263,"text":1814},{"id":1855,"depth":263,"text":1856},{"id":1905,"depth":263,"text":1906},{"id":2083,"depth":263,"text":2084},{"id":2175,"depth":263,"text":2176},{"id":1197,"depth":256,"text":1197},{"id":1035,"depth":256,"text":1036},{"id":1257,"depth":256,"text":1257},{"id":1298,"depth":256,"text":1298},{"id":1464,"depth":256,"text":1464},{"id":1615,"depth":256,"text":1615},{"id":1655,"depth":256,"text":1655},"\u002Fimg\u002Ftools\u002Fclaude-code.webp","Claude Code 真实评测：Anthropic 官方 CLI Agent，跑在终端，跨 IDE，长任务规划与多步骤执行能力强。AIHO 编辑部基于官方文档与社区资料整理，含子代理、slash 命令、MCP、避坑指南。",[1737],{},[2917,2918,2919],"claude-opus-4","claude-sonnet-4-5","claude-haiku-4",[2921,2922,2923],"国内裸跑（账号 \u002F 支付 \u002F 网络三关）","预算 ¥100\u002F月以内的个人开发者","只想做基础代码补全（用 GitHub Copilot 更经济）","\u002Ftools\u002Fcoding\u002Fcli\u002Fclaude-code",[1743,1744,1742],[2927,2933,2938,2942],{"plan":2928,"price":2929,"limit":2930,"cn_pay":2931,"note":2932},"Pay-as-go","按 API token 计费","Sonnet $3\u002F$15 per Mtok，Opus $15\u002F$75","✅ 第三方中转支持支付宝","BYOK 模式",{"plan":2934,"price":2648,"limit":2935,"cn_pay":2936,"note":2937},"Claude Pro","约 1-4 小时\u002F天活跃编码","⚠️ 需海外卡","网页 + Code 共享额度",{"plan":2939,"price":2259,"limit":2940,"cn_pay":2936,"note":2941},"Claude Max 5x","Pro 的 5 倍 + Opus 接入","重度用户",{"plan":2943,"price":2272,"limit":2944,"cn_pay":2936,"note":2945},"Claude Max 20x","Pro 的 20 倍 + 优先队列","8h+\u002F天 agentic 工作流","API 按 token 计费 \u002F Pro $20 \u002F Max $100-$200 \u002F Team Premium $100-$125 seat",{"power":280,"ux":269,"price":263,"cn_support":256,"stability":269},{"title":72,"description":2913},[2950,2952,2953,2955,2958],{"title":2951,"url":2863},"Claude Code 官方文档",{"title":2206,"url":2204},{"title":2954,"url":2876},"Claude Code CLI Reference",{"title":2956,"url":2957},"Claude Code Pricing Guide 2026","https:\u002F\u002Fblog.laozhang.ai\u002Fen\u002Fposts\u002Fclaude-code-pricing-guide",{"title":2959,"url":1899},"Claude Code Cheat Sheet 2026","tools\u002Fcoding\u002Fcli\u002Fclaude-code",[2962,2963,2964,2965,2966],"JetBrains \u002F Vim \u002F Emacs 用户（不想换编辑器）","需要长任务自主规划（>30min 单次任务）","服务器开发、运维脚本、CI\u002FCD 场景","需要在 SSH 远程主机上跑 AI 编程","重视稳定性 + 长上下文连贯性","Anthropic 官方终端 AI Coding Agent，长任务能力业界第一梯队",[1731,1765,2969,1776,2970,2971],"terminal","long-task","mcp","Cursor 的强力补充。终端原生、IDE 无关、长任务跑得比 Cursor 稳。但 API 计费贵且国内更难用。","-xOhSW-XQ63ME7-rjuV0CXSf19Fo3sNpSkuvMX7-Hfs",{"id":2975,"title":75,"alternatives":2976,"api_compatible":2977,"body":2979,"category":1731,"chinese_friendly":263,"cover":3631,"description":3632,"domestic":1734,"extension":242,"faq":3633,"free":1734,"github":3005,"languages":3649,"meta":3650,"models":3651,"navigation":259,"notSuitable":3655,"opensource":259,"path":3659,"pillar":1740,"platforms":3660,"priceTable":3661,"pricing":3677,"published":1746,"relatedPlaybooks":3678,"relatedReviews":763,"score":3681,"self_host":1734,"seo":3682,"slug":748,"sources":3683,"stem":3692,"suitable":3693,"tagline":3698,"tags":3699,"updated":1769,"verdict":3703,"website":3583,"__hash__":3704},"tools\u002Ftools\u002Fcoding\u002Fcli\u002Fcodex.md",[747,750,762],[2978],"openai",{"type":10,"value":2980,"toc":3615},[2981,2983,2998,3001,3013,3016,3036,3039,3069,3071,3129,3134,3138,3143,3147,3168,3171,3175,3198,3202,3222,3225,3227,3328,3338,3341,3477,3482,3484,3538,3540,3547,3549,3575,3577,3604,3612],[13,2982,769],{"id":768},[771,2984,2986,2995],{"className":2985},[774,775,776],[17,2987,2988,2990,2991,2994],{},[147,2989,781],{}," Codex CLI 是 OpenAI 官方做的终端 Coding Agent，对标 Claude Code。",[147,2992,2993],{},"Rust 实现 + Windows 原生沙箱 + 子代理 + MCP + Hooks","，2026 默认模型 gpt-5-codex \u002F gpt-5-codex-mini，ChatGPT Plus\u002FPro\u002FTeam\u002FEdu 已含使用额度。",[17,2996,2997],{},"形态和 Claude Code 几乎一样，差异主要在模型选择。喜欢 GPT 的人选它，喜欢 Claude 的留 Claude Code。",[13,2999,3000],{"id":3000},"它到底是个什么",[17,3002,3003,3008,3009,3012],{},[795,3004,3007],{"href":3005,"rel":3006},"https:\u002F\u002Fgithub.com\u002Fopenai\u002Fcodex",[862],"GitHub: openai\u002Fcodex","，",[147,3010,3011],{},"Apache-2.0 开源","，Rust 写的二进制，428+ 贡献者。在终端里跑一个能读 \u002F 改 \u002F 执行代码的 Agent，类似 Claude Code 但绑定 OpenAI 模型。",[17,3014,3015],{},"2026 的三个主线：",[532,3017,3018,3024,3030],{},[24,3019,3020,3023],{},[147,3021,3022],{},"速度 & 实时","：gpt-5.3-codex-spark 推理速度 1000+ token\u002Fs；WebSocket 远程控制延迟优化。",[24,3025,3026,3029],{},[147,3027,3028],{},"Agent 自主性","：Subagents GA、Smart Approvals、PostToolUse hooks、worktree 自动化。",[24,3031,3032,3035],{},[147,3033,3034],{},"企业就绪","：自定义 CA 证书、userpromptsubmit hooks、托管配置、插件策略强制。",[17,3037,3038],{},"最有用的 4 个能力：",[21,3040,3041,3047,3053,3059],{},[24,3042,3043,3046],{},[147,3044,3045],{},"沙箱执行","：默认在受限沙箱跑命令（macOS Sandbox \u002F Linux Landlock \u002F Windows AppContainer），不会污染主机。",[24,3048,3049,3052],{},[147,3050,3051],{},"MCP 工具调用","：连 GitHub \u002F 数据库 \u002F Slack \u002F 自建 server，支持并行 tool call。",[24,3054,3055,3058],{},[147,3056,3057],{},"Subagents","：把大任务拆给多个并行 sub-agent，token 用得多但效率高。",[24,3060,3061,3064,3065,3068],{},[147,3062,3063],{},"Image inputs","：终端里 ",[159,3066,3067],{},"codex -i screenshot.png \"解释这个错误\""," 直接读图。",[13,3070,2219],{"id":2219},[40,3072,3073,3085],{},[43,3074,3075],{},[46,3076,3077,3080,3082],{},[49,3078,3079],{},"档位",[49,3081,2219],{},[49,3083,3084],{},"说明",[62,3086,3087,3097,3107,3118],{},[46,3088,3089,3092,3094],{},[67,3090,3091],{},"ChatGPT Plus",[67,3093,2648],{},[67,3095,3096],{},"含 Codex CLI 用量（2026-03 起 mini 模型额度 +4×）",[46,3098,3099,3102,3104],{},[67,3100,3101],{},"ChatGPT Pro",[67,3103,2272],{},[67,3105,3106],{},"更高额度 + 优先处理 + Spark 研究预览",[46,3108,3109,3112,3115],{},[67,3110,3111],{},"Business \u002F Edu \u002F Team",[67,3113,3114],{},"$25-30\u002F用户\u002F月起",[67,3116,3117],{},"企业管理 + SSO + Codex 含在内",[46,3119,3120,3123,3126],{},[67,3121,3122],{},"纯 API",[67,3124,3125],{},"按 token",[67,3127,3128],{},"gpt-5.5 ≈ $1.25 \u002F $10 per 1M token",[800,3130,3131],{},[17,3132,3133],{},"已经付 ChatGPT Plus 的人，等于白嫖一个 Codex CLI 用量，几乎不必另开 API 账号。",[13,3135,3137],{"id":3136},"真实任务实测基于官方文档归纳","真实任务实测（基于官方文档归纳）",[800,3139,3140],{},[17,3141,3142],{},"来源说明：以下基于 Codex CLI 官方 features 文档与公开评测整合。",[406,3144,3146],{"id":3145},"任务-1在-50k-行-rust-项目里加新-feature","任务 1：在 50k 行 Rust 项目里加新 feature",[151,3148,3150],{"className":415,"code":3149,"language":417,"meta":157,"style":157},"codex -m gpt-5-codex\n> 在 src\u002Fauth 模块下加 OAuth2 callback handler，参考已有的 token refresh 实现\n",[159,3151,3152,3161],{"__ignoreMap":157},[246,3153,3154,3156,3158],{"class":248,"line":249},[246,3155,500],{"class":424},[246,3157,1054],{"class":428},[246,3159,3160],{"class":432}," gpt-5-codex\n",[246,3162,3163,3165],{"class":248,"line":256},[246,3164,1191],{"class":619},[246,3166,3167],{"class":276}," 在 src\u002Fauth 模块下加 OAuth2 callback handler，参考已有的 token refresh 实现\n",[17,3169,3170],{},"Agent 会 plan → 读相关文件 → 跑 cargo check → 跑测试 → 提 diff。子代理可以同时跑 lint 和 test 两条线。",[406,3172,3174],{"id":3173},"任务-2ci-失败自动-debug","任务 2：CI 失败自动 debug",[151,3176,3178],{"className":415,"code":3177,"language":417,"meta":157,"style":157},"codex --features enable post_tool_use_hook\n# 然后跑 cargo test，CI 失败时 Hook 自动触发 Agent 分析失败 + 写 fix\n",[159,3179,3180,3193],{"__ignoreMap":157},[246,3181,3182,3184,3187,3190],{"class":248,"line":249},[246,3183,500],{"class":424},[246,3185,3186],{"class":428}," --features",[246,3188,3189],{"class":432}," enable",[246,3191,3192],{"class":432}," post_tool_use_hook\n",[246,3194,3195],{"class":248,"line":256},[246,3196,3197],{"class":607},"# 然后跑 cargo test，CI 失败时 Hook 自动触发 Agent 分析失败 + 写 fix\n",[406,3199,3201],{"id":3200},"任务-3跨仓库脚手架生成","任务 3：跨仓库脚手架生成",[151,3203,3205],{"className":415,"code":3204,"language":417,"meta":157,"style":157},"codex -m gpt-5-codex\n> 用 mono-repo 模式建 3 个 package：core \u002F cli \u002F web，统一走 pnpm workspace\n",[159,3206,3207,3215],{"__ignoreMap":157},[246,3208,3209,3211,3213],{"class":248,"line":249},[246,3210,500],{"class":424},[246,3212,1054],{"class":428},[246,3214,3160],{"class":432},[246,3216,3217,3219],{"class":248,"line":256},[246,3218,1191],{"class":619},[246,3220,3221],{"class":276}," 用 mono-repo 模式建 3 个 package：core \u002F cli \u002F web，统一走 pnpm workspace\n",[17,3223,3224],{},"子代理并行起 3 个目录的初始化，单次任务跑完 ~3 分钟，token 用约 80k。",[13,3226,1036],{"id":1035},[151,3228,3230],{"className":415,"code":3229,"language":417,"meta":157,"style":157},"# macOS \u002F Linux\ncurl -fsSL https:\u002F\u002Fchatgpt.com\u002Fcodex\u002Finstall.sh | sh\n\n# Windows（原生 PowerShell）\n# 见官方 Windows setup guide，或用 npm i -g @openai\u002Fcodex\n\ncodex                          # 启动 TUI\ncodex -m gpt-5-codex .         # 在当前目录起 Agent\ncodex --remote wss:\u002F\u002F...       # 远程模式（SSH \u002F 容器）\ncodex features list            # 看可用 feature flag\ncodex features enable unified_exec\n",[159,3231,3232,3237,3251,3255,3260,3265,3269,3276,3291,3304,3317],{"__ignoreMap":157},[246,3233,3234],{"class":248,"line":249},[246,3235,3236],{"class":607},"# macOS \u002F Linux\n",[246,3238,3239,3241,3243,3246,3248],{"class":248,"line":256},[246,3240,2327],{"class":424},[246,3242,2330],{"class":428},[246,3244,3245],{"class":432}," https:\u002F\u002Fchatgpt.com\u002Fcodex\u002Finstall.sh",[246,3247,2336],{"class":619},[246,3249,3250],{"class":424}," sh\n",[246,3252,3253],{"class":248,"line":263},[246,3254,260],{"emptyLinePlaceholder":259},[246,3256,3257],{"class":248,"line":269},[246,3258,3259],{"class":607},"# Windows（原生 PowerShell）\n",[246,3261,3262],{"class":248,"line":280},[246,3263,3264],{"class":607},"# 见官方 Windows setup guide，或用 npm i -g @openai\u002Fcodex\n",[246,3266,3267],{"class":248,"line":288},[246,3268,260],{"emptyLinePlaceholder":259},[246,3270,3271,3273],{"class":248,"line":5},[246,3272,500],{"class":424},[246,3274,3275],{"class":607},"                          # 启动 TUI\n",[246,3277,3278,3280,3282,3285,3288],{"class":248,"line":300},[246,3279,500],{"class":424},[246,3281,1054],{"class":428},[246,3283,3284],{"class":432}," gpt-5-codex",[246,3286,3287],{"class":432}," .",[246,3289,3290],{"class":607},"         # 在当前目录起 Agent\n",[246,3292,3293,3295,3298,3301],{"class":248,"line":306},[246,3294,500],{"class":424},[246,3296,3297],{"class":428}," --remote",[246,3299,3300],{"class":432}," wss:\u002F\u002F...",[246,3302,3303],{"class":607},"       # 远程模式（SSH \u002F 容器）\n",[246,3305,3306,3308,3311,3314],{"class":248,"line":314},[246,3307,500],{"class":424},[246,3309,3310],{"class":432}," features",[246,3312,3313],{"class":432}," list",[246,3315,3316],{"class":607},"            # 看可用 feature flag\n",[246,3318,3319,3321,3323,3325],{"class":248,"line":322},[246,3320,500],{"class":424},[246,3322,3310],{"class":432},[246,3324,3189],{"class":432},[246,3326,3327],{"class":432}," unified_exec\n",[17,3329,3330,3331,3334,3335,1540],{},"配置文件：",[159,3332,3333],{},"$CODEX_HOME\u002Fconfig.toml","（默认 ",[159,3336,3337],{},"~\u002F.codex\u002Fconfig.toml",[13,3339,3340],{"id":3340},"同类对比",[40,3342,3343,3357],{},[43,3344,3345],{},[46,3346,3347,3349,3351,3353,3355],{},[49,3348,1307],{},[49,3350,75],{},[49,3352,72],{},[49,3354,101],{},[49,3356,1324],{},[62,3358,3359,3374,3390,3406,3423,3436,3450,3464],{},[46,3360,3361,3363,3366,3368,3371],{},[67,3362,2531],{},[67,3364,3365],{},"终端 TUI",[67,3367,3365],{},[67,3369,3370],{},"终端 REPL",[67,3372,3373],{},"VS Code 插件",[46,3375,3376,3379,3382,3385,3388],{},[67,3377,3378],{},"默认模型",[67,3380,3381],{},"gpt-5-codex",[67,3383,3384],{},"Claude Sonnet\u002FOpus",[67,3386,3387],{},"BYOK 任意",[67,3389,3387],{},[46,3391,3392,3395,3398,3401,3404],{},[67,3393,3394],{},"含在订阅",[67,3396,3397],{},"ChatGPT Plus\u002FPro",[67,3399,3400],{},"Claude.ai $20\u002F月",[67,3402,3403],{},"❌（仅 API）",[67,3405,3403],{},[46,3407,3408,3411,3414,3417,3420],{},[67,3409,3410],{},"沙箱",[67,3412,3413],{},"macOS Sandbox \u002F Landlock \u002F AppContainer",[67,3415,3416],{},"类似",[67,3418,3419],{},"无",[67,3421,3422],{},"VS Code 环境",[46,3424,3425,3427,3429,3431,3434],{},[67,3426,755],{},[67,3428,1334],{},[67,3430,1334],{},[67,3432,3433],{},"部分",[67,3435,1334],{},[46,3437,3438,3440,3443,3446,3448],{},[67,3439,3057],{},[67,3441,3442],{},"✅ GA",[67,3444,3445],{},"✅ Task tool",[67,3447,1337],{},[67,3449,1337],{},[46,3451,3452,3454,3457,3460,3462],{},[67,3453,1331],{},[67,3455,3456],{},"Apache-2.0",[67,3458,3459],{},"闭源",[67,3461,3456],{},[67,3463,3456],{},[46,3465,3466,3469,3471,3473,3475],{},[67,3467,3468],{},"原生 Windows",[67,3470,1334],{},[67,3472,3433],{},[67,3474,1334],{},[67,3476,1334],{},[800,3478,3479],{},[17,3480,3481],{},"一句话区分：Codex CLI = OpenAI 官方版的 Claude Code；Claude Code = Anthropic 官方版的 Codex；Aider = 任意 OpenAI 兼容 API 都能跑；Cline = VS Code 里的 GUI 终端 Agent。",[13,3483,1464],{"id":1464},[532,3485,3486,3492,3502,3512,3518,3524],{},[24,3487,3488,3491],{},[147,3489,3490],{},"国内访问别频繁切 IP","，OpenAI 风控严，账号被封基本无法找回。",[24,3493,3494,3497,3498,3501],{},[147,3495,3496],{},"沙箱默认会限制网络","，跑 ",[159,3499,3500],{},"npm install"," 等需要联网的命令前先看 approval 弹窗。",[24,3503,3504,3507,3508,3511],{},[147,3505,3506],{},"Subagents 吃 token 多","，预算敏感时关闭 ",[159,3509,3510],{},"[agents]"," 配置或换 mini 模型。",[24,3513,3514,3517],{},[147,3515,3516],{},"WebSocket 远程模式只接受 wss:\u002F\u002F 或 localhost ws:\u002F\u002F","，远程公网必须 TLS。",[24,3519,3520,3523],{},[147,3521,3522],{},"gpt-5-codex 比 gpt-5.5 便宜但能力对齐","，2026-03 之后默认推荐用 codex 系列而非 5.5。",[24,3525,3526,3533,3534,3537],{},[147,3527,3528,3529,3532],{},"不要用过期的 ",[159,3530,3531],{},"--approval-mode"," 旧参数","，新版用 ",[159,3535,3536],{},"codex features"," 子命令管理。",[13,3539,1566],{"id":1565},[17,3541,3542,3543,3546],{},"✅ 终端 \u002F TMUX \u002F Vim 重度用户；已订阅 ChatGPT Plus \u002F Pro 的人；Windows 原生开发者；headless \u002F SSH \u002F 容器场景。",[3544,3545],"br",{},"\n❌ GUI 党；纯内网开发；偏好 Claude 长上下文风格的人。",[13,3548,1615],{"id":1615},[21,3550,3551,3558,3565],{},[24,3552,3553,3554],{},"配套 playbook：",[795,3555,3557],{"href":3556},"\u002Fplaybook\u002Fcodex-cli-vs-claude-code.html","Codex CLI vs Claude Code 怎么选",[24,3559,3560,3561],{},"同分类：",[795,3562,3564],{"href":3563},"\u002Fcoding\u002Fcli\u002F","AI CLI 全分类",[24,3566,3567,3568,3570,3571,3570,3573],{},"替代品：",[795,3569,72],{"href":797}," · ",[795,3572,101],{"href":2490},[795,3574,1324],{"href":1323},[13,3576,1655],{"id":1655},[21,3578,3579,3585,3592,3597],{},[24,3580,1667,3581],{},[795,3582,3583],{"href":3583,"rel":3584},"https:\u002F\u002Fdevelopers.openai.com\u002Fcodex\u002Fcli",[862],[24,3586,3587,3588],{},"Features 页：",[795,3589,3590],{"href":3590,"rel":3591},"https:\u002F\u002Fdevelopers.openai.com\u002Fcodex\u002Fcli\u002Ffeatures",[862],[24,3593,1686,3594],{},[795,3595,3005],{"href":3005,"rel":3596},[862],[24,3598,3599,3600],{},"2026 更新综述：",[795,3601,3602],{"href":3602,"rel":3603},"https:\u002F\u002Fcodex.danielvaughan.com\u002F2026\u002F03\u002F27\u002Fcodex-cli-in-2026-whats-new",[862],[800,3605,3606],{},[17,3607,3608,3609,3611],{},"本卡片由 AIHO 编辑部根据以上公开资料整理，非厂商付费内容；定价与功能以官网为准，欢迎在 ",[795,3610,1709],{"href":1709}," 反馈更新。",[721,3613,3614],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":157,"searchDepth":263,"depth":263,"links":3616},[3617,3618,3619,3620,3625,3626,3627,3628,3629,3630],{"id":768,"depth":256,"text":769},{"id":3000,"depth":256,"text":3000},{"id":2219,"depth":256,"text":2219},{"id":3136,"depth":256,"text":3137,"children":3621},[3622,3623,3624],{"id":3145,"depth":263,"text":3146},{"id":3173,"depth":263,"text":3174},{"id":3200,"depth":263,"text":3201},{"id":1035,"depth":256,"text":1036},{"id":3340,"depth":256,"text":3340},{"id":1464,"depth":256,"text":1464},{"id":1565,"depth":256,"text":1566},{"id":1615,"depth":256,"text":1615},{"id":1655,"depth":256,"text":1655},"\u002Fimg\u002Ftools\u002Fcodex.webp","Codex CLI 真实评测：OpenAI 官方开源（Apache-2.0）终端 Coding Agent，Rust 实现，原生 Windows 沙箱 + 子代理 + MCP + 钩子 + 远程控制；2026 默认模型升级到 gpt-5-codex \u002F gpt-5-codex-mini，Plus\u002FPro\u002FTeam\u002FEdu 计划已含。",[3634,3637,3640,3643,3646],{"q":3635,"a":3636},"Codex CLI 和 Claude Code 有什么区别？","形态几乎一致：都是终端 Agent + 沙箱执行 + MCP + 子代理。差异主要在模型——Codex CLI 走 OpenAI 的 gpt-5-codex 系列，Claude Code 走 Anthropic Sonnet\u002FOpus。OpenAI 在原生 Windows 沙箱（不需要 WSL）和 Rust 实现速度上略胜，Claude 在长任务上下文连续性上略胜。",{"q":3638,"a":3639},"在 Windows 上怎么用？","原生 PowerShell 沙箱模式（推荐），也支持 WSL2。安装命令：curl -fsSL https:\u002F\u002Fchatgpt.com\u002Fcodex\u002Finstall.sh | sh（macOS\u002FLinux），Windows 直接通过 npm 或 PowerShell installer。",{"q":3641,"a":3642},"国内能用吗？","需要 OpenAI 账号 + 稳定代理。Plus \u002F Pro 订阅可走支付宝。直接 `codex` 即可启动。",{"q":3644,"a":3645},"Codex CLI 支持本地模型吗？","原生只走 OpenAI API。如果要本地模型，建议用 Aider（OpenAI 兼容 endpoint，可指向 Ollama \u002F vLLM）。",{"q":3647,"a":3648},"Subagents \u002F Hooks \u002F MCP 是什么？","Subagents：把大任务拆给多个并行子代理；Hooks（PostToolUse \u002F userpromptsubmit）：在工具调用前后插入企业策略；MCP：连外部工具（GitHub \u002F 数据库 \u002F Slack）。Codex 2026 把这三块都做到了 GA。",[1736,1737],{},[3652,3381,3653,3654],"gpt-5.5","gpt-5-codex-mini","gpt-5.3-codex-spark",[3656,3657,3658],"重度 GUI 党（终端排斥者请用 Cursor）","国内纯内网（OpenAI API 需稳定代理）","需要 Claude 上下文风格的人","\u002Ftools\u002Fcoding\u002Fcli\u002Fcodex",[1742,1743,1744],[3662,3666,3669,3673],{"plan":3091,"price":2648,"limit":3663,"cn_pay":3664,"note":3665},"含 Codex CLI 使用额度，默认 gpt-5-codex-mini（2026-03 起额度 +4×）","支付宝","个人入门",{"plan":3101,"price":2272,"limit":3667,"cn_pay":3664,"note":3668},"更高额度 + 优先处理 + GPT-5.3-Codex-Spark 研究预览","Agent 重度用户",{"plan":3111,"price":3114,"limit":3670,"cn_pay":3671,"note":3672},"团队管理 + SSO + Codex 含在内","—","团队档",{"plan":3674,"price":3125,"limit":3675,"cn_pay":3671,"note":3676},"纯 API 调用","gpt-5.5 ≈ $1.25\u002F$10 per 1M tokens（input\u002Foutput）","BYOK 自由模式","ChatGPT Plus\u002FPro\u002FBusiness\u002FEdu\u002FEnterprise 包含 \u002F 或按 OpenAI API 计费",[3679,3680],"ai-coding\u002Fcodex-cli-vs-claude-code","ai-coding\u002Fterminal-agent-workflow",{"power":280,"ux":269,"price":269,"cn_support":263,"stability":269},{"title":75,"description":3632},[3684,3686,3688,3690],{"title":3685,"url":3583},"Codex CLI 官方文档",{"title":3687,"url":3590},"Codex CLI Features 官方",{"title":3689,"url":3005},"Codex CLI GitHub",{"title":3691,"url":3602},"Codex CLI 2026 更新综述","tools\u002Fcoding\u002Fcli\u002Fcodex",[3694,3695,3696,3697],"终端 \u002F TMUX \u002F Vim 重度用户","已经订阅 ChatGPT Plus \u002F Pro 的人（白嫖 Codex 用量）","Windows 原生开发者（Codex CLI 有 PowerShell 沙箱，不必走 WSL）","需要远程 SSH \u002F 容器中跑 Agent 的人（headless 友好）","OpenAI 官方终端 Coding Agent，GPT-5.5 \u002F gpt-5-codex 驱动",[1731,1765,2969,2978,3700,3701,2971,1766,3702],"gpt-5","subagents","rust","Claude Code 的 OpenAI 版镜像。Plus \u002F Pro 已含、Windows 原生沙箱、Rust 速度快，喜欢 GPT 派的人首选；Claude Sonnet 4.5 在长任务上仍略胜，喜欢 Claude 的留 Claude Code。","RtRkWxjULobDTCnHDh2SWVJHfZwXARx9pKdojNOMVWc",{"id":3706,"title":98,"alternatives":3707,"api_compatible":3708,"body":3710,"category":1731,"chinese_friendly":263,"cover":4273,"description":4274,"domestic":1734,"extension":242,"faq":4275,"free":1734,"github":4247,"languages":4288,"meta":4289,"models":4290,"navigation":259,"notSuitable":4293,"opensource":259,"path":4297,"pillar":1740,"platforms":4298,"priceTable":4299,"pricing":4313,"published":745,"relatedPlaybooks":4314,"relatedReviews":763,"score":4316,"self_host":1734,"seo":4317,"slug":749,"sources":4318,"stem":4323,"suitable":4324,"tagline":4329,"tags":4330,"updated":745,"verdict":4333,"website":4240,"__hash__":4334},"tools\u002Ftools\u002Fcoding\u002Fcli\u002Fgemini-cli.md",[747,748,750],[425,3709],"vertex-ai",{"type":10,"value":3711,"toc":4257},[3712,3714,3729,3732,3738,3741,3761,3764,3818,3821,3824,3902,3905,3954,3957,3961,3964,3983,3986,3989,3993,3999,4002,4006,4012,4015,4019,4055,4058,4060,4170,4175,4189,4191,4223,4225,4231,4233,4249,4254],[13,3713,769],{"id":768},[771,3715,3717,3726],{"className":3716},[774,775,776],[17,3718,3719,3721,3722,3725],{},[147,3720,781],{}," Gemini CLI 是 Google 官方开源的终端 AI Agent。它把 Gemini 模型、文件读写、shell、web fetch、Google Search grounding 和 MCP 接到一个命令行工具里，最大卖点是 ",[147,3723,3724],{},"1M token 上下文 + 个人账号免费额度","。",[17,3727,3728],{},"如果你已经在用 Claude Code \u002F Codex CLI，Gemini CLI 不一定替代它们，但很适合作为「第二意见」「低成本大仓库阅读」「联网查新资料」的工具。",[13,3730,3731],{"id":3731},"它是什么",[17,3733,3734,3735,3737],{},"Gemini CLI 是一个 Apache-2.0 开源的终端 Agent。使用方式和 Claude Code \u002F Codex CLI 类似：进入项目目录，运行 ",[159,3736,425],{},"，然后用自然语言让它读文件、解释架构、修改代码、跑命令、调试错误。",[17,3739,3740],{},"它的特点不是「最强代码生成」，而是三件事：",[532,3742,3743,3749,3755],{},[24,3744,3745,3748],{},[147,3746,3747],{},"上下文大","：官方文档强调可访问 Gemini 2.5 Pro 的 1M token context window。",[24,3750,3751,3754],{},[147,3752,3753],{},"免费额度大","：个人 Google 账号入口标注 60 requests\u002Fmin、1,000 requests\u002Fday。",[24,3756,3757,3760],{},[147,3758,3759],{},"搜索原生","：Google Search grounding 是内置能力，查新资料、查报错、查 API 文档时很顺手。",[13,3762,3763],{"id":3763},"安装与启动",[151,3765,3767],{"className":415,"code":3766,"language":417,"meta":157,"style":157},"# 免安装试用\nnpx https:\u002F\u002Fgithub.com\u002Fgoogle-gemini\u002Fgemini-cli\n\n# 全局安装\nnpm install -g @google\u002Fgemini-cli\n\n# 启动当前目录会话\ngemini\n",[159,3768,3769,3774,3782,3786,3791,3804,3808,3813],{"__ignoreMap":157},[246,3770,3771],{"class":248,"line":249},[246,3772,3773],{"class":607},"# 免安装试用\n",[246,3775,3776,3779],{"class":248,"line":256},[246,3777,3778],{"class":424},"npx",[246,3780,3781],{"class":432}," https:\u002F\u002Fgithub.com\u002Fgoogle-gemini\u002Fgemini-cli\n",[246,3783,3784],{"class":248,"line":263},[246,3785,260],{"emptyLinePlaceholder":259},[246,3787,3788],{"class":248,"line":269},[246,3789,3790],{"class":607},"# 全局安装\n",[246,3792,3793,3796,3798,3801],{"class":248,"line":280},[246,3794,3795],{"class":424},"npm",[246,3797,1060],{"class":432},[246,3799,3800],{"class":428}," -g",[246,3802,3803],{"class":432}," @google\u002Fgemini-cli\n",[246,3805,3806],{"class":248,"line":288},[246,3807,260],{"emptyLinePlaceholder":259},[246,3809,3810],{"class":248,"line":5},[246,3811,3812],{"class":607},"# 启动当前目录会话\n",[246,3814,3815],{"class":248,"line":300},[246,3816,3817],{"class":424},"gemini\n",[17,3819,3820],{},"要求 Node.js 20+，支持 Windows \u002F macOS \u002F Linux。",[17,3822,3823],{},"常用命令：",[151,3825,3827],{"className":415,"code":3826,"language":417,"meta":157,"style":157},"# 非交互问答\ngemini -p \"Explain the architecture of this codebase\"\n\n# 指定模型\ngemini -m gemini-2.5-flash\n\n# 额外包含目录\ngemini --include-directories ..\u002Fdocs,..\u002Fpackages\n\n# JSON 输出，方便脚本串联\ngemini -p \"Summarize open issues\" --output-format json\n",[159,3828,3829,3834,3843,3847,3852,3861,3865,3870,3880,3884,3889],{"__ignoreMap":157},[246,3830,3831],{"class":248,"line":249},[246,3832,3833],{"class":607},"# 非交互问答\n",[246,3835,3836,3838,3840],{"class":248,"line":256},[246,3837,425],{"class":424},[246,3839,429],{"class":428},[246,3841,3842],{"class":432}," \"Explain the architecture of this codebase\"\n",[246,3844,3845],{"class":248,"line":263},[246,3846,260],{"emptyLinePlaceholder":259},[246,3848,3849],{"class":248,"line":269},[246,3850,3851],{"class":607},"# 指定模型\n",[246,3853,3854,3856,3858],{"class":248,"line":280},[246,3855,425],{"class":424},[246,3857,1054],{"class":428},[246,3859,3860],{"class":432}," gemini-2.5-flash\n",[246,3862,3863],{"class":248,"line":288},[246,3864,260],{"emptyLinePlaceholder":259},[246,3866,3867],{"class":248,"line":5},[246,3868,3869],{"class":607},"# 额外包含目录\n",[246,3871,3872,3874,3877],{"class":248,"line":300},[246,3873,425],{"class":424},[246,3875,3876],{"class":428}," --include-directories",[246,3878,3879],{"class":432}," ..\u002Fdocs,..\u002Fpackages\n",[246,3881,3882],{"class":248,"line":306},[246,3883,260],{"emptyLinePlaceholder":259},[246,3885,3886],{"class":248,"line":314},[246,3887,3888],{"class":607},"# JSON 输出，方便脚本串联\n",[246,3890,3891,3893,3895,3898,3900],{"class":248,"line":322},[246,3892,425],{"class":424},[246,3894,429],{"class":428},[246,3896,3897],{"class":432}," \"Summarize open issues\"",[246,3899,492],{"class":428},[246,3901,495],{"class":432},[13,3903,3904],{"id":3904},"三种认证路径",[40,3906,3907,3919],{},[43,3908,3909],{},[46,3910,3911,3913,3916],{},[49,3912,2216],{},[49,3914,3915],{},"适合谁",[49,3917,3918],{},"关键点",[62,3920,3921,3932,3943],{},[46,3922,3923,3926,3929],{},[67,3924,3925],{},"Google OAuth",[67,3927,3928],{},"个人开发者",[67,3930,3931],{},"免费额度最大，上手最简单",[46,3933,3934,3937,3940],{},[67,3935,3936],{},"Gemini API Key",[67,3938,3939],{},"脚本 \u002F CI",[67,3941,3942],{},"更适合自动化，额度跟 API tier 走",[46,3944,3945,3948,3951],{},[67,3946,3947],{},"Vertex AI",[67,3949,3950],{},"企业 \u002F GCP 团队",[67,3952,3953],{},"IAM、审计、合规、配额更可控",[17,3955,3956],{},"个人使用优先 OAuth；生产和团队内使用优先 Vertex AI。",[13,3958,3960],{"id":3959},"mcp-与项目记忆","MCP 与项目记忆",[17,3962,3963],{},"Gemini CLI 支持两类扩展：",[21,3965,3966,3972],{},[24,3967,3968,3971],{},[147,3969,3970],{},"MCP server","：把 GitHub、数据库、内部 API 暴露给 Agent。",[24,3973,3974,3976,3977,3979,3980,3982],{},[147,3975,199],{},"：类似 Claude Code 的 ",[159,3978,190],{}," \u002F Copilot 的 ",[159,3981,209],{},"，用于写项目约定、测试命令、编码风格。",[17,3984,3985],{},"这让 Gemini CLI 可以进入 2026 年主流终端 Agent 的标准形态：项目记忆 + 工具协议 + headless 自动化。",[13,3987,3988],{"id":3988},"真实适用场景",[406,3990,3992],{"id":3991},"_1-大仓库先读懂","1. 大仓库先读懂",[151,3994,3997],{"className":3995,"code":3996,"language":156,"meta":157},[154],"先读 package.json、README、src 入口文件，输出这个项目的架构图和关键风险点。\n",[159,3998,3996],{"__ignoreMap":157},[17,4000,4001],{},"1M 上下文让它在「读文档 + 读代码」阶段很有优势，尤其适合 monorepo 的初始摸底。",[406,4003,4005],{"id":4004},"_2-查新资料后改代码","2. 查新资料后改代码",[151,4007,4010],{"className":4008,"code":4009,"language":156,"meta":157},[154],"查一下 Nuxt 4 最新 route rules 写法，然后检查本项目 nuxt.config.ts 是否需要调整。\n",[159,4011,4009],{"__ignoreMap":157},[17,4013,4014],{},"Google Search grounding 的价值在这里体现：它不是只靠训练数据，而是能把搜索结果纳入推理。",[406,4016,4018],{"id":4017},"_3-低成本-issue-triage","3. 低成本 issue triage",[151,4020,4022],{"className":415,"code":4021,"language":417,"meta":157,"style":157},"gh issue list --json title,body \\\n  | gemini -p \"按修复难度给这些 issue 排序，输出 JSON\"\n",[159,4023,4024,4042],{"__ignoreMap":157},[246,4025,4026,4029,4032,4034,4037,4040],{"class":248,"line":249},[246,4027,4028],{"class":424},"gh",[246,4030,4031],{"class":432}," issue",[246,4033,3313],{"class":432},[246,4035,4036],{"class":428}," --json",[246,4038,4039],{"class":432}," title,body",[246,4041,902],{"class":428},[246,4043,4044,4047,4050,4052],{"class":248,"line":256},[246,4045,4046],{"class":619},"  |",[246,4048,4049],{"class":424}," gemini",[246,4051,429],{"class":428},[246,4053,4054],{"class":432}," \"按修复难度给这些 issue 排序，输出 JSON\"\n",[17,4056,4057],{},"和 Jules Tools \u002F GitHub CLI 组合时，可以把 Gemini CLI 当「任务分拣器」。",[13,4059,1298],{"id":1298},[40,4061,4062,4076],{},[43,4063,4064],{},[46,4065,4066,4068,4070,4072,4074],{},[49,4067,1307],{},[49,4069,98],{},[49,4071,72],{},[49,4073,75],{},[49,4075,101],{},[62,4077,4078,4094,4110,4126,4143,4158],{},[46,4079,4080,4083,4086,4088,4091],{},[67,4081,4082],{},"默认生态",[67,4084,4085],{},"Google \u002F Gemini",[67,4087,968],{},[67,4089,4090],{},"OpenAI \u002F ChatGPT",[67,4092,4093],{},"任意模型",[46,4095,4096,4099,4102,4104,4107],{},[67,4097,4098],{},"免费入口",[67,4100,4101],{},"✅ 很强",[67,4103,1337],{},[67,4105,4106],{},"取决于 ChatGPT 订阅",[67,4108,4109],{},"本体免费，模型自费",[46,4111,4112,4115,4118,4121,4124],{},[67,4113,4114],{},"上下文",[67,4116,4117],{},"1M",[67,4119,4120],{},"1M 级别模型可用",[67,4122,4123],{},"取决于模型",[67,4125,4123],{},[46,4127,4128,4131,4134,4137,4140],{},[67,4129,4130],{},"搜索",[67,4132,4133],{},"Google Search 内置",[67,4135,4136],{},"需工具 \u002F MCP",[67,4138,4139],{},"内置 web 能力",[67,4141,4142],{},"取决于模型 \u002F 工具",[46,4144,4145,4148,4151,4154,4156],{},[67,4146,4147],{},"长任务稳定性",[67,4149,4150],{},"中上",[67,4152,4153],{},"强",[67,4155,4153],{},[67,4157,4150],{},[46,4159,4160,4162,4164,4166,4168],{},[67,4161,1331],{},[67,4163,1334],{},[67,4165,1337],{},[67,4167,1334],{},[67,4169,1334],{},[17,4171,4172],{},[147,4173,4174],{},"AIHO 建议：",[21,4176,4177,4180,4183,4186],{},[24,4178,4179],{},"预算敏感 \u002F 想免费试：Gemini CLI",[24,4181,4182],{},"最稳长任务：Claude Code",[24,4184,4185],{},"已有 ChatGPT Plus\u002FPro：Codex CLI",[24,4187,4188],{},"想接国内模型 \u002F 自定义 base_url：Aider",[13,4190,1464],{"id":1464},[532,4192,4193,4199,4205,4211,4217],{},[24,4194,4195,4198],{},[147,4196,4197],{},"不要把免费额度当生产 SLA","：个人额度适合探索，生产任务走 API Key \u002F Vertex AI。",[24,4200,4201,4204],{},[147,4202,4203],{},"长任务先拆小","：即使上下文大，Agent 执行链路也可能漂移；30 分钟以上任务建议拆成 issue。",[24,4206,4207,4210],{},[147,4208,4209],{},"MCP server 要审计","：给 Agent 接工具等于扩权，第三方 server 先看源码和权限。",[24,4212,4213,4216],{},[147,4214,4215],{},"GEMINI.md 别写太散","：只放稳定约定、测试命令、目录说明，别塞临时需求。",[24,4218,4219,4222],{},[147,4220,4221],{},"国内网络先验证 OAuth","：登录流程不稳定会影响体验，必要时用 API key 路径。",[13,4224,1566],{"id":1565},[17,4226,4227,4228,4230],{},"✅ 适合：个人开发者、学生、开源项目维护者、大仓库阅读、联网查新、低成本脚本化分析。",[3544,4229],{},"\n❌ 不适合：强合规生产环境、纯内网开发、预算不敏感但追求最高长任务稳定性的团队。",[13,4232,1655],{"id":1655},[21,4234,4235,4242],{},[24,4236,4237,4238],{},"Gemini CLI 官方文档：",[795,4239,4240],{"href":4240,"rel":4241},"https:\u002F\u002Fgoogle-gemini.github.io\u002Fgemini-cli\u002F",[862],[24,4243,4244,4245],{},"Gemini CLI GitHub：",[795,4246,4247],{"href":4247,"rel":4248},"https:\u002F\u002Fgithub.com\u002Fgoogle-gemini\u002Fgemini-cli",[862],[800,4250,4251],{},[17,4252,4253],{},"本卡片由 AIHO 编辑部根据公开资料整理，非厂商付费内容；功能和额度以官网为准。",[721,4255,4256],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":157,"searchDepth":263,"depth":263,"links":4258},[4259,4260,4261,4262,4263,4264,4269,4270,4271,4272],{"id":768,"depth":256,"text":769},{"id":3731,"depth":256,"text":3731},{"id":3763,"depth":256,"text":3763},{"id":3904,"depth":256,"text":3904},{"id":3959,"depth":256,"text":3960},{"id":3988,"depth":256,"text":3988,"children":4265},[4266,4267,4268],{"id":3991,"depth":263,"text":3992},{"id":4004,"depth":263,"text":4005},{"id":4017,"depth":263,"text":4018},{"id":1298,"depth":256,"text":1298},{"id":1464,"depth":256,"text":1464},{"id":1565,"depth":256,"text":1566},{"id":1655,"depth":256,"text":1655},"\u002Fimg\u002Ftools\u002Fgemini-cli.webp","Gemini CLI 真实评测：Google 官方开源（Apache-2.0）终端 AI Agent，支持 Gemini 2.5 Pro\u002FFlash、1M token 上下文、Google Search grounding、MCP、自定义 GEMINI.md、headless 脚本模式；个人 Google 账号可用 60 requests\u002Fmin、1,000 requests\u002Fday 免费额度。",[4276,4279,4282,4285],{"q":4277,"a":4278},"Gemini CLI 和 Claude Code \u002F Codex CLI 最大区别？","它的核心差异是免费额度和 Google 生态：个人 Google 账号即可获得较高免费请求额度，并内置 Google Search grounding。Claude Code 更稳，Codex 与 ChatGPT 订阅绑定更深，Gemini CLI 更适合低成本探索和大上下文阅读。",{"q":4280,"a":4281},"Gemini CLI 支持 MCP 吗？","支持。可以在 ~\u002F.gemini\u002Fsettings.json 里配置 MCP server，把 GitHub、数据库、Slack、内部 API 等工具接入 CLI。",{"q":4283,"a":4284},"能不能非交互使用？","可以。`gemini -p \"解释这个代码库\"` 会以 headless 模式输出结果，也可以加 `--output-format json` 做脚本化处理。",{"q":4286,"a":4287},"国内开发者适合吗？","如果能稳定访问 Google 服务，它的免费额度很有吸引力；如果网络不稳，建议优先 Aider + 国内模型或 Claude\u002FCodex 的稳定代理方案。",[1737],{},[4291,4292],"gemini-2.5-pro","gemini-2.5-flash",[4294,4295,4296],"要求最稳长任务交付的生产重构","不能访问 Google 服务的纯内网环境","强依赖中文界面和本地化文档的用户","\u002Ftools\u002Fcoding\u002Fcli\u002Fgemini-cli",[1742,1743,1744],[4300,4305,4309],{"plan":4301,"price":4302,"limit":4303,"note":4304},"个人 Google 账号","$0","60 requests\u002Fmin，1,000 requests\u002Fday","官方文档标注的免费入口，适合个人探索",{"plan":3936,"price":4306,"limit":4307,"note":4308},"按量计费","取决于 AI Studio \u002F API tier","适合自动化脚本和 CI",{"plan":3947,"price":4310,"limit":4311,"note":4312},"GCP 按量计费","企业配额与 IAM","适合生产与合规场景","开源免费 \u002F 个人 Google 账号免费额度 \u002F Gemini API 或 Vertex AI 按量计费",[4315],"onboarding\u002Fterminal-agent-stack-2026",{"power":269,"ux":263,"price":280,"cn_support":263,"stability":269},{"title":98,"description":4274},[4319,4321],{"title":4320,"url":4240},"Gemini CLI 官方文档",{"title":4322,"url":4247},"Gemini CLI GitHub","tools\u002Fcoding\u002Fcli\u002Fgemini-cli",[4325,4326,4327,4328],"想低成本体验终端 Coding Agent 的个人开发者","需要 1M token 长上下文做代码库理解 \u002F 文档阅读","需要 Google Search grounding 辅助查新资料的任务","想在脚本里用 headless 模式批量分析 issue \u002F PR","Google 开源终端 AI Agent，1M 上下文 + 免费额度 + Google Search grounding",[1731,1765,2969,4331,425,2971,1766,4332],"google","free-tier","终端 Agent 里最适合『低成本试水』的一支：免费额度大、1M 上下文、内置 Google Search。短板是产品打磨和长任务稳定性还不如 Claude Code \u002F Codex，生产级任务建议把它当第二意见或低成本探索工具。","DNrl7K7VaVcINjwaJBpmwkySjkFXYTiK1L0u0vNqqPM",[4336,4998,5519,6393,7493,8174,8897,9874,11416,12037,12542,13173],{"id":4337,"title":4338,"body":4339,"category":740,"cover":4983,"description":4984,"extension":242,"meta":4985,"navigation":259,"path":4986,"published":745,"relatedTools":4987,"seo":4992,"stem":4993,"tags":4994,"updated":745,"__hash__":4997},"playbook\u002Fplaybook\u002Fonboarding\u002Fasync-coding-agent-workflow.md","异步 Coding Agent 工作流：把 issue 交给 Jules \u002F Devin \u002F Copilot Coding Agent",{"type":10,"value":4340,"toc":4969},[4341,4343,4346,4360,4366,4369,4372,4392,4395,4412,4415,4418,4421,4560,4563,4566,4572,4579,4583,4680,4683,4687,4690,4707,4710,4714,4773,4777,4780,4806,4809,4812,4815,4864,4868,4871,4917,4920,4923,4961,4963,4966],[13,4342,15],{"id":15},[17,4344,4345],{},"异步 Coding Agent 指的是这类工具：你把 GitHub issue \u002F repo \u002F prompt 交给它，它在云端或隔离环境中完成任务，最后返回 diff 或 PR。典型代表：",[21,4347,4348,4351,4354,4357],{},[24,4349,4350],{},"Google Jules",[24,4352,4353],{},"Devin",[24,4355,4356],{},"GitHub Copilot Coding Agent",[24,4358,4359],{},"OpenHands Cloud \u002F 自托管",[17,4361,4362,4363,3725],{},"它们和 Claude Code \u002F Codex CLI \u002F Cursor 最大区别：",[147,4364,4365],{},"不是实时结对，而是任务委派",[13,4367,4368],{"id":4368},"先判断任务适不适合异步委派",[17,4370,4371],{},"适合：",[21,4373,4374,4377,4380,4383,4386,4389],{},[24,4375,4376],{},"补测试",[24,4378,4379],{},"依赖升级",[24,4381,4382],{},"小 bug fix",[24,4384,4385],{},"文档更新",[24,4387,4388],{},"codemod \u002F 机械迁移",[24,4390,4391],{},"有明确复现步骤和验收标准的 issue",[17,4393,4394],{},"不适合：",[21,4396,4397,4400,4403,4406,4409],{},[24,4398,4399],{},"产品方向不明确的新功能",[24,4401,4402],{},"需要大量口头沟通的需求",[24,4404,4405],{},"涉及生产凭据 \u002F 内网数据库 \u002F 隐私数据",[24,4407,4408],{},"紧急线上事故",[24,4410,4411],{},"大规模架构重构的第一步",[17,4413,4414],{},"**判断标准：**如果你不能在 10 行内写清楚「做什么、不能做什么、如何验收」，就先别交给异步 Agent。",[13,4416,4417],{"id":4417},"任务模板",[17,4419,4420],{},"把 issue 写成下面这种结构，成功率会明显高：",[151,4422,4424],{"className":240,"code":4423,"language":242,"meta":157,"style":157},"## Goal\nFix duplicate toast after saving settings.\n\n## Scope\n- Only edit settings page and related toast utility.\n- Do not change the global notification API.\n\n## Reproduction\n1. Open \u002Fsettings\n2. Change display name\n3. Click Save once\n4. Two success toasts appear\n\n## Expected\nOnly one success toast appears.\n\n## Verification\n- pnpm test settings\n- pnpm run typecheck\n- Manual: save settings once and confirm one toast\n\n## Notes\nPrefer removing duplicate caller over adding debounce.\n",[159,4425,4426,4431,4436,4440,4445,4452,4459,4463,4468,4476,4484,4492,4500,4504,4509,4514,4518,4523,4530,4537,4544,4548,4554],{"__ignoreMap":157},[246,4427,4428],{"class":248,"line":249},[246,4429,4430],{"class":252},"## Goal\n",[246,4432,4433],{"class":248,"line":256},[246,4434,4435],{"class":276},"Fix duplicate toast after saving settings.\n",[246,4437,4438],{"class":248,"line":263},[246,4439,260],{"emptyLinePlaceholder":259},[246,4441,4442],{"class":248,"line":269},[246,4443,4444],{"class":252},"## Scope\n",[246,4446,4447,4449],{"class":248,"line":280},[246,4448,273],{"class":272},[246,4450,4451],{"class":276}," Only edit settings page and related toast utility.\n",[246,4453,4454,4456],{"class":248,"line":288},[246,4455,273],{"class":272},[246,4457,4458],{"class":276}," Do not change the global notification API.\n",[246,4460,4461],{"class":248,"line":5},[246,4462,260],{"emptyLinePlaceholder":259},[246,4464,4465],{"class":248,"line":300},[246,4466,4467],{"class":252},"## Reproduction\n",[246,4469,4470,4473],{"class":248,"line":306},[246,4471,4472],{"class":272},"1.",[246,4474,4475],{"class":276}," Open \u002Fsettings\n",[246,4477,4478,4481],{"class":248,"line":314},[246,4479,4480],{"class":272},"2.",[246,4482,4483],{"class":276}," Change display name\n",[246,4485,4486,4489],{"class":248,"line":322},[246,4487,4488],{"class":272},"3.",[246,4490,4491],{"class":276}," Click Save once\n",[246,4493,4494,4497],{"class":248,"line":330},[246,4495,4496],{"class":272},"4.",[246,4498,4499],{"class":276}," Two success toasts appear\n",[246,4501,4502],{"class":248,"line":335},[246,4503,260],{"emptyLinePlaceholder":259},[246,4505,4506],{"class":248,"line":341},[246,4507,4508],{"class":252},"## Expected\n",[246,4510,4511],{"class":248,"line":349},[246,4512,4513],{"class":276},"Only one success toast appears.\n",[246,4515,4516],{"class":248,"line":357},[246,4517,260],{"emptyLinePlaceholder":259},[246,4519,4520],{"class":248,"line":365},[246,4521,4522],{"class":252},"## Verification\n",[246,4524,4525,4527],{"class":248,"line":373},[246,4526,273],{"class":272},[246,4528,4529],{"class":276}," pnpm test settings\n",[246,4531,4532,4534],{"class":248,"line":378},[246,4533,273],{"class":272},[246,4535,4536],{"class":276}," pnpm run typecheck\n",[246,4538,4539,4541],{"class":248,"line":384},[246,4540,273],{"class":272},[246,4542,4543],{"class":276}," Manual: save settings once and confirm one toast\n",[246,4545,4546],{"class":248,"line":392},[246,4547,260],{"emptyLinePlaceholder":259},[246,4549,4551],{"class":248,"line":4550},22,[246,4552,4553],{"class":252},"## Notes\n",[246,4555,4557],{"class":248,"line":4556},23,[246,4558,4559],{"class":276},"Prefer removing duplicate caller over adding debounce.\n",[17,4561,4562],{},"异步 Agent 最怕「帮我优化一下」。它需要像 junior developer 一样拿到清楚的 ticket。",[13,4564,4565],{"id":4565},"推荐流程",[151,4567,4570],{"className":4568,"code":4569,"language":156,"meta":157},[154],"Backlog issue\n  ↓\n人工筛选：是否边界清楚 \u002F 风险低\n  ↓\nAgent 生成 plan\n  ↓\n人工确认 plan\n  ↓\nAgent 在云端 \u002F VM 改代码 + 跑测试\n  ↓\n生成 PR\n  ↓\nAI Review + 人工 Review\n  ↓\nCI 通过后 merge\n",[159,4571,4569],{"__ignoreMap":157},[17,4573,4574,4575,4578],{},"关键点：",[147,4576,4577],{},"不要跳过 plan review 和 PR review","。异步 Agent 是执行者，不是合并权限的拥有者。",[13,4580,4582],{"id":4581},"jules-工作流示例","Jules 工作流示例",[151,4584,4586],{"className":415,"code":4585,"language":417,"meta":157,"style":157},"npm install -g @google\u002Fjules\njules login\n\n# 当前目录对应 GitHub repo 时可用 .\njules remote new --repo . --session \"Fix duplicate toast after saving settings. Run pnpm test settings and pnpm run typecheck.\"\n\n# 查看任务\njules remote list --session\n\n# 拉取完成结果\njules remote pull --session 123456\n",[159,4587,4588,4599,4607,4611,4616,4637,4641,4646,4657,4661,4666],{"__ignoreMap":157},[246,4589,4590,4592,4594,4596],{"class":248,"line":249},[246,4591,3795],{"class":424},[246,4593,1060],{"class":432},[246,4595,3800],{"class":428},[246,4597,4598],{"class":432}," @google\u002Fjules\n",[246,4600,4601,4604],{"class":248,"line":256},[246,4602,4603],{"class":424},"jules",[246,4605,4606],{"class":432}," login\n",[246,4608,4609],{"class":248,"line":263},[246,4610,260],{"emptyLinePlaceholder":259},[246,4612,4613],{"class":248,"line":269},[246,4614,4615],{"class":607},"# 当前目录对应 GitHub repo 时可用 .\n",[246,4617,4618,4620,4623,4626,4629,4631,4634],{"class":248,"line":280},[246,4619,4603],{"class":424},[246,4621,4622],{"class":432}," remote",[246,4624,4625],{"class":432}," new",[246,4627,4628],{"class":428}," --repo",[246,4630,3287],{"class":432},[246,4632,4633],{"class":428}," --session",[246,4635,4636],{"class":432}," \"Fix duplicate toast after saving settings. Run pnpm test settings and pnpm run typecheck.\"\n",[246,4638,4639],{"class":248,"line":288},[246,4640,260],{"emptyLinePlaceholder":259},[246,4642,4643],{"class":248,"line":5},[246,4644,4645],{"class":607},"# 查看任务\n",[246,4647,4648,4650,4652,4654],{"class":248,"line":300},[246,4649,4603],{"class":424},[246,4651,4622],{"class":432},[246,4653,3313],{"class":432},[246,4655,4656],{"class":428}," --session\n",[246,4658,4659],{"class":248,"line":306},[246,4660,260],{"emptyLinePlaceholder":259},[246,4662,4663],{"class":248,"line":314},[246,4664,4665],{"class":607},"# 拉取完成结果\n",[246,4667,4668,4670,4672,4675,4677],{"class":248,"line":322},[246,4669,4603],{"class":424},[246,4671,4622],{"class":432},[246,4673,4674],{"class":432}," pull",[246,4676,4633],{"class":428},[246,4678,4679],{"class":428}," 123456\n",[17,4681,4682],{},"Jules 会在 Google Cloud VM 中 clone repo、制定计划、修改代码、跑测试并返回 diff。适合一次派发多个低风险任务。",[13,4684,4686],{"id":4685},"copilot-coding-agent-工作流示例","Copilot Coding Agent 工作流示例",[17,4688,4689],{},"适合已经用 GitHub Issues 管理任务的团队：",[532,4691,4692,4695,4698,4701,4704],{},[24,4693,4694],{},"在 issue 中写好 Goal \u002F Scope \u002F Verification。",[24,4696,4697],{},"将 issue assign 给 Copilot 或在 GitHub UI 中触发 Coding Agent。",[24,4699,4700],{},"Copilot 在 GitHub Actions 环境中工作。",[24,4702,4703],{},"完成后开 PR。",[24,4705,4706],{},"团队按普通 PR 流程 review。",[17,4708,4709],{},"Copilot 的优势是和 GitHub 权限、Actions、PR review 链路集成最深；缺点是 Actions minutes、仓库权限和企业策略要提前配置。",[13,4711,4713],{"id":4712},"devin-openhands-工作流","Devin \u002F OpenHands 工作流",[40,4715,4716,4728],{},[43,4717,4718],{},[46,4719,4720,4722,4725],{},[49,4721,176],{},[49,4723,4724],{},"适合",[49,4726,4727],{},"注意",[62,4729,4730,4740,4751,4762],{},[46,4731,4732,4734,4737],{},[67,4733,4353],{},[67,4735,4736],{},"企业团队、复杂云端执行",[67,4738,4739],{},"成本较高，仍需严格 review",[46,4741,4742,4745,4748],{},[67,4743,4744],{},"OpenHands",[67,4746,4747],{},"想自托管、代码不能出境",[67,4749,4750],{},"需要自己维护运行环境和模型接入",[46,4752,4753,4756,4759],{},[67,4754,4755],{},"Jules",[67,4757,4758],{},"Google\u002FGemini 用户、低成本试水",[67,4760,4761],{},"代码进入 Google Cloud VM，中文友好一般",[46,4763,4764,4767,4770],{},[67,4765,4766],{},"Copilot Coding Agent",[67,4768,4769],{},"GitHub-first 团队",[67,4771,4772],{},"依赖 Actions 与 GitHub 权限体系",[13,4774,4776],{"id":4775},"review-agent-pr-的检查清单","Review Agent PR 的检查清单",[17,4778,4779],{},"收到异步 Agent PR 后，不要只看「测试通过」。至少检查：",[21,4781,4782,4785,4788,4791,4794,4797,4800,4803],{},[24,4783,4784],{},"是否改了 scope 外的文件？",[24,4786,4787],{},"是否删掉了测试而不是修复测试？",[24,4789,4790],{},"是否引入了新的依赖？依赖是否必要？",[24,4792,4793],{},"是否硬编码 token \u002F URL \u002F 环境变量？",[24,4795,4796],{},"是否只修了表面现象，没有覆盖根因？",[24,4798,4799],{},"是否有回归测试？",[24,4801,4802],{},"CI 日志是否真的跑了目标命令？",[24,4804,4805],{},"PR 描述是否解释了 trade-off？",[17,4807,4808],{},"推荐再加一层 AI review：CodeRabbit \u002F Copilot review \u002F Claude Code 读 diff。一个 Agent 写，另一个 Agent 审，能抓到不少低级问题。",[13,4810,4811],{"id":4811},"权限与安全",[17,4813,4814],{},"异步 Agent 通常需要访问 repo、issue、CI、包管理器甚至部署环境。建议：",[532,4816,4817,4823,4829,4835,4841,4847],{},[24,4818,4819,4822],{},[147,4820,4821],{},"单独 service account","：不要用个人 GitHub token。",[24,4824,4825,4828],{},[147,4826,4827],{},"最小权限","：只给目标 repo，不给 org admin。",[24,4830,4831,4834],{},[147,4832,4833],{},"禁止生产 secret","：Agent 环境不注入生产数据库、支付、云厂商 root key。",[24,4836,4837,4840],{},[147,4838,4839],{},"分支保护","：Agent PR 必须走 CI + 人工 review。",[24,4842,4843,4846],{},[147,4844,4845],{},"日志留存","：保留 Agent plan、命令输出、测试结果。",[24,4848,4849,4852,4853,4856,4857,4856,4860,4863],{},[147,4850,4851],{},"敏感目录排除","：如 ",[159,4854,4855],{},"infra\u002Fprod","、",[159,4858,4859],{},"secrets",[159,4861,4862],{},"billing"," 需要更高门槛。",[13,4865,4867],{"id":4866},"指标怎么判断值不值","指标：怎么判断值不值",[17,4869,4870],{},"看四个数：",[40,4872,4873,4883],{},[43,4874,4875],{},[46,4876,4877,4880],{},[49,4878,4879],{},"指标",[49,4881,4882],{},"目标",[62,4884,4885,4893,4901,4909],{},[46,4886,4887,4890],{},[67,4888,4889],{},"PR 接受率",[67,4891,4892],{},"> 50% 才值得扩大使用",[46,4894,4895,4898],{},[67,4896,4897],{},"平均人工 review 时间",[67,4899,4900],{},"应该下降，而不是变成「帮 Agent 擦屁股」",[46,4902,4903,4906],{},[67,4904,4905],{},"回滚率",[67,4907,4908],{},"不应高于人工 PR",[46,4910,4911,4914],{},[67,4912,4913],{},"单任务成本",[67,4915,4916],{},"包括订阅费、CI minutes、review 人力",[17,4918,4919],{},"开始阶段建议只拿 10-20 个低风险 issue 做试点，不要一口气把 backlog 全派出去。",[13,4921,4922],{"id":4922},"常见失败模式",[532,4924,4925,4931,4937,4943,4949,4955],{},[24,4926,4927,4930],{},[147,4928,4929],{},"任务太大","：Agent 生成 2,000 行 PR，没人敢 merge。",[24,4932,4933,4936],{},[147,4934,4935],{},"没有测试","：Agent 无法判断是否完成，只能猜。",[24,4938,4939,4942],{},[147,4940,4941],{},"权限太小","：跑不了依赖安装 \u002F 测试，反复失败。",[24,4944,4945,4948],{},[147,4946,4947],{},"权限太大","：能改不该改的文件，安全风险上升。",[24,4950,4951,4954],{},[147,4952,4953],{},"review 不及时","：Agent PR 堆积，merge 冲突越来越多。",[24,4956,4957,4960],{},[147,4958,4959],{},"把 Agent 当 owner","：没有人类 owner，需求判断和质量兜底会失控。",[13,4962,707],{"id":707},[17,4964,4965],{},"异步 Coding Agent 最适合做「边界清晰、能自动验证、风险可控」的工程杂活。正确姿势不是让它替代开发者，而是把它纳入现有 issue → PR → CI → review 流程，让人类只处理真正需要判断的部分。",[721,4967,4968],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sq-ep, html code.shiki .sq-ep{--shiki-default:#005CC5;--shiki-default-font-weight:bold;--shiki-dark:#79B8FF;--shiki-dark-font-weight:bold}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":157,"searchDepth":263,"depth":263,"links":4970},[4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,4981,4982],{"id":15,"depth":256,"text":15},{"id":4368,"depth":256,"text":4368},{"id":4417,"depth":256,"text":4417},{"id":4565,"depth":256,"text":4565},{"id":4581,"depth":256,"text":4582},{"id":4685,"depth":256,"text":4686},{"id":4712,"depth":256,"text":4713},{"id":4775,"depth":256,"text":4776},{"id":4811,"depth":256,"text":4811},{"id":4866,"depth":256,"text":4867},{"id":4922,"depth":256,"text":4922},{"id":707,"depth":256,"text":707},"\u002Fog\u002Fplaybook\u002Fasync-coding-agent-workflow.png","面向 Google Jules、Devin、GitHub Copilot Coding Agent 等异步 AI 编程工具的落地指南：如何拆任务、写验收标准、控制权限、review Agent 生成的 PR。",{},"\u002Fplaybook\u002Fonboarding\u002Fasync-coding-agent-workflow",[4988,4989,4990,4991],"coding\u002Fagent\u002Fjules","coding\u002Fagent\u002Fdevin","coding\u002Fcopilot\u002Fgithub-copilot","coding\u002Fagent\u002Fopenhands",{"title":4338,"description":4984},"playbook\u002Fonboarding\u002Fasync-coding-agent-workflow",[4995,4755,4353,4766,4996],"Async Agent","GitHub","L3d_nP-4U5NMhHFqR_SMb1JnpsXSS-QvEpot54K_lkc",{"id":7,"title":8,"body":4999,"category":740,"cover":741,"description":742,"extension":242,"meta":5515,"navigation":259,"path":744,"published":745,"relatedTools":5516,"seo":5517,"stem":752,"tags":5518,"updated":745,"__hash__":756},{"type":10,"value":5000,"toc":5499},[5001,5003,5005,5015,5017,5093,5097,5102,5104,5106,5160,5162,5274,5276,5278,5280,5282,5294,5296,5298,5300,5305,5307,5309,5311,5316,5318,5320,5322,5356,5358,5360,5362,5376,5378,5388,5390,5392,5397,5399,5401,5406,5408,5454,5456,5458,5486,5488,5490,5495,5497],[13,5002,15],{"id":15},[17,5004,19],{},[21,5006,5007,5009,5011,5013],{},[24,5008,26],{},[24,5010,29],{},[24,5012,32],{},[24,5014,35],{},[13,5016,38],{"id":38},[40,5018,5019,5031],{},[43,5020,5021],{},[46,5022,5023,5025,5027,5029],{},[49,5024,51],{},[49,5026,54],{},[49,5028,57],{},[49,5030,60],{},[62,5032,5033,5043,5053,5063,5073,5083],{},[46,5034,5035,5037,5039,5041],{},[67,5036,69],{},[67,5038,72],{},[67,5040,75],{},[67,5042,78],{},[46,5044,5045,5047,5049,5051],{},[67,5046,83],{},[67,5048,75],{},[67,5050,72],{},[67,5052,90],{},[46,5054,5055,5057,5059,5061],{},[67,5056,95],{},[67,5058,98],{},[67,5060,101],{},[67,5062,104],{},[46,5064,5065,5067,5069,5071],{},[67,5066,109],{},[67,5068,101],{},[67,5070,114],{},[67,5072,117],{},[46,5074,5075,5077,5079,5081],{},[67,5076,122],{},[67,5078,98],{},[67,5080,127],{},[67,5082,130],{},[46,5084,5085,5087,5089,5091],{},[67,5086,135],{},[67,5088,138],{},[67,5090,101],{},[67,5092,143],{},[17,5094,5095],{},[147,5096,149],{},[151,5098,5100],{"className":5099,"code":155,"language":156,"meta":157},[154],[159,5101,155],{"__ignoreMap":157},[13,5103,164],{"id":163},[17,5105,167],{},[40,5107,5108,5116],{},[43,5109,5110],{},[46,5111,5112,5114],{},[49,5113,176],{},[49,5115,179],{},[62,5117,5118,5126,5134,5144,5152],{},[46,5119,5120,5122],{},[67,5121,72],{},[67,5123,5124],{},[159,5125,190],{},[46,5127,5128,5130],{},[67,5129,98],{},[67,5131,5132],{},[159,5133,199],{},[46,5135,5136,5138],{},[67,5137,204],{},[67,5139,5140,210,5142],{},[159,5141,209],{},[159,5143,213],{},[46,5145,5146,5148],{},[67,5147,75],{},[67,5149,5150,223],{},[159,5151,222],{},[46,5153,5154,5156],{},[67,5155,228],{},[67,5157,5158,234],{},[159,5159,233],{},[17,5161,237],{},[151,5163,5164],{"className":240,"code":241,"language":242,"meta":157,"style":157},[159,5165,5166,5170,5174,5178,5184,5190,5196,5200,5204,5210,5216,5222,5226,5230,5236,5242,5248,5254,5258,5262,5268],{"__ignoreMap":157},[246,5167,5168],{"class":248,"line":249},[246,5169,253],{"class":252},[246,5171,5172],{"class":248,"line":256},[246,5173,260],{"emptyLinePlaceholder":259},[246,5175,5176],{"class":248,"line":263},[246,5177,266],{"class":252},[246,5179,5180,5182],{"class":248,"line":269},[246,5181,273],{"class":272},[246,5183,277],{"class":276},[246,5185,5186,5188],{"class":248,"line":280},[246,5187,273],{"class":272},[246,5189,285],{"class":276},[246,5191,5192,5194],{"class":248,"line":288},[246,5193,273],{"class":272},[246,5195,293],{"class":276},[246,5197,5198],{"class":248,"line":5},[246,5199,260],{"emptyLinePlaceholder":259},[246,5201,5202],{"class":248,"line":300},[246,5203,303],{"class":252},[246,5205,5206,5208],{"class":248,"line":306},[246,5207,273],{"class":272},[246,5209,311],{"class":276},[246,5211,5212,5214],{"class":248,"line":314},[246,5213,273],{"class":272},[246,5215,319],{"class":276},[246,5217,5218,5220],{"class":248,"line":322},[246,5219,273],{"class":272},[246,5221,327],{"class":276},[246,5223,5224],{"class":248,"line":330},[246,5225,260],{"emptyLinePlaceholder":259},[246,5227,5228],{"class":248,"line":335},[246,5229,338],{"class":252},[246,5231,5232,5234],{"class":248,"line":341},[246,5233,273],{"class":272},[246,5235,346],{"class":276},[246,5237,5238,5240],{"class":248,"line":349},[246,5239,273],{"class":272},[246,5241,354],{"class":276},[246,5243,5244,5246],{"class":248,"line":357},[246,5245,273],{"class":272},[246,5247,362],{"class":276},[246,5249,5250,5252],{"class":248,"line":365},[246,5251,273],{"class":272},[246,5253,370],{"class":276},[246,5255,5256],{"class":248,"line":373},[246,5257,260],{"emptyLinePlaceholder":259},[246,5259,5260],{"class":248,"line":378},[246,5261,381],{"class":252},[246,5263,5264,5266],{"class":248,"line":384},[246,5265,273],{"class":272},[246,5267,389],{"class":276},[246,5269,5270,5272],{"class":248,"line":392},[246,5271,273],{"class":272},[246,5273,397],{"class":276},[17,5275,400],{},[13,5277,404],{"id":403},[406,5279,409],{"id":408},[17,5281,412],{},[151,5283,5284],{"className":415,"code":416,"language":417,"meta":157,"style":157},[159,5285,5286],{"__ignoreMap":157},[246,5287,5288,5290,5292],{"class":248,"line":249},[246,5289,425],{"class":424},[246,5291,429],{"class":428},[246,5293,433],{"class":432},[17,5295,436],{},[406,5297,440],{"id":439},[17,5299,443],{},[151,5301,5303],{"className":5302,"code":447,"language":156,"meta":157},[154],[159,5304,447],{"__ignoreMap":157},[17,5306,452],{},[406,5308,456],{"id":455},[17,5310,459],{},[151,5312,5314],{"className":5313,"code":463,"language":156,"meta":157},[154],[159,5315,463],{"__ignoreMap":157},[17,5317,468],{},[406,5319,472],{"id":471},[17,5321,475],{},[151,5323,5324],{"className":415,"code":478,"language":417,"meta":157,"style":157},[159,5325,5326,5338,5346],{"__ignoreMap":157},[246,5327,5328,5330,5332,5334,5336],{"class":248,"line":249},[246,5329,425],{"class":424},[246,5331,429],{"class":428},[246,5333,489],{"class":432},[246,5335,492],{"class":428},[246,5337,495],{"class":432},[246,5339,5340,5342,5344],{"class":248,"line":256},[246,5341,500],{"class":424},[246,5343,503],{"class":432},[246,5345,506],{"class":432},[246,5347,5348,5350,5352,5354],{"class":248,"line":263},[246,5349,511],{"class":424},[246,5351,514],{"class":428},[246,5353,517],{"class":428},[246,5355,520],{"class":432},[17,5357,523],{},[13,5359,527],{"id":526},[17,5361,530],{},[532,5363,5364,5366,5368,5370,5372,5374],{},[24,5365,536],{},[24,5367,539],{},[24,5369,542],{},[24,5371,545],{},[24,5373,548],{},[24,5375,551],{},[17,5377,554],{},[21,5379,5380,5382,5384,5386],{},[24,5381,559],{},[24,5383,562],{},[24,5385,565],{},[24,5387,568],{},[13,5389,572],{"id":571},[17,5391,575],{},[151,5393,5395],{"className":5394,"code":579,"language":156,"meta":157},[154],[159,5396,579],{"__ignoreMap":157},[17,5398,584],{},[13,5400,588],{"id":587},[151,5402,5404],{"className":5403,"code":592,"language":156,"meta":157},[154],[159,5405,592],{"__ignoreMap":157},[17,5407,597],{},[151,5409,5410],{"className":415,"code":600,"language":417,"meta":157,"style":157},[159,5411,5412,5416,5426,5430,5434,5446,5450],{"__ignoreMap":157},[246,5413,5414],{"class":248,"line":249},[246,5415,608],{"class":607},[246,5417,5418,5420,5422,5424],{"class":248,"line":256},[246,5419,613],{"class":424},[246,5421,616],{"class":432},[246,5423,620],{"class":619},[246,5425,623],{"class":432},[246,5427,5428],{"class":248,"line":263},[246,5429,260],{"emptyLinePlaceholder":259},[246,5431,5432],{"class":248,"line":269},[246,5433,632],{"class":607},[246,5435,5436,5438,5440,5442,5444],{"class":248,"line":280},[246,5437,425],{"class":424},[246,5439,429],{"class":428},[246,5441,641],{"class":432},[246,5443,644],{"class":424},[246,5445,647],{"class":432},[246,5447,5448],{"class":248,"line":288},[246,5449,260],{"emptyLinePlaceholder":259},[246,5451,5452],{"class":248,"line":5},[246,5453,656],{"class":607},[17,5455,659],{},[13,5457,662],{"id":662},[532,5459,5460,5464,5468,5472,5476,5482],{},[24,5461,5462,670],{},[147,5463,669],{},[24,5465,5466,676],{},[147,5467,675],{},[24,5469,5470,682],{},[147,5471,681],{},[24,5473,5474,688],{},[147,5475,687],{},[24,5477,5478,694,5480,698],{},[147,5479,693],{},[159,5481,697],{},[24,5483,5484,704],{},[147,5485,703],{},[13,5487,707],{"id":707},[17,5489,710],{},[151,5491,5493],{"className":5492,"code":714,"language":156,"meta":157},[154],[159,5494,714],{"__ignoreMap":157},[17,5496,719],{},[721,5498,723],{},{"title":157,"searchDepth":263,"depth":263,"links":5500},[5501,5502,5503,5504,5510,5511,5512,5513,5514],{"id":15,"depth":256,"text":15},{"id":38,"depth":256,"text":38},{"id":163,"depth":256,"text":164},{"id":403,"depth":256,"text":404,"children":5505},[5506,5507,5508,5509],{"id":408,"depth":263,"text":409},{"id":439,"depth":263,"text":440},{"id":455,"depth":263,"text":456},{"id":471,"depth":263,"text":472},{"id":526,"depth":256,"text":527},{"id":571,"depth":256,"text":572},{"id":587,"depth":256,"text":588},{"id":662,"depth":256,"text":662},{"id":707,"depth":256,"text":707},{},[747,748,749,750],{"title":8,"description":742},[754,72,75,98,101,755],{"id":5520,"title":5521,"body":5522,"category":6376,"cover":6377,"description":6378,"extension":242,"meta":6379,"navigation":259,"path":6380,"published":6381,"relatedTools":6382,"seo":6385,"stem":6386,"tags":6387,"updated":6381,"__hash__":6392},"playbook\u002Fplaybook\u002Fdeploy\u002Fai-auto-deploy.md","用 AI Agent 全自动部署：从 Git Push 到生产环境零手工",{"type":10,"value":5523,"toc":6365},[5524,5526,5537,5540,5546,5550,5555,5836,5840,5843,5934,5938,6039,6043,6159,6162,6251,6254,6257,6317,6320,6362],[13,5525,15],{"id":15},[21,5527,5528,5531,5534],{},[24,5529,5530],{},"个人项目 \u002F 小团队，不想手动部署",[24,5532,5533],{},"想让 AI 做部署决策（是否回滚、是否发公告）",[24,5535,5536],{},"需要部署后自动验证的",[13,5538,5539],{"id":5539},"架构",[151,5541,5544],{"className":5542,"code":5543,"language":156},[154],"git push main\n  → GitHub Actions 触发\n    → Step 1: 跑测试（pnpm test）\n    → Step 2: Claude Code 审查改动\n    → Step 3: 构建（pnpm build）\n    → Step 4: 部署到 Vercel\n    → Step 5: Claude Code 验证生产环境\n    → Step 6: 失败则自动回滚 + 通知\n",[159,5545,5543],{"__ignoreMap":157},[13,5547,5549],{"id":5548},"第一步基础-ci","第一步：基础 CI",[17,5551,5552,864],{},[159,5553,5554],{},".github\u002Fworkflows\u002Fdeploy.yml",[151,5556,5560],{"className":5557,"code":5558,"language":5559,"meta":157,"style":157},"language-yaml shiki shiki-themes github-light github-dark","name: Deploy\non:\n  push:\n    branches: [main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n      deployments: write\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: pnpm\u002Faction-setup@v2\n        with: { version: 9 }\n      - uses: actions\u002Fsetup-node@v4\n        with: { node-version: 22, cache: pnpm }\n\n      - name: Install\n        run: pnpm install --frozen-lockfile\n\n      - name: Test\n        run: pnpm test\n\n      - name: Build\n        run: pnpm build\n        env:\n          VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}\n","yaml",[159,5561,5562,5573,5581,5588,5600,5604,5611,5618,5628,5635,5645,5654,5661,5674,5685,5704,5715,5741,5745,5756,5766,5770,5781,5790,5795,5807,5817,5825],{"__ignoreMap":157},[246,5563,5564,5568,5570],{"class":248,"line":249},[246,5565,5567],{"class":5566},"s9eBZ","name",[246,5569,2128],{"class":276},[246,5571,5572],{"class":432},"Deploy\n",[246,5574,5575,5578],{"class":248,"line":256},[246,5576,5577],{"class":428},"on",[246,5579,5580],{"class":276},":\n",[246,5582,5583,5586],{"class":248,"line":263},[246,5584,5585],{"class":5566},"  push",[246,5587,5580],{"class":276},[246,5589,5590,5593,5595,5598],{"class":248,"line":269},[246,5591,5592],{"class":5566},"    branches",[246,5594,2142],{"class":276},[246,5596,5597],{"class":432},"main",[246,5599,2154],{"class":276},[246,5601,5602],{"class":248,"line":280},[246,5603,260],{"emptyLinePlaceholder":259},[246,5605,5606,5609],{"class":248,"line":288},[246,5607,5608],{"class":5566},"jobs",[246,5610,5580],{"class":276},[246,5612,5613,5616],{"class":248,"line":5},[246,5614,5615],{"class":5566},"  deploy",[246,5617,5580],{"class":276},[246,5619,5620,5623,5625],{"class":248,"line":300},[246,5621,5622],{"class":5566},"    runs-on",[246,5624,2128],{"class":276},[246,5626,5627],{"class":432},"ubuntu-latest\n",[246,5629,5630,5633],{"class":248,"line":306},[246,5631,5632],{"class":5566},"    permissions",[246,5634,5580],{"class":276},[246,5636,5637,5640,5642],{"class":248,"line":314},[246,5638,5639],{"class":5566},"      contents",[246,5641,2128],{"class":276},[246,5643,5644],{"class":432},"write\n",[246,5646,5647,5650,5652],{"class":248,"line":322},[246,5648,5649],{"class":5566},"      deployments",[246,5651,2128],{"class":276},[246,5653,5644],{"class":432},[246,5655,5656,5659],{"class":248,"line":330},[246,5657,5658],{"class":5566},"    steps",[246,5660,5580],{"class":276},[246,5662,5663,5666,5669,5671],{"class":248,"line":335},[246,5664,5665],{"class":276},"      - ",[246,5667,5668],{"class":5566},"uses",[246,5670,2128],{"class":276},[246,5672,5673],{"class":432},"actions\u002Fcheckout@v4\n",[246,5675,5676,5678,5680,5682],{"class":248,"line":341},[246,5677,5665],{"class":276},[246,5679,5668],{"class":5566},[246,5681,2128],{"class":276},[246,5683,5684],{"class":432},"pnpm\u002Faction-setup@v2\n",[246,5686,5687,5690,5693,5696,5698,5701],{"class":248,"line":349},[246,5688,5689],{"class":5566},"        with",[246,5691,5692],{"class":276},": { ",[246,5694,5695],{"class":5566},"version",[246,5697,2128],{"class":276},[246,5699,5700],{"class":428},"9",[246,5702,5703],{"class":276}," }\n",[246,5705,5706,5708,5710,5712],{"class":248,"line":357},[246,5707,5665],{"class":276},[246,5709,5668],{"class":5566},[246,5711,2128],{"class":276},[246,5713,5714],{"class":432},"actions\u002Fsetup-node@v4\n",[246,5716,5717,5719,5721,5724,5726,5729,5731,5734,5736,5739],{"class":248,"line":365},[246,5718,5689],{"class":5566},[246,5720,5692],{"class":276},[246,5722,5723],{"class":5566},"node-version",[246,5725,2128],{"class":276},[246,5727,5728],{"class":428},"22",[246,5730,2148],{"class":276},[246,5732,5733],{"class":5566},"cache",[246,5735,2128],{"class":276},[246,5737,5738],{"class":432},"pnpm",[246,5740,5703],{"class":276},[246,5742,5743],{"class":248,"line":373},[246,5744,260],{"emptyLinePlaceholder":259},[246,5746,5747,5749,5751,5753],{"class":248,"line":378},[246,5748,5665],{"class":276},[246,5750,5567],{"class":5566},[246,5752,2128],{"class":276},[246,5754,5755],{"class":432},"Install\n",[246,5757,5758,5761,5763],{"class":248,"line":384},[246,5759,5760],{"class":5566},"        run",[246,5762,2128],{"class":276},[246,5764,5765],{"class":432},"pnpm install --frozen-lockfile\n",[246,5767,5768],{"class":248,"line":392},[246,5769,260],{"emptyLinePlaceholder":259},[246,5771,5772,5774,5776,5778],{"class":248,"line":4550},[246,5773,5665],{"class":276},[246,5775,5567],{"class":5566},[246,5777,2128],{"class":276},[246,5779,5780],{"class":432},"Test\n",[246,5782,5783,5785,5787],{"class":248,"line":4556},[246,5784,5760],{"class":5566},[246,5786,2128],{"class":276},[246,5788,5789],{"class":432},"pnpm test\n",[246,5791,5793],{"class":248,"line":5792},24,[246,5794,260],{"emptyLinePlaceholder":259},[246,5796,5798,5800,5802,5804],{"class":248,"line":5797},25,[246,5799,5665],{"class":276},[246,5801,5567],{"class":5566},[246,5803,2128],{"class":276},[246,5805,5806],{"class":432},"Build\n",[246,5808,5810,5812,5814],{"class":248,"line":5809},26,[246,5811,5760],{"class":5566},[246,5813,2128],{"class":276},[246,5815,5816],{"class":432},"pnpm build\n",[246,5818,5820,5823],{"class":248,"line":5819},27,[246,5821,5822],{"class":5566},"        env",[246,5824,5580],{"class":276},[246,5826,5828,5831,5833],{"class":248,"line":5827},28,[246,5829,5830],{"class":5566},"          VERCEL_TOKEN",[246,5832,2128],{"class":276},[246,5834,5835],{"class":432},"${{ secrets.VERCEL_TOKEN }}\n",[13,5837,5839],{"id":5838},"第二步ai-审查改动","第二步：AI 审查改动",[17,5841,5842],{},"在 build 前加 Claude Code 审查：",[151,5844,5846],{"className":5557,"code":5845,"language":5559,"meta":157,"style":157},"      - name: AI Review Changes\n        uses: anthropics\u002Fclaude-code-action@v1\n        with:\n          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}\n          prompt: |\n            检查这次改动是否有部署风险：\n            1. 是否修改了环境变量配置\n            2. 是否修改了数据库 schema\n            3. 是否有 breaking change\n            4. 是否需要发迁移公告\n\n            如果有风险，输出 \"BLOCK_DEPLOY: \u003C原因>\"\n            如果没风险，输出 \"DEPLOY_OK\"\n",[159,5847,5848,5859,5869,5875,5885,5895,5900,5905,5910,5915,5920,5924,5929],{"__ignoreMap":157},[246,5849,5850,5852,5854,5856],{"class":248,"line":249},[246,5851,5665],{"class":276},[246,5853,5567],{"class":5566},[246,5855,2128],{"class":276},[246,5857,5858],{"class":432},"AI Review Changes\n",[246,5860,5861,5864,5866],{"class":248,"line":256},[246,5862,5863],{"class":5566},"        uses",[246,5865,2128],{"class":276},[246,5867,5868],{"class":432},"anthropics\u002Fclaude-code-action@v1\n",[246,5870,5871,5873],{"class":248,"line":263},[246,5872,5689],{"class":5566},[246,5874,5580],{"class":276},[246,5876,5877,5880,5882],{"class":248,"line":269},[246,5878,5879],{"class":5566},"          anthropic_api_key",[246,5881,2128],{"class":276},[246,5883,5884],{"class":432},"${{ secrets.ANTHROPIC_API_KEY }}\n",[246,5886,5887,5890,5892],{"class":248,"line":280},[246,5888,5889],{"class":5566},"          prompt",[246,5891,2128],{"class":276},[246,5893,5894],{"class":619},"|\n",[246,5896,5897],{"class":248,"line":288},[246,5898,5899],{"class":432},"            检查这次改动是否有部署风险：\n",[246,5901,5902],{"class":248,"line":5},[246,5903,5904],{"class":432},"            1. 是否修改了环境变量配置\n",[246,5906,5907],{"class":248,"line":300},[246,5908,5909],{"class":432},"            2. 是否修改了数据库 schema\n",[246,5911,5912],{"class":248,"line":306},[246,5913,5914],{"class":432},"            3. 是否有 breaking change\n",[246,5916,5917],{"class":248,"line":314},[246,5918,5919],{"class":432},"            4. 是否需要发迁移公告\n",[246,5921,5922],{"class":248,"line":322},[246,5923,260],{"emptyLinePlaceholder":259},[246,5925,5926],{"class":248,"line":330},[246,5927,5928],{"class":432},"            如果有风险，输出 \"BLOCK_DEPLOY: \u003C原因>\"\n",[246,5930,5931],{"class":248,"line":335},[246,5932,5933],{"class":432},"            如果没风险，输出 \"DEPLOY_OK\"\n",[13,5935,5937],{"id":5936},"第三步ai-部署","第三步：AI 部署",[151,5939,5941],{"className":5557,"code":5940,"language":5559,"meta":157,"style":157},"      - name: Deploy with Claude\n        if: success()\n        uses: anthropics\u002Fclaude-code-action@v1\n        with:\n          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}\n          prompt: |\n            执行部署：\n            1. 运行 vercel --prod --yes\n            2. 等待部署完成，获取 URL\n            3. curl 测试首页是否 200\n            4. curl 测试 \u002Fapi\u002Fhealth 是否返回 ok\n            5. 如果验证失败，运行 vercel rollback\n            6. 输出部署结果\n          allowed_tools: \"Bash\"\n",[159,5942,5943,5954,5964,5972,5978,5986,5994,5999,6004,6009,6014,6019,6024,6029],{"__ignoreMap":157},[246,5944,5945,5947,5949,5951],{"class":248,"line":249},[246,5946,5665],{"class":276},[246,5948,5567],{"class":5566},[246,5950,2128],{"class":276},[246,5952,5953],{"class":432},"Deploy with Claude\n",[246,5955,5956,5959,5961],{"class":248,"line":256},[246,5957,5958],{"class":5566},"        if",[246,5960,2128],{"class":276},[246,5962,5963],{"class":432},"success()\n",[246,5965,5966,5968,5970],{"class":248,"line":263},[246,5967,5863],{"class":5566},[246,5969,2128],{"class":276},[246,5971,5868],{"class":432},[246,5973,5974,5976],{"class":248,"line":269},[246,5975,5689],{"class":5566},[246,5977,5580],{"class":276},[246,5979,5980,5982,5984],{"class":248,"line":280},[246,5981,5879],{"class":5566},[246,5983,2128],{"class":276},[246,5985,5884],{"class":432},[246,5987,5988,5990,5992],{"class":248,"line":288},[246,5989,5889],{"class":5566},[246,5991,2128],{"class":276},[246,5993,5894],{"class":619},[246,5995,5996],{"class":248,"line":5},[246,5997,5998],{"class":432},"            执行部署：\n",[246,6000,6001],{"class":248,"line":300},[246,6002,6003],{"class":432},"            1. 运行 vercel --prod --yes\n",[246,6005,6006],{"class":248,"line":306},[246,6007,6008],{"class":432},"            2. 等待部署完成，获取 URL\n",[246,6010,6011],{"class":248,"line":314},[246,6012,6013],{"class":432},"            3. curl 测试首页是否 200\n",[246,6015,6016],{"class":248,"line":322},[246,6017,6018],{"class":432},"            4. curl 测试 \u002Fapi\u002Fhealth 是否返回 ok\n",[246,6020,6021],{"class":248,"line":330},[246,6022,6023],{"class":432},"            5. 如果验证失败，运行 vercel rollback\n",[246,6025,6026],{"class":248,"line":335},[246,6027,6028],{"class":432},"            6. 输出部署结果\n",[246,6030,6031,6034,6036],{"class":248,"line":341},[246,6032,6033],{"class":5566},"          allowed_tools",[246,6035,2128],{"class":276},[246,6037,6038],{"class":432},"\"Bash\"\n",[13,6040,6042],{"id":6041},"第四步自动回滚","第四步：自动回滚",[151,6044,6046],{"className":5557,"code":6045,"language":5559,"meta":157,"style":157},"      - name: Rollback on failure\n        if: failure()\n        run: |\n          # 获取上一个稳定部署\n          PREV=$(vercel ls --yes | head -5 | tail -1 | awk '{print $1}')\n          echo \"Rolling back to $PREV\"\n          vercel promote $PREV --yes\n\n      - name: Notify\n        if: always()\n        uses: slackapi\u002Fslack-github-action@v1\n        with:\n          slack-message: |\n            ${{ job.status == 'success' && '✅' || '❌' }} 部署 ${{ job.status }}\n            仓库: ${{ github.repository }}\n            提交: ${{ github.event.head_commit.message }}\n",[159,6047,6048,6059,6068,6076,6081,6086,6091,6096,6100,6111,6120,6129,6135,6144,6149,6154],{"__ignoreMap":157},[246,6049,6050,6052,6054,6056],{"class":248,"line":249},[246,6051,5665],{"class":276},[246,6053,5567],{"class":5566},[246,6055,2128],{"class":276},[246,6057,6058],{"class":432},"Rollback on failure\n",[246,6060,6061,6063,6065],{"class":248,"line":256},[246,6062,5958],{"class":5566},[246,6064,2128],{"class":276},[246,6066,6067],{"class":432},"failure()\n",[246,6069,6070,6072,6074],{"class":248,"line":263},[246,6071,5760],{"class":5566},[246,6073,2128],{"class":276},[246,6075,5894],{"class":619},[246,6077,6078],{"class":248,"line":269},[246,6079,6080],{"class":432},"          # 获取上一个稳定部署\n",[246,6082,6083],{"class":248,"line":280},[246,6084,6085],{"class":432},"          PREV=$(vercel ls --yes | head -5 | tail -1 | awk '{print $1}')\n",[246,6087,6088],{"class":248,"line":288},[246,6089,6090],{"class":432},"          echo \"Rolling back to $PREV\"\n",[246,6092,6093],{"class":248,"line":5},[246,6094,6095],{"class":432},"          vercel promote $PREV --yes\n",[246,6097,6098],{"class":248,"line":300},[246,6099,260],{"emptyLinePlaceholder":259},[246,6101,6102,6104,6106,6108],{"class":248,"line":306},[246,6103,5665],{"class":276},[246,6105,5567],{"class":5566},[246,6107,2128],{"class":276},[246,6109,6110],{"class":432},"Notify\n",[246,6112,6113,6115,6117],{"class":248,"line":314},[246,6114,5958],{"class":5566},[246,6116,2128],{"class":276},[246,6118,6119],{"class":432},"always()\n",[246,6121,6122,6124,6126],{"class":248,"line":322},[246,6123,5863],{"class":5566},[246,6125,2128],{"class":276},[246,6127,6128],{"class":432},"slackapi\u002Fslack-github-action@v1\n",[246,6130,6131,6133],{"class":248,"line":330},[246,6132,5689],{"class":5566},[246,6134,5580],{"class":276},[246,6136,6137,6140,6142],{"class":248,"line":335},[246,6138,6139],{"class":5566},"          slack-message",[246,6141,2128],{"class":276},[246,6143,5894],{"class":619},[246,6145,6146],{"class":248,"line":341},[246,6147,6148],{"class":432},"            ${{ job.status == 'success' && '✅' || '❌' }} 部署 ${{ job.status }}\n",[246,6150,6151],{"class":248,"line":349},[246,6152,6153],{"class":432},"            仓库: ${{ github.repository }}\n",[246,6155,6156],{"class":248,"line":357},[246,6157,6158],{"class":432},"            提交: ${{ github.event.head_commit.message }}\n",[13,6160,6161],{"id":6161},"安全边界",[40,6163,6164,6177],{},[43,6165,6166],{},[46,6167,6168,6171,6174],{},[49,6169,6170],{},"操作",[49,6172,6173],{},"AI 可执行",[49,6175,6176],{},"需人工确认",[62,6178,6179,6188,6197,6206,6215,6224,6233,6242],{},[46,6180,6181,6184,6186],{},[67,6182,6183],{},"跑测试",[67,6185,1334],{},[67,6187],{},[46,6189,6190,6193,6195],{},[67,6191,6192],{},"构建项目",[67,6194,1334],{},[67,6196],{},[46,6198,6199,6202,6204],{},[67,6200,6201],{},"部署到 preview",[67,6203,1334],{},[67,6205],{},[46,6207,6208,6211,6213],{},[67,6209,6210],{},"部署到 production",[67,6212,1334],{},[67,6214],{},[46,6216,6217,6220,6222],{},[67,6218,6219],{},"回滚",[67,6221,1334],{},[67,6223],{},[46,6225,6226,6229,6231],{},[67,6227,6228],{},"修改环境变量",[67,6230],{},[67,6232,1334],{},[46,6234,6235,6238,6240],{},[67,6236,6237],{},"数据库迁移",[67,6239],{},[67,6241,1334],{},[46,6243,6244,6247,6249],{},[67,6245,6246],{},"删除资源",[67,6248],{},[67,6250,1334],{},[13,6252,6253],{"id":6253},"效果",[17,6255,6256],{},"上线 1 个月后：",[40,6258,6259,6271],{},[43,6260,6261],{},[46,6262,6263,6265,6268],{},[49,6264,4879],{},[49,6266,6267],{},"之前（手动）",[49,6269,6270],{},"之后（AI 自动）",[62,6272,6273,6284,6295,6306],{},[46,6274,6275,6278,6281],{},[67,6276,6277],{},"部署频率",[67,6279,6280],{},"2 次\u002F周",[67,6282,6283],{},"5 次\u002F天",[46,6285,6286,6289,6292],{},[67,6287,6288],{},"部署耗时",[67,6290,6291],{},"15 分钟",[67,6293,6294],{},"3 分钟",[46,6296,6297,6300,6303],{},[67,6298,6299],{},"部署失败率",[67,6301,6302],{},"10%",[67,6304,6305],{},"3%（自动回滚）",[46,6307,6308,6311,6314],{},[67,6309,6310],{},"人工介入",[67,6312,6313],{},"每次",[67,6315,6316],{},"5% 的部署",[13,6318,6319],{"id":6319},"踩坑记录",[532,6321,6322,6335,6341,6347,6353],{},[24,6323,6324,6330,6331,6334],{},[147,6325,6326,6327],{},"Claude Code Action 的 ",[159,6328,6329],{},"allowed_tools","——只给 ",[159,6332,6333],{},"Bash","，别给文件编辑权限，否则 AI 可能改代码。",[24,6336,6337,6340],{},[147,6338,6339],{},"Vercel rollback 需要 production deployment 历史","——首次部署没有回滚目标，先手动部署一次。",[24,6342,6343,6346],{},[147,6344,6345],{},"Claude API 成本","——每次部署约 $0.2-0.5（审查 + 部署 + 验证），月费 $30-50。",[24,6348,6349,6352],{},[147,6350,6351],{},"preview 环境先验证","——加一步部署到 preview 验证通过再 promote 到 production。",[24,6354,6355,6358,6359,3725],{},[147,6356,6357],{},"GitHub Actions 超时","——Claude Code 调用有时慢，设置 ",[159,6360,6361],{},"timeout-minutes: 15",[721,6363,6364],{},"html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":157,"searchDepth":263,"depth":263,"links":6366},[6367,6368,6369,6370,6371,6372,6373,6374,6375],{"id":15,"depth":256,"text":15},{"id":5539,"depth":256,"text":5539},{"id":5548,"depth":256,"text":5549},{"id":5838,"depth":256,"text":5839},{"id":5936,"depth":256,"text":5937},{"id":6041,"depth":256,"text":6042},{"id":6161,"depth":256,"text":6161},{"id":6253,"depth":256,"text":6253},{"id":6319,"depth":256,"text":6319},"deploy","\u002Fog\u002Fplaybook\u002Fai-auto-deploy.png","用 Claude Code + GitHub Actions + Vercel\u002FCfly 搭一条全自动部署流水线——push 到 main → AI 跑测试 → AI 审查 → AI 部署 → 验证 → 通知。零手工操作，含回滚机制。",{},"\u002Fplaybook\u002Fdeploy\u002Fai-auto-deploy","2026-06-21",[747,6383,6384],"coding\u002Fbuilder\u002Fv0","agent\u002Fskills\u002Fclaude-skills",{"title":5521,"description":6378},"playbook\u002Fdeploy\u002Fai-auto-deploy",[6388,6389,72,6390,6391],"部署","CI\u002FCD","GitHub Actions","自动化","0C0tbe1lwERKuzXgnhYWUeLJ7FFDITUdnTFvc0MVs-E",{"id":6394,"title":6395,"body":6396,"category":7478,"cover":7479,"description":7480,"extension":242,"meta":7481,"navigation":259,"path":7482,"published":6381,"relatedTools":7483,"seo":7485,"stem":7486,"tags":7487,"updated":6381,"__hash__":7492},"playbook\u002Fplaybook\u002Fmigration\u002Fai-db-migration.md","用 AI 做数据库迁移：零停机 schema 变更工作流",{"type":10,"value":6397,"toc":7464},[6398,6400,6414,6417,6443,6446,6452,6456,6459,6465,6468,6492,6495,6621,6625,6631,6634,6638,6642,6962,6965,7189,7192,7247,7251,7348,7352,7355,7391,7455,7461],[13,6399,15],{"id":15},[21,6401,6402,6405,6408,6411],{},[24,6403,6404],{},"生产数据库需要 schema 变更",[24,6406,6407],{},"大表（千万行+）加列 \u002F 改类型 \u002F 加索引",[24,6409,6410],{},"需要零停机迁移",[24,6412,6413],{},"想让 AI 生成迁移文件 + 回滚方案",[13,6415,6416],{"id":6416},"迁移原则",[532,6418,6419,6425,6431,6437],{},[24,6420,6421,6424],{},[147,6422,6423],{},"永远可回滚","——每个迁移文件都有对应的 down migration",[24,6426,6427,6430],{},[147,6428,6429],{},"分阶段执行","——大变更拆成多步，每步都可独立回滚",[24,6432,6433,6436],{},[147,6434,6435],{},"先兼容后破坏","——先让代码兼容新 schema，再删旧字段",[24,6438,6439,6442],{},[147,6440,6441],{},"AI 生成 + 人工审查","——AI 写迁移，人审 SQL",[13,6444,6445],{"id":6445},"工作流",[151,6447,6450],{"className":6448,"code":6449,"language":156},[154],"需求：给 users 表加 phone 字段\n  → Step 1: Claude 生成迁移文件（含 up + down）\n  → Step 2: Claude 检查兼容性（是否破坏现有代码）\n  → Step 3: 在 shadow DB 测试迁移\n  → Step 4: 生产分阶段执行\n  → Step 5: 验证 + 清理\n",[159,6451,6449],{"__ignoreMap":157},[13,6453,6455],{"id":6454},"step-1-ai-生成迁移","Step 1: AI 生成迁移",[17,6457,6458],{},"用 Claude Code 连数据库（通过 MCP），描述需求：",[151,6460,6463],{"className":6461,"code":6462,"language":156},[154],"给 users 表加一个 phone 字段，varchar(20)，可空，加唯一索引。\n用 Drizzle migration 格式生成，含 up 和 down。\n检查现有代码是否有依赖。\n",[159,6464,6462],{"__ignoreMap":157},[17,6466,6467],{},"Claude 会：",[532,6469,6470,6473,6476,6479,6482],{},[24,6471,6472],{},"查当前 users 表结构",[24,6474,6475],{},"生成 Drizzle schema 改动",[24,6477,6478],{},"生成 SQL migration 文件",[24,6480,6481],{},"生成回滚 SQL",[24,6483,6484,6485,2201,6488,6491],{},"检查代码里的 ",[159,6486,6487],{},"select *",[159,6489,6490],{},"insert"," 是否受影响",[17,6493,6494],{},"生成的文件：",[151,6496,6500],{"className":6497,"code":6498,"language":6499,"meta":157,"style":157},"language-sql shiki shiki-themes github-light github-dark","-- migrations\u002F0024_add_user_phone.sql\n\n-- UP\nALTER TABLE users ADD COLUMN phone VARCHAR(20);\nCREATE UNIQUE INDEX idx_users_phone ON users(phone) WHERE phone IS NOT NULL;\n\n-- DOWN\nDROP INDEX IF EXISTS idx_users_phone;\nALTER TABLE users DROP COLUMN IF EXISTS phone;\n","sql",[159,6501,6502,6507,6511,6516,6545,6574,6578,6583,6600],{"__ignoreMap":157},[246,6503,6504],{"class":248,"line":249},[246,6505,6506],{"class":607},"-- migrations\u002F0024_add_user_phone.sql\n",[246,6508,6509],{"class":248,"line":256},[246,6510,260],{"emptyLinePlaceholder":259},[246,6512,6513],{"class":248,"line":263},[246,6514,6515],{"class":607},"-- UP\n",[246,6517,6518,6521,6524,6527,6530,6533,6536,6539,6542],{"class":248,"line":269},[246,6519,6520],{"class":619},"ALTER",[246,6522,6523],{"class":619}," TABLE",[246,6525,6526],{"class":276}," users ",[246,6528,6529],{"class":619},"ADD",[246,6531,6532],{"class":276}," COLUMN phone ",[246,6534,6535],{"class":619},"VARCHAR",[246,6537,6538],{"class":276},"(",[246,6540,6541],{"class":428},"20",[246,6543,6544],{"class":276},");\n",[246,6546,6547,6550,6553,6556,6559,6562,6565,6568,6571],{"class":248,"line":280},[246,6548,6549],{"class":619},"CREATE",[246,6551,6552],{"class":619}," UNIQUE INDEX",[246,6554,6555],{"class":424}," idx_users_phone",[246,6557,6558],{"class":619}," ON",[246,6560,6561],{"class":276}," users(phone) ",[246,6563,6564],{"class":619},"WHERE",[246,6566,6567],{"class":276}," phone ",[246,6569,6570],{"class":619},"IS NOT NULL",[246,6572,6573],{"class":276},";\n",[246,6575,6576],{"class":248,"line":288},[246,6577,260],{"emptyLinePlaceholder":259},[246,6579,6580],{"class":248,"line":5},[246,6581,6582],{"class":607},"-- DOWN\n",[246,6584,6585,6588,6591,6594,6597],{"class":248,"line":300},[246,6586,6587],{"class":619},"DROP",[246,6589,6590],{"class":619}," INDEX",[246,6592,6593],{"class":619}," IF",[246,6595,6596],{"class":619}," EXISTS",[246,6598,6599],{"class":276}," idx_users_phone;\n",[246,6601,6602,6604,6606,6608,6610,6613,6616,6618],{"class":248,"line":306},[246,6603,6520],{"class":619},[246,6605,6523],{"class":619},[246,6607,6526],{"class":276},[246,6609,6587],{"class":619},[246,6611,6612],{"class":276}," COLUMN ",[246,6614,6615],{"class":619},"IF",[246,6617,6596],{"class":619},[246,6619,6620],{"class":276}," phone;\n",[13,6622,6624],{"id":6623},"step-2-兼容性检查","Step 2: 兼容性检查",[151,6626,6629],{"className":6627,"code":6628,"language":156},[154],"检查这次迁移会影响哪些代码：\n1. 哪些 INSERT 语句需要加 phone 字段\n2. 哪些 SELECT * 会导致返回字段变化\n3. 哪些 API 响应 schema 会变\n",[159,6630,6628],{"__ignoreMap":157},[17,6632,6633],{},"Claude 输出影响清单，你确认后再执行。",[13,6635,6637],{"id":6636},"step-3-高危操作安全模式","Step 3: 高危操作安全模式",[406,6639,6641],{"id":6640},"大表加列千万行","大表加列（千万行+）",[151,6643,6645],{"className":6497,"code":6644,"language":6499,"meta":157,"style":157},"-- ❌ 错误：直接加（锁表）\nALTER TABLE users ADD COLUMN phone VARCHAR(20);\n\n-- ✅ 正确：分阶段\n-- Phase 1: 加可空字段（不锁表，PostgreSQL 11+）\nALTER TABLE users ADD COLUMN phone VARCHAR(20);\n\n-- Phase 2: 回填数据（分批，不锁表）\n-- Claude 生成批处理脚本\nDO $$\nDECLARE\n  batch_size INT := 10000;\n  offset_val INT := 0;\nBEGIN\n  LOOP\n    UPDATE users SET phone = '' WHERE id IN (\n      SELECT id FROM users WHERE phone IS NULL LIMIT batch_size\n    );\n    GET DIAGNOSTICS batch_size = ROW_COUNT;\n    EXIT WHEN batch_size = 0;\n    PERFORM pg_sleep(0.1);  -- 给主从复制留时间\n  END LOOP;\nEND $$;\n\n-- Phase 3: 加约束（先检查再加）\nALTER TABLE users ADD CONSTRAINT chk_phone CHECK (phone ~ '^\\+?[0-9]{6,20}$') NOT VALID;\nALTER TABLE users VALIDATE CONSTRAINT chk_phone;\n",[159,6646,6647,6652,6672,6676,6681,6686,6706,6710,6715,6720,6725,6730,6748,6764,6769,6774,6803,6831,6836,6849,6866,6886,6896,6904,6908,6913,6947],{"__ignoreMap":157},[246,6648,6649],{"class":248,"line":249},[246,6650,6651],{"class":607},"-- ❌ 错误：直接加（锁表）\n",[246,6653,6654,6656,6658,6660,6662,6664,6666,6668,6670],{"class":248,"line":256},[246,6655,6520],{"class":619},[246,6657,6523],{"class":619},[246,6659,6526],{"class":276},[246,6661,6529],{"class":619},[246,6663,6532],{"class":276},[246,6665,6535],{"class":619},[246,6667,6538],{"class":276},[246,6669,6541],{"class":428},[246,6671,6544],{"class":276},[246,6673,6674],{"class":248,"line":263},[246,6675,260],{"emptyLinePlaceholder":259},[246,6677,6678],{"class":248,"line":269},[246,6679,6680],{"class":607},"-- ✅ 正确：分阶段\n",[246,6682,6683],{"class":248,"line":280},[246,6684,6685],{"class":607},"-- Phase 1: 加可空字段（不锁表，PostgreSQL 11+）\n",[246,6687,6688,6690,6692,6694,6696,6698,6700,6702,6704],{"class":248,"line":288},[246,6689,6520],{"class":619},[246,6691,6523],{"class":619},[246,6693,6526],{"class":276},[246,6695,6529],{"class":619},[246,6697,6532],{"class":276},[246,6699,6535],{"class":619},[246,6701,6538],{"class":276},[246,6703,6541],{"class":428},[246,6705,6544],{"class":276},[246,6707,6708],{"class":248,"line":5},[246,6709,260],{"emptyLinePlaceholder":259},[246,6711,6712],{"class":248,"line":300},[246,6713,6714],{"class":607},"-- Phase 2: 回填数据（分批，不锁表）\n",[246,6716,6717],{"class":248,"line":306},[246,6718,6719],{"class":607},"-- Claude 生成批处理脚本\n",[246,6721,6722],{"class":248,"line":314},[246,6723,6724],{"class":276},"DO $$\n",[246,6726,6727],{"class":248,"line":322},[246,6728,6729],{"class":619},"DECLARE\n",[246,6731,6732,6735,6738,6741,6743,6746],{"class":248,"line":330},[246,6733,6734],{"class":276},"  batch_size ",[246,6736,6737],{"class":619},"INT",[246,6739,6740],{"class":276}," :",[246,6742,1109],{"class":619},[246,6744,6745],{"class":428}," 10000",[246,6747,6573],{"class":276},[246,6749,6750,6753,6755,6757,6759,6762],{"class":248,"line":335},[246,6751,6752],{"class":276},"  offset_val ",[246,6754,6737],{"class":619},[246,6756,6740],{"class":276},[246,6758,1109],{"class":619},[246,6760,6761],{"class":428}," 0",[246,6763,6573],{"class":276},[246,6765,6766],{"class":248,"line":341},[246,6767,6768],{"class":619},"BEGIN\n",[246,6770,6771],{"class":248,"line":349},[246,6772,6773],{"class":619},"  LOOP\n",[246,6775,6776,6779,6781,6784,6786,6788,6791,6794,6797,6800],{"class":248,"line":357},[246,6777,6778],{"class":619},"    UPDATE",[246,6780,6526],{"class":276},[246,6782,6783],{"class":619},"SET",[246,6785,6567],{"class":276},[246,6787,1109],{"class":619},[246,6789,6790],{"class":432}," ''",[246,6792,6793],{"class":619}," WHERE",[246,6795,6796],{"class":276}," id ",[246,6798,6799],{"class":619},"IN",[246,6801,6802],{"class":276}," (\n",[246,6804,6805,6808,6810,6813,6815,6817,6819,6822,6825,6828],{"class":248,"line":365},[246,6806,6807],{"class":619},"      SELECT",[246,6809,6796],{"class":276},[246,6811,6812],{"class":619},"FROM",[246,6814,6526],{"class":276},[246,6816,6564],{"class":619},[246,6818,6567],{"class":276},[246,6820,6821],{"class":619},"IS",[246,6823,6824],{"class":619}," NULL",[246,6826,6827],{"class":619}," LIMIT",[246,6829,6830],{"class":276}," batch_size\n",[246,6832,6833],{"class":248,"line":373},[246,6834,6835],{"class":276},"    );\n",[246,6837,6838,6841,6844,6846],{"class":248,"line":378},[246,6839,6840],{"class":619},"    GET",[246,6842,6843],{"class":276}," DIAGNOSTICS batch_size ",[246,6845,1109],{"class":619},[246,6847,6848],{"class":276}," ROW_COUNT;\n",[246,6850,6851,6854,6857,6860,6862,6864],{"class":248,"line":384},[246,6852,6853],{"class":276},"    EXIT ",[246,6855,6856],{"class":619},"WHEN",[246,6858,6859],{"class":276}," batch_size ",[246,6861,1109],{"class":619},[246,6863,6761],{"class":428},[246,6865,6573],{"class":276},[246,6867,6868,6871,6874,6877,6880,6883],{"class":248,"line":392},[246,6869,6870],{"class":276},"    PERFORM pg_sleep(",[246,6872,6873],{"class":428},"0",[246,6875,6876],{"class":276},".",[246,6878,6879],{"class":428},"1",[246,6881,6882],{"class":276},");  ",[246,6884,6885],{"class":607},"-- 给主从复制留时间\n",[246,6887,6888,6891,6894],{"class":248,"line":4550},[246,6889,6890],{"class":619},"  END",[246,6892,6893],{"class":619}," LOOP",[246,6895,6573],{"class":276},[246,6897,6898,6901],{"class":248,"line":4556},[246,6899,6900],{"class":619},"END",[246,6902,6903],{"class":276}," $$;\n",[246,6905,6906],{"class":248,"line":5792},[246,6907,260],{"emptyLinePlaceholder":259},[246,6909,6910],{"class":248,"line":5797},[246,6911,6912],{"class":607},"-- Phase 3: 加约束（先检查再加）\n",[246,6914,6915,6917,6919,6921,6923,6926,6929,6932,6935,6938,6941,6944],{"class":248,"line":5809},[246,6916,6520],{"class":619},[246,6918,6523],{"class":619},[246,6920,6526],{"class":276},[246,6922,6529],{"class":619},[246,6924,6925],{"class":619}," CONSTRAINT",[246,6927,6928],{"class":276}," chk_phone ",[246,6930,6931],{"class":619},"CHECK",[246,6933,6934],{"class":276}," (phone ~ ",[246,6936,6937],{"class":432},"'^\\+?[0-9]{6,20}$'",[246,6939,6940],{"class":276},") ",[246,6942,6943],{"class":619},"NOT",[246,6945,6946],{"class":276}," VALID;\n",[246,6948,6949,6951,6953,6956,6959],{"class":248,"line":5819},[246,6950,6520],{"class":619},[246,6952,6523],{"class":619},[246,6954,6955],{"class":276}," users VALIDATE ",[246,6957,6958],{"class":619},"CONSTRAINT",[246,6960,6961],{"class":276}," chk_phone;\n",[406,6963,6964],{"id":6964},"改字段类型",[151,6966,6968],{"className":6497,"code":6967,"language":6499,"meta":157,"style":157},"-- ❌ 错误：直接改（锁表 + 重写全表）\nALTER TABLE users ALTER COLUMN phone TYPE BIGINT USING phone::BIGINT;\n\n-- ✅ 正确：新字段 + 回填 + 切换 + 删旧\n-- Phase 1: 加新字段\nALTER TABLE users ADD COLUMN phone_int BIGINT;\n\n-- Phase 2: 双写（代码同时写旧和新）\n-- Claude 生成代码改动：INSERT\u002FUPDATE 同时写 phone 和 phone_int\n\n-- Phase 3: 回填\nUPDATE users SET phone_int = phone::BIGINT WHERE phone_int IS NULL AND phone ~ '^[0-9]+$';\n\n-- Phase 4: 验证数据一致\nSELECT COUNT(*) FROM users WHERE phone IS NOT NULL AND phone_int IS NULL;\n-- 必须为 0\n\n-- Phase 5: 代码切到读 phone_int\n\n-- Phase 6: 删旧字段（等一个发布周期后）\nALTER TABLE users DROP COLUMN phone;\nALTER TABLE users RENAME COLUMN phone_int TO phone;\n",[159,6969,6970,6975,7004,7008,7013,7018,7035,7039,7044,7049,7053,7058,7095,7099,7104,7139,7144,7148,7153,7157,7162,7175],{"__ignoreMap":157},[246,6971,6972],{"class":248,"line":249},[246,6973,6974],{"class":607},"-- ❌ 错误：直接改（锁表 + 重写全表）\n",[246,6976,6977,6979,6981,6983,6985,6987,6990,6993,6996,6999,7002],{"class":248,"line":256},[246,6978,6520],{"class":619},[246,6980,6523],{"class":619},[246,6982,6526],{"class":276},[246,6984,6520],{"class":619},[246,6986,6532],{"class":276},[246,6988,6989],{"class":619},"TYPE",[246,6991,6992],{"class":619}," BIGINT",[246,6994,6995],{"class":619}," USING",[246,6997,6998],{"class":276}," phone::",[246,7000,7001],{"class":619},"BIGINT",[246,7003,6573],{"class":276},[246,7005,7006],{"class":248,"line":263},[246,7007,260],{"emptyLinePlaceholder":259},[246,7009,7010],{"class":248,"line":269},[246,7011,7012],{"class":607},"-- ✅ 正确：新字段 + 回填 + 切换 + 删旧\n",[246,7014,7015],{"class":248,"line":280},[246,7016,7017],{"class":607},"-- Phase 1: 加新字段\n",[246,7019,7020,7022,7024,7026,7028,7031,7033],{"class":248,"line":288},[246,7021,6520],{"class":619},[246,7023,6523],{"class":619},[246,7025,6526],{"class":276},[246,7027,6529],{"class":619},[246,7029,7030],{"class":276}," COLUMN phone_int ",[246,7032,7001],{"class":619},[246,7034,6573],{"class":276},[246,7036,7037],{"class":248,"line":5},[246,7038,260],{"emptyLinePlaceholder":259},[246,7040,7041],{"class":248,"line":300},[246,7042,7043],{"class":607},"-- Phase 2: 双写（代码同时写旧和新）\n",[246,7045,7046],{"class":248,"line":306},[246,7047,7048],{"class":607},"-- Claude 生成代码改动：INSERT\u002FUPDATE 同时写 phone 和 phone_int\n",[246,7050,7051],{"class":248,"line":314},[246,7052,260],{"emptyLinePlaceholder":259},[246,7054,7055],{"class":248,"line":322},[246,7056,7057],{"class":607},"-- Phase 3: 回填\n",[246,7059,7060,7063,7065,7067,7070,7072,7074,7076,7078,7080,7082,7084,7087,7090,7093],{"class":248,"line":330},[246,7061,7062],{"class":619},"UPDATE",[246,7064,6526],{"class":276},[246,7066,6783],{"class":619},[246,7068,7069],{"class":276}," phone_int ",[246,7071,1109],{"class":619},[246,7073,6998],{"class":276},[246,7075,7001],{"class":619},[246,7077,6793],{"class":619},[246,7079,7069],{"class":276},[246,7081,6821],{"class":619},[246,7083,6824],{"class":619},[246,7085,7086],{"class":619}," AND",[246,7088,7089],{"class":276}," phone ~ ",[246,7091,7092],{"class":432},"'^[0-9]+$'",[246,7094,6573],{"class":276},[246,7096,7097],{"class":248,"line":335},[246,7098,260],{"emptyLinePlaceholder":259},[246,7100,7101],{"class":248,"line":341},[246,7102,7103],{"class":607},"-- Phase 4: 验证数据一致\n",[246,7105,7106,7109,7112,7114,7117,7119,7121,7123,7125,7127,7129,7131,7133,7135,7137],{"class":248,"line":349},[246,7107,7108],{"class":619},"SELECT",[246,7110,7111],{"class":428}," COUNT",[246,7113,6538],{"class":276},[246,7115,7116],{"class":619},"*",[246,7118,6940],{"class":276},[246,7120,6812],{"class":619},[246,7122,6526],{"class":276},[246,7124,6564],{"class":619},[246,7126,6567],{"class":276},[246,7128,6570],{"class":619},[246,7130,7086],{"class":619},[246,7132,7069],{"class":276},[246,7134,6821],{"class":619},[246,7136,6824],{"class":619},[246,7138,6573],{"class":276},[246,7140,7141],{"class":248,"line":357},[246,7142,7143],{"class":607},"-- 必须为 0\n",[246,7145,7146],{"class":248,"line":365},[246,7147,260],{"emptyLinePlaceholder":259},[246,7149,7150],{"class":248,"line":373},[246,7151,7152],{"class":607},"-- Phase 5: 代码切到读 phone_int\n",[246,7154,7155],{"class":248,"line":378},[246,7156,260],{"emptyLinePlaceholder":259},[246,7158,7159],{"class":248,"line":384},[246,7160,7161],{"class":607},"-- Phase 6: 删旧字段（等一个发布周期后）\n",[246,7163,7164,7166,7168,7170,7172],{"class":248,"line":392},[246,7165,6520],{"class":619},[246,7167,6523],{"class":619},[246,7169,6526],{"class":276},[246,7171,6587],{"class":619},[246,7173,7174],{"class":276}," COLUMN phone;\n",[246,7176,7177,7179,7181,7184,7187],{"class":248,"line":4550},[246,7178,6520],{"class":619},[246,7180,6523],{"class":619},[246,7182,7183],{"class":276}," users RENAME COLUMN phone_int ",[246,7185,7186],{"class":619},"TO",[246,7188,6620],{"class":276},[406,7190,7191],{"id":7191},"加索引",[151,7193,7195],{"className":6497,"code":7194,"language":6499,"meta":157,"style":157},"-- ❌ 错误：直接加（锁表写操作）\nCREATE INDEX idx_users_email ON users(email);\n\n-- ✅ 正确：CONCURRENTLY（不锁表，但慢）\nCREATE INDEX CONCURRENTLY idx_users_email ON users(email);\n-- 注意：CONCURRENTLY 不能在事务里跑\n",[159,7196,7197,7202,7216,7220,7225,7242],{"__ignoreMap":157},[246,7198,7199],{"class":248,"line":249},[246,7200,7201],{"class":607},"-- ❌ 错误：直接加（锁表写操作）\n",[246,7203,7204,7206,7208,7211,7213],{"class":248,"line":256},[246,7205,6549],{"class":619},[246,7207,6590],{"class":619},[246,7209,7210],{"class":424}," idx_users_email",[246,7212,6558],{"class":619},[246,7214,7215],{"class":276}," users(email);\n",[246,7217,7218],{"class":248,"line":263},[246,7219,260],{"emptyLinePlaceholder":259},[246,7221,7222],{"class":248,"line":269},[246,7223,7224],{"class":607},"-- ✅ 正确：CONCURRENTLY（不锁表，但慢）\n",[246,7226,7227,7229,7231,7234,7237,7240],{"class":248,"line":280},[246,7228,6549],{"class":619},[246,7230,6590],{"class":619},[246,7232,7233],{"class":424}," CONCURRENTLY",[246,7235,7236],{"class":276}," idx_users_email ",[246,7238,7239],{"class":619},"ON",[246,7241,7215],{"class":276},[246,7243,7244],{"class":248,"line":288},[246,7245,7246],{"class":607},"-- 注意：CONCURRENTLY 不能在事务里跑\n",[13,7248,7250],{"id":7249},"step-4-执行-监控","Step 4: 执行 + 监控",[151,7252,7254],{"className":415,"code":7253,"language":417,"meta":157,"style":157},"# 1. 在 shadow DB 测试\npsql $SHADOW_DB -f migrations\u002F0024_add_user_phone.sql\n\n# 2. 生产执行（维护窗口）\npsql $PROD_DB -f migrations\u002F0024_add_user_phone.sql\n\n# 3. 监控（Claude 帮你写监控脚本）\nwatch -n 5 'psql $PROD_DB -c \"\n  SELECT\n    count(*) AS total,\n    count(phone) AS with_phone,\n    count(*) - count(phone) AS without_phone\n  FROM users\n\"'\n",[159,7255,7256,7261,7275,7279,7284,7295,7299,7304,7318,7323,7328,7333,7338,7343],{"__ignoreMap":157},[246,7257,7258],{"class":248,"line":249},[246,7259,7260],{"class":607},"# 1. 在 shadow DB 测试\n",[246,7262,7263,7266,7269,7272],{"class":248,"line":256},[246,7264,7265],{"class":424},"psql",[246,7267,7268],{"class":276}," $SHADOW_DB ",[246,7270,7271],{"class":428},"-f",[246,7273,7274],{"class":432}," migrations\u002F0024_add_user_phone.sql\n",[246,7276,7277],{"class":248,"line":263},[246,7278,260],{"emptyLinePlaceholder":259},[246,7280,7281],{"class":248,"line":269},[246,7282,7283],{"class":607},"# 2. 生产执行（维护窗口）\n",[246,7285,7286,7288,7291,7293],{"class":248,"line":280},[246,7287,7265],{"class":424},[246,7289,7290],{"class":276}," $PROD_DB ",[246,7292,7271],{"class":428},[246,7294,7274],{"class":432},[246,7296,7297],{"class":248,"line":288},[246,7298,260],{"emptyLinePlaceholder":259},[246,7300,7301],{"class":248,"line":5},[246,7302,7303],{"class":607},"# 3. 监控（Claude 帮你写监控脚本）\n",[246,7305,7306,7309,7312,7315],{"class":248,"line":300},[246,7307,7308],{"class":424},"watch",[246,7310,7311],{"class":428}," -n",[246,7313,7314],{"class":428}," 5",[246,7316,7317],{"class":432}," 'psql $PROD_DB -c \"\n",[246,7319,7320],{"class":248,"line":306},[246,7321,7322],{"class":432},"  SELECT\n",[246,7324,7325],{"class":248,"line":314},[246,7326,7327],{"class":432},"    count(*) AS total,\n",[246,7329,7330],{"class":248,"line":322},[246,7331,7332],{"class":432},"    count(phone) AS with_phone,\n",[246,7334,7335],{"class":248,"line":330},[246,7336,7337],{"class":432},"    count(*) - count(phone) AS without_phone\n",[246,7339,7340],{"class":248,"line":335},[246,7341,7342],{"class":432},"  FROM users\n",[246,7344,7345],{"class":248,"line":341},[246,7346,7347],{"class":432},"\"'\n",[13,7349,7351],{"id":7350},"step-5-回滚方案","Step 5: 回滚方案",[17,7353,7354],{},"每个迁移执行前，Claude 生成回滚 checklist：",[151,7356,7360],{"className":7357,"code":7358,"language":7359,"meta":157,"style":157},"language-markdown shiki shiki-themes github-light github-dark","## 回滚步骤（如需）\n\n1. 确认 down migration 安全：\n   ```sql\n   SELECT count(*) FROM users WHERE phone IS NOT NULL;\n   -- 如果 > 0，回滚会丢数据，确认是否可接受\n","markdown",[159,7361,7362,7367,7371,7376,7381,7386],{"__ignoreMap":157},[246,7363,7364],{"class":248,"line":249},[246,7365,7366],{},"## 回滚步骤（如需）\n",[246,7368,7369],{"class":248,"line":256},[246,7370,260],{"emptyLinePlaceholder":259},[246,7372,7373],{"class":248,"line":263},[246,7374,7375],{},"1. 确认 down migration 安全：\n",[246,7377,7378],{"class":248,"line":269},[246,7379,7380],{},"   ```sql\n",[246,7382,7383],{"class":248,"line":280},[246,7384,7385],{},"   SELECT count(*) FROM users WHERE phone IS NOT NULL;\n",[246,7387,7388],{"class":248,"line":288},[246,7389,7390],{},"   -- 如果 > 0，回滚会丢数据，确认是否可接受\n",[532,7392,7393,7412,7439],{"start":256},[24,7394,7395,7396],{},"执行回滚：",[151,7397,7399],{"className":415,"code":7398,"language":417,"meta":157,"style":157},"psql $PROD_DB -f migrations\u002F0024_add_user_phone_down.sql\n",[159,7400,7401],{"__ignoreMap":157},[246,7402,7403,7405,7407,7409],{"class":248,"line":249},[246,7404,7265],{"class":424},[246,7406,7290],{"class":276},[246,7408,7271],{"class":428},[246,7410,7411],{"class":432}," migrations\u002F0024_add_user_phone_down.sql\n",[24,7413,7414,7415],{},"代码回滚到上一个版本：",[151,7416,7418],{"className":415,"code":7417,"language":417,"meta":157,"style":157},"git revert \u003Cmerge-commit>\n",[159,7419,7420],{"__ignoreMap":157},[246,7421,7422,7424,7427,7430,7433,7436],{"class":248,"line":249},[246,7423,613],{"class":424},[246,7425,7426],{"class":432}," revert",[246,7428,7429],{"class":619}," \u003C",[246,7431,7432],{"class":432},"merge-commi",[246,7434,7435],{"class":276},"t",[246,7437,7438],{"class":619},">\n",[24,7440,7441,7442],{},"验证：",[151,7443,7445],{"className":6497,"code":7444,"language":6499,"meta":157,"style":157},"\\d users  -- 确认 phone 字段已删\n",[159,7446,7447],{"__ignoreMap":157},[246,7448,7449,7452],{"class":248,"line":249},[246,7450,7451],{"class":276},"\\d users  ",[246,7453,7454],{"class":607},"-- 确认 phone 字段已删\n",[151,7456,7459],{"className":7457,"code":7458,"language":156},[154],"\n## 踩坑记录\n\n1. **PostgreSQL 11+ 加可空字段才是即时**——低版本加字段仍会锁表，先升级。\n2. **CONCURRENTLY 索引失败要手动清理**——失败后留 invalid index，`DROP INDEX` 后重建。\n3. **回填脚本要分批 + sleep**——大批量 UPDATE 会撑爆 WAL 和主从延迟。\n4. **NOT VALID + VALIDATE 两步走**——直接加 CHECK 会全表扫描锁表。\n5. **Claude 生成 SQL 必须 review**——AI 偶尔会忘加 WHERE 条件，删数据操作尤其要审。\n",[159,7460,7458],{"__ignoreMap":157},[721,7462,7463],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":157,"searchDepth":263,"depth":263,"links":7465},[7466,7467,7468,7469,7470,7471,7476,7477],{"id":15,"depth":256,"text":15},{"id":6416,"depth":256,"text":6416},{"id":6445,"depth":256,"text":6445},{"id":6454,"depth":256,"text":6455},{"id":6623,"depth":256,"text":6624},{"id":6636,"depth":256,"text":6637,"children":7472},[7473,7474,7475],{"id":6640,"depth":263,"text":6641},{"id":6964,"depth":263,"text":6964},{"id":7191,"depth":263,"text":7191},{"id":7249,"depth":256,"text":7250},{"id":7350,"depth":256,"text":7351},"migration","\u002Fog\u002Fplaybook\u002Fai-db-migration.png","数据库 schema 迁移最怕搞挂生产。用 Claude Code + Drizzle migrations 搭一套安全迁移流程——AI 生成迁移文件 → 自动检查兼容性 → 分阶段执行 → 验证 → 回滚方案。含大表加列、改类型等高危操作。",{},"\u002Fplaybook\u002Fmigration\u002Fai-db-migration",[747,7484],"coding\u002Fide\u002Fcursor",{"title":6395,"description":7480},"playbook\u002Fmigration\u002Fai-db-migration",[7488,7489,7490,7491,72],"数据库","迁移","Drizzle","零停机","tzaBre4cpBUCVMaO1qaWEjIwBDWReTAlQ9UMCOMI54A",{"id":7494,"title":7495,"body":7496,"category":740,"cover":8164,"description":8165,"extension":242,"meta":8166,"navigation":259,"path":8167,"published":6381,"relatedTools":8168,"seo":8169,"stem":8170,"tags":8171,"updated":6381,"__hash__":8173},"playbook\u002Fplaybook\u002Fonboarding\u002Fclaude-code-getting-started.md","Claude Code 从零上手：CLI AI 编程实战指南",{"type":10,"value":7497,"toc":8141},[7498,7500,7514,7518,7630,7636,7640,7676,7679,7720,7723,7744,7748,7751,7767,7770,7776,7779,7793,7797,7800,7806,7809,7813,7816,7822,7825,7842,7848,7852,7855,7861,7864,7870,7874,7877,7886,8024,8027,8030,8034,8039,8078,8081,8085,8091,8095,8098,8104,8106,8110,8113,8117,8124,8128,8131,8135,8138],[13,7499,15],{"id":15},[21,7501,7502,7505,7508,7511],{},[24,7503,7504],{},"想用 CLI 方式做 AI 编程（不依赖 IDE）",[24,7506,7507],{},"已有 Cursor \u002F Copilot，想试试 Claude 原生体验",[24,7509,7510],{},"需要在服务器 \u002F SSH 环境用 AI 编程",[24,7512,7513],{},"想用 Claude Sonnet 4 \u002F Opus 4 的完整能力",[13,7515,7517],{"id":7516},"claude-code-vs-cursor-vs-copilot","Claude Code vs Cursor vs Copilot",[40,7519,7520,7532],{},[43,7521,7522],{},[46,7523,7524,7526,7528,7530],{},[49,7525,1307],{},[49,7527,72],{},[49,7529,228],{},[49,7531,204],{},[62,7533,7534,7546,7560,7572,7584,7597,7607,7618],{},[46,7535,7536,7538,7540,7543],{},[67,7537,2531],{},[67,7539,2540],{},[67,7541,7542],{},"IDE",[67,7544,7545],{},"IDE 插件",[46,7547,7548,7551,7554,7557],{},[67,7549,7550],{},"模型",[67,7552,7553],{},"Claude 全系",[67,7555,7556],{},"多模型",[67,7558,7559],{},"GPT\u002FClaude",[46,7561,7562,7565,7567,7569],{},[67,7563,7564],{},"多文件修改",[67,7566,1411],{},[67,7568,1334],{},[67,7570,7571],{},"❌ 单文件",[46,7573,7574,7577,7580,7582],{},[67,7575,7576],{},"项目理解",[67,7578,7579],{},"✅ 自动索引",[67,7581,1334],{},[67,7583,3433],{},[46,7585,7586,7589,7592,7595],{},[67,7587,7588],{},"终端操作",[67,7590,7591],{},"✅ 直接执行",[67,7593,7594],{},"需切换",[67,7596,1337],{},[46,7598,7599,7601,7603,7605],{},[67,7600,1378],{},[67,7602,1411],{},[67,7604,3433],{},[67,7606,3433],{},[46,7608,7609,7612,7614,7616],{},[67,7610,7611],{},"SSH\u002F服务器",[67,7613,1334],{},[67,7615,1337],{},[67,7617,1337],{},[46,7619,7620,7622,7625,7627],{},[67,7621,2219],{},[67,7623,7624],{},"$20\u002F月（Max）",[67,7626,2648],{},[67,7628,7629],{},"$10\u002F月",[17,7631,7632,7635],{},[147,7633,7634],{},"Claude Code 的独特优势","：CLI 原生 + 终端操作 + SSH 可用。",[13,7637,7639],{"id":7638},"第一步安装","第一步：安装",[151,7641,7643],{"className":415,"code":7642,"language":417,"meta":157,"style":157},"# 需要 Node.js 18+\nnpm install -g @anthropic-ai\u002Fclaude-code\n\n# 验证\nclaude --version\n",[159,7644,7645,7650,7661,7665,7670],{"__ignoreMap":157},[246,7646,7647],{"class":248,"line":249},[246,7648,7649],{"class":607},"# 需要 Node.js 18+\n",[246,7651,7652,7654,7656,7658],{"class":248,"line":256},[246,7653,3795],{"class":424},[246,7655,1060],{"class":432},[246,7657,3800],{"class":428},[246,7659,7660],{"class":432}," @anthropic-ai\u002Fclaude-code\n",[246,7662,7663],{"class":248,"line":263},[246,7664,260],{"emptyLinePlaceholder":259},[246,7666,7667],{"class":248,"line":269},[246,7668,7669],{"class":607},"# 验证\n",[246,7671,7672,7674],{"class":248,"line":280},[246,7673,1791],{"class":424},[246,7675,2399],{"class":428},[406,7677,7678],{"id":7678},"认证",[151,7680,7682],{"className":415,"code":7681,"language":417,"meta":157,"style":157},"# 方式 1：用 Anthropic 账号（推荐，含 Max 订阅）\nclaude login\n\n# 方式 2：用 API Key（按量付费）\nexport ANTHROPIC_API_KEY=\"sk-ant-xxx\"\nclaude\n",[159,7683,7684,7689,7695,7699,7704,7715],{"__ignoreMap":157},[246,7685,7686],{"class":248,"line":249},[246,7687,7688],{"class":607},"# 方式 1：用 Anthropic 账号（推荐，含 Max 订阅）\n",[246,7690,7691,7693],{"class":248,"line":256},[246,7692,1791],{"class":424},[246,7694,4606],{"class":432},[246,7696,7697],{"class":248,"line":263},[246,7698,260],{"emptyLinePlaceholder":259},[246,7700,7701],{"class":248,"line":269},[246,7702,7703],{"class":607},"# 方式 2：用 API Key（按量付费）\n",[246,7705,7706,7708,7710,7712],{"class":248,"line":280},[246,7707,1103],{"class":619},[246,7709,1106],{"class":276},[246,7711,1109],{"class":619},[246,7713,7714],{"class":432},"\"sk-ant-xxx\"\n",[246,7716,7717],{"class":248,"line":288},[246,7718,7719],{"class":424},"claude\n",[17,7721,7722],{},"国内用户如果直连慢，可以配代理：",[151,7724,7726],{"className":415,"code":7725,"language":417,"meta":157,"style":157},"export HTTPS_PROXY=\"http:\u002F\u002F127.0.0.1:7890\"\nclaude\n",[159,7727,7728,7740],{"__ignoreMap":157},[246,7729,7730,7732,7735,7737],{"class":248,"line":249},[246,7731,1103],{"class":619},[246,7733,7734],{"class":276}," HTTPS_PROXY",[246,7736,1109],{"class":619},[246,7738,7739],{"class":432},"\"http:\u002F\u002F127.0.0.1:7890\"\n",[246,7741,7742],{"class":248,"line":256},[246,7743,7719],{"class":424},[13,7745,7747],{"id":7746},"第二步第一次使用","第二步：第一次使用",[17,7749,7750],{},"进入项目目录，启动 Claude Code：",[151,7752,7754],{"className":415,"code":7753,"language":417,"meta":157,"style":157},"cd my-project\nclaude\n",[159,7755,7756,7763],{"__ignoreMap":157},[246,7757,7758,7760],{"class":248,"line":249},[246,7759,1086],{"class":428},[246,7761,7762],{"class":432}," my-project\n",[246,7764,7765],{"class":248,"line":256},[246,7766,7719],{"class":424},[17,7768,7769],{},"进入交互式 REPL。几个基本操作：",[151,7771,7774],{"className":7772,"code":7773,"language":156,"meta":157},[154],"> 帮我理解这个项目的结构          # 项目理解\n> 找到处理用户登录的代码          # 代码定位\n> 把这个函数改成支持异步          # 代码修改\n> 跑一下测试看看有没有 break      # 执行命令\n",[159,7775,7773],{"__ignoreMap":157},[17,7777,7778],{},"Claude Code 会自动：",[532,7780,7781,7784,7787,7790],{},[24,7782,7783],{},"扫描项目文件结构",[24,7785,7786],{},"读 package.json \u002F README 理解技术栈",[24,7788,7789],{},"找到相关文件",[24,7791,7792],{},"提出修改方案（需你确认后执行）",[13,7794,7796],{"id":7795},"第三步项目理解工作流","第三步：项目理解工作流",[17,7798,7799],{},"新接手一个项目时的标准操作：",[151,7801,7804],{"className":7802,"code":7803,"language":156,"meta":157},[154],"> 先读 README 和 package.json，告诉我这个项目是做什么的、用了什么技术栈\n\n> 画出项目的目录结构，标注每个目录的职责\n\n> 找到项目的入口文件，解释启动流程\n\n> 这个项目的数据流是怎样的？从 API 请求到数据库的完整路径\n\n> 找到所有 TODO 和 FIXME，按优先级排序\n",[159,7805,7803],{"__ignoreMap":157},[17,7807,7808],{},"Claude Code 会实际读取文件并分析，不是瞎猜。",[13,7810,7812],{"id":7811},"第四步多文件修改","第四步：多文件修改",[17,7814,7815],{},"这是 Claude Code 最强的能力。举个例子：",[151,7817,7820],{"className":7818,"code":7819,"language":156,"meta":157},[154],"> 我需要加一个\"用户头像上传\"功能。需要：\n> 1. 后端 API（上传到 S3）\n> 2. 前端组件（拖拽上传 + 预览）\n> 3. 数据库加 avatar_url 字段\n> 4. 用户 profile 页面显示头像\n> 先看一下现有代码结构，告诉我你的计划，我确认后再动手\n",[159,7821,7819],{"__ignoreMap":157},[17,7823,7824],{},"Claude Code 会：",[532,7826,7827,7830,7833,7836,7839],{},[24,7828,7829],{},"扫描相关文件（后端路由、前端组件、数据库 schema）",[24,7831,7832],{},"给出修改计划（改哪些文件、每个文件改什么）",[24,7834,7835],{},"等你确认",[24,7837,7838],{},"一次性修改多个文件",[24,7840,7841],{},"跑测试验证",[17,7843,7844,7847],{},[147,7845,7846],{},"关键","：先说\"告诉我计划\"，确认后再让它动手。避免改出一堆你不想要的东西。",[13,7849,7851],{"id":7850},"第五步git-工作流","第五步：Git 工作流",[17,7853,7854],{},"Claude Code 原生支持 git 操作：",[151,7856,7859],{"className":7857,"code":7858,"language":156,"meta":157},[154],"> 看一下当前的 git diff，帮我写 commit message\n\n> 帮我把这个改动拆成 3 个独立的 commit（按逻辑分组）\n\n> 创建一个分支 feature\u002Favatar-upload，把改动提交上去\n",[159,7860,7858],{"__ignoreMap":157},[17,7862,7863],{},"推荐工作流：",[151,7865,7868],{"className":7866,"code":7867,"language":156,"meta":157},[154],"1. claude  # 启动\n2. \"在 feature 分支上实现 XXX 功能\"  # 让它创建分支 + 改代码\n3. \"跑测试\"  # 验证\n4. \"看一下 diff，写 commit message\"  # 提交\n5. 退出后自己 git push + 开 PR\n",[159,7869,7867],{"__ignoreMap":157},[13,7871,7873],{"id":7872},"第六步mcp-集成","第六步：MCP 集成",[17,7875,7876],{},"Claude Code 支持连接 MCP Server，扩展能力：",[151,7878,7880],{"className":415,"code":7879,"language":417,"meta":157,"style":157},"# 配置文件位置：~\u002F.claude\u002Fmcp_servers.json\n",[159,7881,7882],{"__ignoreMap":157},[246,7883,7884],{"class":248,"line":249},[246,7885,7879],{"class":607},[151,7887,7889],{"className":2096,"code":7888,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"postgres\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-postgres\"],\n      \"env\": {\n        \"DATABASE_URL\": \"postgresql:\u002F\u002F...\"\n      }\n    },\n    \"github\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-github\"],\n      \"env\": {\n        \"GITHUB_TOKEN\": \"ghp_xxx\"\n      }\n    }\n  }\n}\n",[159,7890,7891,7895,7901,7907,7917,7933,7940,7950,7955,7960,7967,7977,7992,7998,8008,8012,8016,8020],{"__ignoreMap":157},[246,7892,7893],{"class":248,"line":249},[246,7894,2105],{"class":276},[246,7896,7897,7899],{"class":248,"line":256},[246,7898,2110],{"class":428},[246,7900,2113],{"class":276},[246,7902,7903,7905],{"class":248,"line":263},[246,7904,2118],{"class":428},[246,7906,2113],{"class":276},[246,7908,7909,7911,7913,7915],{"class":248,"line":269},[246,7910,2125],{"class":428},[246,7912,2128],{"class":276},[246,7914,2131],{"class":432},[246,7916,2134],{"class":276},[246,7918,7919,7921,7923,7926,7928,7930],{"class":248,"line":280},[246,7920,2139],{"class":428},[246,7922,2142],{"class":276},[246,7924,7925],{"class":432},"\"-y\"",[246,7927,2148],{"class":276},[246,7929,2145],{"class":432},[246,7931,7932],{"class":276},"],\n",[246,7934,7935,7938],{"class":248,"line":288},[246,7936,7937],{"class":428},"      \"env\"",[246,7939,2113],{"class":276},[246,7941,7942,7945,7947],{"class":248,"line":5},[246,7943,7944],{"class":428},"        \"DATABASE_URL\"",[246,7946,2128],{"class":276},[246,7948,7949],{"class":432},"\"postgresql:\u002F\u002F...\"\n",[246,7951,7952],{"class":248,"line":300},[246,7953,7954],{"class":276},"      }\n",[246,7956,7957],{"class":248,"line":306},[246,7958,7959],{"class":276},"    },\n",[246,7961,7962,7965],{"class":248,"line":314},[246,7963,7964],{"class":428},"    \"github\"",[246,7966,2113],{"class":276},[246,7968,7969,7971,7973,7975],{"class":248,"line":322},[246,7970,2125],{"class":428},[246,7972,2128],{"class":276},[246,7974,2131],{"class":432},[246,7976,2134],{"class":276},[246,7978,7979,7981,7983,7985,7987,7990],{"class":248,"line":330},[246,7980,2139],{"class":428},[246,7982,2142],{"class":276},[246,7984,7925],{"class":432},[246,7986,2148],{"class":276},[246,7988,7989],{"class":432},"\"@modelcontextprotocol\u002Fserver-github\"",[246,7991,7932],{"class":276},[246,7993,7994,7996],{"class":248,"line":335},[246,7995,7937],{"class":428},[246,7997,2113],{"class":276},[246,7999,8000,8003,8005],{"class":248,"line":341},[246,8001,8002],{"class":428},"        \"GITHUB_TOKEN\"",[246,8004,2128],{"class":276},[246,8006,8007],{"class":432},"\"ghp_xxx\"\n",[246,8009,8010],{"class":248,"line":349},[246,8011,7954],{"class":276},[246,8013,8014],{"class":248,"line":357},[246,8015,2159],{"class":276},[246,8017,8018],{"class":248,"line":365},[246,8019,2164],{"class":276},[246,8021,8022],{"class":248,"line":373},[246,8023,2169],{"class":276},[17,8025,8026],{},"配置后，Claude Code 可以直接查数据库、操作 GitHub。",[13,8028,8029],{"id":8029},"常用技巧",[406,8031,8033],{"id":8032},"_1-用-claudemd-固化项目约定","1. 用 CLAUDE.md 固化项目约定",[17,8035,8036,8037,864],{},"在项目根目录创建 ",[159,8038,190],{},[151,8040,8042],{"className":7357,"code":8041,"language":7359,"meta":157,"style":157},"# 项目约定\n\n- 用 pnpm 不用 npm\n- 测试用 vitest，跑 `pnpm test`\n- 提交前跑 `pnpm lint`\n- Vue 组件用 \u003Cscript setup>\n- 不要用 any，所有变量都要有类型\n",[159,8043,8044,8049,8053,8058,8063,8068,8073],{"__ignoreMap":157},[246,8045,8046],{"class":248,"line":249},[246,8047,8048],{},"# 项目约定\n",[246,8050,8051],{"class":248,"line":256},[246,8052,260],{"emptyLinePlaceholder":259},[246,8054,8055],{"class":248,"line":263},[246,8056,8057],{},"- 用 pnpm 不用 npm\n",[246,8059,8060],{"class":248,"line":269},[246,8061,8062],{},"- 测试用 vitest，跑 `pnpm test`\n",[246,8064,8065],{"class":248,"line":280},[246,8066,8067],{},"- 提交前跑 `pnpm lint`\n",[246,8069,8070],{"class":248,"line":288},[246,8071,8072],{},"- Vue 组件用 \u003Cscript setup>\n",[246,8074,8075],{"class":248,"line":5},[246,8076,8077],{},"- 不要用 any，所有变量都要有类型\n",[17,8079,8080],{},"Claude Code 每次启动会自动读取，不用每次重复说。",[406,8082,8084],{"id":8083},"_2-用-compact-压缩上下文","2. 用 \u002Fcompact 压缩上下文",[17,8086,8087,8088,8090],{},"聊了很久后上下文会满，用 ",[159,8089,1965],{}," 压缩历史对话，保留关键信息。",[406,8092,8094],{"id":8093},"_3-子-agent-并发","3. 子 Agent 并发",[17,8096,8097],{},"复杂任务可以让 Claude Code 开子 Agent 并行处理：",[151,8099,8102],{"className":8100,"code":8101,"language":156,"meta":157},[154],"> 用 3 个并行子任务：\n> 1. 修复 auth 模块的 bug\n> 2. 给 API 模块加测试\n> 3. 重构 utils 模块\n> 分别完成后汇总给我\n",[159,8103,8101],{"__ignoreMap":157},[13,8105,6319],{"id":6319},[406,8107,8109],{"id":8108},"坑-1大项目首次索引慢","坑 1：大项目首次索引慢",[17,8111,8112],{},"10 万行以上的项目，首次启动会花 1-2 分钟扫描。后续有缓存会快。",[406,8114,8116],{"id":8115},"坑-2会主动改你不想改的文件","坑 2：会主动改你不想改的文件",[17,8118,8119,8120,8123],{},"Claude Code 有时会\"顺手\"改一些你没要求的文件（比如格式化）。用 ",[159,8121,8122],{},"--allowedTools"," 限制它只能用特定工具。",[406,8125,8127],{"id":8126},"坑-3国内网络","坑 3：国内网络",[17,8129,8130],{},"Anthropic API 在国内不稳定。必须配代理，否则会频繁超时。",[406,8132,8134],{"id":8133},"坑-4token-消耗快","坑 4：Token 消耗快",[17,8136,8137],{},"Sonnet 4 做大型重构时，一次任务可能消耗 50 万+ token。用 Max 订阅（$200\u002F月）比 API 按量付费划算。",[721,8139,8140],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":157,"searchDepth":263,"depth":263,"links":8142},[8143,8144,8145,8148,8149,8150,8151,8152,8153,8158],{"id":15,"depth":256,"text":15},{"id":7516,"depth":256,"text":7517},{"id":7638,"depth":256,"text":7639,"children":8146},[8147],{"id":7678,"depth":263,"text":7678},{"id":7746,"depth":256,"text":7747},{"id":7795,"depth":256,"text":7796},{"id":7811,"depth":256,"text":7812},{"id":7850,"depth":256,"text":7851},{"id":7872,"depth":256,"text":7873},{"id":8029,"depth":256,"text":8029,"children":8154},[8155,8156,8157],{"id":8032,"depth":263,"text":8033},{"id":8083,"depth":263,"text":8084},{"id":8093,"depth":263,"text":8094},{"id":6319,"depth":256,"text":6319,"children":8159},[8160,8161,8162,8163],{"id":8108,"depth":263,"text":8109},{"id":8115,"depth":263,"text":8116},{"id":8126,"depth":263,"text":8127},{"id":8133,"depth":263,"text":8134},"\u002Fog\u002Fplaybook\u002Fclaude-code-getting-started.png","Anthropic 官方 CLI 工具 Claude Code 30 分钟上手——安装配置、项目理解、多文件修改、git 工作流、MCP 集成、子 Agent 并发，含真实项目踩坑记录。",{},"\u002Fplaybook\u002Fonboarding\u002Fclaude-code-getting-started",[747,7484,750],{"title":7495,"description":8165},"playbook\u002Fonboarding\u002Fclaude-code-getting-started",[72,2540,8172,968],"AI 编程","iY5IsM7_Dx24z0nrqr2srrkmMB01rtDVKpKWe9B0Fz0",{"id":8175,"title":8176,"body":8177,"category":740,"cover":8884,"description":8885,"extension":242,"meta":8886,"navigation":259,"path":8887,"published":6381,"relatedTools":8888,"seo":8892,"stem":8893,"tags":8894,"updated":6381,"__hash__":8896},"playbook\u002Fplaybook\u002Fonboarding\u002Fcursor-mcp-database.md","Cursor + MCP 让 AI 直接操作数据库：从零到生产",{"type":10,"value":8178,"toc":8867},[8179,8181,8192,8196,8203,8206,8213,8217,8220,8243,8246,8322,8325,8329,8332,8338,8439,8443,8520,8526,8529,8532,8617,8621,8625,8628,8634,8637,8655,8659,8665,8667,8685,8689,8695,8697,8714,8717,8787,8793,8795,8864],[13,8180,15],{"id":15},[21,8182,8183,8186,8189],{},[24,8184,8185],{},"开发时频繁需要查表结构、跑 SQL 验证",[24,8187,8188],{},"AI 生成代码时需要知道数据库 schema",[24,8190,8191],{},"想让 AI 帮写数据库迁移文件",[13,8193,8195],{"id":8194},"为什么用-mcp-而不是复制粘贴","为什么用 MCP 而不是复制粘贴",[17,8197,8198,8199,8202],{},"传统做法：手动跑 ",[159,8200,8201],{},"\\d table_name"," → 复制结果 → 粘给 Cursor → AI 生成 SQL → 手动执行验证。",[17,8204,8205],{},"MCP 做法：Cursor 直接连数据库 → AI 自己查 schema → 生成 SQL → 自己执行验证 → 返回结果。",[17,8207,8208,8209,8212],{},"省的是",[147,8210,8211],{},"中间的复制粘贴往返","。在复杂查询调试时，这个往返可能 5-10 次。",[13,8214,8216],{"id":8215},"第一步装-mcp-postgresql-server","第一步：装 MCP PostgreSQL Server",[17,8218,8219],{},"用 Smithery 一行装好：",[151,8221,8223],{"className":415,"code":8222,"language":417,"meta":157,"style":157},"npx @smithery\u002Fcli install @modelcontextprotocol\u002Fserver-postgres --client cursor\n",[159,8224,8225],{"__ignoreMap":157},[246,8226,8227,8229,8232,8234,8237,8240],{"class":248,"line":249},[246,8228,3778],{"class":424},[246,8230,8231],{"class":432}," @smithery\u002Fcli",[246,8233,1060],{"class":432},[246,8235,8236],{"class":432}," @modelcontextprotocol\u002Fserver-postgres",[246,8238,8239],{"class":428}," --client",[246,8241,8242],{"class":432}," cursor\n",[17,8244,8245],{},"或手动配 Cursor Settings → MCP → Add Server：",[151,8247,8249],{"className":2096,"code":8248,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"postgres\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-postgres\"],\n      \"env\": {\n        \"DATABASE_URL\": \"postgresql:\u002F\u002Fuser:pass@localhost:5432\u002Fmydb\"\n      }\n    }\n  }\n}\n",[159,8250,8251,8255,8261,8267,8277,8291,8297,8306,8310,8314,8318],{"__ignoreMap":157},[246,8252,8253],{"class":248,"line":249},[246,8254,2105],{"class":276},[246,8256,8257,8259],{"class":248,"line":256},[246,8258,2110],{"class":428},[246,8260,2113],{"class":276},[246,8262,8263,8265],{"class":248,"line":263},[246,8264,2118],{"class":428},[246,8266,2113],{"class":276},[246,8268,8269,8271,8273,8275],{"class":248,"line":269},[246,8270,2125],{"class":428},[246,8272,2128],{"class":276},[246,8274,2131],{"class":432},[246,8276,2134],{"class":276},[246,8278,8279,8281,8283,8285,8287,8289],{"class":248,"line":280},[246,8280,2139],{"class":428},[246,8282,2142],{"class":276},[246,8284,7925],{"class":432},[246,8286,2148],{"class":276},[246,8288,2145],{"class":432},[246,8290,7932],{"class":276},[246,8292,8293,8295],{"class":248,"line":288},[246,8294,7937],{"class":428},[246,8296,2113],{"class":276},[246,8298,8299,8301,8303],{"class":248,"line":5},[246,8300,7944],{"class":428},[246,8302,2128],{"class":276},[246,8304,8305],{"class":432},"\"postgresql:\u002F\u002Fuser:pass@localhost:5432\u002Fmydb\"\n",[246,8307,8308],{"class":248,"line":300},[246,8309,7954],{"class":276},[246,8311,8312],{"class":248,"line":306},[246,8313,2159],{"class":276},[246,8315,8316],{"class":248,"line":314},[246,8317,2164],{"class":276},[246,8319,8320],{"class":248,"line":322},[246,8321,2169],{"class":276},[17,8323,8324],{},"重启 Cursor，Agent 模式现在能查数据库了。",[13,8326,8328],{"id":8327},"第二步安全配置重要","第二步：安全配置（重要）",[406,8330,8331],{"id":8331},"用只读账号",[17,8333,8334,8337],{},[147,8335,8336],{},"绝对不要用超级用户账号连 MCP。"," 创建只读账号：",[151,8339,8341],{"className":6497,"code":8340,"language":6499,"meta":157,"style":157},"CREATE ROLE mcp_readonly WITH LOGIN PASSWORD 'xxx';\nGRANT USAGE ON SCHEMA public TO mcp_readonly;\nGRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_readonly;\nALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mcp_readonly;\n",[159,8342,8343,8367,8388,8410],{"__ignoreMap":157},[246,8344,8345,8347,8350,8353,8356,8359,8362,8365],{"class":248,"line":249},[246,8346,6549],{"class":619},[246,8348,8349],{"class":619}," ROLE",[246,8351,8352],{"class":276}," mcp_readonly ",[246,8354,8355],{"class":619},"WITH",[246,8357,8358],{"class":619}," LOGIN",[246,8360,8361],{"class":619}," PASSWORD",[246,8363,8364],{"class":432}," 'xxx'",[246,8366,6573],{"class":276},[246,8368,8369,8372,8375,8377,8380,8383,8385],{"class":248,"line":256},[246,8370,8371],{"class":619},"GRANT",[246,8373,8374],{"class":276}," USAGE ",[246,8376,7239],{"class":619},[246,8378,8379],{"class":619}," SCHEMA",[246,8381,8382],{"class":276}," public ",[246,8384,7186],{"class":619},[246,8386,8387],{"class":276}," mcp_readonly;\n",[246,8389,8390,8392,8395,8397,8400,8402,8404,8406,8408],{"class":248,"line":263},[246,8391,8371],{"class":619},[246,8393,8394],{"class":619}," SELECT",[246,8396,6558],{"class":619},[246,8398,8399],{"class":276}," ALL TABLES ",[246,8401,6799],{"class":619},[246,8403,8379],{"class":619},[246,8405,8382],{"class":276},[246,8407,7186],{"class":619},[246,8409,8387],{"class":276},[246,8411,8412,8414,8417,8420,8422,8424,8426,8428,8430,8432,8435,8437],{"class":248,"line":269},[246,8413,6520],{"class":619},[246,8415,8416],{"class":619}," DEFAULT",[246,8418,8419],{"class":276}," PRIVILEGES ",[246,8421,6799],{"class":619},[246,8423,8379],{"class":619},[246,8425,8382],{"class":276},[246,8427,8371],{"class":619},[246,8429,8394],{"class":619},[246,8431,6558],{"class":619},[246,8433,8434],{"class":276}," TABLES ",[246,8436,7186],{"class":619},[246,8438,8387],{"class":276},[406,8440,8442],{"id":8441},"开发生产隔离","开发\u002F生产隔离",[151,8444,8446],{"className":2096,"code":8445,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"postgres-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-postgres\"],\n      \"env\": {\n        \"DATABASE_URL\": \"postgresql:\u002F\u002Fmcp_readonly:xxx@localhost:5432\u002Fmydb_dev\"\n      }\n    }\n  }\n}\n",[159,8447,8448,8452,8458,8465,8475,8489,8495,8504,8508,8512,8516],{"__ignoreMap":157},[246,8449,8450],{"class":248,"line":249},[246,8451,2105],{"class":276},[246,8453,8454,8456],{"class":248,"line":256},[246,8455,2110],{"class":428},[246,8457,2113],{"class":276},[246,8459,8460,8463],{"class":248,"line":263},[246,8461,8462],{"class":428},"    \"postgres-dev\"",[246,8464,2113],{"class":276},[246,8466,8467,8469,8471,8473],{"class":248,"line":269},[246,8468,2125],{"class":428},[246,8470,2128],{"class":276},[246,8472,2131],{"class":432},[246,8474,2134],{"class":276},[246,8476,8477,8479,8481,8483,8485,8487],{"class":248,"line":280},[246,8478,2139],{"class":428},[246,8480,2142],{"class":276},[246,8482,7925],{"class":432},[246,8484,2148],{"class":276},[246,8486,2145],{"class":432},[246,8488,7932],{"class":276},[246,8490,8491,8493],{"class":248,"line":288},[246,8492,7937],{"class":428},[246,8494,2113],{"class":276},[246,8496,8497,8499,8501],{"class":248,"line":5},[246,8498,7944],{"class":428},[246,8500,2128],{"class":276},[246,8502,8503],{"class":432},"\"postgresql:\u002F\u002Fmcp_readonly:xxx@localhost:5432\u002Fmydb_dev\"\n",[246,8505,8506],{"class":248,"line":300},[246,8507,7954],{"class":276},[246,8509,8510],{"class":248,"line":306},[246,8511,2159],{"class":276},[246,8513,8514],{"class":248,"line":314},[246,8515,2164],{"class":276},[246,8517,8518],{"class":248,"line":322},[246,8519,2169],{"class":276},[17,8521,8522,8525],{},[147,8523,8524],{},"只在 dev 环境配 MCP","。生产数据库永远不连 MCP。",[406,8527,8528],{"id":8528},"限制可查的表",[17,8530,8531],{},"如果有些表（用户密码、token）不想让 AI 看到，用视图：",[151,8533,8535],{"className":6497,"code":8534,"language":6499,"meta":157,"style":157},"CREATE VIEW public_safe.users_safe AS\n  SELECT id, username, created_at FROM public.users;\n\nREVOKE SELECT ON public.users FROM mcp_readonly;\nGRANT SELECT ON public_safe.users_safe TO mcp_readonly;\n",[159,8536,8537,8553,8573,8577,8597],{"__ignoreMap":157},[246,8538,8539,8541,8544,8547,8550],{"class":248,"line":249},[246,8540,6549],{"class":619},[246,8542,8543],{"class":619}," VIEW",[246,8545,8546],{"class":424}," public_safe",[246,8548,8549],{"class":276},".users_safe ",[246,8551,8552],{"class":619},"AS\n",[246,8554,8555,8558,8561,8563,8566,8568,8571],{"class":248,"line":256},[246,8556,8557],{"class":619},"  SELECT",[246,8559,8560],{"class":276}," id, username, created_at ",[246,8562,6812],{"class":619},[246,8564,8565],{"class":428}," public",[246,8567,6876],{"class":276},[246,8569,8570],{"class":428},"users",[246,8572,6573],{"class":276},[246,8574,8575],{"class":248,"line":263},[246,8576,260],{"emptyLinePlaceholder":259},[246,8578,8579,8582,8584,8586,8588,8590,8592,8595],{"class":248,"line":269},[246,8580,8581],{"class":619},"REVOKE",[246,8583,8394],{"class":619},[246,8585,6558],{"class":619},[246,8587,8565],{"class":428},[246,8589,6876],{"class":276},[246,8591,8570],{"class":428},[246,8593,8594],{"class":619}," FROM",[246,8596,8387],{"class":276},[246,8598,8599,8601,8603,8605,8607,8609,8612,8615],{"class":248,"line":280},[246,8600,8371],{"class":619},[246,8602,8394],{"class":619},[246,8604,6558],{"class":619},[246,8606,8546],{"class":428},[246,8608,6876],{"class":276},[246,8610,8611],{"class":428},"users_safe",[246,8613,8614],{"class":619}," TO",[246,8616,8387],{"class":276},[13,8618,8620],{"id":8619},"第三步实战用法","第三步：实战用法",[406,8622,8624],{"id":8623},"场景一查-schema-生成代码","场景一：查 schema 生成代码",[17,8626,8627],{},"在 Cursor Agent 模式输入：",[151,8629,8632],{"className":8630,"code":8631,"language":156},[154],"帮我写一个查询用户订单的 API，需要分页\n",[159,8633,8631],{"__ignoreMap":157},[17,8635,8636],{},"Cursor 会：",[532,8638,8639,8646,8652],{},[24,8640,8641,8642,8645],{},"调 MCP ",[159,8643,8644],{},"list_tables"," 看有哪些表",[24,8647,8641,8648,8651],{},[159,8649,8650],{},"describe_table"," 看 orders 和 users 表结构",[24,8653,8654],{},"生成 JOIN 查询 + 分页代码",[406,8656,8658],{"id":8657},"场景二调试-sql","场景二：调试 SQL",[151,8660,8663],{"className":8661,"code":8662,"language":156},[154],"这个查询很慢，帮我优化\nSELECT * FROM orders o JOIN users u ON o.user_id = u.id WHERE o.status = 'pending'\n",[159,8664,8662],{"__ignoreMap":157},[17,8666,8636],{},[532,8668,8669,8676,8679,8682],{},[24,8670,8671,8672,8675],{},"跑 ",[159,8673,8674],{},"EXPLAIN ANALYZE"," 看执行计划",[24,8677,8678],{},"发现全表扫描",[24,8680,8681],{},"建议加索引",[24,8683,8684],{},"生成 migration 文件",[406,8686,8688],{"id":8687},"场景三生成迁移","场景三：生成迁移",[151,8690,8693],{"className":8691,"code":8692,"language":156},[154],"给 orders 表加一个 shipping_address 字段，类型 jsonb，可空\n",[159,8694,8692],{"__ignoreMap":157},[17,8696,8636],{},[532,8698,8699,8702,8709,8712],{},[24,8700,8701],{},"查当前 orders 表结构",[24,8703,8704,8705,8708],{},"生成 ",[159,8706,8707],{},"ALTER TABLE"," SQL",[24,8710,8711],{},"生成 Drizzle\u002FPrisma migration 文件",[24,8713,6481],{},[13,8715,8716],{"id":8716},"权限边界",[40,8718,8719,8731],{},[43,8720,8721],{},[46,8722,8723,8725,8728],{},[49,8724,6170],{},[49,8726,8727],{},"只读 MCP",[49,8729,8730],{},"可写 MCP",[62,8732,8733,8742,8751,8760,8769,8779],{},[46,8734,8735,8738,8740],{},[67,8736,8737],{},"查表结构",[67,8739,1334],{},[67,8741,1334],{},[46,8743,8744,8747,8749],{},[67,8745,8746],{},"SELECT 查询",[67,8748,1334],{},[67,8750,1334],{},[46,8752,8753,8756,8758],{},[67,8754,8755],{},"EXPLAIN",[67,8757,1334],{},[67,8759,1334],{},[46,8761,8762,8765,8767],{},[67,8763,8764],{},"INSERT\u002FUPDATE\u002FDELETE",[67,8766,1337],{},[67,8768,1334],{},[46,8770,8771,8774,8776],{},[67,8772,8773],{},"CREATE\u002FDROP TABLE",[67,8775,1337],{},[67,8777,8778],{},"⚠️ 需额外授权",[46,8780,8781,8783,8785],{},[67,8782,8707],{},[67,8784,1337],{},[67,8786,8778],{},[17,8788,8789,8792],{},[147,8790,8791],{},"建议","：日常用只读 MCP，需要写操作时切到可写 MCP 并加确认步骤。",[13,8794,6319],{"id":6319},[532,8796,8797,8803,8842,8848],{},[24,8798,8799,8802],{},[147,8800,8801],{},"MCP Server 连接池","：默认无连接池，大量查询会打满 PG 连接。用 PgBouncer 做连接池。",[24,8804,8805,8808,8809,8812,8813,8816,8817],{},[147,8806,8807],{},"大表 SELECT","：AI 可能跑 ",[159,8810,8811],{},"SELECT * FROM huge_table","。设 ",[159,8814,8815],{},"statement_timeout"," 防止卡死：\n",[151,8818,8820],{"className":6497,"code":8819,"language":6499,"meta":157,"style":157},"ALTER ROLE mcp_readonly SET statement_timeout = '10s';\n",[159,8821,8822],{"__ignoreMap":157},[246,8823,8824,8826,8828,8830,8832,8835,8837,8840],{"class":248,"line":249},[246,8825,6520],{"class":619},[246,8827,8349],{"class":619},[246,8829,8352],{"class":276},[246,8831,6783],{"class":619},[246,8833,8834],{"class":276}," statement_timeout ",[246,8836,1109],{"class":619},[246,8838,8839],{"class":432}," '10s'",[246,8841,6573],{"class":276},[24,8843,8844,8847],{},[147,8845,8846],{},"Cursor MCP 不支持事务","：每个 SQL 是独立执行，不能 BEGIN\u002FCOMMIT。多步操作用存储过程。",[24,8849,8850,864,8853,8856,8857,8860,8861,3725],{},[147,8851,8852],{},"DATABASE_URL 泄露",[159,8854,8855],{},".cursor\u002Fmcp.json"," 可能被 git 提交。加到 ",[159,8858,8859],{},".gitignore","，用 ",[159,8862,8863],{},".cursor\u002Fmcp.local.json",[721,8865,8866],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":157,"searchDepth":263,"depth":263,"links":8868},[8869,8870,8871,8872,8877,8882,8883],{"id":15,"depth":256,"text":15},{"id":8194,"depth":256,"text":8195},{"id":8215,"depth":256,"text":8216},{"id":8327,"depth":256,"text":8328,"children":8873},[8874,8875,8876],{"id":8331,"depth":263,"text":8331},{"id":8441,"depth":263,"text":8442},{"id":8528,"depth":263,"text":8528},{"id":8619,"depth":256,"text":8620,"children":8878},[8879,8880,8881],{"id":8623,"depth":263,"text":8624},{"id":8657,"depth":263,"text":8658},{"id":8687,"depth":263,"text":8688},{"id":8716,"depth":256,"text":8716},{"id":6319,"depth":256,"text":6319},"\u002Fog\u002Fplaybook\u002Fcursor-mcp-database.png","用 MCP 协议让 Cursor \u002F Claude Code 直接读写 PostgreSQL——AI 能查表结构、跑 SQL、生成迁移文件。含安全配置、权限边界和踩坑记录。",{},"\u002Fplaybook\u002Fonboarding\u002Fcursor-mcp-database",[8889,8890,8891,7484],"agent\u002Fprotocol\u002Fsmithery","agent\u002Fprotocol\u002Fcomposio","agent\u002Fprotocol\u002Fmcp-toolbox",{"title":8176,"description":8885},"playbook\u002Fonboarding\u002Fcursor-mcp-database",[755,228,8895,7488],"PostgreSQL","Xz0aDqhIFWiE0v5sBvsHZqBKQn_S_xNSzHCeNesIXxA",{"id":8898,"title":8899,"body":8900,"category":740,"cover":9864,"description":9865,"extension":242,"meta":9866,"navigation":259,"path":9867,"published":6381,"relatedTools":9868,"seo":9869,"stem":9870,"tags":9871,"updated":6381,"__hash__":9873},"playbook\u002Fplaybook\u002Fonboarding\u002Fcursor-mcp-deep-integration.md","Cursor + MCP 深度集成：让 AI IDE 连接一切",{"type":10,"value":8901,"toc":9835},[8902,8904,8915,8919,8922,8933,8939,8943,8953,9032,9035,9039,9043,9046,9108,9111,9127,9131,9134,9210,9212,9226,9230,9233,9297,9301,9304,9383,9386,9390,9393,9452,9455,9459,9462,9521,9524,9528,9532,9538,9541,9560,9564,9570,9572,9592,9596,9602,9604,9624,9627,9630,9633,9637,9651,9654,9675,9709,9713,9721,9724,9728,9731,9742,9745,9748,9756,9760,9827,9832],[13,8903,15],{"id":15},[21,8905,8906,8909,8912],{},[24,8907,8908],{},"已在用 Cursor，想让 AI 能直接查数据库 \u002F 操作 GitHub",[24,8910,8911],{},"想让 AI 在写代码时能访问外部 API（Slack、Jira、Linear）",[24,8913,8914],{},"想构建\"AI 能看能做\"的开发环境，不只是\"AI 建议、人执行\"",[13,8916,8918],{"id":8917},"mcp-在-cursor-中的定位","MCP 在 Cursor 中的定位",[17,8920,8921],{},"Cursor 0.42+ 原生支持 MCP。配置 MCP Server 后：",[21,8923,8924,8927,8930],{},[24,8925,8926],{},"AI Agent 模式下可以调用 MCP 工具",[24,8928,8929],{},"AI 能看到工具的返回结果，基于结果继续推理",[24,8931,8932],{},"不需要离开 IDE 去查数据库 \u002F 看 GitHub Issue",[17,8934,8935,8938],{},[147,8936,8937],{},"本质","：把\"复制粘贴往返\"变成\"AI 直接操作\"。",[13,8940,8942],{"id":8941},"第一步理解-mcp-配置","第一步：理解 MCP 配置",[17,8944,8945,8946,8949,8950,8952],{},"Cursor 的 MCP 配置在 ",[159,8947,8948],{},"~\u002F.cursor\u002Fmcp.json","（全局）或项目根目录 ",[159,8951,8855],{},"（项目级）。",[151,8954,8956],{"className":2096,"code":8955,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"server-name\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@mcp\u002Fserver-package\"],\n      \"env\": {\n        \"API_KEY\": \"xxx\"\n      }\n    }\n  }\n}\n",[159,8957,8958,8962,8968,8975,8985,9000,9006,9016,9020,9024,9028],{"__ignoreMap":157},[246,8959,8960],{"class":248,"line":249},[246,8961,2105],{"class":276},[246,8963,8964,8966],{"class":248,"line":256},[246,8965,2110],{"class":428},[246,8967,2113],{"class":276},[246,8969,8970,8973],{"class":248,"line":263},[246,8971,8972],{"class":428},"    \"server-name\"",[246,8974,2113],{"class":276},[246,8976,8977,8979,8981,8983],{"class":248,"line":269},[246,8978,2125],{"class":428},[246,8980,2128],{"class":276},[246,8982,2131],{"class":432},[246,8984,2134],{"class":276},[246,8986,8987,8989,8991,8993,8995,8998],{"class":248,"line":280},[246,8988,2139],{"class":428},[246,8990,2142],{"class":276},[246,8992,7925],{"class":432},[246,8994,2148],{"class":276},[246,8996,8997],{"class":432},"\"@mcp\u002Fserver-package\"",[246,8999,7932],{"class":276},[246,9001,9002,9004],{"class":248,"line":288},[246,9003,7937],{"class":428},[246,9005,2113],{"class":276},[246,9007,9008,9011,9013],{"class":248,"line":5},[246,9009,9010],{"class":428},"        \"API_KEY\"",[246,9012,2128],{"class":276},[246,9014,9015],{"class":432},"\"xxx\"\n",[246,9017,9018],{"class":248,"line":300},[246,9019,7954],{"class":276},[246,9021,9022],{"class":248,"line":306},[246,9023,2159],{"class":276},[246,9025,9026],{"class":248,"line":314},[246,9027,2164],{"class":276},[246,9029,9030],{"class":248,"line":322},[246,9031,2169],{"class":276},[17,9033,9034],{},"配置后重启 Cursor，在 Agent 模式下 AI 自动可用这些工具。",[13,9036,9038],{"id":9037},"第二步6-个常用-mcp-server-配置","第二步：6 个常用 MCP Server 配置",[406,9040,9042],{"id":9041},"_1-postgresql最常用","1. PostgreSQL（最常用）",[17,9044,9045],{},"让 AI 能查表结构、跑 SQL、分析数据。",[151,9047,9049],{"className":2096,"code":9048,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"postgres\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-postgres\", \"postgresql:\u002F\u002Fuser:pass@localhost:5432\u002Fmydb\"]\n    }\n  }\n}\n",[159,9050,9051,9055,9061,9067,9077,9096,9100,9104],{"__ignoreMap":157},[246,9052,9053],{"class":248,"line":249},[246,9054,2105],{"class":276},[246,9056,9057,9059],{"class":248,"line":256},[246,9058,2110],{"class":428},[246,9060,2113],{"class":276},[246,9062,9063,9065],{"class":248,"line":263},[246,9064,2118],{"class":428},[246,9066,2113],{"class":276},[246,9068,9069,9071,9073,9075],{"class":248,"line":269},[246,9070,2125],{"class":428},[246,9072,2128],{"class":276},[246,9074,2131],{"class":432},[246,9076,2134],{"class":276},[246,9078,9079,9081,9083,9085,9087,9089,9091,9094],{"class":248,"line":280},[246,9080,2139],{"class":428},[246,9082,2142],{"class":276},[246,9084,7925],{"class":432},[246,9086,2148],{"class":276},[246,9088,2145],{"class":432},[246,9090,2148],{"class":276},[246,9092,9093],{"class":432},"\"postgresql:\u002F\u002Fuser:pass@localhost:5432\u002Fmydb\"",[246,9095,2154],{"class":276},[246,9097,9098],{"class":248,"line":288},[246,9099,2159],{"class":276},[246,9101,9102],{"class":248,"line":5},[246,9103,2164],{"class":276},[246,9105,9106],{"class":248,"line":300},[246,9107,2169],{"class":276},[17,9109,9110],{},"AI 能力：",[21,9112,9113,9118,9121,9124],{},[24,9114,9115,9117],{},[159,9116,8201],{}," 查表结构",[24,9119,9120],{},"跑 SELECT 查询（只读）",[24,9122,9123],{},"分析数据分布",[24,9125,9126],{},"生成数据库迁移建议",[406,9128,9130],{"id":9129},"_2-github","2. GitHub",[17,9132,9133],{},"让 AI 能看 Issue \u002F PR \u002F 代码评论。",[151,9135,9137],{"className":2096,"code":9136,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"github\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-github\"],\n      \"env\": {\n        \"GITHUB_PERSONAL_ACCESS_TOKEN\": \"ghp_xxx\"\n      }\n    }\n  }\n}\n",[159,9138,9139,9143,9149,9155,9165,9179,9185,9194,9198,9202,9206],{"__ignoreMap":157},[246,9140,9141],{"class":248,"line":249},[246,9142,2105],{"class":276},[246,9144,9145,9147],{"class":248,"line":256},[246,9146,2110],{"class":428},[246,9148,2113],{"class":276},[246,9150,9151,9153],{"class":248,"line":263},[246,9152,7964],{"class":428},[246,9154,2113],{"class":276},[246,9156,9157,9159,9161,9163],{"class":248,"line":269},[246,9158,2125],{"class":428},[246,9160,2128],{"class":276},[246,9162,2131],{"class":432},[246,9164,2134],{"class":276},[246,9166,9167,9169,9171,9173,9175,9177],{"class":248,"line":280},[246,9168,2139],{"class":428},[246,9170,2142],{"class":276},[246,9172,7925],{"class":432},[246,9174,2148],{"class":276},[246,9176,7989],{"class":432},[246,9178,7932],{"class":276},[246,9180,9181,9183],{"class":248,"line":288},[246,9182,7937],{"class":428},[246,9184,2113],{"class":276},[246,9186,9187,9190,9192],{"class":248,"line":5},[246,9188,9189],{"class":428},"        \"GITHUB_PERSONAL_ACCESS_TOKEN\"",[246,9191,2128],{"class":276},[246,9193,8007],{"class":432},[246,9195,9196],{"class":248,"line":300},[246,9197,7954],{"class":276},[246,9199,9200],{"class":248,"line":306},[246,9201,2159],{"class":276},[246,9203,9204],{"class":248,"line":314},[246,9205,2164],{"class":276},[246,9207,9208],{"class":248,"line":322},[246,9209,2169],{"class":276},[17,9211,9110],{},[21,9213,9214,9217,9220,9223],{},[24,9215,9216],{},"查看某个 Issue 的讨论",[24,9218,9219],{},"列出分配给你的 PR",[24,9221,9222],{},"根据 Issue 描述直接开始修 bug",[24,9224,9225],{},"创建 PR 描述",[406,9227,9229],{"id":9228},"_3-文件系统增强版","3. 文件系统（增强版）",[17,9231,9232],{},"Cursor 自带文件读写，但 MCP 文件系统 Server 支持更复杂的操作（搜索、批量重命名）。",[151,9234,9236],{"className":2096,"code":9235,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-filesystem\", \"\u002FUsers\u002Fme\u002Fprojects\"]\n    }\n  }\n}\n",[159,9237,9238,9242,9248,9255,9265,9285,9289,9293],{"__ignoreMap":157},[246,9239,9240],{"class":248,"line":249},[246,9241,2105],{"class":276},[246,9243,9244,9246],{"class":248,"line":256},[246,9245,2110],{"class":428},[246,9247,2113],{"class":276},[246,9249,9250,9253],{"class":248,"line":263},[246,9251,9252],{"class":428},"    \"filesystem\"",[246,9254,2113],{"class":276},[246,9256,9257,9259,9261,9263],{"class":248,"line":269},[246,9258,2125],{"class":428},[246,9260,2128],{"class":276},[246,9262,2131],{"class":432},[246,9264,2134],{"class":276},[246,9266,9267,9269,9271,9273,9275,9278,9280,9283],{"class":248,"line":280},[246,9268,2139],{"class":428},[246,9270,2142],{"class":276},[246,9272,7925],{"class":432},[246,9274,2148],{"class":276},[246,9276,9277],{"class":432},"\"@modelcontextprotocol\u002Fserver-filesystem\"",[246,9279,2148],{"class":276},[246,9281,9282],{"class":432},"\"\u002FUsers\u002Fme\u002Fprojects\"",[246,9284,2154],{"class":276},[246,9286,9287],{"class":248,"line":288},[246,9288,2159],{"class":276},[246,9290,9291],{"class":248,"line":5},[246,9292,2164],{"class":276},[246,9294,9295],{"class":248,"line":300},[246,9296,2169],{"class":276},[406,9298,9300],{"id":9299},"_4-slack","4. Slack",[17,9302,9303],{},"让 AI 能看频道消息、搜索历史讨论。",[151,9305,9307],{"className":2096,"code":9306,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"slack\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-slack\"],\n      \"env\": {\n        \"SLACK_BOT_TOKEN\": \"xoxb-xxx\"\n      }\n    }\n  }\n}\n",[159,9308,9309,9313,9319,9326,9336,9351,9357,9367,9371,9375,9379],{"__ignoreMap":157},[246,9310,9311],{"class":248,"line":249},[246,9312,2105],{"class":276},[246,9314,9315,9317],{"class":248,"line":256},[246,9316,2110],{"class":428},[246,9318,2113],{"class":276},[246,9320,9321,9324],{"class":248,"line":263},[246,9322,9323],{"class":428},"    \"slack\"",[246,9325,2113],{"class":276},[246,9327,9328,9330,9332,9334],{"class":248,"line":269},[246,9329,2125],{"class":428},[246,9331,2128],{"class":276},[246,9333,2131],{"class":432},[246,9335,2134],{"class":276},[246,9337,9338,9340,9342,9344,9346,9349],{"class":248,"line":280},[246,9339,2139],{"class":428},[246,9341,2142],{"class":276},[246,9343,7925],{"class":432},[246,9345,2148],{"class":276},[246,9347,9348],{"class":432},"\"@modelcontextprotocol\u002Fserver-slack\"",[246,9350,7932],{"class":276},[246,9352,9353,9355],{"class":248,"line":288},[246,9354,7937],{"class":428},[246,9356,2113],{"class":276},[246,9358,9359,9362,9364],{"class":248,"line":5},[246,9360,9361],{"class":428},"        \"SLACK_BOT_TOKEN\"",[246,9363,2128],{"class":276},[246,9365,9366],{"class":432},"\"xoxb-xxx\"\n",[246,9368,9369],{"class":248,"line":300},[246,9370,7954],{"class":276},[246,9372,9373],{"class":248,"line":306},[246,9374,2159],{"class":276},[246,9376,9377],{"class":248,"line":314},[246,9378,2164],{"class":276},[246,9380,9381],{"class":248,"line":322},[246,9382,2169],{"class":276},[17,9384,9385],{},"场景：开发时遇到问题，AI 可以搜 Slack 历史看团队之前是否讨论过。",[406,9387,9389],{"id":9388},"_5-puppeteer浏览器","5. Puppeteer（浏览器）",[17,9391,9392],{},"让 AI 能打开网页、截图、提取内容。",[151,9394,9396],{"className":2096,"code":9395,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"puppeteer\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-puppeteer\"]\n    }\n  }\n}\n",[159,9397,9398,9402,9408,9415,9425,9440,9444,9448],{"__ignoreMap":157},[246,9399,9400],{"class":248,"line":249},[246,9401,2105],{"class":276},[246,9403,9404,9406],{"class":248,"line":256},[246,9405,2110],{"class":428},[246,9407,2113],{"class":276},[246,9409,9410,9413],{"class":248,"line":263},[246,9411,9412],{"class":428},"    \"puppeteer\"",[246,9414,2113],{"class":276},[246,9416,9417,9419,9421,9423],{"class":248,"line":269},[246,9418,2125],{"class":428},[246,9420,2128],{"class":276},[246,9422,2131],{"class":432},[246,9424,2134],{"class":276},[246,9426,9427,9429,9431,9433,9435,9438],{"class":248,"line":280},[246,9428,2139],{"class":428},[246,9430,2142],{"class":276},[246,9432,7925],{"class":432},[246,9434,2148],{"class":276},[246,9436,9437],{"class":432},"\"@modelcontextprotocol\u002Fserver-puppeteer\"",[246,9439,2154],{"class":276},[246,9441,9442],{"class":248,"line":288},[246,9443,2159],{"class":276},[246,9445,9446],{"class":248,"line":5},[246,9447,2164],{"class":276},[246,9449,9450],{"class":248,"line":300},[246,9451,2169],{"class":276},[17,9453,9454],{},"场景：调试前端时让 AI 打开 localhost:3000 截图，对比设计稿。",[406,9456,9458],{"id":9457},"_6-memory持久记忆","6. Memory（持久记忆）",[17,9460,9461],{},"让 AI 跨会话记住信息。",[151,9463,9465],{"className":2096,"code":9464,"language":2098,"meta":157,"style":157},"{\n  \"mcpServers\": {\n    \"memory\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-memory\"]\n    }\n  }\n}\n",[159,9466,9467,9471,9477,9484,9494,9509,9513,9517],{"__ignoreMap":157},[246,9468,9469],{"class":248,"line":249},[246,9470,2105],{"class":276},[246,9472,9473,9475],{"class":248,"line":256},[246,9474,2110],{"class":428},[246,9476,2113],{"class":276},[246,9478,9479,9482],{"class":248,"line":263},[246,9480,9481],{"class":428},"    \"memory\"",[246,9483,2113],{"class":276},[246,9485,9486,9488,9490,9492],{"class":248,"line":269},[246,9487,2125],{"class":428},[246,9489,2128],{"class":276},[246,9491,2131],{"class":432},[246,9493,2134],{"class":276},[246,9495,9496,9498,9500,9502,9504,9507],{"class":248,"line":280},[246,9497,2139],{"class":428},[246,9499,2142],{"class":276},[246,9501,7925],{"class":432},[246,9503,2148],{"class":276},[246,9505,9506],{"class":432},"\"@modelcontextprotocol\u002Fserver-memory\"",[246,9508,2154],{"class":276},[246,9510,9511],{"class":248,"line":288},[246,9512,2159],{"class":276},[246,9514,9515],{"class":248,"line":5},[246,9516,2164],{"class":276},[246,9518,9519],{"class":248,"line":300},[246,9520,2169],{"class":276},[17,9522,9523],{},"场景：让 AI 记住\"这个项目用 pnpm 不用 npm\"，下次启动自动加载。",[13,9525,9527],{"id":9526},"第三步实战场景","第三步：实战场景",[406,9529,9531],{"id":9530},"场景-1根据-github-issue-修-bug","场景 1：根据 GitHub Issue 修 Bug",[151,9533,9536],{"className":9534,"code":9535,"language":156,"meta":157},[154],"@agent 看一下 github issue #142，理解问题，然后修复它\n",[159,9537,9535],{"__ignoreMap":157},[17,9539,9540],{},"AI 流程：",[532,9542,9543,9546,9549,9552,9555,9557],{},[24,9544,9545],{},"调 GitHub MCP 读 Issue 内容",[24,9547,9548],{},"分析问题原因",[24,9550,9551],{},"找到相关代码",[24,9553,9554],{},"修改",[24,9556,6183],{},[24,9558,9559],{},"生成 PR 描述（可让它直接创建 PR）",[406,9561,9563],{"id":9562},"场景-2数据驱动的功能开发","场景 2：数据驱动的功能开发",[151,9565,9568],{"className":9566,"code":9567,"language":156,"meta":157},[154],"@agent 我要加用户积分功能。先查一下 users 表结构和现有数据量，然后设计 schema 和 API\n",[159,9569,9567],{"__ignoreMap":157},[17,9571,9540],{},[532,9573,9574,9577,9580,9583,9586,9589],{},[24,9575,9576],{},"调 PostgreSQL MCP 查 users 表结构",[24,9578,9579],{},"查现有数据量（SELECT COUNT(*)）",[24,9581,9582],{},"设计 points 字段和积分日志表",[24,9584,9585],{},"生成迁移 SQL",[24,9587,9588],{},"设计 API 接口",[24,9590,9591],{},"写代码实现",[406,9593,9595],{"id":9594},"场景-3前端调试","场景 3：前端调试",[151,9597,9600],{"className":9598,"code":9599,"language":156,"meta":157},[154],"@agent 打开 localhost:3000\u002Fprofile，截图看看头像上传组件的样式问题\n",[159,9601,9599],{"__ignoreMap":157},[17,9603,9540],{},[532,9605,9606,9609,9612,9615,9618,9621],{},[24,9607,9608],{},"调 Puppeteer MCP 打开页面",[24,9610,9611],{},"截图",[24,9613,9614],{},"分析样式问题",[24,9616,9617],{},"找到对应组件代码",[24,9619,9620],{},"修改 CSS",[24,9622,9623],{},"重新截图验证",[13,9625,9626],{"id":9626},"权限边界与安全",[406,9628,9629],{"id":9629},"数据库只读",[17,9631,9632],{},"PostgreSQL MCP Server 默认只允许 SELECT。不要给它写权限，除非你完全信任 AI 的判断。",[406,9634,9636],{"id":9635},"token-最小权限","Token 最小权限",[17,9638,9639,9640,823,9643,9646,9647,9650],{},"GitHub Token 只给 ",[159,9641,9642],{},"repo:read",[159,9644,9645],{},"issues:read","，不要给 ",[159,9648,9649],{},"repo:write","（除非你想让 AI 直接 push 代码）。",[406,9652,9653],{"id":9653},"敏感信息不进配置文件",[151,9655,9657],{"className":415,"code":9656,"language":417,"meta":157,"style":157},"# 不要把 token 写死在 mcp.json，用环境变量\nexport GITHUB_TOKEN=\"ghp_xxx\"\n",[159,9658,9659,9664],{"__ignoreMap":157},[246,9660,9661],{"class":248,"line":249},[246,9662,9663],{"class":607},"# 不要把 token 写死在 mcp.json，用环境变量\n",[246,9665,9666,9668,9671,9673],{"class":248,"line":256},[246,9667,1103],{"class":619},[246,9669,9670],{"class":276}," GITHUB_TOKEN",[246,9672,1109],{"class":619},[246,9674,8007],{"class":432},[151,9676,9678],{"className":2096,"code":9677,"language":2098,"meta":157,"style":157},"{\n  \"env\": {\n    \"GITHUB_PERSONAL_ACCESS_TOKEN\": \"${GITHUB_TOKEN}\"\n  }\n}\n",[159,9679,9680,9684,9691,9701,9705],{"__ignoreMap":157},[246,9681,9682],{"class":248,"line":249},[246,9683,2105],{"class":276},[246,9685,9686,9689],{"class":248,"line":256},[246,9687,9688],{"class":428},"  \"env\"",[246,9690,2113],{"class":276},[246,9692,9693,9696,9698],{"class":248,"line":263},[246,9694,9695],{"class":428},"    \"GITHUB_PERSONAL_ACCESS_TOKEN\"",[246,9697,2128],{"class":276},[246,9699,9700],{"class":432},"\"${GITHUB_TOKEN}\"\n",[246,9702,9703],{"class":248,"line":269},[246,9704,2164],{"class":276},[246,9706,9707],{"class":248,"line":280},[246,9708,2169],{"class":276},[406,9710,9712],{"id":9711},"gitignore-掉-mcpjson",".gitignore 掉 mcp.json",[17,9714,9715,9716,9718,9719,3725],{},"项目级 ",[159,9717,8855],{}," 可能含 token，务必加到 ",[159,9720,8859],{},[13,9722,9723],{"id":9723},"性能注意事项",[406,9725,9727],{"id":9726},"mcp-server-启动慢","MCP Server 启动慢",[17,9729,9730],{},"每个 MCP Server 是一个独立进程。配 6 个就是 6 个 npx 进程。建议：",[21,9732,9733,9736],{},[24,9734,9735],{},"只配当前任务需要的",[24,9737,1239,9738,9741],{},[159,9739,9740],{},"npx --prefer-offline"," 加速",[406,9743,9744],{"id":9744},"上下文膨胀",[17,9746,9747],{},"MCP 工具的返回结果会进入 AI 上下文。数据库返回 1000 行结果会吃掉大量 token。建议：",[21,9749,9750,9753],{},[24,9751,9752],{},"让 AI 用 LIMIT 限制查询行数",[24,9754,9755],{},"只查需要的字段",[13,9757,9759],{"id":9758},"与-claude-code-mcp-的区别","与 Claude Code MCP 的区别",[40,9761,9762,9774],{},[43,9763,9764],{},[46,9765,9766,9768,9771],{},[49,9767,1307],{},[49,9769,9770],{},"Cursor MCP",[49,9772,9773],{},"Claude Code MCP",[62,9775,9776,9786,9797,9808,9817],{},[46,9777,9778,9781,9783],{},[67,9779,9780],{},"配置位置",[67,9782,8855],{},[67,9784,9785],{},"~\u002F.claude\u002Fmcp_servers.json",[46,9787,9788,9791,9794],{},[67,9789,9790],{},"UI 可视化",[67,9792,9793],{},"✅ 有 MCP 面板",[67,9795,9796],{},"❌ 纯命令行",[46,9798,9799,9802,9805],{},[67,9800,9801],{},"工具调用可见性",[67,9803,9804],{},"✅ 在 chat 里显示",[67,9806,9807],{},"✅ 在终端显示",[46,9809,9810,9813,9815],{},[67,9811,9812],{},"多 Server 同时",[67,9814,1334],{},[67,9816,1334],{},[46,9818,9819,9822,9824],{},[67,9820,9821],{},"项目级配置",[67,9823,1334],{},[67,9825,9826],{},"❌ 全局",[17,9828,9829,9831],{},[147,9830,8791],{},"：两个工具配同样的 MCP Server，根据场景切换用。",[721,9833,9834],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":157,"searchDepth":263,"depth":263,"links":9836},[9837,9838,9839,9840,9848,9853,9859,9863],{"id":15,"depth":256,"text":15},{"id":8917,"depth":256,"text":8918},{"id":8941,"depth":256,"text":8942},{"id":9037,"depth":256,"text":9038,"children":9841},[9842,9843,9844,9845,9846,9847],{"id":9041,"depth":263,"text":9042},{"id":9129,"depth":263,"text":9130},{"id":9228,"depth":263,"text":9229},{"id":9299,"depth":263,"text":9300},{"id":9388,"depth":263,"text":9389},{"id":9457,"depth":263,"text":9458},{"id":9526,"depth":256,"text":9527,"children":9849},[9850,9851,9852],{"id":9530,"depth":263,"text":9531},{"id":9562,"depth":263,"text":9563},{"id":9594,"depth":263,"text":9595},{"id":9626,"depth":256,"text":9626,"children":9854},[9855,9856,9857,9858],{"id":9629,"depth":263,"text":9629},{"id":9635,"depth":263,"text":9636},{"id":9653,"depth":263,"text":9653},{"id":9711,"depth":263,"text":9712},{"id":9723,"depth":256,"text":9723,"children":9860},[9861,9862],{"id":9726,"depth":263,"text":9727},{"id":9744,"depth":263,"text":9744},{"id":9758,"depth":256,"text":9759},"\u002Fog\u002Fplaybook\u002Fcursor-mcp-deep-integration.png","Cursor 已支持 MCP——连接数据库、GitHub、Slack、文件系统、浏览器，让 AI 在 IDE 里直接操作外部服务。含 6 个常用 MCP Server 配置 + 权限边界 + 真实场景。",{},"\u002Fplaybook\u002Fonboarding\u002Fcursor-mcp-deep-integration",[7484,8889,8890,8891],{"title":8899,"description":9865},"playbook\u002Fonboarding\u002Fcursor-mcp-deep-integration",[228,755,9872,6445],"集成","7qzEiYO3w5v5Fw3TTNc64WmPJaxqOD2eo9lXwr7Yv1c",{"id":9875,"title":9876,"body":9877,"category":740,"cover":11402,"description":11403,"extension":242,"meta":11404,"navigation":259,"path":11405,"published":6381,"relatedTools":11406,"seo":11410,"stem":11411,"tags":11412,"updated":6381,"__hash__":11415},"playbook\u002Fplaybook\u002Fonboarding\u002Frag-pipeline-build.md","RAG 管道从零搭建：文档问答系统实战",{"type":10,"value":9878,"toc":11375},[9879,9881,9895,9899,9905,9908,9991,9995,10019,10023,10026,10149,10152,10211,10216,10220,10428,10432,10575,10578,10581,10585,10736,10740,10743,10843,10847,10850,11111,11114,11117,11202,11205,11209,11214,11219,11230,11234,11238,11249,11253,11257,11268,11272,11276,11290,11293,11372],[13,9880,15],{"id":15},[21,9882,9883,9886,9889,9892],{},[24,9884,9885],{},"公司内部知识库问答（HR 政策、技术文档、FAQ）",[24,9887,9888],{},"法律\u002F医疗文档检索 + 问答",[24,9890,9891],{},"产品手册智能客服",[24,9893,9894],{},"个人笔记\u002F文献智能检索",[13,9896,9898],{"id":9897},"rag-架构总览","RAG 架构总览",[151,9900,9903],{"className":9901,"code":9902,"language":156,"meta":157},[154],"文档 → 切分 → Embedding → 存入向量数据库\n                                    ↓\n用户提问 → Embedding → 检索 Top-K → 重排序 → LLM 生成回答\n",[159,9904,9902],{"__ignoreMap":157},[13,9906,9907],{"id":9907},"技术选型",[40,9909,9910,9923],{},[43,9911,9912],{},[46,9913,9914,9917,9920],{},[49,9915,9916],{},"组件",[49,9918,9919],{},"选型",[49,9921,9922],{},"理由",[62,9924,9925,9936,9947,9958,9969,9980],{},[46,9926,9927,9930,9933],{},[67,9928,9929],{},"框架",[67,9931,9932],{},"LlamaIndex",[67,9934,9935],{},"比 LangChain 更专注 RAG",[46,9937,9938,9941,9944],{},[67,9939,9940],{},"Embedding",[67,9942,9943],{},"BGE-large-zh-v1.5",[67,9945,9946],{},"中文效果最佳，开源免费",[46,9948,9949,9952,9955],{},[67,9950,9951],{},"向量数据库",[67,9953,9954],{},"ChromaDB",[67,9956,9957],{},"轻量，原型够用",[46,9959,9960,9963,9966],{},[67,9961,9962],{},"重排序",[67,9964,9965],{},"bge-reranker-large",[67,9967,9968],{},"显著提升准确率",[46,9970,9971,9974,9977],{},[67,9972,9973],{},"LLM",[67,9975,9976],{},"GPT-4o",[67,9978,9979],{},"性价比好，支持国内中转",[46,9981,9982,9985,9988],{},[67,9983,9984],{},"文档解析",[67,9986,9987],{},"Unstructured",[67,9989,9990],{},"支持 PDF\u002FWord\u002FHTML",[13,9992,9994],{"id":9993},"第一步环境准备","第一步：环境准备",[151,9996,9998],{"className":415,"code":9997,"language":417,"meta":157,"style":157},"pip install llama-index chromadb sentence-transformers unstructured\n",[159,9999,10000],{"__ignoreMap":157},[246,10001,10002,10005,10007,10010,10013,10016],{"class":248,"line":249},[246,10003,10004],{"class":424},"pip",[246,10006,1060],{"class":432},[246,10008,10009],{"class":432}," llama-index",[246,10011,10012],{"class":432}," chromadb",[246,10014,10015],{"class":432}," sentence-transformers",[246,10017,10018],{"class":432}," unstructured\n",[13,10020,10022],{"id":10021},"第二步文档加载与切分","第二步：文档加载与切分",[17,10024,10025],{},"切分是 RAG 效果的决定性因素。",[151,10027,10030],{"className":10028,"code":10029,"language":1051,"meta":157,"style":157},"language-python shiki shiki-themes github-light github-dark","from llama_index.core import SimpleDirectoryReader\nfrom llama_index.core.node_parser import SentenceSplitter\n\n# 1. 加载文档\ndocuments = SimpleDirectoryReader(\".\u002Fdocs\").load_data()\n\n# 2. 切分\nsplitter = SentenceSplitter(\n    chunk_size=512,      # 每块 512 token\n    chunk_overlap=50,    # 重叠 50 token，保证上下文连贯\n)\nnodes = splitter.get_nodes_from_documents(documents)\n",[159,10031,10032,10046,10058,10062,10067,10083,10087,10092,10102,10118,10134,10139],{"__ignoreMap":157},[246,10033,10034,10037,10040,10043],{"class":248,"line":249},[246,10035,10036],{"class":619},"from",[246,10038,10039],{"class":276}," llama_index.core ",[246,10041,10042],{"class":619},"import",[246,10044,10045],{"class":276}," SimpleDirectoryReader\n",[246,10047,10048,10050,10053,10055],{"class":248,"line":256},[246,10049,10036],{"class":619},[246,10051,10052],{"class":276}," llama_index.core.node_parser ",[246,10054,10042],{"class":619},[246,10056,10057],{"class":276}," SentenceSplitter\n",[246,10059,10060],{"class":248,"line":263},[246,10061,260],{"emptyLinePlaceholder":259},[246,10063,10064],{"class":248,"line":269},[246,10065,10066],{"class":607},"# 1. 加载文档\n",[246,10068,10069,10072,10074,10077,10080],{"class":248,"line":280},[246,10070,10071],{"class":276},"documents ",[246,10073,1109],{"class":619},[246,10075,10076],{"class":276}," SimpleDirectoryReader(",[246,10078,10079],{"class":432},"\".\u002Fdocs\"",[246,10081,10082],{"class":276},").load_data()\n",[246,10084,10085],{"class":248,"line":288},[246,10086,260],{"emptyLinePlaceholder":259},[246,10088,10089],{"class":248,"line":5},[246,10090,10091],{"class":607},"# 2. 切分\n",[246,10093,10094,10097,10099],{"class":248,"line":300},[246,10095,10096],{"class":276},"splitter ",[246,10098,1109],{"class":619},[246,10100,10101],{"class":276}," SentenceSplitter(\n",[246,10103,10104,10107,10109,10112,10115],{"class":248,"line":306},[246,10105,10106],{"class":272},"    chunk_size",[246,10108,1109],{"class":619},[246,10110,10111],{"class":428},"512",[246,10113,10114],{"class":276},",      ",[246,10116,10117],{"class":607},"# 每块 512 token\n",[246,10119,10120,10123,10125,10128,10131],{"class":248,"line":314},[246,10121,10122],{"class":272},"    chunk_overlap",[246,10124,1109],{"class":619},[246,10126,10127],{"class":428},"50",[246,10129,10130],{"class":276},",    ",[246,10132,10133],{"class":607},"# 重叠 50 token，保证上下文连贯\n",[246,10135,10136],{"class":248,"line":322},[246,10137,10138],{"class":276},")\n",[246,10140,10141,10144,10146],{"class":248,"line":330},[246,10142,10143],{"class":276},"nodes ",[246,10145,1109],{"class":619},[246,10147,10148],{"class":276}," splitter.get_nodes_from_documents(documents)\n",[406,10150,10151],{"id":10151},"切分策略选择",[40,10153,10154,10166],{},[43,10155,10156],{},[46,10157,10158,10161,10164],{},[49,10159,10160],{},"策略",[49,10162,10163],{},"chunk_size",[49,10165,15],{},[62,10167,10168,10179,10189,10200],{},[46,10169,10170,10173,10176],{},[67,10171,10172],{},"小块",[67,10174,10175],{},"256",[67,10177,10178],{},"FAQ、短问答",[46,10180,10181,10184,10186],{},[67,10182,10183],{},"中块",[67,10185,10111],{},[67,10187,10188],{},"通用文档（推荐起步值）",[46,10190,10191,10194,10197],{},[67,10192,10193],{},"大块",[67,10195,10196],{},"1024",[67,10198,10199],{},"长文档、技术手册",[46,10201,10202,10205,10208],{},[67,10203,10204],{},"按段落",[67,10206,10207],{},"不固定",[67,10209,10210],{},"保持语义完整",[17,10212,10213,10215],{},[147,10214,7846],{},"：chunk_overlap 设 chunk_size 的 10%，避免切断语义。",[13,10217,10219],{"id":10218},"第三步embedding-与入库","第三步：Embedding 与入库",[151,10221,10223],{"className":10028,"code":10222,"language":1051,"meta":157,"style":157},"from llama_index.embeddings.huggingface import HuggingFaceEmbedding\nfrom llama_index.vector_stores.chroma import ChromaVectorStore\nimport chromadb\n\n# 1. 用 BGE 中文模型\nembed_model = HuggingFaceEmbedding(\n    model_name=\"BAAI\u002Fbge-large-zh-v1.5\",\n    max_length=512,\n)\n\n# 2. 创建向量数据库\ndb = chromadb.PersistentClient(path=\".\u002Fchroma_db\")\nchroma_collection = db.get_or_create_collection(\"docs\")\nvector_store = ChromaVectorStore(chroma_collection=chroma_collection)\n\n# 3. 构建索引\nfrom llama_index.core import StorageContext, VectorStoreIndex\nstorage_context = StorageContext.from_defaults(vector_store=vector_store)\nindex = VectorStoreIndex(nodes, embed_model=embed_model, storage_context=storage_context)\n",[159,10224,10225,10237,10249,10256,10260,10265,10275,10287,10298,10302,10306,10311,10331,10346,10364,10368,10373,10384,10402],{"__ignoreMap":157},[246,10226,10227,10229,10232,10234],{"class":248,"line":249},[246,10228,10036],{"class":619},[246,10230,10231],{"class":276}," llama_index.embeddings.huggingface ",[246,10233,10042],{"class":619},[246,10235,10236],{"class":276}," HuggingFaceEmbedding\n",[246,10238,10239,10241,10244,10246],{"class":248,"line":256},[246,10240,10036],{"class":619},[246,10242,10243],{"class":276}," llama_index.vector_stores.chroma ",[246,10245,10042],{"class":619},[246,10247,10248],{"class":276}," ChromaVectorStore\n",[246,10250,10251,10253],{"class":248,"line":263},[246,10252,10042],{"class":619},[246,10254,10255],{"class":276}," chromadb\n",[246,10257,10258],{"class":248,"line":269},[246,10259,260],{"emptyLinePlaceholder":259},[246,10261,10262],{"class":248,"line":280},[246,10263,10264],{"class":607},"# 1. 用 BGE 中文模型\n",[246,10266,10267,10270,10272],{"class":248,"line":288},[246,10268,10269],{"class":276},"embed_model ",[246,10271,1109],{"class":619},[246,10273,10274],{"class":276}," HuggingFaceEmbedding(\n",[246,10276,10277,10280,10282,10285],{"class":248,"line":5},[246,10278,10279],{"class":272},"    model_name",[246,10281,1109],{"class":619},[246,10283,10284],{"class":432},"\"BAAI\u002Fbge-large-zh-v1.5\"",[246,10286,2134],{"class":276},[246,10288,10289,10292,10294,10296],{"class":248,"line":300},[246,10290,10291],{"class":272},"    max_length",[246,10293,1109],{"class":619},[246,10295,10111],{"class":428},[246,10297,2134],{"class":276},[246,10299,10300],{"class":248,"line":306},[246,10301,10138],{"class":276},[246,10303,10304],{"class":248,"line":314},[246,10305,260],{"emptyLinePlaceholder":259},[246,10307,10308],{"class":248,"line":322},[246,10309,10310],{"class":607},"# 2. 创建向量数据库\n",[246,10312,10313,10316,10318,10321,10324,10326,10329],{"class":248,"line":330},[246,10314,10315],{"class":276},"db ",[246,10317,1109],{"class":619},[246,10319,10320],{"class":276}," chromadb.PersistentClient(",[246,10322,10323],{"class":272},"path",[246,10325,1109],{"class":619},[246,10327,10328],{"class":432},"\".\u002Fchroma_db\"",[246,10330,10138],{"class":276},[246,10332,10333,10336,10338,10341,10344],{"class":248,"line":335},[246,10334,10335],{"class":276},"chroma_collection ",[246,10337,1109],{"class":619},[246,10339,10340],{"class":276}," db.get_or_create_collection(",[246,10342,10343],{"class":432},"\"docs\"",[246,10345,10138],{"class":276},[246,10347,10348,10351,10353,10356,10359,10361],{"class":248,"line":341},[246,10349,10350],{"class":276},"vector_store ",[246,10352,1109],{"class":619},[246,10354,10355],{"class":276}," ChromaVectorStore(",[246,10357,10358],{"class":272},"chroma_collection",[246,10360,1109],{"class":619},[246,10362,10363],{"class":276},"chroma_collection)\n",[246,10365,10366],{"class":248,"line":349},[246,10367,260],{"emptyLinePlaceholder":259},[246,10369,10370],{"class":248,"line":357},[246,10371,10372],{"class":607},"# 3. 构建索引\n",[246,10374,10375,10377,10379,10381],{"class":248,"line":365},[246,10376,10036],{"class":619},[246,10378,10039],{"class":276},[246,10380,10042],{"class":619},[246,10382,10383],{"class":276}," StorageContext, VectorStoreIndex\n",[246,10385,10386,10389,10391,10394,10397,10399],{"class":248,"line":373},[246,10387,10388],{"class":276},"storage_context ",[246,10390,1109],{"class":619},[246,10392,10393],{"class":276}," StorageContext.from_defaults(",[246,10395,10396],{"class":272},"vector_store",[246,10398,1109],{"class":619},[246,10400,10401],{"class":276},"vector_store)\n",[246,10403,10404,10407,10409,10412,10415,10417,10420,10423,10425],{"class":248,"line":378},[246,10405,10406],{"class":276},"index ",[246,10408,1109],{"class":619},[246,10410,10411],{"class":276}," VectorStoreIndex(nodes, ",[246,10413,10414],{"class":272},"embed_model",[246,10416,1109],{"class":619},[246,10418,10419],{"class":276},"embed_model, ",[246,10421,10422],{"class":272},"storage_context",[246,10424,1109],{"class":619},[246,10426,10427],{"class":276},"storage_context)\n",[13,10429,10431],{"id":10430},"第四步检索-重排序","第四步：检索 + 重排序",[151,10433,10435],{"className":10028,"code":10434,"language":1051,"meta":157,"style":157},"from llama_index.core.postprocessor import SentenceTransformerRerank\n\n# 重排序模型——显著提升检索质量\nreranker = SentenceTransformerRerank(\n    model=\"BAAI\u002Fbge-reranker-large\",\n    top_n=3,  # 重排序后取前 3\n)\n\n# 检索器\nretriever = index.as_retriever(similarity_top_k=10)  # 先粗检索 10 条\n\n# 检索 + 重排序\nnodes = retriever.retrieve(\"年假怎么请？\")\nreranked = reranker.postprocess_nodes(nodes, query_str=\"年假怎么请？\")\n",[159,10436,10437,10449,10453,10458,10468,10480,10496,10500,10504,10509,10533,10537,10542,10556],{"__ignoreMap":157},[246,10438,10439,10441,10444,10446],{"class":248,"line":249},[246,10440,10036],{"class":619},[246,10442,10443],{"class":276}," llama_index.core.postprocessor ",[246,10445,10042],{"class":619},[246,10447,10448],{"class":276}," SentenceTransformerRerank\n",[246,10450,10451],{"class":248,"line":256},[246,10452,260],{"emptyLinePlaceholder":259},[246,10454,10455],{"class":248,"line":263},[246,10456,10457],{"class":607},"# 重排序模型——显著提升检索质量\n",[246,10459,10460,10463,10465],{"class":248,"line":269},[246,10461,10462],{"class":276},"reranker ",[246,10464,1109],{"class":619},[246,10466,10467],{"class":276}," SentenceTransformerRerank(\n",[246,10469,10470,10473,10475,10478],{"class":248,"line":280},[246,10471,10472],{"class":272},"    model",[246,10474,1109],{"class":619},[246,10476,10477],{"class":432},"\"BAAI\u002Fbge-reranker-large\"",[246,10479,2134],{"class":276},[246,10481,10482,10485,10487,10490,10493],{"class":248,"line":288},[246,10483,10484],{"class":272},"    top_n",[246,10486,1109],{"class":619},[246,10488,10489],{"class":428},"3",[246,10491,10492],{"class":276},",  ",[246,10494,10495],{"class":607},"# 重排序后取前 3\n",[246,10497,10498],{"class":248,"line":5},[246,10499,10138],{"class":276},[246,10501,10502],{"class":248,"line":300},[246,10503,260],{"emptyLinePlaceholder":259},[246,10505,10506],{"class":248,"line":306},[246,10507,10508],{"class":607},"# 检索器\n",[246,10510,10511,10514,10516,10519,10522,10524,10527,10530],{"class":248,"line":314},[246,10512,10513],{"class":276},"retriever ",[246,10515,1109],{"class":619},[246,10517,10518],{"class":276}," index.as_retriever(",[246,10520,10521],{"class":272},"similarity_top_k",[246,10523,1109],{"class":619},[246,10525,10526],{"class":428},"10",[246,10528,10529],{"class":276},")  ",[246,10531,10532],{"class":607},"# 先粗检索 10 条\n",[246,10534,10535],{"class":248,"line":322},[246,10536,260],{"emptyLinePlaceholder":259},[246,10538,10539],{"class":248,"line":330},[246,10540,10541],{"class":607},"# 检索 + 重排序\n",[246,10543,10544,10546,10548,10551,10554],{"class":248,"line":335},[246,10545,10143],{"class":276},[246,10547,1109],{"class":619},[246,10549,10550],{"class":276}," retriever.retrieve(",[246,10552,10553],{"class":432},"\"年假怎么请？\"",[246,10555,10138],{"class":276},[246,10557,10558,10561,10563,10566,10569,10571,10573],{"class":248,"line":341},[246,10559,10560],{"class":276},"reranked ",[246,10562,1109],{"class":619},[246,10564,10565],{"class":276}," reranker.postprocess_nodes(nodes, ",[246,10567,10568],{"class":272},"query_str",[246,10570,1109],{"class":619},[246,10572,10553],{"class":432},[246,10574,10138],{"class":276},[406,10576,10577],{"id":10577},"为什么要重排序",[17,10579,10580],{},"Embedding 检索快但不够精准。先粗检索 10 条，再用重排序模型精选 3 条，准确率提升 20-30%。",[13,10582,10584],{"id":10583},"第五步生成回答","第五步：生成回答",[151,10586,10588],{"className":10028,"code":10587,"language":1051,"meta":157,"style":157},"from llama_index.llms.openai import OpenAI\n\nllm = OpenAI(model=\"gpt-4o\", temperature=0)\n\n# 构建 query engine\nquery_engine = index.as_query_engine(\n    llm=llm,\n    similarity_top_k=10,\n    node_postprocessors=[reranker],\n    response_mode=\"compact\",  # 紧凑模式，省 token\n)\n\n# 提问\nresponse = query_engine.query(\"年假怎么请？需要提前多久申请？\")\nprint(response.response)\n",[159,10589,10590,10602,10606,10635,10639,10644,10654,10664,10675,10685,10700,10704,10708,10713,10728],{"__ignoreMap":157},[246,10591,10592,10594,10597,10599],{"class":248,"line":249},[246,10593,10036],{"class":619},[246,10595,10596],{"class":276}," llama_index.llms.openai ",[246,10598,10042],{"class":619},[246,10600,10601],{"class":276}," OpenAI\n",[246,10603,10604],{"class":248,"line":256},[246,10605,260],{"emptyLinePlaceholder":259},[246,10607,10608,10611,10613,10616,10619,10621,10624,10626,10629,10631,10633],{"class":248,"line":263},[246,10609,10610],{"class":276},"llm ",[246,10612,1109],{"class":619},[246,10614,10615],{"class":276}," OpenAI(",[246,10617,10618],{"class":272},"model",[246,10620,1109],{"class":619},[246,10622,10623],{"class":432},"\"gpt-4o\"",[246,10625,2148],{"class":276},[246,10627,10628],{"class":272},"temperature",[246,10630,1109],{"class":619},[246,10632,6873],{"class":428},[246,10634,10138],{"class":276},[246,10636,10637],{"class":248,"line":269},[246,10638,260],{"emptyLinePlaceholder":259},[246,10640,10641],{"class":248,"line":280},[246,10642,10643],{"class":607},"# 构建 query engine\n",[246,10645,10646,10649,10651],{"class":248,"line":288},[246,10647,10648],{"class":276},"query_engine ",[246,10650,1109],{"class":619},[246,10652,10653],{"class":276}," index.as_query_engine(\n",[246,10655,10656,10659,10661],{"class":248,"line":5},[246,10657,10658],{"class":272},"    llm",[246,10660,1109],{"class":619},[246,10662,10663],{"class":276},"llm,\n",[246,10665,10666,10669,10671,10673],{"class":248,"line":300},[246,10667,10668],{"class":272},"    similarity_top_k",[246,10670,1109],{"class":619},[246,10672,10526],{"class":428},[246,10674,2134],{"class":276},[246,10676,10677,10680,10682],{"class":248,"line":306},[246,10678,10679],{"class":272},"    node_postprocessors",[246,10681,1109],{"class":619},[246,10683,10684],{"class":276},"[reranker],\n",[246,10686,10687,10690,10692,10695,10697],{"class":248,"line":314},[246,10688,10689],{"class":272},"    response_mode",[246,10691,1109],{"class":619},[246,10693,10694],{"class":432},"\"compact\"",[246,10696,10492],{"class":276},[246,10698,10699],{"class":607},"# 紧凑模式，省 token\n",[246,10701,10702],{"class":248,"line":322},[246,10703,10138],{"class":276},[246,10705,10706],{"class":248,"line":330},[246,10707,260],{"emptyLinePlaceholder":259},[246,10709,10710],{"class":248,"line":335},[246,10711,10712],{"class":607},"# 提问\n",[246,10714,10715,10718,10720,10723,10726],{"class":248,"line":341},[246,10716,10717],{"class":276},"response ",[246,10719,1109],{"class":619},[246,10721,10722],{"class":276}," query_engine.query(",[246,10724,10725],{"class":432},"\"年假怎么请？需要提前多久申请？\"",[246,10727,10138],{"class":276},[246,10729,10730,10733],{"class":248,"line":349},[246,10731,10732],{"class":428},"print",[246,10734,10735],{"class":276},"(response.response)\n",[406,10737,10739],{"id":10738},"prompt-优化","Prompt 优化",[17,10741,10742],{},"默认 prompt 是英文的，中文场景建议自定义：",[151,10744,10746],{"className":10028,"code":10745,"language":1051,"meta":157,"style":157},"from llama_index.core import PromptTemplate\n\nqa_prompt = PromptTemplate(\"\"\"\n你是一个文档问答助手。请根据以下检索到的文档片段回答问题。\n如果文档中没有相关信息，明确说\"文档中未找到相关信息\"，不要编造。\n\n文档片段：\n{context_str}\n\n问题：{query_str}\n\n回答：\n\"\"\")\n\nquery_engine.update_prompts({\"response_synthesis_prompt\": qa_prompt})\n",[159,10747,10748,10759,10763,10776,10781,10786,10790,10795,10800,10804,10812,10816,10821,10828,10832],{"__ignoreMap":157},[246,10749,10750,10752,10754,10756],{"class":248,"line":249},[246,10751,10036],{"class":619},[246,10753,10039],{"class":276},[246,10755,10042],{"class":619},[246,10757,10758],{"class":276}," PromptTemplate\n",[246,10760,10761],{"class":248,"line":256},[246,10762,260],{"emptyLinePlaceholder":259},[246,10764,10765,10768,10770,10773],{"class":248,"line":263},[246,10766,10767],{"class":276},"qa_prompt ",[246,10769,1109],{"class":619},[246,10771,10772],{"class":276}," PromptTemplate(",[246,10774,10775],{"class":432},"\"\"\"\n",[246,10777,10778],{"class":248,"line":269},[246,10779,10780],{"class":432},"你是一个文档问答助手。请根据以下检索到的文档片段回答问题。\n",[246,10782,10783],{"class":248,"line":280},[246,10784,10785],{"class":432},"如果文档中没有相关信息，明确说\"文档中未找到相关信息\"，不要编造。\n",[246,10787,10788],{"class":248,"line":288},[246,10789,260],{"emptyLinePlaceholder":259},[246,10791,10792],{"class":248,"line":5},[246,10793,10794],{"class":432},"文档片段：\n",[246,10796,10797],{"class":248,"line":300},[246,10798,10799],{"class":428},"{context_str}\n",[246,10801,10802],{"class":248,"line":306},[246,10803,260],{"emptyLinePlaceholder":259},[246,10805,10806,10809],{"class":248,"line":314},[246,10807,10808],{"class":432},"问题：",[246,10810,10811],{"class":428},"{query_str}\n",[246,10813,10814],{"class":248,"line":322},[246,10815,260],{"emptyLinePlaceholder":259},[246,10817,10818],{"class":248,"line":330},[246,10819,10820],{"class":432},"回答：\n",[246,10822,10823,10826],{"class":248,"line":335},[246,10824,10825],{"class":432},"\"\"\"",[246,10827,10138],{"class":276},[246,10829,10830],{"class":248,"line":341},[246,10831,260],{"emptyLinePlaceholder":259},[246,10833,10834,10837,10840],{"class":248,"line":349},[246,10835,10836],{"class":276},"query_engine.update_prompts({",[246,10838,10839],{"class":432},"\"response_synthesis_prompt\"",[246,10841,10842],{"class":276},": qa_prompt})\n",[13,10844,10846],{"id":10845},"第六步评估","第六步：评估",[406,10848,10849],{"id":10849},"检索质量评估",[151,10851,10853],{"className":10028,"code":10852,"language":1051,"meta":157,"style":157},"# 准备测试集：问题 + 正确答案所在文档\ntest_cases = [\n    {\"question\": \"年假怎么请？\", \"relevant_doc_id\": \"hr_policy_003\"},\n    {\"question\": \"报销流程是什么？\", \"relevant_doc_id\": \"finance_007\"},\n]\n\n# 计算 Recall@K\ndef eval_retrieval(query_engine, test_cases, k=5):\n    hits = 0\n    for tc in test_cases:\n        nodes = query_engine.retrieve(tc[\"question\"])\n        retrieved_ids = [n.node.metadata[\"doc_id\"] for n in nodes[:k]]\n        if tc[\"relevant_doc_id\"] in retrieved_ids:\n            hits += 1\n    return hits \u002F len(test_cases)\n\nrecall = eval_retrieval(query_engine, test_cases, k=5)\nprint(f\"Recall@5: {recall:.1%}\")\n",[159,10854,10855,10860,10870,10895,10917,10921,10925,10930,10949,10959,10973,10988,11015,11031,11042,11059,11063,11082],{"__ignoreMap":157},[246,10856,10857],{"class":248,"line":249},[246,10858,10859],{"class":607},"# 准备测试集：问题 + 正确答案所在文档\n",[246,10861,10862,10865,10867],{"class":248,"line":256},[246,10863,10864],{"class":276},"test_cases ",[246,10866,1109],{"class":619},[246,10868,10869],{"class":276}," [\n",[246,10871,10872,10875,10878,10880,10882,10884,10887,10889,10892],{"class":248,"line":263},[246,10873,10874],{"class":276},"    {",[246,10876,10877],{"class":432},"\"question\"",[246,10879,2128],{"class":276},[246,10881,10553],{"class":432},[246,10883,2148],{"class":276},[246,10885,10886],{"class":432},"\"relevant_doc_id\"",[246,10888,2128],{"class":276},[246,10890,10891],{"class":432},"\"hr_policy_003\"",[246,10893,10894],{"class":276},"},\n",[246,10896,10897,10899,10901,10903,10906,10908,10910,10912,10915],{"class":248,"line":269},[246,10898,10874],{"class":276},[246,10900,10877],{"class":432},[246,10902,2128],{"class":276},[246,10904,10905],{"class":432},"\"报销流程是什么？\"",[246,10907,2148],{"class":276},[246,10909,10886],{"class":432},[246,10911,2128],{"class":276},[246,10913,10914],{"class":432},"\"finance_007\"",[246,10916,10894],{"class":276},[246,10918,10919],{"class":248,"line":280},[246,10920,2154],{"class":276},[246,10922,10923],{"class":248,"line":288},[246,10924,260],{"emptyLinePlaceholder":259},[246,10926,10927],{"class":248,"line":5},[246,10928,10929],{"class":607},"# 计算 Recall@K\n",[246,10931,10932,10935,10938,10941,10943,10946],{"class":248,"line":300},[246,10933,10934],{"class":619},"def",[246,10936,10937],{"class":424}," eval_retrieval",[246,10939,10940],{"class":276},"(query_engine, test_cases, k",[246,10942,1109],{"class":619},[246,10944,10945],{"class":428},"5",[246,10947,10948],{"class":276},"):\n",[246,10950,10951,10954,10956],{"class":248,"line":306},[246,10952,10953],{"class":276},"    hits ",[246,10955,1109],{"class":619},[246,10957,10958],{"class":428}," 0\n",[246,10960,10961,10964,10967,10970],{"class":248,"line":314},[246,10962,10963],{"class":619},"    for",[246,10965,10966],{"class":276}," tc ",[246,10968,10969],{"class":619},"in",[246,10971,10972],{"class":276}," test_cases:\n",[246,10974,10975,10978,10980,10983,10985],{"class":248,"line":322},[246,10976,10977],{"class":276},"        nodes ",[246,10979,1109],{"class":619},[246,10981,10982],{"class":276}," query_engine.retrieve(tc[",[246,10984,10877],{"class":432},[246,10986,10987],{"class":276},"])\n",[246,10989,10990,10993,10995,10998,11001,11004,11007,11010,11012],{"class":248,"line":330},[246,10991,10992],{"class":276},"        retrieved_ids ",[246,10994,1109],{"class":619},[246,10996,10997],{"class":276}," [n.node.metadata[",[246,10999,11000],{"class":432},"\"doc_id\"",[246,11002,11003],{"class":276},"] ",[246,11005,11006],{"class":619},"for",[246,11008,11009],{"class":276}," n ",[246,11011,10969],{"class":619},[246,11013,11014],{"class":276}," nodes[:k]]\n",[246,11016,11017,11019,11022,11024,11026,11028],{"class":248,"line":335},[246,11018,5958],{"class":619},[246,11020,11021],{"class":276}," tc[",[246,11023,10886],{"class":432},[246,11025,11003],{"class":276},[246,11027,10969],{"class":619},[246,11029,11030],{"class":276}," retrieved_ids:\n",[246,11032,11033,11036,11039],{"class":248,"line":341},[246,11034,11035],{"class":276},"            hits ",[246,11037,11038],{"class":619},"+=",[246,11040,11041],{"class":428}," 1\n",[246,11043,11044,11047,11050,11053,11056],{"class":248,"line":349},[246,11045,11046],{"class":619},"    return",[246,11048,11049],{"class":276}," hits ",[246,11051,11052],{"class":619},"\u002F",[246,11054,11055],{"class":428}," len",[246,11057,11058],{"class":276},"(test_cases)\n",[246,11060,11061],{"class":248,"line":357},[246,11062,260],{"emptyLinePlaceholder":259},[246,11064,11065,11068,11070,11073,11076,11078,11080],{"class":248,"line":365},[246,11066,11067],{"class":276},"recall ",[246,11069,1109],{"class":619},[246,11071,11072],{"class":276}," eval_retrieval(query_engine, test_cases, ",[246,11074,11075],{"class":272},"k",[246,11077,1109],{"class":619},[246,11079,10945],{"class":428},[246,11081,10138],{"class":276},[246,11083,11084,11086,11088,11091,11094,11097,11100,11103,11106,11109],{"class":248,"line":373},[246,11085,10732],{"class":428},[246,11087,6538],{"class":276},[246,11089,11090],{"class":619},"f",[246,11092,11093],{"class":432},"\"Recall@5: ",[246,11095,11096],{"class":428},"{",[246,11098,11099],{"class":276},"recall",[246,11101,11102],{"class":619},":.1%",[246,11104,11105],{"class":428},"}",[246,11107,11108],{"class":432},"\"",[246,11110,10138],{"class":276},[406,11112,11113],{"id":11113},"回答质量评估",[17,11115,11116],{},"用 LLM 自动评估回答质量：",[151,11118,11120],{"className":10028,"code":11119,"language":1051,"meta":157,"style":157},"eval_prompt = f\"\"\"\n请评估以下回答的质量，打分 1-5：\n问题：{question}\n检索到的文档：{retrieved_docs}\n回答：{answer}\n\n评分标准：\n5 — 完全正确，基于文档\n3 — 部分正确，有遗漏\n1 — 错误或编造\n\"\"\"\n",[159,11121,11122,11134,11139,11150,11162,11174,11178,11183,11188,11193,11198],{"__ignoreMap":157},[246,11123,11124,11127,11129,11132],{"class":248,"line":249},[246,11125,11126],{"class":276},"eval_prompt ",[246,11128,1109],{"class":619},[246,11130,11131],{"class":619}," f",[246,11133,10775],{"class":432},[246,11135,11136],{"class":248,"line":256},[246,11137,11138],{"class":432},"请评估以下回答的质量，打分 1-5：\n",[246,11140,11141,11143,11145,11148],{"class":248,"line":263},[246,11142,10808],{"class":432},[246,11144,11096],{"class":428},[246,11146,11147],{"class":276},"question",[246,11149,2169],{"class":428},[246,11151,11152,11155,11157,11160],{"class":248,"line":269},[246,11153,11154],{"class":432},"检索到的文档：",[246,11156,11096],{"class":428},[246,11158,11159],{"class":276},"retrieved_docs",[246,11161,2169],{"class":428},[246,11163,11164,11167,11169,11172],{"class":248,"line":280},[246,11165,11166],{"class":432},"回答：",[246,11168,11096],{"class":428},[246,11170,11171],{"class":276},"answer",[246,11173,2169],{"class":428},[246,11175,11176],{"class":248,"line":288},[246,11177,260],{"emptyLinePlaceholder":259},[246,11179,11180],{"class":248,"line":5},[246,11181,11182],{"class":432},"评分标准：\n",[246,11184,11185],{"class":248,"line":300},[246,11186,11187],{"class":432},"5 — 完全正确，基于文档\n",[246,11189,11190],{"class":248,"line":306},[246,11191,11192],{"class":432},"3 — 部分正确，有遗漏\n",[246,11194,11195],{"class":248,"line":314},[246,11196,11197],{"class":432},"1 — 错误或编造\n",[246,11199,11200],{"class":248,"line":322},[246,11201,10775],{"class":432},[13,11203,11204],{"id":11204},"常见问题与优化",[406,11206,11208],{"id":11207},"问题-1检索不到相关文档","问题 1：检索不到相关文档",[17,11210,11211,11213],{},[147,11212,60],{},"：切分太碎，语义丢失。",[17,11215,11216,864],{},[147,11217,11218],{},"解决",[21,11220,11221,11224,11227],{},[24,11222,11223],{},"增大 chunk_size（512 → 1024）",[24,11225,11226],{},"加 chunk_overlap",[24,11228,11229],{},"用 parent-child 切分（检索小块，返回大块）",[406,11231,11233],{"id":11232},"问题-2回答不基于文档幻觉","问题 2：回答不基于文档（幻觉）",[17,11235,11236,864],{},[147,11237,11218],{},[21,11239,11240,11243,11246],{},[24,11241,11242],{},"prompt 强制要求\"只基于文档回答\"",[24,11244,11245],{},"temperature 设 0",[24,11247,11248],{},"检查检索结果是否相关（不相关就回答\"未找到\"）",[406,11250,11252],{"id":11251},"问题-3中文检索效果差","问题 3：中文检索效果差",[17,11254,11255,864],{},[147,11256,11218],{},[21,11258,11259,11262,11265],{},[24,11260,11261],{},"用 BGE 系列中文 Embedding 模型",[24,11263,11264],{},"不要用 OpenAI 的 Embedding（中文效果一般）",[24,11266,11267],{},"加重排序模型",[406,11269,11271],{"id":11270},"问题-4速度慢","问题 4：速度慢",[17,11273,11274,864],{},[147,11275,11218],{},[21,11277,11278,11281,11284,11287],{},[24,11279,11280],{},"Embedding 用 GPU",[24,11282,11283],{},"向量数据库加 HNSW 索引",[24,11285,11286],{},"减少 similarity_top_k（10 → 5）",[24,11288,11289],{},"LLM 用流式输出",[13,11291,11292],{"id":11292},"生产部署清单",[21,11294,11297,11306,11312,11318,11324,11330,11336,11342,11348,11354,11360,11366],{"className":11295},[11296],"contains-task-list",[24,11298,11301,11305],{"className":11299},[11300],"task-list-item",[11302,11303],"input",{"disabled":259,"type":11304},"checkbox"," 文档解析支持 PDF\u002FWord\u002FHTML\u002FMarkdown",[24,11307,11309,11311],{"className":11308},[11300],[11302,11310],{"disabled":259,"type":11304}," 切分策略测试过（chunk_size 调优）",[24,11313,11315,11317],{"className":11314},[11300],[11302,11316],{"disabled":259,"type":11304}," Embedding 模型选定并部署",[24,11319,11321,11323],{"className":11320},[11300],[11302,11322],{"disabled":259,"type":11304}," 向量数据库持久化",[24,11325,11327,11329],{"className":11326},[11300],[11302,11328],{"disabled":259,"type":11304}," 重排序模型集成",[24,11331,11333,11335],{"className":11332},[11300],[11302,11334],{"disabled":259,"type":11304}," LLM prompt 优化（中文 + 防幻觉）",[24,11337,11339,11341],{"className":11338},[11300],[11302,11340],{"disabled":259,"type":11304}," 检索质量评估（Recall@K > 80%）",[24,11343,11345,11347],{"className":11344},[11300],[11302,11346],{"disabled":259,"type":11304}," 回答质量评估（人工抽检）",[24,11349,11351,11353],{"className":11350},[11300],[11302,11352],{"disabled":259,"type":11304}," 流式输出（用户体验）",[24,11355,11357,11359],{"className":11356},[11300],[11302,11358],{"disabled":259,"type":11304}," 缓存层（常见问题缓存回答）",[24,11361,11363,11365],{"className":11362},[11300],[11302,11364],{"disabled":259,"type":11304}," 日志记录（问题 + 检索结果 + 回答）",[24,11367,11369,11371],{"className":11368},[11300],[11302,11370],{"disabled":259,"type":11304}," 限流 + 鉴权",[721,11373,11374],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":157,"searchDepth":263,"depth":263,"links":11376},[11377,11378,11379,11380,11381,11384,11385,11388,11391,11395,11401],{"id":15,"depth":256,"text":15},{"id":9897,"depth":256,"text":9898},{"id":9907,"depth":256,"text":9907},{"id":9993,"depth":256,"text":9994},{"id":10021,"depth":256,"text":10022,"children":11382},[11383],{"id":10151,"depth":263,"text":10151},{"id":10218,"depth":256,"text":10219},{"id":10430,"depth":256,"text":10431,"children":11386},[11387],{"id":10577,"depth":263,"text":10577},{"id":10583,"depth":256,"text":10584,"children":11389},[11390],{"id":10738,"depth":263,"text":10739},{"id":10845,"depth":256,"text":10846,"children":11392},[11393,11394],{"id":10849,"depth":263,"text":10849},{"id":11113,"depth":263,"text":11113},{"id":11204,"depth":256,"text":11204,"children":11396},[11397,11398,11399,11400],{"id":11207,"depth":263,"text":11208},{"id":11232,"depth":263,"text":11233},{"id":11251,"depth":263,"text":11252},{"id":11270,"depth":263,"text":11271},{"id":11292,"depth":256,"text":11292},"\u002Fog\u002Fplaybook\u002Frag-pipeline-build.png","用 LlamaIndex + ChromaDB + GPT-4o 搭一个生产级 RAG 系统——文档切分策略、Embedding 选型、检索优化、重排序、回答生成、评估指标，含完整代码和踩坑记录。",{},"\u002Fplaybook\u002Fonboarding\u002Frag-pipeline-build",[11407,11408,11409],"agent\u002Fplatform\u002Fdify","agent\u002Fplatform\u002Ffastgpt","coding\u002Flocal\u002Follama",{"title":9876,"description":11403},"playbook\u002Fonboarding\u002Frag-pipeline-build",[11413,9932,9951,11414],"RAG","文档问答","iDBgSssiFFBzdFhaAXgu0ePo29Ov3xLYoHWpnnCPo04",{"id":11417,"title":11418,"body":11419,"category":12023,"cover":12024,"description":12025,"extension":242,"meta":12026,"navigation":259,"path":12027,"published":6381,"relatedTools":12028,"seo":12031,"stem":12032,"tags":12033,"updated":6381,"__hash__":12036},"playbook\u002Fplaybook\u002Freview\u002Fai-pr-review-pipeline.md","用 AI Agent 搭一个自动化 PR Review 流水线",{"type":10,"value":11420,"toc":12014},[11421,11423,11434,11436,11442,11446,11449,11469,11559,11564,11568,11571,11577,11838,11842,11845,11903,11909,11911,11914,11974,11976,12011],[13,11422,15],{"id":15},[21,11424,11425,11428,11431],{},[24,11426,11427],{},"团队 5-20 人，PR review 是瓶颈",[24,11429,11430],{},"想让 AI 做第一轮审查，人只看 AI 标记的问题",[24,11432,11433],{},"需要 CI 阻断有严重问题的 PR（而非只评论）",[13,11435,5539],{"id":5539},[151,11437,11440],{"className":11438,"code":11439,"language":156},[154],"PR 提交 → GitHub Actions 触发\n  ├─ CodeRabbit Bot 自动评论（逐行 + 摘要）\n  ├─ Claude Code 自定义规则审查（安全 \u002F 性能 \u002F 规范）\n  └─ 严重问题 → 设置 commit status = failed → 阻断合并\n",[159,11441,11439],{"__ignoreMap":157},[13,11443,11445],{"id":11444},"第一步coderabbit-接入","第一步：CodeRabbit 接入",[17,11447,11448],{},"CodeRabbit 是开箱即用的 GitHub App，装上就自动 review。",[532,11450,11451,11460,11463],{},[24,11452,11453,11454,11459],{},"去 ",[795,11455,11458],{"href":11456,"rel":11457},"https:\u002F\u002Fcoderabbit.ai",[862],"coderabbit.ai"," 安装 GitHub App",[24,11461,11462],{},"选择要 review 的仓库",[24,11464,11465,11466,864],{},"在仓库根目录加 ",[159,11467,11468],{},".coderabbit.yml",[151,11470,11472],{"className":5557,"code":11471,"language":5559,"meta":157,"style":157},"reviews:\n  auto_review:\n    enabled: true\n    drafts: false\n  path_filters:\n    - \"!**\u002F*.lock\"\n    - \"!**\u002Fdist\u002F**\"\n  instructions: |\n    - 用中文评论\n    - 重点关注 SQL 注入、XSS、敏感信息泄露\n    - 不要评论代码风格（用 ESLint 管）\n    - 性能问题只在 O(n²) 以上才报\n",[159,11473,11474,11481,11488,11498,11508,11515,11523,11530,11539,11544,11549,11554],{"__ignoreMap":157},[246,11475,11476,11479],{"class":248,"line":249},[246,11477,11478],{"class":5566},"reviews",[246,11480,5580],{"class":276},[246,11482,11483,11486],{"class":248,"line":256},[246,11484,11485],{"class":5566},"  auto_review",[246,11487,5580],{"class":276},[246,11489,11490,11493,11495],{"class":248,"line":263},[246,11491,11492],{"class":5566},"    enabled",[246,11494,2128],{"class":276},[246,11496,11497],{"class":428},"true\n",[246,11499,11500,11503,11505],{"class":248,"line":269},[246,11501,11502],{"class":5566},"    drafts",[246,11504,2128],{"class":276},[246,11506,11507],{"class":428},"false\n",[246,11509,11510,11513],{"class":248,"line":280},[246,11511,11512],{"class":5566},"  path_filters",[246,11514,5580],{"class":276},[246,11516,11517,11520],{"class":248,"line":288},[246,11518,11519],{"class":276},"    - ",[246,11521,11522],{"class":432},"\"!**\u002F*.lock\"\n",[246,11524,11525,11527],{"class":248,"line":5},[246,11526,11519],{"class":276},[246,11528,11529],{"class":432},"\"!**\u002Fdist\u002F**\"\n",[246,11531,11532,11535,11537],{"class":248,"line":300},[246,11533,11534],{"class":5566},"  instructions",[246,11536,2128],{"class":276},[246,11538,5894],{"class":619},[246,11540,11541],{"class":248,"line":306},[246,11542,11543],{"class":432},"    - 用中文评论\n",[246,11545,11546],{"class":248,"line":314},[246,11547,11548],{"class":432},"    - 重点关注 SQL 注入、XSS、敏感信息泄露\n",[246,11550,11551],{"class":248,"line":322},[246,11552,11553],{"class":432},"    - 不要评论代码风格（用 ESLint 管）\n",[246,11555,11556],{"class":248,"line":330},[246,11557,11558],{"class":432},"    - 性能问题只在 O(n²) 以上才报\n",[532,11560,11561],{"start":269},[24,11562,11563],{},"提交一个 PR 测试，CodeRabbit 会在 30 秒内出评论",[13,11565,11567],{"id":11566},"第二步claude-code-自定义规则","第二步：Claude Code 自定义规则",[17,11569,11570],{},"CodeRabbit 是通用审查，团队特定规范用 Claude Code 补。",[17,11572,11573,11574,864],{},"创建 ",[159,11575,11576],{},".github\u002Fworkflows\u002Fai-review.yml",[151,11578,11580],{"className":5557,"code":11579,"language":5559,"meta":157,"style":157},"name: AI Review\non:\n  pull_request:\n    types: [opened, synchronize]\n\njobs:\n  claude-review:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Get changed files\n        id: changed\n        run: |\n          files=$(git diff --name-only ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }})\n          echo \"files=$files\" >> $GITHUB_OUTPUT\n\n      - name: Claude Code Review\n        uses: anthropics\u002Fclaude-code-action@v1\n        with:\n          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}\n          prompt: |\n            审查以下文件的改动，重点关注：\n            1. 是否有未处理的 Promise rejection\n            2. 是否有 SQL 拼接（而非参数化查询）\n            3. 是否有 console.log 遗留在生产代码中\n            4. 是否有 hardcoded 密钥 \u002F token\n\n            输出格式：\n            - 🔴 严重问题（必须修复）：文件:行号 + 原因\n            - 🟡 建议（可选）：文件:行号 + 建议\n            - ✅ 没问题的文件不用提\n\n            改动的文件：\n            ${{ steps.changed.outputs.files }}\n",[159,11581,11582,11591,11597,11604,11621,11625,11631,11638,11646,11652,11662,11668,11678,11682,11693,11703,11711,11716,11721,11725,11736,11744,11750,11758,11766,11771,11776,11781,11786,11792,11797,11803,11809,11815,11821,11826,11832],{"__ignoreMap":157},[246,11583,11584,11586,11588],{"class":248,"line":249},[246,11585,5567],{"class":5566},[246,11587,2128],{"class":276},[246,11589,11590],{"class":432},"AI Review\n",[246,11592,11593,11595],{"class":248,"line":256},[246,11594,5577],{"class":428},[246,11596,5580],{"class":276},[246,11598,11599,11602],{"class":248,"line":263},[246,11600,11601],{"class":5566},"  pull_request",[246,11603,5580],{"class":276},[246,11605,11606,11609,11611,11614,11616,11619],{"class":248,"line":269},[246,11607,11608],{"class":5566},"    types",[246,11610,2142],{"class":276},[246,11612,11613],{"class":432},"opened",[246,11615,2148],{"class":276},[246,11617,11618],{"class":432},"synchronize",[246,11620,2154],{"class":276},[246,11622,11623],{"class":248,"line":280},[246,11624,260],{"emptyLinePlaceholder":259},[246,11626,11627,11629],{"class":248,"line":288},[246,11628,5608],{"class":5566},[246,11630,5580],{"class":276},[246,11632,11633,11636],{"class":248,"line":5},[246,11634,11635],{"class":5566},"  claude-review",[246,11637,5580],{"class":276},[246,11639,11640,11642,11644],{"class":248,"line":300},[246,11641,5622],{"class":5566},[246,11643,2128],{"class":276},[246,11645,5627],{"class":432},[246,11647,11648,11650],{"class":248,"line":306},[246,11649,5658],{"class":5566},[246,11651,5580],{"class":276},[246,11653,11654,11656,11658,11660],{"class":248,"line":314},[246,11655,5665],{"class":276},[246,11657,5668],{"class":5566},[246,11659,2128],{"class":276},[246,11661,5673],{"class":432},[246,11663,11664,11666],{"class":248,"line":322},[246,11665,5689],{"class":5566},[246,11667,5580],{"class":276},[246,11669,11670,11673,11675],{"class":248,"line":330},[246,11671,11672],{"class":5566},"          fetch-depth",[246,11674,2128],{"class":276},[246,11676,11677],{"class":428},"0\n",[246,11679,11680],{"class":248,"line":335},[246,11681,260],{"emptyLinePlaceholder":259},[246,11683,11684,11686,11688,11690],{"class":248,"line":341},[246,11685,5665],{"class":276},[246,11687,5567],{"class":5566},[246,11689,2128],{"class":276},[246,11691,11692],{"class":432},"Get changed files\n",[246,11694,11695,11698,11700],{"class":248,"line":349},[246,11696,11697],{"class":5566},"        id",[246,11699,2128],{"class":276},[246,11701,11702],{"class":432},"changed\n",[246,11704,11705,11707,11709],{"class":248,"line":357},[246,11706,5760],{"class":5566},[246,11708,2128],{"class":276},[246,11710,5894],{"class":619},[246,11712,11713],{"class":248,"line":365},[246,11714,11715],{"class":432},"          files=$(git diff --name-only ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }})\n",[246,11717,11718],{"class":248,"line":373},[246,11719,11720],{"class":432},"          echo \"files=$files\" >> $GITHUB_OUTPUT\n",[246,11722,11723],{"class":248,"line":378},[246,11724,260],{"emptyLinePlaceholder":259},[246,11726,11727,11729,11731,11733],{"class":248,"line":384},[246,11728,5665],{"class":276},[246,11730,5567],{"class":5566},[246,11732,2128],{"class":276},[246,11734,11735],{"class":432},"Claude Code Review\n",[246,11737,11738,11740,11742],{"class":248,"line":392},[246,11739,5863],{"class":5566},[246,11741,2128],{"class":276},[246,11743,5868],{"class":432},[246,11745,11746,11748],{"class":248,"line":4550},[246,11747,5689],{"class":5566},[246,11749,5580],{"class":276},[246,11751,11752,11754,11756],{"class":248,"line":4556},[246,11753,5879],{"class":5566},[246,11755,2128],{"class":276},[246,11757,5884],{"class":432},[246,11759,11760,11762,11764],{"class":248,"line":5792},[246,11761,5889],{"class":5566},[246,11763,2128],{"class":276},[246,11765,5894],{"class":619},[246,11767,11768],{"class":248,"line":5797},[246,11769,11770],{"class":432},"            审查以下文件的改动，重点关注：\n",[246,11772,11773],{"class":248,"line":5809},[246,11774,11775],{"class":432},"            1. 是否有未处理的 Promise rejection\n",[246,11777,11778],{"class":248,"line":5819},[246,11779,11780],{"class":432},"            2. 是否有 SQL 拼接（而非参数化查询）\n",[246,11782,11783],{"class":248,"line":5827},[246,11784,11785],{"class":432},"            3. 是否有 console.log 遗留在生产代码中\n",[246,11787,11789],{"class":248,"line":11788},29,[246,11790,11791],{"class":432},"            4. 是否有 hardcoded 密钥 \u002F token\n",[246,11793,11795],{"class":248,"line":11794},30,[246,11796,260],{"emptyLinePlaceholder":259},[246,11798,11800],{"class":248,"line":11799},31,[246,11801,11802],{"class":432},"            输出格式：\n",[246,11804,11806],{"class":248,"line":11805},32,[246,11807,11808],{"class":432},"            - 🔴 严重问题（必须修复）：文件:行号 + 原因\n",[246,11810,11812],{"class":248,"line":11811},33,[246,11813,11814],{"class":432},"            - 🟡 建议（可选）：文件:行号 + 建议\n",[246,11816,11818],{"class":248,"line":11817},34,[246,11819,11820],{"class":432},"            - ✅ 没问题的文件不用提\n",[246,11822,11824],{"class":248,"line":11823},35,[246,11825,260],{"emptyLinePlaceholder":259},[246,11827,11829],{"class":248,"line":11828},36,[246,11830,11831],{"class":432},"            改动的文件：\n",[246,11833,11835],{"class":248,"line":11834},37,[246,11836,11837],{"class":432},"            ${{ steps.changed.outputs.files }}\n",[13,11839,11841],{"id":11840},"第三步严重问题阻断合并","第三步：严重问题阻断合并",[17,11843,11844],{},"在 review workflow 末尾加 commit status：",[151,11846,11848],{"className":5557,"code":11847,"language":5559,"meta":157,"style":157},"      - name: Set check status\n        if: steps.claude-review.outputs.severity == 'critical'\n        run: |\n          curl -X POST \\\n            -H \"Authorization: token ${{ secrets.GITHUB_TOKEN }}\" \\\n            -H \"Accept: application\u002Fvnd.github.v3+json\" \\\n            https:\u002F\u002Fapi.github.com\u002Frepos\u002F${{ github.repository }}\u002Fstatuses\u002F${{ github.event.pull_request.head.sha }} \\\n            -d '{\"state\": \"failure\", \"context\": \"AI Review \u002F Critical Issues\", \"description\": \"发现严重问题，请修复后重新提交\"}'\n",[159,11849,11850,11861,11870,11878,11883,11888,11893,11898],{"__ignoreMap":157},[246,11851,11852,11854,11856,11858],{"class":248,"line":249},[246,11853,5665],{"class":276},[246,11855,5567],{"class":5566},[246,11857,2128],{"class":276},[246,11859,11860],{"class":432},"Set check status\n",[246,11862,11863,11865,11867],{"class":248,"line":256},[246,11864,5958],{"class":5566},[246,11866,2128],{"class":276},[246,11868,11869],{"class":432},"steps.claude-review.outputs.severity == 'critical'\n",[246,11871,11872,11874,11876],{"class":248,"line":263},[246,11873,5760],{"class":5566},[246,11875,2128],{"class":276},[246,11877,5894],{"class":619},[246,11879,11880],{"class":248,"line":269},[246,11881,11882],{"class":432},"          curl -X POST \\\n",[246,11884,11885],{"class":248,"line":280},[246,11886,11887],{"class":432},"            -H \"Authorization: token ${{ secrets.GITHUB_TOKEN }}\" \\\n",[246,11889,11890],{"class":248,"line":288},[246,11891,11892],{"class":432},"            -H \"Accept: application\u002Fvnd.github.v3+json\" \\\n",[246,11894,11895],{"class":248,"line":5},[246,11896,11897],{"class":432},"            https:\u002F\u002Fapi.github.com\u002Frepos\u002F${{ github.repository }}\u002Fstatuses\u002F${{ github.event.pull_request.head.sha }} \\\n",[246,11899,11900],{"class":248,"line":300},[246,11901,11902],{"class":432},"            -d '{\"state\": \"failure\", \"context\": \"AI Review \u002F Critical Issues\", \"description\": \"发现严重问题，请修复后重新提交\"}'\n",[17,11904,11905,11906,3725],{},"在 GitHub 仓库设置 → Branch protection → Require status checks → 添加 ",[159,11907,11908],{},"AI Review \u002F Critical Issues",[13,11910,6253],{"id":6253},[17,11912,11913],{},"上线一个月后：",[40,11915,11916,11928],{},[43,11917,11918],{},[46,11919,11920,11922,11925],{},[49,11921,4879],{},[49,11923,11924],{},"之前",[49,11926,11927],{},"之后",[62,11929,11930,11941,11952,11963],{},[46,11931,11932,11935,11938],{},[67,11933,11934],{},"PR 平均 review 时间",[67,11936,11937],{},"8 小时",[67,11939,11940],{},"2 小时",[46,11942,11943,11946,11949],{},[67,11944,11945],{},"人工 review 评论数",[67,11947,11948],{},"15 条\u002FPR",[67,11950,11951],{},"5 条\u002FPR",[46,11953,11954,11957,11960],{},[67,11955,11956],{},"合并后发现的 bug",[67,11958,11959],{},"3 个\u002F周",[67,11961,11962],{},"1 个\u002F周",[46,11964,11965,11968,11971],{},[67,11966,11967],{},"开发者满意度",[67,11969,11970],{},"6\u002F10",[67,11972,11973],{},"8\u002F10",[13,11975,6319],{"id":6319},[532,11977,11978,11984,11990,11996,12002],{},[24,11979,11980,11983],{},[147,11981,11982],{},"CodeRabbit 免费版限制","：开源仓库免费，私有仓库 $24\u002Fseat\u002Fmo。小团队可只给核心仓库开。",[24,11985,11986,11989],{},[147,11987,11988],{},"Claude Code API 成本","：每个 PR 约 $0.1-0.5（取决于改动量），月费 $50 以内可控。",[24,11991,11992,11995],{},[147,11993,11994],{},"不要让 AI 阻断全部问题","——只阻断安全类严重问题（SQL 注入、密钥泄露），否则开发者会绕过。",[24,11997,11998,12001],{},[147,11999,12000],{},"path_filters 很重要","——不加的话会 review lock 文件、dist 目录，浪费 API 调用。",[24,12003,12004,12010],{},[147,12005,12006,12007],{},"Claude Code Action 需要 ",[159,12008,12009],{},"fetch-depth: 0","——否则 git diff 拿不到完整历史。",[721,12012,12013],{},"html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":157,"searchDepth":263,"depth":263,"links":12015},[12016,12017,12018,12019,12020,12021,12022],{"id":15,"depth":256,"text":15},{"id":5539,"depth":256,"text":5539},{"id":11444,"depth":256,"text":11445},{"id":11566,"depth":256,"text":11567},{"id":11840,"depth":256,"text":11841},{"id":6253,"depth":256,"text":6253},{"id":6319,"depth":256,"text":6319},"review","\u002Fog\u002Fplaybook\u002Fai-pr-review.png","从零用 CodeRabbit + Claude Code + GitHub Actions 搭一条自动化 PR Review 流水线：提交 PR → AI 审查代码 → 评论区出报告 → 严重问题阻断合并。含完整配置和踩坑记录。",{},"\u002Fplaybook\u002Freview\u002Fai-pr-review-pipeline",[12029,747,12030],"coding\u002Freview\u002Fcoderabbit","coding\u002Freview\u002Fgreptile",{"title":11418,"description":12025},"playbook\u002Freview\u002Fai-pr-review-pipeline",[12034,6390,12035,6391],"PR Review","CodeRabbit","SsbL8A6w0qdO6rgCdogrJAPlq2NrJdkxw6n5D6zV5is",{"id":12038,"title":12039,"body":12040,"category":12023,"cover":12528,"description":12529,"extension":242,"meta":12530,"navigation":259,"path":12531,"published":12532,"relatedTools":12533,"seo":12535,"stem":12536,"tags":12537,"updated":12540,"__hash__":12541},"playbook\u002Fplaybook\u002Freview\u002Fai-code-review-workflow.md","AI 做 PR Review：开发者的 5 倍速 review 工作流",{"type":10,"value":12041,"toc":12504},[12042,12045,12056,12065,12068,12087,12091,12095,12153,12156,12160,12166,12172,12176,12179,12184,12190,12194,12200,12209,12213,12219,12223,12229,12233,12239,12245,12248,12251,12325,12336,12339,12365,12368,12372,12379,12383,12390,12394,12404,12408,12415,12417,12421,12424,12485,12488,12490,12501],[13,12043,12044],{"id":12044},"谁需要这套流程",[21,12046,12047,12050,12053],{},[24,12048,12049],{},"团队 leader \u002F staff engineer，每天 review 5-10 个 PR",[24,12051,12052],{},"独立维护者，开源项目 PR 多但人手少",[24,12054,12055],{},"想给自己的 PR 自查的开发者",[17,12057,12058,12061,12062,3725],{},[147,12059,12060],{},"核心承诺","：让 AI 做\"第一道筛\"——把明显问题 + 一致性问题先过一遍，",[147,12063,12064],{},"人脑只看 AI 标出来的高价值地方",[13,12066,12067],{"id":12067},"不要做什么",[21,12069,12070,12077,12084],{},[24,12071,12072,12073,12076],{},"❌ 让 AI 写 ",[159,12074,12075],{},"LGTM"," 然后 merge——AI 会把烂代码 review 通过",[24,12078,12079,12080,12083],{},"❌ 让 AI ",[147,12081,12082],{},"决定","合不合并——AI 只做建议，决策权在人",[24,12085,12086],{},"❌ 把 PR 全文丢给 ChatGPT 网页版让它\"看看\"——上下文不够，结论不可信",[13,12088,12090],{"id":12089},"工作流4-步法","工作流：4 步法",[406,12092,12094],{"id":12093},"step-1-准备-review-上下文2-min","Step 1 — 准备 review 上下文（2 min）",[151,12096,12098],{"className":415,"code":12097,"language":417,"meta":157,"style":157},"# 在 PR 分支\ngit fetch origin main\ngit diff main...HEAD > \u002Ftmp\u002Fpr.diff\ngit log main..HEAD --pretty=format:'%h %s%n%b' > \u002Ftmp\u002Fpr.commits\n",[159,12099,12100,12105,12118,12132],{"__ignoreMap":157},[246,12101,12102],{"class":248,"line":249},[246,12103,12104],{"class":607},"# 在 PR 分支\n",[246,12106,12107,12109,12112,12115],{"class":248,"line":256},[246,12108,613],{"class":424},[246,12110,12111],{"class":432}," fetch",[246,12113,12114],{"class":432}," origin",[246,12116,12117],{"class":432}," main\n",[246,12119,12120,12122,12124,12127,12129],{"class":248,"line":263},[246,12121,613],{"class":424},[246,12123,616],{"class":432},[246,12125,12126],{"class":432}," main...HEAD",[246,12128,620],{"class":619},[246,12130,12131],{"class":432}," \u002Ftmp\u002Fpr.diff\n",[246,12133,12134,12136,12139,12142,12145,12148,12150],{"class":248,"line":269},[246,12135,613],{"class":424},[246,12137,12138],{"class":432}," log",[246,12140,12141],{"class":432}," main..HEAD",[246,12143,12144],{"class":428}," --pretty=format:",[246,12146,12147],{"class":432},"'%h %s%n%b'",[246,12149,620],{"class":619},[246,12151,12152],{"class":432}," \u002Ftmp\u002Fpr.commits\n",[17,12154,12155],{},"进入项目根，开 Claude Code 或 Cursor。",[406,12157,12159],{"id":12158},"step-2-让-ai-分类改动5-min","Step 2 — 让 AI 分类改动（5 min）",[151,12161,12164],{"className":12162,"code":12163,"language":156,"meta":157},[154],"请分析本分支相对 main 的改动（git diff main...HEAD），按类型归类：\n\nA. 业务逻辑改动（新功能 \u002F bug 修复 \u002F 行为变更）\nB. 重构（不改行为）\nC. 测试改动\nD. 配置 \u002F 依赖\nE. 文档\n\n输出 markdown 表格：类型 | 文件 | 改动摘要（1 句）\n\n特别标出：\n- 是否有\"业务逻辑改动\"但没有对应测试\n- 是否有\"重构\"但行为可能被无意改变\n- 是否有任何 secret \u002F API key 出现在 diff 里\n",[159,12165,12163],{"__ignoreMap":157},[17,12167,12168,12171],{},[147,12169,12170],{},"这一步的产出物极其有价值","——你瞬间知道这个 PR 的盘子有多大、风险点在哪。",[406,12173,12175],{"id":12174},"step-3-深度审视10-30-min","Step 3 — 深度审视（10-30 min）",[17,12177,12178],{},"针对 Step 2 标出的高风险项，挨个深问：",[12180,12181,12183],"h4",{"id":12182},"_31-业务逻辑深查","3.1 业务逻辑深查",[151,12185,12188],{"className":12186,"code":12187,"language":156,"meta":157},[154],"对于改动【文件 X 第 Y-Z 行】，请回答：\n\n1. 改动前的行为是什么？（读 git blame \u002F git show HEAD~1）\n2. 改动后的行为是什么？\n3. 这两个行为的差异是否符合 commit message \u002F PR description 的承诺？\n4. 有没有 edge case 没考虑？（null \u002F 空数组 \u002F 极大值 \u002F 并发）\n5. 有没有可能影响其他调用方？\n\n每条都要给确凿依据，不要\"我觉得\"。\n",[159,12189,12187],{"__ignoreMap":157},[12180,12191,12193],{"id":12192},"_32-一致性扫描","3.2 一致性扫描",[151,12195,12198],{"className":12196,"code":12197,"language":156,"meta":157},[154],"请扫描整个项目，看本 PR 的改动有没有\"漏改\"：\n\n- 如果 PR 改了某个函数的签名，所有调用方都改了吗？\n- 如果 PR 加了新的常量，类似的常量定义是否同步更新？\n- 如果 PR 改了某个文件的 pattern，类似文件是否需要同样改？\n\n逐条列出\"可能漏改但 PR 里没改\"的地方，给文件:行号。\n",[159,12199,12197],{"__ignoreMap":157},[17,12201,12202,12205,12206,3725],{},[147,12203,12204],{},"这是 AI 比人类强的地方","——人类做 PR review 容易盯着 diff 看，",[147,12207,12208],{},"AI 会去看 diff 之外的地方",[12180,12210,12212],{"id":12211},"_33-测试-review","3.3 测试 review",[151,12214,12217],{"className":12215,"code":12216,"language":156,"meta":157},[154],"对于本 PR 中的测试改动 + 新增测试，请评估：\n\n1. 测试是否真的覆盖了\"业务逻辑改动\"？还是只覆盖了 happy path？\n2. 测试的断言是否够强？（不要只 assert 不抛异常）\n3. 有没有\"修测试让它通过\"的痕迹（注释掉的 assert \u002F 改宽容的 matcher）？\n4. 哪些 edge case 没被测到？\n\n输出：测试覆盖度评估 + 建议补的测试用例（伪代码）\n",[159,12218,12216],{"__ignoreMap":157},[12180,12220,12222],{"id":12221},"_34-风险与回滚","3.4 风险与回滚",[151,12224,12227],{"className":12225,"code":12226,"language":156,"meta":157},[154],"假设这个 PR 合并到生产后出了严重问题，回滚成本如何？\n\n- 单纯 revert 这个 commit 能恢复吗？\n- 有没有不可逆的改动（DB 迁移 \u002F 数据格式变更 \u002F 删了字段）？\n- 有没有\"客户端已经发了新版本，服务端不能简单回滚\"的耦合？\n\n如果回滚成本高，建议拆 PR 或加 feature flag。\n",[159,12228,12226],{"__ignoreMap":157},[406,12230,12232],{"id":12231},"step-4-整合-review-反馈5-min","Step 4 — 整合 review 反馈（5 min）",[151,12234,12237],{"className":12235,"code":12236,"language":156,"meta":157},[154],"请整合前面 3.1-3.4 的所有发现，输出一份最终 review 评论，格式：\n\n## ✅ 看起来没问题的部分\n（简短列出）\n\n## ⚠️ 需要 PR author 回应的问题\n（每条带文件:行号 + 具体问题）\n\n## 🛑 阻塞合并的问题\n（如有，必须解决才能合）\n\n## 💡 建议（非阻塞）\n（可选优化）\n\n语气专业、具体，不要客套话。\n",[159,12238,12236],{"__ignoreMap":157},[17,12240,12241,12244],{},[147,12242,12243],{},"人工 review 这份 markdown","——70% 的内容你直接 copy 到 PR 评论区。剩下 30% 自己再补充判断和上下文。",[12246,12247],"hr",{},[13,12249,12250],{"id":12250},"实战时间分配",[40,12252,12253,12266],{},[43,12254,12255],{},[46,12256,12257,12260,12263],{},[49,12258,12259],{},"步骤",[49,12261,12262],{},"耗时",[49,12264,12265],{},"谁做",[62,12267,12268,12279,12290,12301,12311],{},[46,12269,12270,12273,12276],{},[67,12271,12272],{},"1 准备",[67,12274,12275],{},"2 min",[67,12277,12278],{},"人",[46,12280,12281,12284,12287],{},[67,12282,12283],{},"2 分类",[67,12285,12286],{},"5 min",[67,12288,12289],{},"AI",[46,12291,12292,12295,12298],{},[67,12293,12294],{},"3 深查",[67,12296,12297],{},"10-30 min",[67,12299,12300],{},"AI 主导，人 review",[46,12302,12303,12306,12308],{},[67,12304,12305],{},"4 整合",[67,12307,12286],{},[67,12309,12310],{},"AI 输出，人调整",[46,12312,12313,12318,12323],{},[67,12314,12315],{},[147,12316,12317],{},"合计",[67,12319,12320],{},[147,12321,12322],{},"~30 min \u002F PR",[67,12324],{},[17,12326,12327,12328,12331,12332,12335],{},"对比纯人工 review 一个中型 PR（~500 行 diff）通常 60-90 min，",[147,12329,12330],{},"省一半时间","，且",[147,12333,12334],{},"漏掉问题更少","（AI 看的范围比人广）。",[13,12337,12338],{"id":12338},"工具选择",[21,12340,12341,12346,12352,12358],{},[24,12342,12343,12345],{},[147,12344,72],{}," ← 首选。能跑命令读 git history，做\"全局一致性扫描\"最强",[24,12347,12348,12351],{},[147,12349,12350],{},"Cursor + @codebase"," ← 中型项目够用，便宜",[24,12353,12354,12357],{},[147,12355,12356],{},"Augment"," ← 团队场景，原生集成 PR 流程",[24,12359,12360,12361,12364],{},"ChatGPT 网页版 ← ",[147,12362,12363],{},"不推荐","，上下文不够",[13,12366,12367],{"id":12367},"踩坑",[406,12369,12371],{"id":12370},"_1-不要给-ai-pr-description作为唯一上下文","1. 不要给 AI \"PR description\"作为唯一上下文",[17,12373,12374,12375,12378],{},"PR description 是作者自己写的，",[147,12376,12377],{},"不一定准","。让 AI 自己读 diff，不要被 description 带偏。",[406,12380,12382],{"id":12381},"_2-警惕-ai-的看起来-lgtm","2. 警惕 AI 的\"看起来 LGTM\"",[17,12384,12385,12386,12389],{},"AI 倾向于温和。如果它说\"看起来没问题\"，",[147,12387,12388],{},"强制让它给出 3 条具体担忧","——总能挖出来。",[406,12391,12393],{"id":12392},"_3-别完全替代人脑","3. 别完全替代人脑",[17,12395,12396,12397,12400,12401,3725],{},"AI 的 review 是",[147,12398,12399],{},"第一道筛","，不是终审。",[147,12402,12403],{},"关键判断（架构是否合理 \u002F 是否符合产品方向）只能人做",[406,12405,12407],{"id":12406},"_4-注意-token-预算","4. 注意 token 预算",[17,12409,12410,12411,12414],{},"大 PR review 容易烧 $1-5。",[147,12412,12413],{},"对小 PR（\u003C 50 行）直接人脑 review","，不值得开 AI。",[12246,12416],{},[13,12418,12420],{"id":12419},"bonus把这套做成-git-hook","Bonus：把这套做成 git hook",[17,12422,12423],{},"把 Step 2-3 写成一个 shell 脚本 + Claude Code prompt 文件，挂在 PR 创建\u002F更新时自动跑：",[151,12425,12427],{"className":415,"code":12426,"language":417,"meta":157,"style":157},"# .github\u002Fhooks\u002Fpr-review.sh （示意）\n#!\u002Fbin\u002Fbash\ngit diff main...HEAD > \u002Ftmp\u002Fpr.diff\nclaude-code --prompt-file=.github\u002Fhooks\u002Freview-prompt.md \\\n            --output-file=\u002Ftmp\u002Freview.md\ngh pr comment $PR_NUMBER --body-file \u002Ftmp\u002Freview.md\n",[159,12428,12429,12434,12439,12451,12461,12466],{"__ignoreMap":157},[246,12430,12431],{"class":248,"line":249},[246,12432,12433],{"class":607},"# .github\u002Fhooks\u002Fpr-review.sh （示意）\n",[246,12435,12436],{"class":248,"line":256},[246,12437,12438],{"class":607},"#!\u002Fbin\u002Fbash\n",[246,12440,12441,12443,12445,12447,12449],{"class":248,"line":263},[246,12442,613],{"class":424},[246,12444,616],{"class":432},[246,12446,12126],{"class":432},[246,12448,620],{"class":619},[246,12450,12131],{"class":432},[246,12452,12453,12456,12459],{"class":248,"line":269},[246,12454,12455],{"class":424},"claude-code",[246,12457,12458],{"class":428}," --prompt-file=.github\u002Fhooks\u002Freview-prompt.md",[246,12460,902],{"class":428},[246,12462,12463],{"class":248,"line":280},[246,12464,12465],{"class":428},"            --output-file=\u002Ftmp\u002Freview.md\n",[246,12467,12468,12470,12473,12476,12479,12482],{"class":248,"line":288},[246,12469,4028],{"class":424},[246,12471,12472],{"class":432}," pr",[246,12474,12475],{"class":432}," comment",[246,12477,12478],{"class":276}," $PR_NUMBER ",[246,12480,12481],{"class":428},"--body-file",[246,12483,12484],{"class":432}," \u002Ftmp\u002Freview.md\n",[17,12486,12487],{},"完整 GitHub Actions 工作流即将整理上线。",[12246,12489],{},[17,12491,12492,12493,4856,12497,3725],{},"继续阅读：",[795,12494,12496],{"href":12495},"\u002Fplaybook\u002Fonboarding\u002Flegacy-codebase-onboarding","陌生项目 onboarding 工作流",[795,12498,12500],{"href":12499},"\u002Fplaybook\u002Frefactor\u002Flarge-refactor-with-ai-agent","大型重构工作流",[721,12502,12503],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":157,"searchDepth":263,"depth":263,"links":12505},[12506,12507,12508,12519,12520,12521,12527],{"id":12044,"depth":256,"text":12044},{"id":12067,"depth":256,"text":12067},{"id":12089,"depth":256,"text":12090,"children":12509},[12510,12511,12512,12518],{"id":12093,"depth":263,"text":12094},{"id":12158,"depth":263,"text":12159},{"id":12174,"depth":263,"text":12175,"children":12513},[12514,12515,12516,12517],{"id":12182,"depth":269,"text":12183},{"id":12192,"depth":269,"text":12193},{"id":12211,"depth":269,"text":12212},{"id":12221,"depth":269,"text":12222},{"id":12231,"depth":263,"text":12232},{"id":12250,"depth":256,"text":12250},{"id":12338,"depth":256,"text":12338},{"id":12367,"depth":256,"text":12367,"children":12522},[12523,12524,12525,12526],{"id":12370,"depth":263,"text":12371},{"id":12381,"depth":263,"text":12382},{"id":12392,"depth":263,"text":12393},{"id":12406,"depth":263,"text":12407},{"id":12419,"depth":256,"text":12420},"\u002Fog\u002Fplaybook\u002Fai-code-review.png","用 Claude Code \u002F Cursor 给 PR 做第一道 review 的标准化工作流：风险扫描、命名一致性、测试覆盖、文档同步。",{},"\u002Fplaybook\u002Freview\u002Fai-code-review-workflow","2026-06-01",[747,7484,12534],"coding\u002Fagent\u002Faugment",{"title":12039,"description":12529},"playbook\u002Freview\u002Fai-code-review-workflow",[12538,12539,72,6445],"code review","PR","2026-06-15","t09WfO0oBlGLWe6k_9Q9vCP5UiVK2HxMSQqK1Ipa43Q",{"id":12543,"title":12544,"body":12545,"category":13159,"cover":13160,"description":13161,"extension":242,"meta":13162,"navigation":259,"path":12499,"published":13163,"relatedTools":13164,"seo":13166,"stem":13167,"tags":13168,"updated":13171,"__hash__":13172},"playbook\u002Fplaybook\u002Frefactor\u002Flarge-refactor-with-ai-agent.md","用 AI Agent 跑大型重构：不翻车工作流",{"type":10,"value":12546,"toc":13132},[12547,12549,12556,12573,12579,12581,12584,12591,12594,12597,12614,12617,12624,12631,12651,12657,12664,12671,12673,12677,12681,12684,12690,12700,12704,12710,12716,12720,12753,12761,12824,12829,12833,12836,12842,12847,12867,12871,12874,12923,12929,12932,12936,12960,12962,12964,13025,13027,13031,13038,13042,13048,13051,13060,13064,13071,13075,13081,13083,13087,13094,13113,13122,13124,13129],[13,12548,15],{"id":15},[17,12550,12551,12552,12555],{},"任何",[147,12553,12554],{},"符合下列任意一条","的重构都属于\"大型重构\"：",[21,12557,12558,12561,12564,12567,12570],{},[24,12559,12560],{},"影响超过 30 个文件",[24,12562,12563],{},"涉及 API 签名变更（调用方需要同步改）",[24,12565,12566],{},"涉及数据格式变更（DB schema \u002F 序列化协议）",[24,12568,12569],{},"跨模块、跨进程",[24,12571,12572],{},"需要保留向后兼容",[17,12574,12575,12578],{},[147,12576,12577],{},"这类任务用 IDE 手改太慢，让 AI 一次性跑完又容易翻车。"," 本工作流的目标是：让 AI 跑大头，但每一步可验证、可回滚。",[12246,12580],{},[13,12582,12583],{"id":12583},"核心原则",[406,12585,12587,12588],{"id":12586},"_1-任务必须拆","1. ",[147,12589,12590],{},"任务必须拆",[17,12592,12593],{},"不要给 AI：\"把整个项目从 Pinia 1 迁到 Pinia 2\"。",[17,12595,12596],{},"要给 AI：",[21,12598,12599,12602,12605,12608,12611],{},[24,12600,12601],{},"Step A: 找出所有用 Pinia 1 API 的文件，输出清单",[24,12603,12604],{},"Step B: 改第 1-10 个文件，跑测试",[24,12606,12607],{},"Step C: 改第 11-20 个，跑测试",[24,12609,12610],{},"...",[24,12612,12613],{},"Step Z: 全跑通后删 Pinia 1 依赖",[17,12615,12616],{},"每步独立 commit。",[406,12618,12620,12621],{"id":12619},"_2-每步都有-checkpoint","2. ",[147,12622,12623],{},"每步都有 checkpoint",[17,12625,12626,12627,12630],{},"checkpoint = 一个",[147,12628,12629],{},"可机器验证","的状态。比如：",[21,12632,12633,12639,12644],{},[24,12634,12635,12638],{},[159,12636,12637],{},"pnpm typecheck"," 通过",[24,12640,12641,12638],{},[159,12642,12643],{},"pnpm test",[24,12645,12646,12647,12650],{},"启动 dev server 后 ",[159,12648,12649],{},"curl \u002Fhealth"," 返 200",[17,12652,12653,12656],{},[147,12654,12655],{},"没有 checkpoint 的步骤不要放进工作流","——因为你没法知道它对不对。",[406,12658,12660,12661],{"id":12659},"_3-git-隔离","3. ",[147,12662,12663],{},"git 隔离",[17,12665,12666,12667,12670],{},"每个大任务开独立分支。每个 step 一个 commit。\n",[147,12668,12669],{},"不要让 AI 直接 push 到主干","，永远先 PR。",[12246,12672],{},[13,12674,12676],{"id":12675},"完整工作流6-阶段","完整工作流：6 阶段",[406,12678,12680],{"id":12679},"阶段-1调研人工-ai30-min","阶段 1：调研（人工 + AI，30 min）",[17,12682,12683],{},"让 AI 帮你回答 4 个问题：",[151,12685,12688],{"className":12686,"code":12687,"language":156,"meta":157},[154],"针对【重构目标】，请回答：\n\n1. 影响面：哪些文件会被修改？给出完整列表 + 行数估算\n2. 阻塞依赖：有没有外部库 \u002F API 升级也需要做？\n3. 不可逆操作：有没有数据迁移 \u002F 二进制格式变更？\n4. 测试覆盖：现有测试能 cover 多少？哪些路径无测试？\n\n不要开始改代码，只产出调研报告。\n",[159,12689,12687],{"__ignoreMap":157},[17,12691,12692,12695,12696,12699],{},[147,12693,12694],{},"输出物","：一份 markdown 报告。",[147,12697,12698],{},"人工 review 这份报告再决定是否继续","——很多时候你会发现\"这个重构不该做\"或\"该用别的方案\"。",[406,12701,12703],{"id":12702},"阶段-2拆任务人工-ai20-min","阶段 2：拆任务（人工 + AI，20 min）",[151,12705,12708],{"className":12706,"code":12707,"language":156,"meta":157},[154],"基于调研报告，请把整个重构拆成 N 个 step。每个 step 满足：\n\n- 影响 ≤ 5 个文件\n- 有明确的 checkpoint（typecheck \u002F 测试 \u002F 编译）\n- 每步独立可 commit、可回滚\n- step 之间有依赖时显式标出\n\n输出 markdown 表格：step 编号 | 描述 | 影响文件 | checkpoint | 依赖 step\n",[159,12709,12707],{"__ignoreMap":157},[17,12711,12712,12715],{},[147,12713,12714],{},"人工 review 这份拆解","——如果某 step 影响超过 5 文件，强制再拆。",[406,12717,12719],{"id":12718},"阶段-3建脚手架ai10-min","阶段 3：建脚手架（AI，10 min）",[151,12721,12723],{"className":415,"code":12722,"language":417,"meta":157,"style":157},"git checkout -b refactor\u002Fpinia-2-migration\nmkdir -p .refactor\n# 把拆解后的 task list 存进去\n",[159,12724,12725,12738,12748],{"__ignoreMap":157},[246,12726,12727,12729,12732,12735],{"class":248,"line":249},[246,12728,613],{"class":424},[246,12730,12731],{"class":432}," checkout",[246,12733,12734],{"class":428}," -b",[246,12736,12737],{"class":432}," refactor\u002Fpinia-2-migration\n",[246,12739,12740,12743,12745],{"class":248,"line":256},[246,12741,12742],{"class":424},"mkdir",[246,12744,429],{"class":428},[246,12746,12747],{"class":432}," .refactor\n",[246,12749,12750],{"class":248,"line":263},[246,12751,12752],{"class":607},"# 把拆解后的 task list 存进去\n",[17,12754,12755,864,12758],{},[147,12756,12757],{},"关键文件",[159,12759,12760],{},".refactor\u002FSTATUS.md",[151,12762,12764],{"className":7357,"code":12763,"language":7359,"meta":157,"style":157},"# Pinia 2 Migration Status\n\n- [ ] step-01: 列出所有 Pinia 1 调用点\n- [ ] step-02: 改 stores\u002Fuser.ts + 调用方\n- [ ] step-03: 改 stores\u002Fcart.ts + 调用方\n...\n\n## Checkpoints\n- [ ] all `pnpm typecheck` passes\n- [ ] all `pnpm test` passes\n- [ ] dev server boots\n- [ ] e2e smoke test passes\n",[159,12765,12766,12771,12775,12780,12785,12790,12795,12799,12804,12809,12814,12819],{"__ignoreMap":157},[246,12767,12768],{"class":248,"line":249},[246,12769,12770],{},"# Pinia 2 Migration Status\n",[246,12772,12773],{"class":248,"line":256},[246,12774,260],{"emptyLinePlaceholder":259},[246,12776,12777],{"class":248,"line":263},[246,12778,12779],{},"- [ ] step-01: 列出所有 Pinia 1 调用点\n",[246,12781,12782],{"class":248,"line":269},[246,12783,12784],{},"- [ ] step-02: 改 stores\u002Fuser.ts + 调用方\n",[246,12786,12787],{"class":248,"line":280},[246,12788,12789],{},"- [ ] step-03: 改 stores\u002Fcart.ts + 调用方\n",[246,12791,12792],{"class":248,"line":288},[246,12793,12794],{},"...\n",[246,12796,12797],{"class":248,"line":5},[246,12798,260],{"emptyLinePlaceholder":259},[246,12800,12801],{"class":248,"line":300},[246,12802,12803],{},"## Checkpoints\n",[246,12805,12806],{"class":248,"line":306},[246,12807,12808],{},"- [ ] all `pnpm typecheck` passes\n",[246,12810,12811],{"class":248,"line":314},[246,12812,12813],{},"- [ ] all `pnpm test` passes\n",[246,12815,12816],{"class":248,"line":322},[246,12817,12818],{},"- [ ] dev server boots\n",[246,12820,12821],{"class":248,"line":330},[246,12822,12823],{},"- [ ] e2e smoke test passes\n",[17,12825,12826,3725],{},[147,12827,12828],{},"让 AI 每完成一步就更新这份文件",[406,12830,12832],{"id":12831},"阶段-4执行ai-主导1-n-小时","阶段 4：执行（AI 主导，1-N 小时）",[17,12834,12835],{},"每个 step 用同一个 prompt 模板：",[151,12837,12840],{"className":12838,"code":12839,"language":156,"meta":157},[154],"现在执行 step-{N}：{描述}。\n\n要求：\n1. 只改清单内的文件，不要碰其他文件\n2. 改完后跑 checkpoint：{checkpoint 命令}\n3. 如果 checkpoint 失败，先 debug 失败原因，再决定是修改还是回滚\n4. 成功后：\n   a. 在 .refactor\u002FSTATUS.md 把这一项打勾\n   b. git add 改动 + git commit -m \"refactor(step-{N}): {描述}\"\n5. 不要继续下一步，等我确认\n",[159,12841,12839],{"__ignoreMap":157},[17,12843,12844],{},[147,12845,12846],{},"关键纪律：",[21,12848,12849,12855,12861],{},[24,12850,12851,12854],{},[147,12852,12853],{},"每步 commit","，不要憋一个大 commit",[24,12856,12857,12860],{},[147,12858,12859],{},"每步等人确认","，AI 不要连续跑 5 步——很容易在第 3 步偏轨道但你没发现",[24,12862,12863,12864],{},"如果 step 失败 2 次，",[147,12865,12866],{},"停下来人工介入",[406,12868,12870],{"id":12869},"阶段-5合并验证人工-ai30-min","阶段 5：合并验证（人工 + AI，30 min）",[17,12872,12873],{},"所有 step 完成后：",[151,12875,12877],{"className":415,"code":12876,"language":417,"meta":157,"style":157},"# 1. 跑全套测试\npnpm test\npnpm e2e\n\n# 2. 启动 dev server，手测核心路径\npnpm dev\n\n# 3. 让 AI 做\"自我代码审查\"\n",[159,12878,12879,12884,12891,12898,12902,12907,12914,12918],{"__ignoreMap":157},[246,12880,12881],{"class":248,"line":249},[246,12882,12883],{"class":607},"# 1. 跑全套测试\n",[246,12885,12886,12888],{"class":248,"line":256},[246,12887,5738],{"class":424},[246,12889,12890],{"class":432}," test\n",[246,12892,12893,12895],{"class":248,"line":263},[246,12894,5738],{"class":424},[246,12896,12897],{"class":432}," e2e\n",[246,12899,12900],{"class":248,"line":269},[246,12901,260],{"emptyLinePlaceholder":259},[246,12903,12904],{"class":248,"line":280},[246,12905,12906],{"class":607},"# 2. 启动 dev server，手测核心路径\n",[246,12908,12909,12911],{"class":248,"line":288},[246,12910,5738],{"class":424},[246,12912,12913],{"class":432}," dev\n",[246,12915,12916],{"class":248,"line":5},[246,12917,260],{"emptyLinePlaceholder":259},[246,12919,12920],{"class":248,"line":300},[246,12921,12922],{"class":607},"# 3. 让 AI 做\"自我代码审查\"\n",[151,12924,12927],{"className":12925,"code":12926,"language":156,"meta":157},[154],"请审视本分支相对 main 的所有改动，找出：\n- 不一致：相同模式有没有漏改的地方\n- 风险：有没有可能的运行时错误（null deref、type 转换失败）\n- 兼容：旧代码调用新代码会不会出问题\n- 性能：有没有 N+1 查询、不必要的循环\n\n输出 markdown 报告，每条带文件路径和行号。\n",[159,12928,12926],{"__ignoreMap":157},[17,12930,12931],{},"人工 review 报告，必要时再开新 step 修补。",[406,12933,12935],{"id":12934},"阶段-6发布人工时间不定","阶段 6：发布（人工，时间不定）",[21,12937,12938,12941,12946,12949],{},[24,12939,12940],{},"发 PR，标题写清楚 \"Refactor: ...\" + 影响面摘要",[24,12942,12943],{},[147,12944,12945],{},"PR description 直接贴 .refactor\u002FSTATUS.md 内容",[24,12947,12948],{},"至少一个 reviewer 看",[24,12950,12951,12952,12955,12956,12959],{},"合并后保留 ",[159,12953,12954],{},".refactor\u002F"," 目录在 git 里",[147,12957,12958],{},"作为历史记录","——下次类似重构可参考",[12246,12961],{},[13,12963,12338],{"id":12338},[40,12965,12966,12978],{},[43,12967,12968],{},[46,12969,12970,12973,12976],{},[49,12971,12972],{},"阶段",[49,12974,12975],{},"推荐工具",[49,12977,60],{},[62,12979,12980,12990,13003,13014],{},[46,12981,12982,12985,12987],{},[67,12983,12984],{},"调研 \u002F 拆任务",[67,12986,72],{},[67,12988,12989],{},"自由探索能力强",[46,12991,12992,12995,13001],{},[67,12993,12994],{},"执行 step",[67,12996,12997,13000],{},[147,12998,12999],{},"Windsurf Cascade"," 或 Claude Code",[67,13002,2547],{},[46,13004,13005,13008,13011],{},[67,13006,13007],{},"单步快速改",[67,13009,13010],{},"Cursor Composer",[67,13012,13013],{},"Tab 流畅",[46,13015,13016,13019,13022],{},[67,13017,13018],{},"自我代码审查",[67,13020,13021],{},"Claude Code（独立 session）",[67,13023,13024],{},"切换 context 更客观",[13,13026,12367],{"id":12367},[406,13028,13030],{"id":13029},"_1-不要相信-ai-说我已完成","1. 不要相信 AI 说\"我已完成\"",[17,13032,13033,13034,13037],{},"每步都要",[147,13035,13036],{},"自己跑 checkpoint"," 确认，不能信 AI 的口头报告。",[406,13039,13041],{"id":13040},"_2-别让-ai-改测试","2. 别让 AI 改测试",[17,13043,13044,13045,3725],{},"如果跑测试失败，AI 倾向于\"修测试让它通过\"——这是",[147,13046,13047],{},"最危险的反模式",[17,13049,13050],{},"明确禁止：",[800,13052,13053],{},[17,13054,13055,13056,13059],{},"\"如果测试失败，分析为什么失败。",[147,13057,13058],{},"不允许修改测试文件","——除非测试本身有 bug 且你能在改之前向我证明。\"",[406,13061,13063],{"id":13062},"_3-不要跨大版本改依赖","3. 不要跨大版本改依赖",[17,13065,13066,13067,13070],{},"step 中遇到\"顺便升一下这个库\"的诱惑——",[147,13068,13069],{},"说不","。把依赖升级单独开 PR。",[406,13072,13074],{"id":13073},"_4-注意-token-成本","4. 注意 token 成本",[17,13076,13077,13078,3725],{},"跨 50 文件的重构容易烧掉 $10-50 的 token（Claude Sonnet 4.5）。",[147,13079,13080],{},"先估预算再开始",[12246,13082],{},[13,13084,13086],{"id":13085},"实战案例本站项目从-src-改根级","实战案例：本站项目从 src\u002F 改根级",[17,13088,13089,13090,13093],{},"我们自己用这套工作流把姊妹站 oltools.net 从 ",[159,13091,13092],{},"src\u002F"," 根布局改成 Nuxt 4 标准布局，影响 200+ 文件。",[21,13095,13096,13099,13102,13105,13108],{},[24,13097,13098],{},"调研：30 min",[24,13100,13101],{},"拆任务：拆成 14 个 step",[24,13103,13104],{},"执行：4 小时（Windsurf Cascade，重度人工 review）",[24,13106,13107],{},"合并验证：1 小时",[24,13109,13110],{},[147,13111,13112],{},"零线上事故",[17,13114,13115,13116,13121],{},"完整 commit 历史可看 ",[795,13117,13120],{"href":13118,"rel":13119},"https:\u002F\u002Fgithub.com\u002Faiho\u002Foltools",[862],"oltools.net 仓库","（即将开放）。",[12246,13123],{},[17,13125,12492,13126,3725],{},[795,13127,13128],{"href":12531},"AI 做 PR review 工作流",[721,13130,13131],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":157,"searchDepth":263,"depth":263,"links":13133},[13134,13135,13143,13151,13152,13158],{"id":15,"depth":256,"text":15},{"id":12583,"depth":256,"text":12583,"children":13136},[13137,13139,13141],{"id":12586,"depth":263,"text":13138},"1. 任务必须拆",{"id":12619,"depth":263,"text":13140},"2. 每步都有 checkpoint",{"id":12659,"depth":263,"text":13142},"3. git 隔离",{"id":12675,"depth":256,"text":12676,"children":13144},[13145,13146,13147,13148,13149,13150],{"id":12679,"depth":263,"text":12680},{"id":12702,"depth":263,"text":12703},{"id":12718,"depth":263,"text":12719},{"id":12831,"depth":263,"text":12832},{"id":12869,"depth":263,"text":12870},{"id":12934,"depth":263,"text":12935},{"id":12338,"depth":256,"text":12338},{"id":12367,"depth":256,"text":12367,"children":13153},[13154,13155,13156,13157],{"id":13029,"depth":263,"text":13030},{"id":13040,"depth":263,"text":13041},{"id":13062,"depth":263,"text":13063},{"id":13073,"depth":263,"text":13074},{"id":13085,"depth":256,"text":13086},"refactor","\u002Fog\u002Fplaybook\u002Flarge-refactor.png","跨 50+ 文件的重构任务如何让 AI Agent 安全完成？任务拆解、checkpoint、git 隔离、验证策略与回滚预案的完整 playbook。",{},"2026-05-15",[747,13165,12534],"coding\u002Fide\u002Fwindsurf",{"title":12544,"description":13161},"playbook\u002Frefactor\u002Flarge-refactor-with-ai-agent",[13169,13170,72,1224,6445],"重构","Agent","2026-06-12","wtg_idmRZ3PBBQlCMTaD7GBi9U74mmV8uBlvN5dIArQ",{"id":13174,"title":13175,"body":13176,"category":740,"cover":13614,"description":13615,"extension":242,"meta":13616,"navigation":259,"path":12495,"published":13617,"relatedTools":13618,"seo":13619,"stem":13620,"tags":13621,"updated":13624,"__hash__":13625},"playbook\u002Fplaybook\u002Fonboarding\u002Flegacy-codebase-onboarding.md","用 AI 接手老代码：陌生项目 onboarding 工作流",{"type":10,"value":13177,"toc":13601},[13178,13180,13194,13199,13203,13209,13215,13217,13221,13285,13288,13293,13302,13308,13310,13314,13317,13323,13339,13341,13345,13351,13361,13370,13372,13376,13383,13389,13399,13401,13405,13411,13417,13419,13423,13426,13432,13438,13440,13443,13524,13531,13533,13535,13567,13569,13593,13598],[13,13179,15],{"id":15},[21,13181,13182,13185,13188,13191],{},[24,13183,13184],{},"新人入职，被丢给一个 5 年老项目",[24,13186,13187],{},"接手前同事跑路留下的代码",[24,13189,13190],{},"评估一个开源项目能否用作技术选型",[24,13192,13193],{},"给客户做代码 audit \u002F 接手报价",[17,13195,13196],{},[147,13197,13198],{},"用人脑读两周做的事，AI 协助下 2-4 小时完成 80%。",[13,13200,13202],{"id":13201},"总览六步法","总览：六步法",[151,13204,13207],{"className":13205,"code":13206,"language":156,"meta":157},[154],"1. clone & 准备 → 2. 项目体检 → 3. 架构图 → 4. 核心路径 →\n5. 风险与债务 → 6. 关键问题清单\n",[159,13208,13206],{"__ignoreMap":157},[17,13210,13211,13212,3725],{},"每一步都有",[147,13213,13214],{},"具体 Prompt + 验收标准",[12246,13216],{},[13,13218,13220],{"id":13219},"step-1-clone-与环境准备10-分钟","Step 1 — clone 与环境准备（10 分钟）",[151,13222,13224],{"className":415,"code":13223,"language":417,"meta":157,"style":157},"git clone \u003Crepo>\ncd \u003Crepo>\n# 关键：先让 AI 看 git 历史活跃度\ngit log --since='1 year ago' --pretty=format:'%h %s' | wc -l\n",[159,13225,13226,13243,13255,13260],{"__ignoreMap":157},[246,13227,13228,13230,13233,13235,13238,13241],{"class":248,"line":249},[246,13229,613],{"class":424},[246,13231,13232],{"class":432}," clone",[246,13234,7429],{"class":619},[246,13236,13237],{"class":432},"rep",[246,13239,13240],{"class":276},"o",[246,13242,7438],{"class":619},[246,13244,13245,13247,13249,13251,13253],{"class":248,"line":256},[246,13246,1086],{"class":428},[246,13248,7429],{"class":619},[246,13250,13237],{"class":432},[246,13252,13240],{"class":276},[246,13254,7438],{"class":619},[246,13256,13257],{"class":248,"line":263},[246,13258,13259],{"class":607},"# 关键：先让 AI 看 git 历史活跃度\n",[246,13261,13262,13264,13266,13269,13272,13274,13277,13279,13282],{"class":248,"line":269},[246,13263,613],{"class":424},[246,13265,12138],{"class":432},[246,13267,13268],{"class":428}," --since=",[246,13270,13271],{"class":432},"'1 year ago'",[246,13273,12144],{"class":428},[246,13275,13276],{"class":432},"'%h %s'",[246,13278,2336],{"class":619},[246,13280,13281],{"class":424}," wc",[246,13283,13284],{"class":428}," -l\n",[17,13286,13287],{},"打开 Claude Code 或 Cursor，进入项目目录。",[17,13289,13290,864],{},[147,13291,13292],{},"第一条 Prompt",[800,13294,13295],{},[17,13296,13297,13298,13301],{},"\"请扫描当前目录，告诉我：(1) 这是什么类型的项目；(2) 主要技术栈；(3) 入口文件在哪；(4) 有没有 README \u002F docs。",[147,13299,13300],{},"先不要读源码","，只看 package.json \u002F pyproject.toml \u002F Cargo.toml \u002F go.mod 这类元文件。\"",[17,13303,13304,13307],{},[147,13305,13306],{},"为什么","：先让 AI 建立宏观认知，避免它一上来就被某个文件带偏。",[12246,13309],{},[13,13311,13313],{"id":13312},"step-2-项目体检20-分钟","Step 2 — 项目体检（20 分钟）",[17,13315,13316],{},"让 AI 出一份\"健康报告\"：",[151,13318,13321],{"className":13319,"code":13320,"language":156,"meta":157},[154],"请生成一份项目体检报告，包含：\n\n1. 代码量：按语言\u002F目录分布\n2. 测试覆盖：有没有测试，跑得起来吗，覆盖率多少\n3. 依赖健康：有几个依赖、最旧的几个分别多久没更新\n4. 文档完整度：README \u002F CHANGELOG \u002F CONTRIBUTING \u002F docs\u002F\n5. CI 状态：有 CI 吗，最近一次跑成功了吗\n6. 死代码迹象：明显未使用的文件 \u002F 函数\n\n不要猜测，只报告确凿能看到的事实。每条结论给出依据。\n",[159,13322,13320],{"__ignoreMap":157},[17,13324,13325,13328,13329,4856,13332,4856,13335,13338],{},[147,13326,13327],{},"Claude Code 做这事最强","——它会自己跑 ",[159,13330,13331],{},"find",[159,13333,13334],{},"git log",[159,13336,13337],{},"npm outdated"," 这类命令，给出真凭实据。",[12246,13340],{},[13,13342,13344],{"id":13343},"step-3-架构图30-分钟","Step 3 — 架构图（30 分钟）",[151,13346,13349],{"className":13347,"code":13348,"language":156,"meta":157},[154],"基于刚才的体检，画一张项目架构图（Mermaid 格式）。\n要求：\n- 顶层模块用方框\n- 数据流向用箭头\n- 外部依赖（DB \u002F 第三方 API \u002F 队列）单独标出\n- **如果某个边界你不确定，标 \"?\" 而不是猜**\n\n画完后，用 5-10 句话解释这个架构的核心思路。\n",[159,13350,13348],{"__ignoreMap":157},[17,13352,13353,13356,13357,13360],{},[147,13354,13355],{},"关键技巧","：明确告诉 AI ",[147,13358,13359],{},"\"不确定就标 ?\"","，否则它会编。",[17,13362,13363,13364,13369],{},"把生成的 Mermaid 复制到 ",[795,13365,13368],{"href":13366,"rel":13367},"https:\u002F\u002Fmermaid.live",[862],"mermaid.live"," 验证可视化效果。",[12246,13371],{},[13,13373,13375],{"id":13374},"step-4-找到核心路径30-分钟","Step 4 — 找到\"核心路径\"（30 分钟）",[17,13377,13378,13379,13382],{},"这是 onboarding 最关键的一步。每个项目都有 1-3 条",[147,13380,13381],{},"核心业务路径","——用户最常用的功能链路。把它走通，整个项目就懂一半了。",[151,13384,13387],{"className":13385,"code":13386,"language":156,"meta":157},[154],"请找出本项目的 3 条核心业务路径（按重要性排序）：\n\n每条路径需要回答：\n1. 用户从哪触发（URL \u002F API endpoint \u002F CLI 命令）\n2. 经过哪些关键文件 \u002F 函数\n3. 数据如何流动（DB 读什么、写什么）\n4. 在哪里返回结果\n\n用编号列表给出，每个文件名 + 行号都要确凿。\n",[159,13388,13386],{"__ignoreMap":157},[17,13390,13391,13394,13395,13398],{},[147,13392,13393],{},"验收标准","：你能照着这份路径，",[147,13396,13397],{},"自己手动 trace 一遍而不卡壳","。如果哪一步看不懂，回去问 AI 那一段具体是什么。",[12246,13400],{},[13,13402,13404],{"id":13403},"step-5-风险-技术债清单30-分钟","Step 5 — 风险 + 技术债清单（30 分钟）",[151,13406,13409],{"className":13407,"code":13408,"language":156,"meta":157},[154],"请审视代码库，列出：\n\nA. 高风险代码（运行时容易出问题）\n   - 没有错误处理的 IO \u002F 网络调用\n   - 明显的 race condition \u002F 并发问题\n   - 写死的 secret \u002F API key\n   - SQL 注入 \u002F XSS 风险\n\nB. 技术债（影响开发效率）\n   - 重复的代码 (DRY 违反)\n   - 函数过长（>200 行）\n   - 圈复杂度过高的函数\n   - 循环依赖\n\nC. 维护性差的部分\n   - 完全没注释的关键算法\n   - \"magic number\"\n   - 命名混乱的模块\n\n每条给出文件路径 + 行号，并用 1 句话解释为什么是问题。\n",[159,13410,13408],{"__ignoreMap":157},[17,13412,13413,13416],{},[147,13414,13415],{},"这一步的输出可以直接交给客户\u002F老板","——如果你是接外包、做 audit，这就是付费报告的核心内容。",[12246,13418],{},[13,13420,13422],{"id":13421},"step-6-关键问题清单20-分钟","Step 6 — 关键问题清单（20 分钟）",[17,13424,13425],{},"最后一步，让 AI 列出\"作为新人接手，你最该问原作者的 10 个问题\"：",[151,13427,13430],{"className":13428,"code":13429,"language":156,"meta":157},[154],"假设你即将接手这个项目，原作者今天最后一天上班，\n你只能问他 10 个问题。请列出这 10 个问题，按重要性排序。\n\n每个问题要：\n- 具体（不能是\"这个项目怎么部署\"这种宽泛问题）\n- 可被一句话回答\n- 解决之后你能独立运行\u002F修改这个项目\n",[159,13431,13429],{"__ignoreMap":157},[17,13433,13434,13437],{},[147,13435,13436],{},"这份清单极其有价值","——它把\"未知的未知\"转化成\"已知的未知\"。你可以拿着它去问前同事 \u002F 客户 \u002F 文档 \u002F 社区。",[12246,13439],{},[13,13441,13442],{"id":13442},"总耗时与产出",[40,13444,13445,13456],{},[43,13446,13447],{},[46,13448,13449,13451,13453],{},[49,13450,12972],{},[49,13452,12262],{},[49,13454,13455],{},"产出物",[62,13457,13458,13469,13478,13488,13497,13508],{},[46,13459,13460,13463,13466],{},[67,13461,13462],{},"1-2",[67,13464,13465],{},"30 min",[67,13467,13468],{},"项目体检报告",[46,13470,13471,13473,13475],{},[67,13472,10489],{},[67,13474,13465],{},[67,13476,13477],{},"Mermaid 架构图",[46,13479,13480,13483,13485],{},[67,13481,13482],{},"4",[67,13484,13465],{},[67,13486,13487],{},"核心业务路径文档",[46,13489,13490,13492,13494],{},[67,13491,10945],{},[67,13493,13465],{},[67,13495,13496],{},"风险 + 技术债清单",[46,13498,13499,13502,13505],{},[67,13500,13501],{},"6",[67,13503,13504],{},"20 min",[67,13506,13507],{},"关键问题清单",[46,13509,13510,13514,13519],{},[67,13511,13512],{},[147,13513,12317],{},[67,13515,13516],{},[147,13517,13518],{},"~2.5 小时",[67,13520,13521],{},[147,13522,13523],{},"5 份可交付文档",[17,13525,13526,13527,13530],{},"把这 5 份文档存进项目 ",[159,13528,13529],{},"docs\u002Fonboarding\u002F","，下一个新人来直接读，再省 2 小时。",[12246,13532],{},[13,13534,12338],{"id":12338},[21,13536,13537,13544,13552,13561],{},[24,13538,13539,13541,13542,3725],{},[147,13540,72],{},"：最适合这种\"广撒网\"任务，自己跑命令、读文件。",[147,13543,54],{},[24,13545,13546,13551],{},[147,13547,13548,13549],{},"Cursor + ",[159,13550,1491],{},"：体验也很好，胜在便宜。中型项目（\u003C 5 万行）够用。",[24,13553,13554,13556,13557,13560],{},[147,13555,101],{},"：可以，但要手动 ",[159,13558,13559],{},"add"," 文件，节奏更慢。",[24,13562,13563,13566],{},[147,13564,13565],{},"Trae","：国内项目首选，中文 prompt 体验最佳。",[13,13568,12367],{"id":12367},[21,13570,13571,13581,13587],{},[24,13572,13573,13576,13577,13580],{},[147,13574,13575],{},"不要让 AI 一次读完整个项目","——它会丢上下文。",[147,13578,13579],{},"分模块"," + 每模块独立提问。",[24,13582,13583,13586],{},[147,13584,13585],{},"关键结论要让它给出文件:行号"," 作为依据，否则容易编。",[24,13588,13589,13592],{},[147,13590,13591],{},"不要过度依赖 AI 的\"我觉得\"","——遇到不确定的地方，强制让它标记不确定，然后人工 verify。",[17,13594,13595,13596,3725],{},"下一篇：",[795,13597,12500],{"href":12499},[721,13599,13600],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":157,"searchDepth":263,"depth":263,"links":13602},[13603,13604,13605,13606,13607,13608,13609,13610,13611,13612,13613],{"id":15,"depth":256,"text":15},{"id":13201,"depth":256,"text":13202},{"id":13219,"depth":256,"text":13220},{"id":13312,"depth":256,"text":13313},{"id":13343,"depth":256,"text":13344},{"id":13374,"depth":256,"text":13375},{"id":13403,"depth":256,"text":13404},{"id":13421,"depth":256,"text":13422},{"id":13442,"depth":256,"text":13442},{"id":12338,"depth":256,"text":12338},{"id":12367,"depth":256,"text":12367},"\u002Fog\u002Fplaybook\u002Flegacy-onboarding.png","新人面对几十万行老代码不知从何下手？用 Claude Code \u002F Cursor 在 2 小时内画出项目架构、找到核心入口、定位关键风险点的标准化工作流。",{},"2026-04-25",[747,7484,750],{"title":13175,"description":13615},"playbook\u002Fonboarding\u002Flegacy-codebase-onboarding",[740,13622,13623,72],"代码理解","架构图","2026-06-08","0F1OVuaSvo8nT4EWBpyuDs7C5ypSOig0svKHVsTriyM",1782480894087]