跳到主要内容
返回ClaudeCode
工具教程

14|16 小时 Claude Code:插件参考、Chrome、并行任务与环境变量

星核工具箱编辑部约 79 分钟阅读

38 · 插件参考手册:把自己那套配置,打成一个能发出去的包

给一个插件跑一下 claude plugin details,输出里常有一行数字值得留意:这个插件每个会话常驻占 ~180 token,里头两个 skill 触发时各自再吃掉 ~2400 和 ~1800 token

就这么个看着人畜无害的小插件,光「挂在那儿什么都没干」就先占了一截工作台。这时候就能意识到:插件不是个黑盒——它由几类明确的组件拼成,每一类占多少、放哪儿、怎么触发,全是有据可查的。你把这套结构吃透,才谈得上「自己造一个、还造得干净」。

第 24 篇我们已经把「用别人的插件」走通了:加市场、装插件、/reload-plugins 生效、装前看信任。这一篇不重复那些,专啃更硬的一块——插件的内部构造和开发发布。说白了,第 24 篇是「会开车」,这一篇是「会拆发动机、还能自己攒一台」。

这一篇偏「参考手册」,信息密度会比前面高。你不用一次记全,先跟着把一个能跑的插件造出来、发出去,剩下的字段表当字典随用随查。

看完这一篇,你会拿到:

  • 插件的标准目录长相,以及那条「.claude-plugin/ 里只放 plugin.json」铁律背后的完整结构
  • plugin.json 清单的字段全景:必填的、元数据、组件路径、用户配置、依赖,一张表查到底
  • 插件能打包的全部组件(skill / command / agent / hook / MCP / LSP / monitor)各自放哪、有什么限制
  • ${CLAUDE_PLUGIN_ROOT} 这几个路径变量为什么必须用、不用会怎样
  • 从零造一个插件、本地测、建市场、发给团队的完整链路,全程给命令和预期输出
  • 版本管理和依赖这两个发布时绕不开的坑,怎么填

01 先把插件的「骨架」摆正:标准目录长相

第 24 篇你已经见过插件最简的样子——一个 plugin.json 加几个组件文件夹。但要自己造一个像样的插件,得先把完整骨架看清楚,不然加到一半就乱。

先给结论:一个插件就是一个文件夹,里头一个「清单文件」定身份,其余按组件类型分门别类摆在根目录下。

类比:一套乐高积木。 一盒乐高里有两样东西——一本拼装说明书,告诉你这套叫什么、有哪些零件;几个分格的零件盒,按类型把积木块装好(轮子一格、窗户一格)。插件就是这么个结构:plugin.json 是那本说明书,skills/agents/hooks/ 这些文件夹是分格零件盒。说明书有它专属的位置,零件盒全摊在外面——这就是下面那条铁律的由来。

官方给的完整插件目录长这样(我删掉了不常用的,留核心):

my-plugin/
├── .claude-plugin/           # 元数据目录
│   └── plugin.json           # 清单(说明书)——只有它放这儿
├── skills/                   # Skills,每个一个 <名字>/SKILL.md
│   └── code-reviewer/
│       └── SKILL.md
├── commands/                 # Skills 的扁平 .md 写法(老形式)
│   └── status.md
├── agents/                   # Subagent 定义
│   └── security-reviewer.md
├── hooks/                    # Hook 配置
│   └── hooks.json
├── .mcp.json                 # MCP server 定义
├── .lsp.json                 # LSP server 配置
├── bin/                      # 加进 PATH 的可执行文件
├── scripts/                  # Hook 和工具脚本
└── settings.json             # 插件的默认设置

这里有条官方用警告框圈起来、新手必踩的铁律,我替你钉死:

.claude-plugin/ 目录包含 plugin.json 文件。所有其他目录(commands/、agents/、skills/、output-styles/、themes/、monitors/、hooks/)必须在 plugin 根目录,而不是在 .claude-plugin/ 内。

说白了:.claude-plugin/ 这个文件夹里只准躺着 plugin.json 一个东西skills/agents/hooks/ 全部摆在它的外面、跟它平级。这个坑第 24 篇就提过——第一次打包很容易手贱把 skills/ 塞进 .claude-plugin/,结果插件能加载、skill 死活不出现,排查半天才发现是位置摆错。记住乐高那个画面:说明书归说明书的盒,零件盒全摆外头。

还有个容易被忽略的点,官方写得很明确:插件根目录里的 CLAUDE.md 不会被当成项目上下文加载。插件想给 Claude 喂指令,得通过 skill、agent、hook 这些组件,不能靠在插件里塞一个 CLAUDE.md。这跟第 18 篇讲的项目级 CLAUDE.md 是两码事,别搞混。

💡 一句话总结:插件 = 一本说明书(.claude-plugin/plugin.json)+ 根目录下分格的零件盒(各组件文件夹);铁律就一条——.claude-plugin/ 里只放 plugin.json,别的文件夹全摆根目录


02 plugin.json:这份「清单」每个字段管什么

骨架摆正了,来拆那本说明书——plugin.json。它声明插件的身份和配置,是整个插件的核心。

先记一个反直觉但很省心的事实:清单是可选的。 官方原话——如果你省略 plugin.json,Claude Code 会自动去默认位置(skills/agents/ 这些)找组件,连插件名都从文件夹名推出来。只有当你需要写元数据、或自定义组件路径时,才需要这份清单。 但凡你想正经发布,肯定要写,所以咱们按写的来讲。

类比:报关单。 一批货物出关,得附一份报关单——里头写清这批货叫什么名字、谁发的、版本批次、装了哪些东西。海关(Claude Code)照着这份单子核对、登记、上架。plugin.json 就是插件的报关单:名字、作者、版本、装了哪些组件,全在这一张纸上说清。

唯一的必填字段

如果你写了清单,只有一个字段是必填的

字段类型说明
namestring唯一标识符,kebab-case(小写加连字符)、不带空格

name 为什么这么关键?因为它就是组件的命名空间(namespace)前缀。一个叫 plugin-dev 的插件里有个 agent 叫 agent-creator,在界面里会显示成 plugin-dev:agent-creator;skill 调用就是 /plugin-dev:xxx命名空间是插件防撞名的根本机制——你装十个插件,各家的 skill 都带自家前缀,不会打架。

元数据字段(描述插件「是什么」)

这些不影响功能,但发布时该填,让用户看得明白:

字段干什么
displayName界面里显示的人类可读名,能带空格大小写;省了就回退用 name
version语义版本号(semantic versioning)。设了它,用户只在你提版本号时才收到更新(这是个大坑,第 08 节细说)
description一句话说清插件干嘛,浏览/安装时显示
author作者信息(name / email / url
homepage / repository / license文档地址 / 源码地址 / 许可证
keywords发现标签,帮人搜到你

组件路径字段(指明组件「在哪」)

默认情况下组件就放在 skills/agents/ 这些标准位置,你完全可以不写这些字段。只有当你想把组件放到非标准路径时才用:

字段指向什么
skills额外的 skill 目录(追加到默认 skills/
commands / agents / outputStyles自定义路径(替换默认目录)
hooks / mcpServers / lspServers配置文件路径,或直接内联写在这儿
dependencies这个插件依赖的其他插件(第 08 节讲)

这里藏着一个特别容易栽的细节,官方专门列了「路径行为规则」:有的字段是「替换默认」,有的是「追加到默认」

  • 替换默认commandsagentsoutputStyles。一旦你写了 commands,默认的 commands/ 目录就不再被扫描了。想保留默认还加别的,得显式列上:"commands": ["./commands/", "./extras/"]
  • 追加到默认skills。默认 skills/ 永远会被扫描,你在 skills 字段里列的目录是跟它一起加载的。

这个坑很容易踩:给一个插件加了 "agents": ["./extra-agents/reviewer.md"],想着「再加一个 agent」,结果原来 agents/ 目录里那俩 agent 全不见了——因为 agents替换不是追加。改成把三个都列进数组才好。记不住就查这张规则,别凭感觉。

一份带元数据的完整清单大概长这样:

{
  "name": "deployment-tools",
  "displayName": "Deployment Tools",
  "version": "1.2.0",
  "description": "Deployment automation tools",
  "author": { "name": "Dev Team", "email": "dev@company.com" },
  "license": "MIT",
  "keywords": ["deployment", "ci-cd"]
}

💡 一句话总结:plugin.json 是插件的报关单,唯一必填的是 name(它定命名空间);组件路径字段里要分清「替换默认」(commands/agents)和「追加默认」(skills),搞反了组件会凭空消失。


03 插件能打包哪些组件:七类零件认全

这是本篇最该记牢的一节——插件这个盒子,到底能装哪七类零件。第 24 篇粗讲过几类,这里把官方支持的全列清,标明各自放哪、有什么独有的限制。

类比:乐高那几格零件盒,每格只装一种件。 轮子格、窗户格、人仔格——分门别类才拼得快。插件的组件也是一格一类:

组件放哪一句话作用触发方式
Skillsskills/<名字>/SKILL.md可调用的专项能力(第 26 篇)/插件名:skill名,或 Claude 自动调
Commandscommands/*.mdskill 的扁平老写法,新插件用 skills同上
Agentsagents/*.md专项 subagent(第 23 篇)出现在 /agents,Claude 派或你点
Hookshooks/hooks.json事件触发的自动动作(第 33 篇)生命周期事件自动触发
MCP servers.mcp.json连外部服务(第 22 篇)启用即自动起,工具混进工具箱
LSP servers.lsp.json实时代码智能(跳定义、查引用)处理代码时自动用,需另装语言服务器
Monitorsmonitors/monitors.json后台监视日志/状态,有动静通知 Claude插件激活时自动起(实验性)

几类需要单独点几句,都是官方文档里写明、但容易漏的限制:

Agents 在插件里被「削权」了。 这点很关键。官方明确:出于安全原因,插件提供的 agent 不支持 hooksmcpServerspermissionMode 这三个 frontmatter 字段。 也就是说,插件里的 subagent 不能自己偷偷挂 hook、起 MCP、或改权限模式——这是防止你装个插件,它的 agent 在背后给你换权限。它支持的字段包括 namedescriptionmodeleffortmaxTurnstoolsdisallowedToolsskillsmemorybackgroundisolation 这些(isolation 唯一合法值是 "worktree")。

Hooks 能监听的事件巨多。 插件 hook 跟你自己写的 hook(第 33 篇)监听的是同一批生命周期事件——从 SessionStart(会话开始)、PreToolUse(工具调用前,能拦)、PostToolUse(调用成功后),到 Stop(回答结束)、SessionEnd(会话终止),官方列了三十个。新手不用记全,记住「几乎任何时机都能挂个动作」就行,具体留到第 33 篇。

Hook 类型不止「跑脚本」。 除了最常见的 command(跑 shell 命令),还有 http(把事件发到一个 URL)、mcp_tool(调 MCP 工具)、prompt(用模型评估一段提示)、agent(跑个 agentic 验证器)。

Monitors 是实验性的。 它让插件在后台盯着日志或状态,有新行就当通知喂给 Claude,不用你开口让它监视。实验性,架构可能变,且只在交互式会话里跑、需要 Claude Code v2.1.105 以上。新手了解有这么个东西即可。

还有两类「半组件」值得知道:bin/ 目录里的可执行文件,插件启用时会被加进 Bash 工具的 PATH,能当裸命令直接调;settings.json 是插件的默认设置,但目前只支持 agentsubagentStatusLine 两个键——其中设 agent 能让插件启用时直接把某个自定义 agent 顶成主线程,等于「装上这个插件就换了套人设」。

💡 一句话总结:插件能装七类零件——skill / command / agent / hook / MCP / LSP / monitor,各有固定位置;重点记两条限制:插件里的 agent 不许带 hook/MCP/权限模式(安全削权)、monitor 是实验性的


04 ${CLAUDE_PLUGIN_ROOT}:为什么路径必须用变量,不能写死

这一节单拎出来,因为它是自己造插件时最高频的报错来源,而道理一句话能说透。

先看场景:你的插件里有个 hook 要跑 scripts/format.sh,或者 MCP server 要 node server.js。你想当然地写绝对路径 /Users/你/my-plugin/scripts/format.sh——完蛋,这条路在别人机器上根本不存在,而且就算在你机器上,插件每次更新缓存目录都会变

官方的解法是给你三个路径变量,在 hook 命令、MCP/LSP 配置、skill/agent 内容里都会被自动替换:

变量指向用来
${CLAUDE_PLUGIN_ROOT}插件安装目录的绝对路径引用插件自带的脚本、二进制、配置
${CLAUDE_PLUGIN_DATA}插件的持久数据目录(更新后保留)node_modules、缓存、跨版本要保留的状态
${CLAUDE_PROJECT_DIR}项目根目录引用项目里的脚本/配置

类比:活页夹里写「本夹位置」,而不是抄死页码。 想象一份会被反复重新装订的活页夹,你要在里头写「去附录那页」。如果你写死「第 87 页」,一重新装订页码全乱;聪明的做法是写「本夹的附录」这种相对本夹的占位说法${CLAUDE_PLUGIN_ROOT} 就是这个「本店地址」占位符——不管插件被装到哪、更新到第几版,它永远指向当前这一版的根目录

所以插件里引用自带脚本,标准写法长这样(注意双引号,防路径带空格):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"${CLAUDE_PLUGIN_ROOT}\"/scripts/format-code.sh"
          }
        ]
      }
    ]
  }
}

这里有个官方反复强调的硬规矩,值得贴脑门上:

当 plugin 更新时,此路径会更改。前一个版本的目录在更新后约七天内保留在磁盘上以进行清理,但应将其视为临时的,不要在此处写入状态。

翻译一下:${CLAUDE_PLUGIN_ROOT} 是临时的,别往里写要长期保留的东西(比如装好的依赖、缓存)——那些该写进 ${CLAUDE_PLUGIN_DATA},因为数据目录跨版本保留。常见的翻车是把插件装的 node_modules 放进 ROOT,结果插件一更新依赖全没了,得重装。自带的脚本用 ROOT,要保留的状态用 DATA,这条分清就不出事。

还有个相关坑,官方在「插件缓存」那节专门讲:已安装的插件不能引用自己目录外的文件。你写 ../shared-utils 这种往外跳的相对路径,安装后会失效——因为插件被装时是整个复制进缓存~/.claude/plugins/cache)的,外面的文件根本没被复制过去。要跨插件共享文件,得用符号链接,这是进阶话题,新手先记住「别往插件外引用」。

💡 一句话总结:插件里引用路径必须用 ${CLAUDE_PLUGIN_ROOT} 这类变量,不能写死绝对路径(每次更新都变);自带脚本用 ROOT、要保留的状态用 DATA,且绝不引用插件目录外的文件


05 动手:从零造一个能跑的插件,再本地测

讲了四节构造,该真上手了。下面带你亲手造一个最小但完整的插件、本地加载、跑通它的 skill——全程不依赖任何复杂环境,跟着抄就行。我们造一个 my-greeter 插件,带一个打招呼的 skill。

第一步:用官方脚手架命令起一个插件骨架

最省事的不是手动建目录,而是用官方的 plugin init 命令,它会把骨架搭好:

claude plugin init my-greeter --with skills

--with skills 表示顺便搭一个示例 skill 文件夹。这条命令会在 ~/.claude/skills/my-greeter/ 下建好 .claude-plugin/plugin.json 和一个启动用的 SKILL.md

预期:终端提示插件骨架已创建,告诉你建在了 ~/.claude/skills/my-greeter/

这里有个官方设计的便利:放在 ~/.claude/skills/ 下、带 plugin.json 清单的文件夹,下个会话会自动作为 my-greeter@skills-dir 加载,不用建市场、不用安装。这种叫「skills 目录插件」,是开发自用插件最轻的路子。

第二步:看看脚手架生成了什么

直接列一下目录(注意用绝对路径):

ls -R ~/.claude/skills/my-greeter

预期:你会看到 .claude-plugin/plugin.jsonskills/(或一个 SKILL.md)。确认 plugin.json.claude-plugin/ 里、skill 在外面——这就是第 01 节那条铁律的实物。

第三步:写一个属于自己的 skill

打开(或新建)~/.claude/skills/my-greeter/skills/hello/SKILL.md,内容写成:

---
description: 用热情的语气跟用户打招呼
---

# Hello Skill

热情地跟名叫 "$ARGUMENTS" 的用户打招呼,问问今天能帮上什么忙。语气友好、鼓励一点。

$ARGUMENTS 是占位符——它会捕获你在 skill 名后面打的任何文字。这是给 skill 传参的标准做法(第 26、27 篇讲过 skill,这里复用)。

第四步:本地加载这个插件

开发期不用建市场,--plugin-dir 直接加载本地插件目录,这是官方专给开发测试的标志:

claude --plugin-dir ~/.claude/skills/my-greeter

预期:Claude Code 正常启动。敲 /help,能在插件命名空间下看到你的 skill 列出来。

第五步:喊起你的 skill,亲眼看它跑

插件 skill 永远带命名空间,所以这么调(后面跟个名字当参数):

/my-greeter:hello Walter

预期:Claude 用一段热情的、带上「Walter」这个名字的话回应你。看到它按你写的 description 和正文打了招呼,说明这个插件不光建对了、它带的 skill 真能用了。

第六步:改了 skill,热重载看效果

SKILL.md 的正文改两句(比如让它用中文加 emoji),然后不用重启,在 Claude Code 里敲:

/reload-plugins

预期:重新跑一遍 /my-greeter:hello Walter,能看到改动生效了。

⚠️ 一个官方写明的区别:SKILL.md 当前会话立即生效;但改 hooks、.mcp.jsonagents/ 这些,得 /reload-plugins 或重启才生效。别改了 hook 发现没反应就以为写错了,先 reload 一下。

跑通这六步,你就把「造骨架 → 写组件 → 本地加载 → 调用 → 热重载」这条插件开发的完整内循环亲手走了一遍。以后造任何插件,本质都是这套流程,只是组件更多。

💡 一句话总结:claude plugin init 起骨架、--plugin-dir 本地加载、/reload-plugins 热重载——这三条命令是插件开发的内循环;放进 ~/.claude/skills/ 的还能免市场免安装自动加载。


06 把插件发出去:建一个市场

自用的插件,放 ~/.claude/skills/--plugin-dir 就够了。但要发给团队、发给社区,得走「市场(marketplace)」这一层——第 24 篇你是市场的「消费者」,这一节当一回市场的「店主」。

先理清两个长得像、极易混的概念,官方专门用 Note 框区分过:

概念是什么在哪定义
市场源(marketplace source)去哪拿那本「商品目录」(marketplace.json用户 /plugin marketplace add 时,或设置里
插件源(plugin source)目录里每个插件本体从哪拿marketplace.json 里每个插件条目的 source 字段

类比:商场 vs 商场里每件商品的供货地。 「市场源」是这家商场开在哪、目录册从哪取;「插件源」是目录册里每件商品实际从哪个工厂发货。两者完全可以不在一处——商场目录可以挂在 A 仓库,里头某件商品从 B 工厂直发。

市场的核心是一个文件:仓库根目录下的 .claude-plugin/marketplace.json。它声明市场名、所有者、和插件清单。最小的一个长这样:

{
  "name": "my-plugins",
  "owner": { "name": "Your Name" },
  "plugins": [
    {
      "name": "my-greeter",
      "source": "./plugins/my-greeter",
      "description": "A friendly greeting plugin"
    }
  ]
}

每个插件条目至少要 namesource(从哪拿这个插件)。source 支持好几种来源,这是市场最实用的部分:

插件源类型怎么写适合
相对路径"./plugins/my-greeter"插件就在市场同一个仓库里(最常见)
github{ "source": "github", "repo": "owner/repo" }插件在另一个 GitHub 仓库
git-subdirurl + path插件在某个大仓库(monorepo,多项目合一仓库)的子目录,稀疏克隆省带宽
npm{ "source": "npm", "package": "@org/plugin" }作为 npm 包发布的插件

动手:把第 05 节那个插件,装进一个本地市场试试。 假设你按上面的结构建好了 my-marketplace/(里头 .claude-plugin/marketplace.json + plugins/my-greeter/),在 Claude Code 里:

/plugin marketplace add ./my-marketplace
/plugin install my-greeter@my-plugins

预期:第一条提示市场添加成功;第二条把插件装上。然后 /my-greeter:hello 就能调了——这条链路跟第 24 篇你装别人插件时一模一样,只不过这次货是你自己的

发布前一定先验证,官方给了专门命令:

claude plugin validate ./my-marketplace

预期:检查 marketplace.json 的 schema、有没有重复插件名、源路径有没有非法的 ..、版本对不对得上。指向市场目录时它只查 marketplace.json;要连 skill/agent 的 frontmatter 一起查,得指向具体插件目录claude plugin validate ./my-marketplace/plugins/my-greeter)。

真要发给团队,把这个市场仓库推到 GitHub,同事一句 /plugin marketplace add owner/repo 就能加。想自动让团队装,可以在项目的 .claude/settings.json 里写 extraKnownMarketplaces,同事信任项目目录时会被提示安装——这块属于团队配置,新手先知道有这条路即可。

💡 一句话总结:发布走市场——根目录建 .claude-plugin/marketplace.json,列出插件和它们的 source(相对路径/github/npm 等);分清「市场源」(目录从哪来)和「插件源」(每个插件从哪来);发布前 claude plugin validate


07 一组对照:自用、本地测、正式发布,三条路别走错

造插件的人最常犯的不是写错代码,是用错了「分发方式」——明明只是自己试,却去吭哧建市场;或者要发团队了,还在用只对自己生效的 --plugin-dir。这一节一张表把三条路钉清。

你的处境该用命令特点
纯自用、想随手改随手用skills 目录插件放进 ~/.claude/skills/<名>/(带 plugin.json自动加载,免市场免安装,改 SKILL.md 立即生效
开发中、反复测一个本地包--plugin-dirclaude --plugin-dir ./my-plugin直接加载,不入库;可多次指定加载多个;.zip 也行
发给团队/社区市场marketplace.json + /plugin install能版本管理、能自动更新、能共享

几个用起来才知道的细节:

--plugin-dir 是开发利器,但只管当前这一次会话。 你这次启动加载了,关掉再开就没了——它不写进任何配置。好处是干净:测完插件,关掉会话就一干二净,不留痕迹。开发时一个顺手的做法是一直挂着一个 --plugin-dir 的会话,改完 /reload-plugins,比每次重装市场快太多。官方还有个贴心设计:--plugin-dir 的本地副本,会临时盖过同名的已装市场插件——所以你能拿本地改动直接覆盖测试一个线上插件,不用先卸载。

skills 目录插件有个范围陷阱。~/.claude/skills/(个人级)的,每个项目都能用;但放项目 .claude/skills/ 的(项目级),官方明确警告:它只从你启动 Claude Code 的那个目录加载,不会像普通 skill 那样往仓库根目录上找。所以从子目录启动会漏掉根目录的插件——要么从仓库根启动,要么 /reload-plugins

别一上来就建市场。 这是过度工程的典型。官方的建议很实在:先用 .claude/ 散装或 --plugin-dir 快速迭代,准备好共享了再转成插件、建市场。一个插件通常要在 --plugin-dir 下改十几轮才稳定,这期间建市场纯属给自己找麻烦——每改一次还得提交、刷新市场。

💡 一句话总结:三条路别走错——自用塞 ~/.claude/skills/、开发用 --plugin-dir、发布才建市场--plugin-dir 只活一次会话(干净),发布前先在前两条路上把插件迭代稳。


08 发布绕不开的两个坑:版本管理与依赖

插件能跑、能装,不代表能「发好」。版本管理和依赖是发布时两个最容易翻车的地方,官方都用警告框圈过,这一节专门填。

坑一:设了 version,推新提交却没人更新

这是最反直觉、最坑人的一个。Claude Code 怎么判断「插件有没有新版本」?它按这个顺序取版本号:

  1. plugin.json 里的 version
  2. 市场条目里的 version
  3. 都没有的话,用 git 提交的 SHA

关键就在这儿。官方警告说得很重:

设置 version 会固定 plugin。如果 plugin.json 声明 "version": "1.0.0",推送新提交而不改变该字符串对现有用户没有任何作用,因为 Claude Code 看到相同的版本并保留缓存副本。

翻译成大白话:你一旦写死了 "version": "1.0.0",光往仓库推新代码是没用的——用户那边版本号没变,/plugin update 会回你「已是最新」,缓存压根不刷新。 你必须每次发版都手动把版本号往上提(1.0.11.1.0……)。

所以官方给了两种策略,二选一,别混:

策略怎么做更新行为适合
显式版本plugin.json 里设 version,每次发版手动提用户只在你提版本号时收到更新有稳定发布节奏的正式插件
提交 SHA 版本不写 version,git 托管每推一个新提交都算新版本,用户自动拿到内部、团队、快速迭代的插件

还有个加倍坑的:别在 plugin.json 和市场条目里都写 version 官方明确——plugin.json 的值会无声地盖过市场条目的,你在 marketplace.json 里改了版本可能根本不生效,因为被那个陈旧的 plugin.json 版本号压住了。

显式版本这个坑很容易栽:一个团队内部插件设了 "version": "1.0.0",改了好几次代码推上去,同事一直反馈「怎么没更新」。你很容易以为是市场没刷新,折腾半天才反应过来——版本号没动,Claude Code 当然认为没变化。内部插件一律不写 version、让它用 SHA,推一次同事更新一次,就清净了。结论:快速迭代的内部插件别设 version,稳定发布的正式插件才设、且每次记得提。

坑二:依赖怎么声明

如果你的插件 A 必须有插件 B 才能工作,用 dependencies 字段声明:

{
  "name": "my-plugin",
  "dependencies": [
    "helper-lib",
    { "name": "secrets-vault", "version": "~2.1.0" }
  ]
}

声明后,装/启用你的插件时,Claude Code 会自动把依赖也装上/启上。版本可以用 semver(语义版本范围)约束(像 ~2.1.0),免得依赖出个大版本把你的插件搞崩。卸载时,claude plugin uninstall --prune 能顺手清掉那些「只为满足依赖而自动装、现在没人要」的插件;你手动直接装的插件永远不会被 prune 碰

类比:配料表里标「需另购的配件」。 一份家具说明书末尾写着「本款需另购 M4 螺丝包(2.1 规格)」——你照单备齐配件,家具才装得起来。dependencies 就是插件的这张配件清单:它把「我需要谁、要哪个版本」写明,Claude Code 照单自动备齐

💡 一句话总结:发布两个坑——设了 version 就必须每次发版手动提,否则用户收不到更新(快速迭代干脆别设、用 SHA);依赖用 dependencies 声明、可加 semver 约束,装你的插件时会自动连依赖一起装。


09 小结

这一篇把插件从「会用」推进到「会造、会发」——它本质就是一盒乐高:一本说明书(plugin.json)定身份,几格零件盒(组件文件夹)装能力,整盒打包就能发给任何人

把核心要点串起来回顾:

你要搞清的事关键点
目录骨架.claude-plugin/只放 plugin.json,其余组件全摆根目录
清单字段唯一必填 name(定命名空间);组件路径分「替换」(agents/commands)和「追加」(skills)
能装哪些组件skill/command/agent/hook/MCP/LSP/monitor 七类;插件里的 agent 被削权(无 hook/MCP/权限模式)
路径怎么写必须用 ${CLAUDE_PLUGIN_ROOT} 等变量,不写死、不引用目录外文件;状态放 DATA 不放 ROOT
开发内循环plugin init 起骨架 → --plugin-dir 加载 → /reload-plugins 热重载
发布marketplace.json,分清市场源/插件源,claude plugin validate 验证
两个坑设了 version 必须每次提;依赖用 dependencies 声明

你现在应该能: 看懂任何一个插件的目录在干嘛、自己从零搭一个能跑的插件骨架、用 --plugin-dir 本地测、再建个市场把它发给团队;也清楚 ${CLAUDE_PLUGIN_ROOT} 为什么不能写死、version 那个「不提就不更新」的坑怎么躲。第 24 篇你学会了消费别人的插件,这一篇你成了能生产插件的人——把自己那套攒了好久的配置打成一个包发出去,从此不再是只能抄别人的。

到这里,Claude Code 的「扩展 + 配置 + 打包分发」这条线就齐全了。从第 18 篇的 CLAUDE.md、第 22 篇的 MCP、第 23 篇的 subagent,到第 24、38 这两篇的插件——你不光会用这些工具,还会把它们组装、打包、交付给别人


下一篇 39「实战入门」——前面三十多篇全是「一个个功能拆开讲」,你手里的零件已经堆成山了。下一篇不再讲新功能,而是把这些零件第一次串成一条完整的实战路径:拿一个真实的小需求,从开工到交付走一遍,让你亲眼看见「学过的东西怎么拧成一股绳干活」。想想看——你现在会的每一招,单独使都顺手,但真打一仗时,该先抽哪把、再接哪把?


39 · 实战入门:拿一个真需求,从开工到交付走一整趟

说句实话,大多数人以为 AI 写代码就是「一句话然后等结果」——说清楚需求,Claude 自己跑完,你接过来用。这条路听起来顺,踩一次坑就知道哪里断了:

方向跑偏了、顺手多改了三个文件、说好的 bug 修完照崩……最后花在收拾的时间,比自己动手还多。

不是工具不够聪明,是这趟流程里少了几个关键交接棒。

说白了,这就是「学过每个动作」和「能把动作连成一趟」之间的鸿沟。 你练过打方向、练过看后视镜、练过点刹车,但第一次独自上路,得把这些动作按正确的顺序连起来才叫会开车。这一篇不教任何新功能,只干一件事——带你把已经会的零件,第一次连成一条能跑通的实战路径

我们挑的任务小到不能再小,但五脏俱全:给一个数单词频率的小脚本加个功能,顺手修个 bug。麻雀虽小,从开工到交付那条完整的路,一步都不缺。

看完这一篇,你会拿到:

  • 一条「开工 → 探索 → 规划 → 动手 → 验证 → 交付」的标准实战路径,每一步该敲什么、看什么
  • 一个能照着抄的真实小任务(数单词的脚本加 --top N、修空参数崩溃),全程命令 + 预期输出
  • 「先让它探索、再让它动手」这条铁律为什么是新手最该养成的肌肉记忆
  • 怎么用 plan mode(详见第 20 篇)让它先出方案再砸代码,以及怎么审查它给你的 diff
  • 一张「老手怎么走 vs 新手怎么走」的对照表,把最常踩的顺序坑标出来

01 先看全景:一趟实战,就这六步

动手之前,先把整趟路在脑子里过一遍。一个真实任务从接到手到交付,无论大小,骨架都是这六步:

Claude Code 实战六步法:开工 → 探索 → 规划 → 动手 → 验证 → 交付

类比:接力赛的交接棒。 这六步就是六个交接棒的人:探索把「我看懂了什么」交给规划,规划把「打算怎么改」交给动手,动手把「改了什么」交给验证。任何一棒掉了棒,整趟都得返工——新手翻车,九成是某个交接没做,最典型的就是「没探索就直接让它动手」,棒还没拿稳就开跑。

这六步不是我编的,它就是官方快速开始(quickstart)和常见工作流(common workflows)两篇文档拼起来的实操顺序。官方那句话点得很到位:

在进行更改之前,让 Claude 理解您的代码。

这六步还能压缩,但不能跳。 熟手会把「探索 + 规划」合成一句话、把「验证 + 交付」连成一个动作,看起来像三步——但每一步都还在,只是节奏快了。新手最爱犯的不是「走得慢」,而是直接把中间四步全删了,只剩「说需求 → 拿结果」,等于把棒从第一个人手里直接扔到终点线,中间没人接。这一篇剩下的篇幅,就是带你把这六步在一个真实任务上踏踏实实走一遍,每一棒都亲手交一次。我会在每步开头标清「这一步对应前面哪一篇学过的东西」,让你边走边把零件对上号。

💡 一句话总结:一趟实战的骨架永远是「开工 → 探索 → 规划 → 动手 → 验证 → 交付」六步,像接力赛一样棒棒得交到位;新手最常掉的那一棒,是「没让它探索就直接动手」。


02 准备:造一个练手的小项目

为了让你能原样照着跑,我们不碰任何真实的大项目,先花两分钟造一个最小的练手场。它只有一个 Python 脚本加一个文本文件,不依赖任何第三方库,有 python3 就能跑(Mac / Linux 自带;Windows 装了 Python 即可)。

第一步:建目录、进去、放两个文件

在终端里执行(这一步是纯手动准备,还没动用 Claude Code):

mkdir wordcount-demo && cd wordcount-demo

新建一个 wordcount.py,内容如下(这就是我们要改的「祖传代码」,故意写得糙一点):

import sys
from collections import Counter

def count_words(path):
    with open(path) as f:
        text = f.read()
    words = text.lower().split()
    return Counter(words)

def main():
    path = sys.argv[1]
    counts = count_words(path)
    for word, n in counts.items():
        print(f"{word}: {n}")

if __name__ == "__main__":
    main()

再建一个 sample.txt 当测试数据:

the quick brown fox the lazy dog the fox

第二步:手动跑一遍,确认它能用

python3 wordcount.py sample.txt

预期输出(顺序可能略有不同,数字一定一样):

the: 3
quick: 1
brown: 1
fox: 2
lazy: 1
dog: 1

看到这些计数 = 脚本正常工作,练手场搭好了。这个脚本有两个毛病,正好当我们的任务

  • 缺个功能:我想只看「最高频的前 N 个词」,现在它一股脑全打出来。
  • 藏个 bug:你试试不带文件名直接跑 python3 wordcount.py,它会甩你一脸 IndexError 崩溃,而不是好好提示你「该传个文件」。

第三步:把它纳入 git(这一步很关键,别跳)

git init && git add . && git commit -m "init: 一个简陋的数词脚本"

预期:末尾出现一行类似 2 files changed 的提交确认(wordcount.pysample.txt 各记一笔)。看到它 = 你已经有了一个干净的「原点」,后面无论 Claude 把代码改成什么样,你都能一键退回这里。

为什么开工前一定先 git commit?因为它是你最硬的那张后悔药。第 37 篇讲过检查点(checkpoint)能倒带 Claude 的编辑,但检查点和 git 是两套东西、各管一段(第 37 篇专门掰过)。开工前一个干净的 git 提交,是你「无论后面怎么折腾都能一键回到原点」的地基——没提交就让它大改、改完想反悔却没有干净基线可对比,是很常见的亏,所以雷打不动先提交再开工。

💡 一句话总结:练手场就一个糙脚本 + 一个文本文件,python3 就能跑;它故意留了「缺功能」和「藏 bug」两个活儿;开工前先 git commit 一次,给自己留最硬的后悔药


03 开工:在项目目录里启动,先写一份最小的 CLAUDE.md

环境有了,正式开第一棒——开工。这一步对应第 02 篇(启动)、第 07 篇(第一次跑通)、第 12 / 18 篇(CLAUDE.md)。

第一步:在项目根目录启动 Claude Code

你得wordcount-demo 这个目录里claude,而不是在别处。Claude Code 默认拿「你启动它的那个目录」当工作区——站错地方,它读的就是别的项目的文件。

claude

预期:看到 Claude Code 的欢迎屏,底部显示当前目录是 wordcount-demo。这就是第 07 篇带你跑通过的那个起点。

第二步:先给它一份「最小可用」的 CLAUDE.md

第 18 篇反复强调过一句话:最没用的 CLAUDE.md 是写了三百行 Claude 一条没听的那种。所以练手项目别贪多,三五行说清最要紧的规矩就够。我们这个小脚本,规矩其实就两条:用什么跑、改完怎么验。在会话里直接让它生成(也可以手写,但让它写更省事):

帮我在项目根目录建一个 CLAUDE.md,写清两条:
1. 这是个纯标准库的 Python 命令行小工具,不要引入任何第三方依赖
2. 每次改完代码,用 python3 wordcount.py sample.txt 跑一遍验证不报错

预期:Claude 会先把要写的内容给你看,再请求批准写文件(第 20 篇讲的权限机制——它动文件前一定先问你)。批准后,项目根目录多出一个 CLAUDE.md,内容大致长这样:

# wordcount-demo

一个数文本里单词频率的命令行小工具。

## 技术约束
- 纯 Python 标准库,**不要引入任何第三方依赖**

## 验证
- 每次改完代码,跑一遍确认不报错:`python3 wordcount.py sample.txt`

短,但两条最要紧的规矩都钉死了。别嫌它简陋——三五行能管住的事,不必写三十行。

这里你可能想到第 12 篇的 /init。区别在:/init 是让 Claude 自己扫一遍代码库、自动生成一份较完整的说明书,适合有点规模的真实项目;咱们这个脚本就两个文件,手动指明那两条核心规矩反而更准、更短。两条路都对,看项目大小挑。

为什么开工就花这一步写 CLAUDE.md?因为它是给后面所有交接棒定的「总规矩」。等下你让它加功能,它会自动记得「别引第三方库」;改完它会自动记得「跑一遍验证」——你只说一次,整场都生效,不用每个指令都复读。这就是 CLAUDE.md 最实在的价值:把「每次都要嘱咐的话」固化成它每会话自动加载的背景。

💡 一句话总结:开工 = 站对目录敲 claude + 写一份三五行的最小 CLAUDE.md 把核心规矩定死;练手小项目手动指明两条规矩,比 /init 扫全库更准更短。


04 探索:先让它「看懂」,别急着让它「动手」

这是整趟路最该养成肌肉记忆、也最容易被新手跳过的一棒——探索。对应第 16 篇「四个最常用的活儿」里的第一类。

先说结论:拿到任务的第一句话,不是「给我改」,而是「先看懂」。

开头那个愣住的场景,犯的就是这个错——一上来就想敲「给脚本加个 --top 参数」。坏在哪? Claude 对你的代码一无所知,它会一边猜一边改,猜错了就给你改出一堆四不像。正确的开法是先派它去摸清现状

先别改任何代码。给我讲讲 @wordcount.py 现在是怎么工作的,
入口在哪、有没有什么明显的问题或者容易崩的地方?

注意两个细节:

  • 开头那句 「先别改任何代码」,是给它划一道线——这一棒只许看、不许动。第 15 篇讲过,把边界说清,它就不会越界。
  • 那个 @wordcount.py,是用 @ 直接把文件内容塞进对话(第 16、17 篇提过的 @ 引用),省得它再去翻一道。

预期:Claude 会读完文件,给你一段讲解——大致会说:这是个用 Counter 数词频的脚本,入口是 main(),它从 sys.argv[1] 取文件路径,然后大概率会主动点出那个隐患:如果不传文件名,sys.argv[1] 会越界崩溃

看到没——你还没提那个 bug,它探索的时候自己就发现了。这就是「先探索」白赚的好处:它不光看懂了现状,还顺手帮你把问题摸出来了。这一棒交得漂亮,下一棒(规划)才有谱。

这个脚本只有十几行,探索一句就够;但真实项目里,探索往往要「由宽到窄」问几层。 官方常见工作流里给的探索套路就是这个节奏:先问全局,再钻局部——

先给我这个代码库的整体结构和它是干嘛的(先别改任何代码)
处理用户登录的逻辑在哪几个文件?它们怎么配合的?

第一句拿到「全局地图」,第二句顺着地图钻进你要改的那块。为什么不一上来就问细节? 因为它对项目越没概念,越容易把「看起来相关」的文件当成「真正相关」的——先给它一张全局地图,它后面定位才准。进一个没碰过的中等项目,雷打不动先来这么两三句,宁可多花两分钟探索,也不让它带着错误的全局印象去改

类比:第一次独自上路前,先绕车走一圈。 老司机上车前会下意识扫一眼——轮胎瘪没瘪、后面有没有障碍、镜子角度对不对。这一圈花不了十秒,但能避开「直接挂挡撞上没看见的柱子」。让 Claude 先探索,就是上路前这一圈——十秒钟的「看一眼」,省掉的是后面「改错了推倒重来」的半小时

探索阶段读文件会吃上下文(第 19 篇讲过工作台塞满会变蠢)。任务大、要翻一堆文件时,可以让它派个 subagent 去探索(第 23 篇)——子代理在自己的窗口里翻,只把结论递回来,你的主对话不被一堆文件内容灌满。小任务用不上,知道有这条路即可。

💡 一句话总结:拿到任务第一句话永远是「先别改、先看懂」;让它探索不仅省掉瞎猜乱改,还常常白赚一个「它主动帮你发现的问题」——这一棒,新手最该练成本能。


05 规划:让它先出方案,你点头了再砸代码

探索完,它懂了现状,也知道你要干嘛。但还差一步——让它先把「打算怎么改」摆出来给你看,你认可了再动手。这一棒对应第 20 篇里的 plan mode(计划模式)。

为什么不直接让它改?因为 「它理解的方案」未必是「你想要的方案」。让它先讲一遍打算,是花一分钟堵住「方向就跑偏了还一路改到底」的最便宜的保险。

方式一:直接让它先说方案、别动手

最简单的,一句话约束它:

我想给这个脚本加一个 --top N 参数,只显示最高频的前 N 个词;
顺手把不传文件名就崩溃的问题也修了。
先告诉我你打算怎么改、动哪几个地方,等我说「开始」你再动手。

预期:它会回你一份计划,类似——用 argparse 替掉手写的 sys.argv、加一个 --top 选项、用 Counter.most_common(N) 取前 N 个、不传文件名时由 argparse 自动报友好提示而不是崩溃。它停在这儿等你拍板,不会擅自改文件。

方式二:正经用 plan mode

如果是更大的任务,更稳妥的是切到官方的计划模式——它会强制Claude 不编辑源代码、只产出方案,不批准就一行都不改(但它仍可运行 shell 命令做探索)。两种进法(第 20 篇讲过):

claude --permission-mode plan

或者在会话里按 Shift+Tab 循环切到 plan mode。官方对它的定位很清楚:

Claude 读取文件并提出计划,但在您批准前不进行任何编辑。

这两种方式的区别,一张表看清:

做法怎么约束它强制程度适合
一句话叫它先说方案靠你在提示里写「先别动手」软约束(它一般会听,但没拦死)小改动、你盯着的时候
plan mode模式层面禁止编辑源代码(shell 命令仍可跑)硬约束(批准前源代码一行都改不了)大改动、不放心、想认真审方案

一个实用的习惯:像这个 --top 这么小的改动,方式一一句话就够;但凡涉及多文件、或心里没底的改动,一律 Shift+Tab 切 plan mode——让模式替你把住「没点头不许动」这道闸,比盯着省心。给一个不熟的项目做较大改动时,要是图快没切 plan mode,它很可能一口气改了四个文件、方向还跟你想的不一样,回退花的时间够看三遍方案了。所以拿不准就 plan。

💡 一句话总结:动手前让它先出方案、你点头再改;小改动一句「先别动手」就行,大改动 / 没底的改动用 Shift+Tabplan mode 硬性锁住「批准前一行不改」。


06 动手 + 审查:放它改,但每一处 diff 你都过一眼

方案点头了,第六棒(其实是动手和审查连着的一棒)——让它改,同时你盯着每一处改动。对应第 20 篇的权限确认。

第一步:给它开绿灯

方案可以,开始改吧。

预期:Claude 开始编辑 wordcount.py关键来了——它每改一处,会把那段 diff(改动对照:删了哪几行、加了哪几行)摆到你面前请求批准(除非你开了「全部接受」模式,新手强烈别开)。第 20 篇讲过这套权限机制,这一步就是它真正落地的时刻

第二步:认真看 diff,别无脑回车

这是新手最容易松懈的地方——diff 划过去看都不看就一路 y。我的铁律是:每一处改动至少扫一眼「它动的是不是我让它动的地方」。这个任务里你该看到的改动大致是:

- import sys
+ import argparse

- def main():
-     path = sys.argv[1]
-     counts = count_words(path)
-     for word, n in counts.items():
+ def main():
+     parser = argparse.ArgumentParser(...)
+     parser.add_argument("path", ...)
+     parser.add_argument("--top", type=int, default=None, ...)
+     args = parser.parse_args()
+     counts = count_words(args.path)
+     items = counts.most_common(args.top) if args.top else counts.most_common()
+     for word, n in items:

扫一眼确认三件事:① 它确实在加 --top 和改入参(符合方案);② 没顺手乱动 count_words 那个本来就好的函数;③ 没偷偷引入第三方库(CLAUDE.md 立的规矩)。 对得上,就批准。

怎么快速扫一段 diff? 不用逐字读,盯三类信号就够:红行(-,删了什么)别有你舍不得删的;绿行(+,加了什么)别有你没要的依赖或没让加的功能;改动的范围别超出你说的那几个地方。这个任务里红行删的是手写 sys.argv、绿行加的是 argparse--top,范围只在 main() 里——全在预期内,放心批。

关于那个「全部接受」模式,给新手一句忠告:练手阶段别开。 quickstart 里提过你可以「为会话启用全部接受模式」(也就是第 20 篇的 acceptEdits),开了它就不再逐处问你、自己一路改下去。省事,但代价是你彻底交出了「事中拦截」这道窗口。 比较稳的做法是只在两种情况开:一是改动已经在 plan mode 里逐行看过方案、心里有数;二是一堆机械的重复改动(比如批量改个变量名)。头一两个月,老老实实一处一处看,把「读 diff」的眼力练出来再谈放飞。

为什么审查这一步省不得? 因为 AI 改代码不是「对或错」的二极管,它常常「大体对、细节偏」——可能多改了你没让改的地方,可能用了你不想要的写法。第 20 篇那句话值得再贴一遍:

Claude Code 在修改文件前始终请求许可。

这道许可不是走过场,它是你「事中拦截」的唯一窗口——一旦批了、改下去了,就得靠第 37 篇的检查点或 git 去「事后倒带」,成本高一截。事中扫一眼 diff,永远比事后回滚划算。

💡 一句话总结:动手阶段放它改、但每处 diff 都过一眼——确认「动的是该动的、没乱碰好代码、没违反 CLAUDE.md」;这道批准是你事中拦截的唯一窗口,无脑回车等于把后悔药留给事后。


07 验证:跑给你看,别信「我改好了」

代码改完了,它八成会跟你说一句「已经改好了,加上了 --top 参数,也修复了崩溃问题」。这句话你一个字都别信,直到你亲眼看它跑通。 这是整趟路的倒数第二棒,也是新手最爱省的一棒。

先说结论:「它说改好了」不算数,「跑一遍对了」才算数。 这正是项目规范里那条「改完主动验证、不要只改不验」的硬要求,落到实操就是——亲手把验收标准跑一遍

第一步:验证新功能(--top

python3 wordcount.py sample.txt --top 3

预期输出(按词频从高到低,只出前 3 个):

the: 3
fox: 2
quick: 1

看到只剩前三、且是按频率排好序的 = 新功能成了。(the 出现 3 次、fox 2 次,第三名是任意一个出现 1 次的词。)

第二步:验证旧功能没被改坏(回归)

加了新参数,老用法不能崩——不带 --top 时得跟原来一样全打出来:

python3 wordcount.py sample.txt

预期:跟第 02 节那份原始输出一致(六个词全在)。一致 = 没有「修好新的、碰坏旧的」

第三步:验证 bug 真的修了

这步最关键——重现当初那个崩溃,看它现在是不是好好提示而不是甩 traceback:

python3 wordcount.py

预期不再是那串 IndexError 崩溃,而是一行干净的用法提示,类似:

usage: wordcount.py [-h] [--top TOP] path
wordcount.py: error: the following arguments are required: path

从「程序崩了甩你一脸 traceback」变成「明确告诉你少传了 path」——这就是 bug 修好的铁证。三步全过,这趟活儿才算真的成了。

想再稳一档?让它把验证「钉成一个测试」。 上面三步是你手动跑、这次过了就完事;但同一个 bug,下次别人一改代码可能又崩回去。更稳的做法是让 Claude 顺手写个小测试,把「不传文件名要友好报错」这条变成可重复跑的关卡——官方常见工作流里专门有「修复 bug 时先写一个能重现它的测试,再让测试通过」这套(项目规范里那条「写重现 bug 的测试再让它通过」也是这个意思):

给「不传文件名时不崩溃、而是退出码非 0 并打印用法提示」写一个测试,再确认它通过。

预期:Claude 写一小段测试(用 subprocess 跑脚本、断言退出码和输出),然后跑给你看绿灯。这一步把「我这次跑过了」升级成「以后每次都能自动验」——对一次性练手是锦上添花,对真实项目几乎是必备。小任务你嫌重可以跳,但心里得有这根弦

为什么对「亲手跑」这么轴?因为被「我改好了」坑过的人不止一两个。 让它修一个边界情况,它信誓旦旦说修好了,没跑就提交,结果那个边界根本没覆盖到——它改的是「看起来相关」的另一处。所以认一个死理:AI 说的「完成」是假设,你跑出来的「通过」才是事实。 这跟项目规范里那句「凡声称已验证,必须真的跑一遍」是一个意思。

💡 一句话总结:验证 = 亲手跑三遍——新功能对不对、旧功能有没有被改坏、bug 是不是真修了;「它说改好了」是假设,「你跑出来对了」才是事实,这一棒省不得。


08 交付:让它写提交信息,把成果存进库

三步验证全过,最后一棒——交付,把这次成果稳稳存进 git。对应第 07 篇尾巴提过的「对话式 Git」。

第一步:先看一眼到底改了什么

我改了哪些文件?给我一个改动概览。

预期:Claude 跑 git status / git diff,告诉你这次只动了 wordcount.py,新增了 --top 参数、把入参改成 argparse交付前再确认一次「改动范围跟预期一致」,是临门一脚的复查。

第二步:让它生成提交信息并提交

用一句话描述清楚这次改动,提交它。

预期:Claude 会先把它拟的提交信息(commit message)给你看——类似「feat: 给 wordcount 加 —top N 参数并用 argparse 修复缺参崩溃」——再请求批准执行 git commit。这又是第 20 篇那道权限闸:它动你的 git 历史前,照样先问你

这里插一句重要的边界:git commit 它会先把要提交的内容给你确认;但 git push(推到远程)是另一回事。把成果推上 GitHub 之类的远程仓库前,务必你自己心里有数、亲自把关——这是第 43 篇「Git 工作流」要细讲的,这里你先记住:本地提交可以放手让它代劳,推远程这一步自己捏在手里

第三步:确认提交成功

显示我最后 1 次提交。

预期:它跑 git log -1,你能看到刚才那条提交信息和改动。看到它 = 这趟活儿正式交付,从开工到入库全程闭环

走到这儿,你回头看看:从一个崩溃、功能也不全的糙脚本,到一个带 --top、缺参数还会友好提示的小工具,全程你只敲了六七句自然语言——但每一句都卡在那六步的正确位置上。这就是「把零件连成一趟」的样子。

💡 一句话总结:交付 = 先看改动概览 → 让它拟提交信息并 commit(它会先给你确认)→ git log 验证入库;记住边界——本地 commit 可放手,push 远程自己把关(留给第 43 篇)。


09 改岔了怎么办:干净地退回去,别在烂摊子上硬补

上面那趟走得顺,是因为这里故意挑了个小任务。真实任务多半没这么乖——验证那一步常常是红的:功能没实现对、或者它把别处改坏了。这时候新手的本能反应往往是错的:对着已经改乱的代码,再让它「在这基础上修一下」

别这么干。 在一个已经偏了的状态上反复打补丁,越补越乱——它每次都带着上一版的错误上下文,很容易把窟窿越捅越大。正确的处理是:先干净地退回到一个已知正确的点,再带着「这次该怎么说得更清楚」重开一次。 这正好把第 37 篇的检查点和第 02 节那个开工前的 git 提交派上用场。

退回有两档,看你改到哪一步了:

退回档位用什么退到哪适合
轻档:撤销刚才的编辑第 37 篇的检查点,/rewindClaude 改这一批文件之前改岔了一两处、刚发现就想撤
重档:回到开工原点git,git restore . / git reset --hard你开工前那个干净提交整个方向都偏了、想从零重来

轻档最常用:在会话里敲 /rewind,它能把 Claude 这一轮的文件编辑倒带回去(第 37 篇专门讲过它的边界——能回文件、回对话,但别拿它当 git 使)。重档是兜底:要是改得面目全非、检查点也理不清了,就回到第 02 节那个开工提交——这就是当初为什么坚持「开工前先 commit」,那一个干净提交,就是你永远能逃回去的原点

退回去之后别急着原样重说一遍。先想想这次为什么偏了——十有八九是探索没做够、或者指令给得太含糊(第 15 篇讲的「话说清」)。一条经验:第一次让它改偏了,90% 是那句指令里漏了关键约束,比如没说清「只改这个函数、别动别的」。退回原点、把那句话补具体,第二次往往就顺了。退回不是失败,是止损——比在烂摊子上硬补省太多事。

💡 一句话总结:改岔了第一反应是「干净退回」,不是「在烂摊子上硬补」;轻档用 /rewind 撤编辑、重档用 git 回开工原点(开工前那次 commit 就是干这个的);退回后先补清指令再重开,别原样重说。


10 一组对照:老手怎么走 vs 新手怎么走

同样这六步,老手和新手走出来天差地别——差的全在那几个「省掉的交接棒」上。我把最常见的坑并排列出来,你对着自查:

环节❌ 新手常踩✅ 老手怎么走
开工随便哪个目录就敲 claude,不写 CLAUDE.md站对项目目录,先写三五行最小 CLAUDE.md 定规矩
探索上来就「给我改」,跳过看懂第一句永远「先别改、先看懂」,让它先摸现状
规划直接让它动手,方向偏了才发现让它先出方案、点头再改;没底就 plan mode
动手diff 看都不看一路 y每处 diff 扫一眼:动的对不对、有没有越界
验证信「我改好了」就完事亲手跑三遍:新功能、旧功能、bug 各验一遍
交付改完晾着,或不看范围直接提交先看改动概览、让它拟提交信息、log 确认入库

这张表的精髓就一句:新手把六步压成两步(说需求 → 拿结果),老手老老实实走六步。 刚上手那阵子谁都爱抄近道,吃过几次「方向跑偏 + 没验证就提交」的连环亏,才慢慢把这六步走顺。最该先练成本能的是头尾两棒——开头的「先探索」和结尾的「亲手验证」,这两棒守住,翻大车的概率就低一大半。

还有个常被问的:「每次都这么六步,不嫌麻烦?」 不嫌,因为任务越小,每步越快——咱这个练手任务,六步全走完也就十分钟。而且熟了以后,探索和规划常常能合并成一句话(「先看懂 @file 再告诉我你打算怎么改 X,别动手」)。流程是骨架,不是镣铐;骨架记牢了,怎么打快板是你的事。

💡 一句话总结:老手 vs 新手的差距全在「省没省掉交接棒」;最该练成本能的是头尾两棒——开头「先探索」、结尾「亲手验证」;任务越小每步越快,六步是骨架不是镣铐。


11 小结

这一篇没教任何新功能,只干了一件事——带你把前面三十八篇学的零件,第一次在一个真实小任务上连成一趟完整的实战路径

先把整趟你敲过的话连起来回放一遍,你会发现就这六七句、每句卡在一个交接棒上:

# 开工后(先定规矩)
帮我建个 CLAUDE.md:纯标准库别引第三方依赖;改完跑 python3 wordcount.py sample.txt 验证

# 探索(先看懂、别动手)
先别改任何代码。讲讲 @wordcount.py 怎么工作的、有没有容易崩的地方?

# 规划(出方案、等点头)
我想加 --top N 只看高频前 N 个词,顺手修不传文件名就崩溃的问题。先说方案,等我说开始再动手。

# 动手(点头放行,然后逐处审 diff)
方案可以,开始改吧。

# 验证(亲手跑,不信它说的)
(回终端跑:--top 3 / 不带 top / 不带文件名,三条各验一遍)

# 交付(看范围 → 提交 → 确认)
我改了哪些文件? → 用一句话描述这次改动,提交它。 → 显示我最后 1 次提交。

看清楚没——真正的「实战」就是这几句自然语言,难的从来不是话术,是把每句话放对位置。 把这趟路的六步串起来回顾:

步骤这一步干什么用到的前篇一句话关键点
开工站对目录启动 + 写最小 CLAUDE.md02 / 07 / 12 / 18核心规矩说一次,全场生效
探索让它先看懂代码、别动手16第一句永远「先别改、先看懂」
规划让它出方案、你点头20(plan mode)没底就 Shift+Tab 硬锁「批准前不改」
动手放它改、每处 diff 过一眼20(权限确认)事中拦截比事后回滚划算
验证亲手跑通,别信「我改好了」16 / 37跑出来的「通过」才是事实
交付看范围 → 拟提交信息 → 入库07本地 commit 可放手,push 自己把关

你现在应该能: 拿到任何一个「帮我给某个东西加个功能 / 修个 bug」的真实小需求,不再对着终端发懵不知先敲哪句——心里默念那六步(开工、探索、规划、动手、验证、交付),一棒一棒交到位地走下来;尤其守住头尾两棒「先探索、后验证」,让 Claude 既不瞎猜乱改、改完也确实跑得通。这套流程跑顺了,前面学的所有零件才算真正活了过来,能拧成一股绳替你干活。

这一篇是个分水岭——从这儿往后,咱们默认你「会把零件连成一趟」了,后面几篇会在这条实战路径上继续加新本事。


下一篇 40「Chrome:让它操作浏览器」——这一趟实战,Claude 干的全是「本地文件 + 命令行」的活。但真实工作里,多少事得在浏览器里完成:填个表单、点几下页面、抓一段网页上的数据、对着真实渲染的界面调样式。下一篇就给它接上浏览器这只「手」,让它从「只会改代码」迈向「能替你点鼠标」。想想看——当 Claude 不光能改你的代码、还能亲自打开浏览器替你操作时,它能帮你干的活,又要宽一大圈了。


40 · Chrome:让它操作浏览器

⚠️ 实验性功能,可能随版本变化。 本篇讲的 Chrome 集成目前处于测试版(beta),命令、前置版本、支持的浏览器都以官方文档为准,后续版本可能调整。

兄弟们,今天聊一个能让 Claude Code「长出手」的功能——操作浏览器

前面三十九篇里,Claude 干的活基本都在「文件 + 命令行」这一亩三分地:读你的代码、改你的文件、跑你的脚本。但真实开发里有一大堆事是离不开浏览器的——改完登录表单得打开页面点一下试试、报了个 bug 得看浏览器控制台(console)里红色的报错、设计稿还原得对着浏览器一像素一像素比。这些事,以前你只能自己切到 Chrome 手动来,然后把看到的复制回来喂给 Claude。

现在不用了。 接上 Chrome 集成,你在终端里说一句「打开 localhost:3000,用错误数据提交那个表单,看看报错提示对不对」,Claude 自己就把浏览器开了、表单填了、报错读了,回头告诉你结果。「改代码」和「在浏览器里验代码」第一次能在同一个对话里从头到尾搞定,不用来回切窗口。

我第一次接上它那天,盯着自己那个 Chrome 自动弹出新标签页、鼠标点搜索框、一个字一个字敲进去,愣是看了一会儿——那种「它真的在替我点」的感觉,跟之前在沙箱里跑命令完全是两码事。

这么说吧:前面 MCP(详见第 22 篇)是给它接上了数据库、Jira 这些数据源;Chrome 集成是给它接上了你天天在用的那个浏览器本身——连着你所有的登录态。这一篇就讲清楚它能干嘛、怎么接、有哪些坑、以及操作你「真浏览器」这件事的安全边界在哪。

看完这一篇,你会拿到:

  • 一句话讲明白 Chrome 集成是什么、它和 MCP / computer use 各管哪一块
  • 接上它的完整步骤(装扩展、--chrome 启动、前置版本和套餐要求),以及哪些浏览器 / 环境不支持
  • 六类高频用例(实时调试、设计验证、填表单、扒数据……,选自官方列出的典型工作流),每类配一句你真实会怎么用
  • 操作「真浏览器」相对沙箱的风险在哪、官方给了哪些护栏、你自己该守哪几条
  • 一个能照着跑、给了预期结果的最小实战:接上 Chrome 让它读一次页面

01 先搞懂:它到底是什么、能干什么

先给结论:Chrome 集成 = 让 Claude Code 借用你已经登录好一切的那个 Chrome,替你开网页、点按钮、填表单、读页面

关键词是「你已经登录好的那个」。官方说得很直接:

Claude 为浏览器任务打开新标签页,并共享您浏览器的登录状态,因此它可以访问您已登录的任何网站。浏览器操作在实时可见的 Chrome 窗口中运行。

把这句话拆开,有三个点对小白特别重要:

  • 开的是新标签页,不是另起一个陌生浏览器——它就在你眼前那个 Chrome 里干活。
  • 共享你的登录态——你 Gmail、Notion、公司后台都登录着,它直接就能进,不用你再配什么 API、贴什么 token。
  • 窗口实时可见——它点哪、填哪你全看得见,不是在后台偷偷摸摸

类比:叫了个代驾。 你今晚喝了点酒,叫个代驾把你送回家。代驾开的不是他自己的车,是你这台车——车里插着你的 ETC、储物格放着你的停车卡、导航里存着你家地址,这些他全能直接用,你不用重新给他办一张卡。但方向盘你随时能要回来:遇到要刷脸的小区门禁(代驾刷不了),他停下让你来。Claude 操作浏览器就是这么个「代驾」——开的是你那台登录好一切的浏览器,该它干的它干,遇到登录页、验证码(CAPTCHA)这种它过不了的,它停下来喊你

那它具体能干哪些活?官方列了一串,我挑出小白最有体感的几类,配上「你真实会怎么用」:

  • 实时调试:直接读浏览器控制台的报错和页面 DOM 状态,然后回头就把导致报错的代码改了——这是它和 MCP 最不一样的地方,能「看见」浏览器里发生了啥。
  • 设计验证:照 Figma 稿写完 UI,打开浏览器比一比对不对得上(衔接第 17 篇讲的还原设计稿)。
  • 网页应用测试:测表单校验、查视觉有没有变形、验用户流程走不走得通。
  • 操作已登录的应用:直接在 Gmail、Notion、Google Docs 里写东西、改东西,不用 API 连接器
  • 扒数据:把页面上的列表(名称、价格、库存)抽成结构化数据,存成本地 CSV。
  • 录 GIF:把一段浏览器操作录成 GIF,用来记录或者分享「这事儿是怎么发生的」。

举个我自己印象最深的场景:有回调一个前端的诡异 bug,页面加载时控制台报一个 undefined,我对着代码看了快半小时也没看出哪错了。接上 Chrome 后我就甩了句「打开 dashboard 页,把加载时控制台里的报错念给我听,再定位是哪段代码」——它读完报错、顺着调用栈找到了一个没做空值判断的地方,前后不到两分钟。换以前我得自己开 F12、复制报错、再贴回终端描述一遍,光来回倒腾就比这久。

💡 一句话总结:Chrome 集成让 Claude 借用你那台登录好一切的浏览器开网页、读控制台、填表单、扒数据——「改代码」和「在浏览器里验」第一次能在同一个对话里完整跑通


02 它和 MCP、computer use 各管哪一块

接之前先把一个容易混的事捋清:Claude 操作「外部世界」有好几条路,Chrome 集成只是其中一条。三条路别搞混了,不然你会纠结「这事该用哪个」。

官方在 computer use 那页讲了一个优先级顺序——Claude 干外部的活,会从最精准的工具往最笨重的工具试

如果您有该服务的 MCP server,Claude 会使用它。如果任务是 shell 命令,Claude 会使用 Bash。如果任务是浏览器工作且您已设置 Claude in Chrome,Claude 会使用它。如果以上都不适用,Claude 会使用 computer use。

类比:能打电话办的事就别专门跑一趟。 同一件事,能发个消息说清的就发消息(最快),发消息说不清就打个电话(慢一点),电话也办不了才亲自上门跑一趟(最慢最费事)。Claude 也是这个排序——先试最省事的,最省事的够不着才升级到更重的手段

三条路对照着看,你就知道各自的主场:

手段干什么什么时候轮到它本篇是它吗
MCP(详见第 22 篇)连数据库、Jira、Slack 这些有接口的服务服务有现成 MCP server,最精准,优先用
Chrome 集成操作浏览器里的网页:点、填、读控制台、扒数据活儿是网页操作、又装了 Chrome 集成
computer use控制本机原生 app:点 macOS 应用、看屏幕、截图上面都够不着(原生应用、模拟器、没 API 的工具)否,见下方

computer use(让 Claude 用你的电脑) 是兄弟篇,这里顺带提一句让你有个数。它比 Chrome 集成更「广」也更「慢」——Chrome 集成只能碰浏览器,computer use 能控制整个 macOS 桌面:打开原生 app、点任意按钮、截你的屏。官方原话:

屏幕控制保留用于其他工具无法到达的事物:原生应用、模拟器和没有 API 的工具。

几个关键差别记住就行(都以官方文档为准):

  • computer use 目前是研究预览版,只在 macOS 上的 CLI 可用(Windows 用桌面 app 那条线,见第 10 篇),要 Pro / Max 套餐,且不支持 -p 非交互模式
  • 它在 /mcp 菜单里以一个叫 computer-use 的内置 server 出现,默认关着,要手动启用。
  • 它跑在你真实的桌面上,会请求 macOS 的「辅助功能」和「屏幕录制」权限。

一句话分工:有接口走 MCP,网页里的事走 Chrome,连原生桌面都得碰才上 computer use。这一篇专讲中间那条——Chrome。

💡 一句话总结:Claude 碰外部世界从精准到笨重三条路——MCP(有接口的服务)→ Chrome(浏览器网页)→ computer use(整个 macOS 桌面);本篇专讲 Chrome 这条,它的主场是浏览器里的操作


03 怎么接上:装扩展、--chrome 启动

接 Chrome 集成,比接一个普通 MCP server 还简单——核心就两步:装个 Chrome 扩展,启动时带个 --chrome 标志。但有几个前置条件不满足就是接不上,先把门槛摆清楚。

先对四个前置条件

官方列了四条硬要求,差一条都连不上,挨个对一遍:

前置条件具体要求怎么查
浏览器Google Chrome 或 Microsoft Edge别的浏览器不行,见下方「不支持清单」
Chrome 扩展「Claude in Chrome」扩展 v1.0.36 或更高chrome://extensions 里看
Claude Code 版本v2.0.73 或更高终端跑 claude --version
套餐直接的 Anthropic 计划(Pro / Max / Team / Enterprise)/status 看订阅

最后一条套餐最容易栽,单独强调一下。官方明确:

Chrome 集成不可通过 Amazon Bedrock、Google Cloud Vertex AI 或 Microsoft Foundry 等第三方提供商获得。如果您仅通过第三方提供商访问 Claude,则需要单独的 claude.ai 账户来使用此功能。

翻成人话:你要是走 Bedrock / Vertex / Foundry 这些第三方接入(第 05 篇讲过),或者只用 API key,这功能用不了——它只认直接的 Anthropic 订阅。这点和桌面 app、computer use 一个脾气,记住就行。

哪些浏览器 / 环境不支持

这张「不支持清单」我专门拎出来,因为踩了会很懵

  • 浏览器:目前只支持 Chrome 和 Edge。Brave、Arc、以及其他基于 Chromium 的浏览器都不支持——别看它们也是 Chromium 内核就想当然。
  • 环境不支持 WSL(Windows 子系统 Linux)。你在 WSL 里跑 Claude Code 想接 Windows 上的 Chrome,这条路目前不通。

Arc 这个坑我亲自踩过。我日常主力浏览器就是 Arc(同样 Chromium 内核),想当然以为装上扩展就能用,结果 /chrome 死活连不上,扩展也装了、版本也对,就是不通。折腾了二十来分钟才翻到文档里那行小字「尚不支持 Brave、Arc 或其他基于 Chromium 的浏览器」——白忙活。后来老老实实单独装了个 Chrome 专门给它用,才秒连上。

装扩展 + 启动

前置条件齐了,正式接:

第一步:装「Claude in Chrome」扩展。 去 Chrome 应用商店搜「Claude」装上(Edge 也是在 Chrome 应用商店装同一个)。

装扩展、访问 Chrome 应用商店在国内一般需要「魔法上网」;扩展本身要连 Anthropic,网络不通时也连不上。

第二步:带 --chrome 启动 Claude Code。 在终端:

claude --chrome

或者你已经在一个会话里了,直接敲 /chrome 启用,不用退出重开。

就这两步。 接上之后,任何时候敲 /chrome 都能:检查连接状态、管理权限、重新连接扩展、选用哪个已连接的浏览器。要是同时连了多个浏览器,浏览器操作一开始 Claude 会问你用哪个。

不想每次都打 --chrome

嫌每个会话都加 --chrome 烦,可以设成默认:运行 /chrome,选「默认启用」

但官方专门提醒了一句代价,值得你想清楚再开:

在 CLI 中默认启用 Chrome 会增加上下文使用,因为浏览器工具始终被加载。如果您注意到上下文消耗增加,请禁用此设置,仅在需要时使用 --chrome

说白了:默认启用 = 浏览器那套工具每次会话都常驻,会吃掉一截上下文窗口(第 19 篇讲过工作台塞满会变蠢)。一般来说更稳的做法是不设默认,需要操作浏览器的会话才临时 --chrome——大多数纯改代码的活根本用不上浏览器,没必要让它一直占着地方。

顺带一提:如果你主力在 VS Code 扩展(第 08 篇)里干活,只要装了 Chrome 扩展,浏览器自动化就直接可用,不用加任何标志——这点比 CLI 省心。

网站权限从哪管

还有个细节:Claude 能浏览、点击、输入哪些网站,是从 Chrome 扩展那边继承的。官方:

网站级权限从 Chrome 扩展程序继承。在 Chrome 扩展程序设置中管理权限,以控制 Claude 可以浏览、点击和输入的网站。

也就是说,控制它能碰哪些站,去 Chrome 扩展的设置里调,不在 Claude Code 这边。这是它的第一道闸,下一节讲安全会再提。

💡 一句话总结:接 Chrome 就两步——装「Claude in Chrome」扩展 + 用 --chrome 启动(或会话里 /chrome);但先对齐四个前置(浏览器、扩展版本、CC 版本、Anthropic 订阅),且 Brave / Arc / 其他 Chromium、WSL 都不支持


04 典型用例:六类活儿,照着抄

接上只是开始,会用才值钱。官方给了一串示例工作流,我按「你大概率会遇到」的顺序,把六类最实用的拎出来,每类给一条可以直接照着改的指令。这些指令都是用自然语言说的,你照着套自己的场景就行。

用例一:测本地网页应用

开发时改完一个功能,让它直接帮你在浏览器里验:

我刚改了登录表单的校验逻辑。打开 localhost:3000,
用一组无效数据提交表单,看看错误提示有没有正确出现。

它会导航到你的本地服务器、跟表单交互、把观察到的结果报给你。这大概是用得最多的一类——改完前端不用自己切浏览器手点,它替你跑一遍验证流程。

用例二:用控制台日志调试

让它读浏览器控制台帮你定位问题。这里有个官方给的诀窍:别让它「把所有控制台输出都给我」,日志太长会刷屏——告诉它你要找的模式

打开 dashboard 页面,检查页面加载时控制台里有没有报错。

它会读控制台消息,按你说的模式或错误类型过滤,不会把一大堆无关日志全倒给你。

用例三:批量填表单

重复的数据录入最适合丢给它:

我有一个客户联系人表格在 contacts.csv 里。对每一行,
打开 crm.example.com 的 CRM,点「添加联系人」,
把姓名、邮箱、电话填进去。

它读你的本地文件、操作网页界面、一条条录进去。说句实话,这类「机械重复」的活儿是它最香的用武之地——你只要把数据准备好,剩下的它照着填。

用例四:直接在已登录的应用里写东西

这类最能体现「共享登录态」的爽:

根据最近的几个 commit 起草一份项目进展更新,
加到我那份 Google Doc(docs.google.com/document/d/abc123)里。

它打开文档、点进编辑器、把内容敲进去。Gmail、Notion、Sheets——凡是你已经登录的网页应用都吃这套,不用配任何 API。

用例五:从网页扒结构化数据

把页面上散着的信息抽成规整的数据:

打开商品列表页,把每件商品的名称、价格、库存状态抽出来,
存成一个 CSV 文件。

它导航到页面、读内容、编译成结构化格式存到本地。

用例六:录一段操作 GIF

想给同事演示「这功能怎么走」,让它录:

录一个 GIF,展示怎么走完整个结账流程,
从把商品加进购物车一直到确认页。

它把这段交互序列录下来、存成 GIF 文件。写文档、提 issue 配个动图,比打一堆字描述清楚多了。

把这六类对照「以前怎么干」摆一下,你就知道它省在哪:

场景❌ 没有 Chrome 集成✅ 有 Chrome 集成
验证前端改动自己切浏览器手点、看效果、回来描述一句话让它打开页面跑一遍报结果
调控制台报错F12 开控制台、复制报错、贴回终端让它直接读控制台、过滤出报错
批量录数据一条条手动复制粘贴进网页喂个 CSV,它照着逐行填
在 Notion / Docs 写自己整理好再粘进去让它直接进文档写(共享登录态)

提醒: /mcpclaude-in-chrome 能看到这些浏览器工具的完整列表,想知道它到底有哪些「手上的动作」,去那儿翻。官方还列了「多站点工作流」这类用例,这里略过,有兴趣可自行在 /mcpclaude-in-chrome 里探索。

💡 一句话总结:六类高频用例——测本地应用、读控制台调 bug、批量填表单、在已登录应用里写、扒页面数据、录演示 GIF,每类一句自然语言指令就能让它干,核心都是「省掉你手动切浏览器那一段」。


05 安全:操作「真浏览器」的风险在哪

这一节最不能跳过——因为它操作的是你真实的、登录着一切的浏览器,不是一个用完即焚的沙箱。这跟前面 Claude 在沙箱里跑命令(第 21 篇)是完全不同的信任边界。

风险到底在哪

回到「代驾」那个比方:代驾开的是你那台插着 ETC、放着停车卡的车。方便是真方便,但风险也实打实——他在你车里、用着你所有的卡。Chrome 集成同理:它共享你的登录态,意味着它能进的,是你登录着的所有网站——你的邮箱、你的公司后台、你的银行页面(只要你登录着)。

具体两类风险你得有数:

  • 登录态等于钥匙串:它访问网站不需要再认证,你登录了什么,它就够得着什么。让它去某个页面操作时,心里要清楚这台浏览器上还登录着哪些敏感账号。
  • 提示注入(prompt injection):这个第 21 篇专门讲过——网页内容里可能藏着「写给 AI 看」的恶意指令。它读一个页面时,页面上某段文字可能在偷偷指挥它干别的。操作浏览器时这个风险格外真实,因为它读的全是外部的、你控制不了的网页内容

官方给了哪些护栏

好在 Chrome 集成不是「敞开了让它乱来」,内置了几道闸:

  • 遇到登录 / 验证码会停下喊你:碰到登录页或 CAPTCHA,它暂停、要你手动处理,不会替你瞎填、瞎点过。
  • 操作实时可见:它在一个你看得见的 Chrome 窗口里干活,点哪填哪你全程盯得到,不对劲随时能掐。
  • 网站权限可控:上一节说的,在 Chrome 扩展设置里限定它能碰哪些网站——这是你最该用起来的一道闸,把它能动的范围圈小。

你自己该守的几条

官方护栏之外,还有几条操作真浏览器的土规矩值得记下来:

场景该怎么办
让它操作浏览器前先想清楚这台 Chrome 上还登录着哪些敏感账号
涉及钱 / 不可逆操作(下单、转账、删数据)⚠️ 自己来,别交给它,或全程死盯每一步
给它操作的网站范围✅ 在扩展设置里圈小,只放它确实需要的站
让它访问陌生 / 不可信网页⚠️ 警惕提示注入,内容里的「指令」别让它照单全收

总原则就一条:它在浏览器里点的每一下都是「真的」——不像沙箱里跑错了删个容器重来,浏览器里点了「确认付款」就是真付了。所以越是不可逆、越是涉及钱的操作,越要自己把着方向盘,让它干那些「错了也好收拾」的活。

这跟前面所有篇章的安全主线是一根弦:便利和风险成正比。Chrome 集成把便利拉满了——直接用你登录态——那对应的,你得把「它能碰什么」这道闸也守紧。

💡 一句话总结:Chrome 集成操作的是你登录着一切的真浏览器,不是沙箱——风险在「登录态即钥匙」和「网页里的提示注入」;官方护栏有「遇登录 / 验证码停手、操作可见、网站权限可控」,你自己则要圈小网站范围、把不可逆和涉钱操作攥在自己手里


06 动手:接上 Chrome,让它读一次页面

光看不练假把式。下面带你跑一个最小实战:接上 Chrome,让它打开一个网页、读点东西回来。全程不碰你的敏感账号,专门拿来验证「接通了没」

前提:你得是 Pro / Max / Team / Enterprise 直接订阅(不是 Bedrock / Vertex / API key),装好 Chrome 或 Edge。装扩展、访问网页可能需要「魔法上网」。

第一步:装「Claude in Chrome」扩展

在 Chrome 应用商店搜「Claude」,装上官方扩展。装完去 chrome://extensions 确认它已启用、版本 ≥ 1.0.36

✅ 自验:扩展列表里能看到「Claude」且是开启状态。

第二步:确认 Claude Code 版本够新

claude --version

预期:打印的版本号 ≥ 2.0.73。低了就先升级(npm update -g @anthropic-ai/claude-code 或按第 02 篇的方式更新),否则接不上。

第三步:带 --chrome 启动

claude --chrome

进去后敲 /chrome 看状态:

/chrome

预期:显示 Chrome 已连接、扩展状态正常。如果提示没检测到扩展,按官方排查:确认扩展已装并启用 → 确认 CC 是最新 → 确认 Chrome 在运行 → /chrome 选「重新连接扩展程序」。第一次启用时它会装一个本机消息传递配置,Chrome 要重启一次才读得到——头一回连不上,先重启 Chrome 再试。

第四步:让它打开页面读点东西

连上后,给它一条「只读、不碰敏感账号」的指令(官方文档站正好拿来练手):

打开 code.claude.com/docs,点一下搜索框,
输入「hooks」,把出现的结果告诉我。

预期:你会看见你那个 Chrome 弹出新标签页、自动导航过去、点搜索框、敲字——全程肉眼可见(这就是第 05 节说的「操作实时可见」)。然后它把搜到的结果列回终端。看到浏览器真的动起来、结果回来了 = 接通成功。

如果操作到一半浏览器没反应了,官方提示先查有没有弹出的对话框(alert / confirm)挡着页面——JavaScript 对话框会卡住浏览器事件;手动关掉再让它继续。长时间不动后断连,就 /chrome 选「重新连接扩展程序」(扩展的后台 service worker 会进空闲状态)。

跑通这四步,你就把「装扩展 → 启动 → 验连接 → 让它操作页面」这条完整链路走了一遍。以后让它干任何浏览器的活,本质都是这套,无非把第四步换成你真实的任务。

💡 一句话总结:动手就四步——装扩展、claude --chrome 启动、/chrome 验连接、给一条只读指令看浏览器真动起来;头回连不上多半是扩展没装好或 Chrome 没重启,按官方那串排查走一遍。


07 小结

这一篇给 Claude Code 接上了你天天在用的那个浏览器——从「只会摸文件和命令行」,到能开网页、读控制台、填表单、扒数据,「改代码」和「在浏览器里验」这两件事终于能在一个对话里从头到尾跑完

把核心串起来回顾:

你要做的事关键点
理解它是什么借用你登录好一切的真 Chrome,开新标签页操作,实时可见
分清它和别的工具MCP(有接口)→ Chrome(网页)→ computer use(整个桌面) 三条路,从精准到笨重
接上它装「Claude in Chrome」扩展 + --chrome 启动;对齐扩展 / CC 版本、要 Anthropic 直接订阅
知道哪不支持Brave / Arc / 其他 Chromium、WSL 都不行,只支持 Chrome / Edge
会用测本地应用、读控制台、批量填表单、在已登录应用写、扒数据、录 GIF
守住安全操作的是真浏览器(非沙箱):圈小网站权限、不可逆和涉钱操作自己来、警惕提示注入

你现在应该能: 讲清 Chrome 集成是什么、它和 MCP / computer use 各管哪一块,独立把它接上(装扩展 + --chrome),用自然语言指令让它干六类常见的浏览器活儿,并且清楚操作真浏览器的风险在哪、该守哪几条闸。这一接,Claude Code 从「本地代码助手」又往前迈了一步——能直接替你操作那个你最常打交道的窗口了。


下一篇 41「并行任务」——这一篇让一个 Claude 能操作浏览器了,但活儿一多,你会发现一个会话串着干还是慢:它开浏览器测着 A 功能,你 B、C 两个需求只能干等着。下一篇换个思路:怎么让多个任务真正并行铺开、各干各的、互不打扰。想想看:如果改前端、跑测试、扒数据这三件事能同时进行,而不是排队等一个 Claude 来回切,是不是又能省下一大段时间?


41 · 并行任务:让几个 Claude 同时开工,而不是排队

说出来有点丢人,但我自己第一次想「并行干活」时,干的就是这么一件蠢事:开了两个终端,都 cd 到同一个项目目录,一个让 Claude 改前端登录页,另一个让它顺手修一个后端的 bug。

心里还美滋滋地想:「这不双倍效率嘛。」

结果呢——两边都在改 package.json,一边刚写进去的依赖,被另一边的改动直接覆盖回滚了;git status 一看,工作区乱成一锅粥,谁改的哪行根本分不清。我那天花了比「老老实实一件件干」多得多的时间,才把两边的改动手动捋开,越捋越火大。就是那回我才明白:并行不是「多开几个窗口」这么简单,核心是「别让它们踩到同一块地」。

其实 Claude Code 早就备好了正经的并行工具——--worktree 给每个会话一份隔离的代码副本,--bg 把任务甩到后台批量跑,claude agents 给你一块总控台盯着它们。这一篇,咱们把上面那个坑连根填平,再带你把这几套手段亲手跑一遍。

看完这一篇,你会拿到:

  • 一句话讲清「为什么要并行」,以及并行的两个前提:任务互相独立、不抢同一份文件
  • 官方四种并行方式(子代理 / 代理视图 / 代理团队 / 动态工作流)一张表分清,知道该挑哪个
  • --worktree 给每个会话一份隔离副本,再不互相覆盖——附 .worktreeinclude、清理这些坑点
  • claude agents--bg 把任务甩到后台、一块屏幕盯进度,只在需要时介入
  • claude -p(无头模式,headless)把任务写进脚本批量跑,配 --bare 启动更快
  • 那条最重要的判断线:什么时候值得并行、什么时候反而把自己绕进去

01 先想清楚:并行到底解决什么问题,前提是什么

先给结论:并行解决的是「几件互不相干的活,不想排队一件件等」;但它能成立,全靠一个前提——这几件活别抢同一份文件

回想前面四十篇,咱们基本都在「一个会话」里折腾——开一个 Claude,给指令,它一步步干。这模式九成的活儿够用。但有两种时候你会嫌它慢。

一是任务天然就能拆开、互不依赖。 比如「改前端样式」「修后端一个 bug」「补一批单元测试」,三件事八竿子打不着,却只能排队:改完前端才轮到后端。明明能同时干,却被逼着串行。

二是任务大到一个会话扛不动。 比如「把整个代码库里某个旧 API 全换成新的」,涉及几十上百个文件,一个会话从头改到尾,上下文(context,可理解成它的「工作记忆」,详见第 19 篇)早塞满了,越往后越「忘事」。

类比:超市结账。 一条收银通道,十个人拎着购物车排长龙,第十个人得干等前面九个全结完——这就是串行。聪明的超市会多开几个收银口,十个人分到三四条队里同时结,总时间立刻砍下来。并行干活就是「多开收银口」:几件独立的活,分给几个 Claude 同时结账,而不是挤在一条队里。

但收银口能多开有个隐含前提:每条队是独立的,互不干扰。要是三个收银员共用同一个钱箱、同时往里塞钱找零,立刻乱套——这正是开头那个坑。所以并行的铁律就一条:

任务接触相同的文件吗?使用 worktrees 隔离工作。

落到你会遇到的真实场景,能并行的活儿长这样:

  • 「这三个互不相干的模块,各修各的 bug」——分三个会话同时修,互不打扰
  • 「把 utils/ 整个目录里没人用的死代码扫出来」——派个子代理去翻,主对话不被一堆文件灌满(详见第 23 篇)
  • 「同一份脚本,对 30 个文件各跑一遍同样的改动」——写成 headless 批量任务,机器自己跑完

💡 一句话总结:并行是为了让互相独立的活儿不用排队(像超市多开收银口),但它成立的铁律只有一条——别让它们抢同一份文件,否则越并行越乱。


02 官方四种并行方式:先认门,别一上来就挑花眼

Claude Code 的并行不止一招。官方专门有一页《并行运行代理》把它们摆在一起比,核心区别就一个问题:谁来协调这些活儿? 是 Claude 在一个对话里派活收活,是你甩出去回头再看,还是 Claude 当工头统筹一队。

先把四种方式一张表认清,这一节是地图,下面几节才是逐个深挖

方式它是什么谁协调什么时候用
子代理(Subagent)一个会话内派出去的工作者,在自己上下文里干完返回摘要Claude 在对话里派活收活辅助任务会用一堆搜索结果 / 日志把主对话灌满,而你不会再翻这些过程
代理视图(Agent view)一块屏幕,调度并监控多个后台会话,claude agents 打开(研究预览)你甩出任务、回头检查你有几个独立任务,想交出去、一眼扫状态、只在需要时介入
代理团队(Agent teams)多个会话协调干活,共享任务列表、互发消息,有个 leader 统筹(实验性,默认关)Claude 当工头统筹一队你想让 Claude 把项目拆成几块、分派、还让工人们保持同步(详见第 29 篇)
动态工作流(Workflows)一段脚本,跑一大批子代理并交叉验证结果(研究预览)脚本而非 Claude 逐轮判断活儿大到几个子代理协调不过来,或要结果互相验证:全库审计、500 个文件迁移

⚠️ 实验性标注:上表里代理视图(agent view)和动态工作流(workflows)是研究预览版、代理团队(agent teams)是实验性默认关闭——界面、快捷键、行为后续都可能变。照做前先 claude --version 对一下版本。子代理则是稳定功能。

这表你不用背,记住一句就行:「谁协调」是分水岭——Claude 在对话里顺手派 → 子代理;你撒手甩后台 → 代理视图;Claude 当工头带队 → 代理团队;脚本死板地批量跑 → 动态工作流。

还有两个东西它们本身不是「并行方式」,而是给并行打配合的工具,这一篇重点讲前一个:

  • Worktrees:给每个会话一份单独的 git 副本,让并行会话永远不会改到同一份文件。这是开头那个坑的正解,第 03 节专讲。
  • /batch:一个 skill,让 Claude 把一个大改动拆成 5 到 30 个 worktree 隔离的子代理,每个开一个 PR。它是「子代理 + worktree」的打包用法,不是单独一种协调风格。

子代理(第 23 篇)和代理团队(第 29 篇)前面都专门讲透了,这一篇不重复——本篇聚焦那块还没碰过的:worktree 隔离、后台多会话、headless 批量

💡 一句话总结:并行有四种正经方式,「谁协调」是区分关键;worktree 和 /batch 是给并行打配合的工具,不算单独方式;本篇专攻前面没讲过的 worktree、后台会话、headless 三块。


03 用 worktree 隔离:给每个会话一份「自己的副本」

这一节是开头那个坑的正解,也是整篇最该吃透的一块

先说那个坑到底坑在哪:两个会话 cd同一个目录,等于俩人在同一张图纸上同时涂改,后写的盖住先写的,天经地义会乱。git worktree(工作树,git 的一项原生能力)就是来根治这个的。

类比:把同一张图纸复印几份,几个人各改各的副本。 设计图只有一张原稿,三个人要同时在上面标注,挤在一张纸上必然涂乱。正确做法是复印三份——每人拿一份副本随便改,改完再合并。git worktree 干的就是这事:它从同一个仓库历史里,给你拉出几个独立的工作目录,各有各的文件和分支,但共享同一套提交历史和远程。一个会话在它的副本里怎么改,都碰不到另一个会话的副本。

官方把这个值钱的点讲得很清楚:

在自己的 worktree 中运行每个 Claude Code 会话意味着一个会话中的编辑永远不会触及另一个会话中的文件,因此您可以让 Claude 在一个终端中构建功能,同时在第二个终端中修复错误。

一行命令开一个隔离会话

最省事的用法:启动时加 --worktree(或简写 -w),后面跟个名字。Claude 会自动创建一个隔离的 worktree 并在里头开工。默认这个 worktree 放在你仓库根目录下的 .claude/worktrees/<名字>/,分支名叫 worktree-<名字>

claude --worktree feature-auth

想再开第二个独立会话?另一个终端、换个名字,跑同样的命令:

claude --worktree bugfix-123

这下两个会话各在自己的副本里,一个搭功能、一个修 bug,谁也碰不到谁的文件——开头那个「互相覆盖」的惨剧从根上没了。名字懒得起?省略它,Claude 自动生成一个像 bright-running-fox 这样的:

claude --worktree

会话里也能临时让它进 worktree——直接说一句「在 worktree 中工作」,它会用 EnterWorktree 工具给你建一个。

第一次在某个目录用 --worktree 之前,得先在该目录里跑一次普通的 claude接受那个工作区信任对话框。没接受过信任,--worktree 会直接报错让你先去跑一次 claude——连 -p 模式也一样。

三个新手必踩的坑点

坑点一:.claude/worktrees/ 要进 .gitignore 不然这些 worktree 的内容会在你主目录里显示成一堆「未跟踪文件」,看着碜得慌。官方专门提醒了这条。

坑点二:worktree 是干净的新副本,你的 .env 不在里面。 worktree 是个全新检出,主仓库里那些没被 git 跟踪的文件(像 .env.env.local)默认不会跟过去——结果新会话一跑就缺环境变量。解法是在项目根放一个 .worktreeinclude 文件,列出要自动复制进每个 worktree 的本地文件,语法和 .gitignore 一样:

.env
.env.local
config/secrets.json

这个坑我亲自栽过:兴冲冲 -w 开了个会话准备改后端,结果 Claude 跑起来一直报连不上数据库,我对着报错排查了半天,甚至怀疑是数据库挂了——最后才反应过来,.env 压根没复制进 worktree,连接串它根本读不到。后来在每个项目根都顺手放上 .worktreeinclude,就再没犯过这毛病。

坑点三:退出时记得「保留还是删除」。 官方的清理规则很实在:

  • 没改任何东西(无未提交改动、无未跟踪文件、无新提交):worktree 和它的分支会自动删除;但如果会话事先命了名(--name),Claude 会弹提示让你决定保留还是删除。
  • 改了东西:Claude 会问你「保留还是删除」——保留就留着目录和分支,以后能回来接着干;删除就连同未提交的改动一起丢掉。
  • 非交互(-p)跑出来的 worktree 不自动清理,因为没有退出提示,得自己 git worktree remove 删。

不想让 Claude 自动建,也能手动来

要完全掌控 worktree 放哪、用哪个分支,直接用 git 自己建也行(git 工作流第 43 篇会专门讲):

# 在新分支上建一个 worktree
git worktree add ../project-feature-a -b feature-a

# 进去启动 Claude
cd ../project-feature-a && claude

# 列出所有 worktree
git worktree list

# 干完删掉
git worktree remove ../project-feature-a

官方提醒一句很容易忘的:每个新 worktree 都是独立检出,记得在里头重新装依赖、配虚拟环境——别指望它继承主目录装好的 node_modules

💡 一句话总结:worktree 给每个会话一份独立的代码副本(像复印图纸各改各的),claude --worktree <名字> 一行开一个隔离会话;记牢三坑——.claude/worktrees/.gitignore.env.worktreeinclude 复制、退出时选「保留 / 删除」。


04 多会话并行:后台甩任务 + 一块总控台盯着

worktree 解决了「文件不打架」,但还有个问题:开了三五个会话,难道得开三五个终端来回切、一个个盯? 太累了。这就轮到「代理视图(agent view)」上场。

类比:机场塔台的航班动态板。 塔台不会派一个人盯一架飞机——一块大屏上,所有航班的状态一目了然:哪架在滑行、哪架等指令、哪架已落地。调度员平时扫一眼总览,只在某架要他拍板时才接管对讲claude agents 给你的就是这么块塔台屏:所有后台会话排成行,状态一眼扫清,谁需要你才介入。

⚠️ 研究预览:agent view 是官方标注的研究预览功能,需要较新版本的 Claude Code,界面和快捷键后续可能变。先 claude --version 对一下版本。

把任务甩到后台

后台会话的精髓是:它不绑在你的终端上——你关掉这块屏、关掉 shell、甚至另开一个交互会话,它照样在跑。有几种甩法。

第一种,从 shell 直接甩,加 --bg

claude --bg "调查一下 SettingsChangeDetector 这个不稳定的测试为啥老挂"

甩出去后,Claude 会打印这个会话的短 ID 和管理它的命令,大概长这样:

backgrounded · 7c5dcf5d
  claude agents             list sessions
  claude attach 7c5dcf5d    open in this terminal
  claude logs 7c5dcf5d      show recent output
  claude stop 7c5dcf5d      stop this session

第二种,从正在聊的会话里甩:敲 /bg/background 的简写),把当前对话挪到后台。

claude agents 这块塔台屏管它们

打开总控台:

claude agents

它会占满整个终端,把所有后台会话按状态分组列出来——「需要输入」「正在工作」「已完成」各归一拨。每行开头一个图标,颜色和动画告诉你这个会话啥状态:

状态图标含义
工作中动画闪动正在跑工具或生成回复
需要输入黄色在等你回答或批权限
已完成绿色任务成功干完
失败红色出错结束了

塔台屏的核心操作就三个,新手记住这仨足够

  • Space(窥视):选中一行按空格,弹出小面板看它最近的输出、或它正卡在哪个问题上——多数时候不用进完整对话,瞄一眼就够
  • 回复:在窥视面板里直接打字回它,按 Enter 发出去,不用离开总控台
  • Enter / (附加):想钻进某个会话好好聊,按回车「附加」进去,它就变成一个完整的交互会话;在空输入框按 又退回总控台。

这里有个藏得很深但极关键的细节,正好把上一节的 worktree 串起来:每个后台会话在改文件前,Claude 会自动把它挪进 .claude/worktrees/ 下的隔离 worktree。也就是说——你用代理视图并行甩任务,文件隔离是自动帮你做好的,不用像第 03 节那样手动 -w。官方文档确认:代理视图在分派每个会话时,会自动为它创建独立的 worktree。

举个常见的并行组合:同时甩出三个后台会话——一个修 flaky 测试、一个审一个 PR、一个补文档。你该干嘛干嘛,每隔一阵 claude agents 扫一眼——谁变绿了去验收,谁标黄了去拍板。比开三个终端来回切省心太多了。

⚠️ 一个会消耗你额度的事实:后台会话和交互会话一样吃你的订阅用量。并行跑十个,额度消耗速度大约是跑一个的十倍。别看后台跑得欢就无脑开一堆。

💡 一句话总结:--bg 把任务甩到后台、/bg 把当前会话甩后台,claude agents 给你一块塔台屏(像机场航班板)——Space 窥视、直接回复、Enter 附加;后台会话的文件隔离是自动用 worktree 做好的,但并行越多越费额度。


05 Headless 批量:写进脚本里,让它无人值守地跑

前面两套是「你坐在终端前盯着」。但有一类活儿你压根不想盯——同一个套路,对一批东西各跑一遍;或者把 Claude 塞进 CI、塞进脚本,让它像个命令行工具一样被自动调用。这就是无头模式(headless,即不开交互界面、跑完就退出的运行方式)。

类比:把指令写成纸条投进自助机,跑完吐结果。 你不会守着自动售货机看它出货——投币、按键、东西掉出来,全程不用你盯。headless 就是这种「无人值守」:你把提示和参数一次性写清,塞给 claude -p,它跑完把结果吐出来,你拿去用就行。

核心就一个标志:-p(或 --print)。加上它,claude非交互地跑一次然后退出

claude -p "找出 auth.py 里的 bug 并修掉" --allowedTools "Read,Edit,Bash"

这里 --allowedTools预先批准它能用哪些工具——因为没人在旁边点「同意」,你得提前告诉它「这几样工具随便用,别停下来问」(权限模式详见第 20、35 篇)。

三个让它真正好用的配套

配套一:管道喂数据。 headless 会读标准输入(stdin),所以你能像用任何命令行工具一样,把数据用管道喂进去。比如把构建报错丢给它解释,结果写进文件:

cat build-error.txt | claude -p "简明扼要说清这个构建错误的根因" > output.txt

排查构建挂掉时,就这么一行甩过去——比复制报错粘进会话快多了。

配套二:--bare 让启动更快。 默认 claude -p 会加载和交互会话一样的全套上下文(hooks、skills、plugins、MCP、CLAUDE.md 全读一遍),脚本里跑就嫌慢、还可能被队友 ~/.claude 里的配置干扰。加 --bare 跳过这些自动发现,启动快、结果还在每台机器上一致:

claude --bare -p "总结这个文件" --allowedTools "Read"

官方明确说了:

--bare 是脚本和 SDK 调用的推荐模式,将在未来版本中成为 -p 的默认值。

配套三:--output-format json 拿结构化结果。 脚本要解析 Claude 的输出,纯文本不好处理。加 --output-format json,它会返回带元数据的结构化 JSON(结果、会话 ID,还有 total_cost_usd 这次花了多少钱),配 jq 一提取就能用:

claude -p "总结这个项目" --output-format json | jq -r '.result'

把 headless 拼成「批量」

单条 -p 还不算批量。真正的批量是拿 shell 循环把它套起来——对一批文件各跑一遍同样的活。比如给某个目录下每个 .py 文件都生成一句话说明:

for f in src/*.py; do
  claude --bare -p "用一句话说明 $f 是干什么的" --allowedTools "Read"
done

这就是「无人值守批量」的雏形:循环、-p--bare,三件套。当然,如果这批活儿大到几十上百个文件、还想互相验证结果,那就该上第 02 节提的动态工作流或 /batch 了——它们本质就是把这种批量正经工程化。

⚠️ 一个要留意的计费变化:官方文档注明,从 2026 年 6 月 15 日起,订阅套餐下的 Agent SDK 和 claude -p 用量会从一份独立的月度 Agent SDK 额度里扣,跟你的交互用量分开算。脚本批量跑之前,心里有个数(计费细节见第 06 篇)。

💡 一句话总结:headless 用 claude -p 非交互跑一次就退出(像投自助机不用盯),配 --allowedTools 预批工具、--bare 加速、--output-format json 拿结构化结果;拿 shell for 循环套起来就是「批量」雏形。


06 最关键的一节:什么时候别并行

讲了三套并行手段,但这一节比前面都重要——因为太多人一学会并行就上头,啥都想拆,结果越并行越乱、越并行越贵

先把判断线立起来。值得并行,得同时满足两条:任务互相独立(A 不依赖 B 的结果)、不抢同一份文件(或者用 worktree 隔开了)。少一条,并行就是给自己挖坑。

并排看一眼,什么该并行、什么老实串行:

场景该不该并行为什么
三个互不相干的模块各修各的 bug✅ 并行独立、不抢文件,典型该并行
同一套改动批量跑 30 个文件✅ 并行(headless / /batch互不依赖,机器代跑最省事
「先重构 A,再基于新 A 改 B」❌ 串行B 依赖 A 的结果,并行只会拿到旧 A
两个会话都要改 package.json❌ 串行(或务必 worktree 隔离)抢同一份文件,正是开头那个坑
一个小改动,五分钟能干完❌ 串行拆开的协调成本比省下的时间还多
任务之间要频繁互通中间结果⚠️ 看情况沟通成本高,不如一个会话顺着干

下面三条土规矩,是踩出来的经验,送给你。

第一,有先后依赖的活儿,死活别并行。 「重构完核心模块,再让其他模块适配新接口」这种,后一步就得等前一步——硬并行,后面那个会照着旧版本改,跑完发现全得返工。这么干一次,就白白浪费两个会话的额度。

第二,小活儿别拆。 五分钟能改完的东西,你光是「想清楚怎么拆、开几个会话、回头怎么合并」就不止五分钟。拆活儿本身有成本,小活儿拆了纯亏。

第三,并行越多越烧额度。 第 04 节那条得再强调一遍:并行十个会话,额度大约按十倍速度烧。一个稳妥的习惯是——手动并行控制在三五个以内,真要大批量(几十上百)就交给 /batch 或动态工作流去工程化,而不是手动开一屏会话。

说白了,并行是把双刃剑:对的场景上它,效率翻几倍;错的场景上它,比串行还慢还贵还乱。判断「该不该并行」,永远比「怎么并行」更值钱。

💡 一句话总结:值得并行的铁律是 「独立 + 不抢文件」,少一条就别拆;有先后依赖的活儿、五分钟的小活儿别并行;并行越多越烧额度,控制在三五个以内,大批量交给 /batch


07 动手:亲手跑一遍 worktree 隔离 + 后台甩任务

光看不练假把式。下面这套全程基于一个 git 仓库,没仓库的先随便建一个练手。命令真实可跑,每步都给了预期输出,你照着走一遍,这几套手段就有肌肉记忆了。

用到 git 仓库;后台会话部分需要较新版本的 Claude Code(agent view 是研究预览),先 claude --version 看一眼。下面命令不依赖魔法上网。

第一步:进一个 git 项目,先接受信任对话框

cd 你的某个git项目
claude

进去后随便问一句(比如「这个项目是干嘛的」)再退出。这一步是为了接受工作区信任——没接受过,下一步 --worktree 会直接报错。

第二步:用 --worktree 开一个隔离会话

claude --worktree test-parallel

预期:Claude 在 .claude/worktrees/test-parallel/ 下建好一个隔离 worktree 并在里头启动。你在这个会话里改任何文件,都只动这份副本,主目录纹丝不动。退出时如果改过东西,它会问你「保留还是删除」——练手就选删除。

第三步:确认 worktree 真建出来了(另开一个终端,回到主项目目录)

git worktree list

预期:列表里除了主检出,多出一行指向 .../.claude/worktrees/test-parallel,带自己的分支。看到这行 = 隔离副本确实建好了。

第四步:把一个任务甩到后台

claude --bg "列出这个项目所有 markdown 文件的标题"

预期:终端打印一行 backgrounded · <短ID>,后面跟着 claude attach / claude logs / claude stop 几条管理命令。看到这串 = 任务已甩进后台在跑,你的终端立刻就能干别的。

第五步:打开塔台屏盯它

claude agents

预期:整个终端被代理视图占满,刚甩的那个会话作为一行出现,旁边标着状态(工作中 / 已完成)。选中它按 Space 窥视输出,按 Esc 关面板,再按 Esc 退出代理视图。看到这块分组列表 = 你已经能用一块屏管多个后台会话了。

第六步:清理

# 停掉刚才那个后台会话(短ID 换成第四步打印的)
claude stop <短ID>

# 删掉练手的 worktree(在主项目目录)
git worktree remove .claude/worktrees/test-parallel

预期claude stop 打印停止确认;git worktree remove 之后再跑一次 git worktree list,那行 test-parallel 已经没了。清干净 = 一条完整链路走通

跑通这六步,你就把「开隔离会话 → 确认副本 → 甩后台 → 塔台盯 → 清理」这条并行主链亲手走了一遍。以后真要并行干活,本质都是这套,无非换任务、加几个会话。

💡 一句话总结:动手链路就六步——claude(接受信任)→ --worktree 开隔离会话 → git worktree list 确认 → --bg 甩后台 → claude agents 盯 → stop + git worktree remove 清理;走通一遍比记十条命令都管用。


08 小结

这一篇把「让几个 Claude 同时开工」这件事,从「为什么并行」一路讲到「什么时候别并行」,中间塞了三套能上手的手段。

把核心要点串起来回顾:

你想干的事用什么关键点
搞清并行解决啥「独立 + 不抢文件」两前提像超市多开收银口,但每条队得独立
认清并行有哪几种四种方式一张表「谁协调」是分水岭;agent view / workflows 是研究预览,teams 实验性
让会话不互相覆盖文件--worktree / git worktree给每个会话一份独立副本,记牢 .gitignore.worktreeinclude、清理三坑
后台甩任务、一屏盯进度--bg + claude agents后台会话不绑终端,文件隔离自动用 worktree;Space 窥视、Enter 附加
把任务写进脚本批量跑claude -p(headless)--allowedTools 预批、--bare 加速、--output-format json 拿结构化结果
判断该不该并行「独立 + 不抢文件」铁律有依赖、小活儿别拆;并行越多越烧额度,控制在三五个内

你现在应该能: 看明白并行到底解决什么、铁律是「独立且不抢文件」;分清官方四种并行方式该挑哪个;用 --worktree 给会话开隔离副本,再不重蹈开头那个「互相覆盖」的覆辙;用 --bgclaude agents 把任务甩后台、一屏盯着;用 claude -p 把活儿写进脚本批量跑;最重要的是——拿到一个任务,先冷静判断「这玩意儿值不值得并行」,而不是一上头就拆

回头看开头那个「俩终端同改一个目录」的蠢事,根子就是不懂隔离、也没想清依赖。现在你手里有 worktree 这把隔离的钥匙、也有那条判断线,能比一头扎进去的人少走一大圈弯路。


下一篇 42「环境变量」——这一篇里你已经撞见好几个环境变量了:--bare 背后那个 CLAUDE_CODE_SIMPLE、关掉后台任务的 CLAUDE_CODE_DISABLE_BACKGROUND_TASKS、改配置目录的 CLAUDE_CONFIG_DIR……它们像一排藏在背后的「拨动开关」,不显眼,却能悄悄改掉 Claude Code 的行为。下一篇就把这排开关一个个翻出来,告诉你哪个管什么、哪个值得你动。想想看:同样一条命令,在你机器上和在 CI 里跑出来的行为可能不一样——差别往往就藏在这几个环境变量里。


42 · 环境变量:藏在背后那排「总开关」

都说环境变量是「高阶玩家才碰的东西」,说句实话——这话害了不少人。

太多人连模型、配代理、调超时,全靠每次开会话手动 /model 点一遍、手动改一遍,改完下次开新会话又得重来。问起为啥不一次配死,答案多半是「环境变量听着好硬核,怕搞坏」。

可你回头看看前面四十一篇——第 04 篇配 API key、第 05 篇接国产模型、第 19 篇管上下文、第 21 篇关遥测……这些事的底层,几乎全是同一套机制在兜底:环境变量。 你早就在用了,只是没人把它们摊开摆在一起讲。

这么说吧:环境变量不是「高阶才碰」,而是 「一次拨好、终身受益」的那排总开关。怕它,纯粹是因为没人告诉你哪几个开关常用、拨错了顶多什么后果。今天就把这层窗户纸捅破。

看完这一篇,你会拿到:

  • 一句话讲明白环境变量在 Claude Code 里到底管什么、为什么值得花十分钟搞懂
  • 三种设置方式(shell 临时 / shell 配置文件持久 / settings.jsonenv 字段)分别什么时候用,一张表说清
  • settings.json 那四类文件各管多大范围、哪个进 git 哪个不进——直接接上第 31 篇
  • 一份「最该认识的环境变量」清单:连接、超时、隐私、配置目录,带默认值和踩坑提示
  • 当同一件事既能用环境变量又能用设置字段时,到底谁说了算(优先级规则)
  • 一个能照着跑、给了预期输出的实战:亲手设一个变量并验证它真的生效了

01 先搞懂:环境变量在 Claude Code 里到底管什么

先给结论:环境变量是 Claude Code 启动时读的一组「键值对开关」,用来定它怎么连模型、怎么认证、超时多久、要不要上报数据这些底层行为。

你前面用的那些功能——/model 换模型、claude mcp add 接服务、/config 调设置——大多是「会话里临时拨一下」。但有些行为,你希望每次启动都按你的来,不用每回手动设:比如「我永远走自建代理的地址」「我所有请求超时都给我放宽到 20 分钟」「我这台机器绝不上报任何遥测」。这些「定下来就别变」的底层规矩,就是环境变量管的。

官方一句话给它定了性:

环境变量可以控制 Claude Code 的行为,例如模型选择、身份验证、请求路由和功能切换。

类比:咖啡机上的预设按钮。 一台带预设的咖啡机,你可以每次现调——水量多少、浓度几档、要不要加奶,按一杯调一次;也可以把常喝的那杯存成「我的预设」,以后一键出杯,机器自己记着参数。 环境变量就是后者:它把那些你「每次都想这么来」的设置固化下来,Claude Code 一启动就照着读,省得你回回手动拨。

落到真实场景,你大概率会在这几种时候想起它:

  • 「我接了 DeepSeek,不想每次都手动指模型」——把模型和地址写进环境变量(第 05 篇那套,底层就是它)
  • 「公司网络慢,默认 10 分钟超时老不够」——一个变量把超时放宽
  • 「这台是公司机器,合规要求一律不上报遥测」——一个变量直接关掉(第 21 篇提过)
  • 「我有工作和个人两个账号,想分开互不干扰」——一个变量切换配置目录

看出来没?这些全是「设一次,长期生效」的需求。 环境变量就是为这类需求生的。

💡 一句话总结:环境变量是 Claude Code 启动时读的一组「键值对总开关」,管连接、认证、超时、隐私这些底层行为;它的价值在于把「每次都想这么来」的设置一次固化,不用回回手动拨


02 在哪设:三种方式,从「就这一次」到「永远生效」

知道了它管什么,接下来最实在的问题——到底在哪儿设? 答案是三个地方,差别就一条线:这次设的,影响多久、影响谁。

官方把这条线讲得很干脆:

在 shell 中设置的变量仅在该终端会话期间有效,而在设置文件中的变量在每次运行 claude 时都适用。

我把三种方式按「生效范围从窄到宽」排开,你对着选:

方式一:shell 里临时设(就管这一个终端)

在启动 claude 之前,在终端里 export 一下。只对当前这个终端窗口有效,关掉就没了。

macOS / Linux / WSL:

export API_TIMEOUT_MS="1200000"
claude

Windows PowerShell:

$env:API_TIMEOUT_MS = "1200000"
claude

这种适合 「我就想这一次试试」——临时放宽个超时、临时换个地址,跑完关掉终端,啥也没留下。

方式二:写进 shell 配置文件(这台机器每次都生效)

如果你想每开一个终端都自动带上,把那行 export 加进你的 shell 配置文件。Mac 上默认是 ~/.zshrc,很多 Linux 是 ~/.bashrc

# 加到 ~/.zshrc 末尾
export API_TIMEOUT_MS="1200000"

存盘后开新终端(或 source ~/.zshrc)就生效。这是「我这台机器上,所有项目、所有终端都这么来」的做法。

Windows 上要持久化,用 setx API_TIMEOUT_MS "1200000"(CMD)或 [Environment]::SetEnvironmentVariable("API_TIMEOUT_MS", "1200000", "User")(PowerShell),然后开一个新终端才生效。

方式三:写进 settings.json 的 env 字段(跟着配置走,跟启动方式无关)

第三种,也是最常用的——写进 settings.json 里的 env 键。官方说得很清楚它的好处:

Claude Code 在启动时直接从文件读取它们,因此无论如何启动 claude,它们都会生效。

{
  "env": {
    "API_TIMEOUT_MS": "1200000",
    "BASH_DEFAULT_TIMEOUT_MS": "300000"
  }
}

这个文件路径和写法,第 31 篇讲 settings.json 时已经铺过底了。这里你只要记住:env 是它专门留给环境变量的那个口子,把变量写这儿,跟你怎么敲 claude 无关,它都读得到。

三种方式并排一看就清楚该怎么选:

设置方式生效范围关掉终端还在吗最适合
shell 临时 export仅当前终端❌ 没了「就想这一次试试」
写进 ~/.zshrc这台机器所有终端✅ 在「我个人机器全局这么来」
写进 settings.jsonenv跟着该配置文件作用范围走✅ 在「跟项目/团队绑定,谁启动都生效」

一个顺手的习惯:临时验证一个变量管不管用,用 shell export 试;确认要长期用,就挪进 settings.jsonenv 为啥偏爱 settings.json 而不是 ~/.zshrc?因为下一节那张「文件分级」表——settings.json 能让你精确控制「这个变量是只给我、还是全团队、还是只这个项目」,~/.zshrc 做不到这种区分。

💡 一句话总结:三种设置方式按生效范围排开——shell 临时 export(就这一次)、写进 ~/.zshrc(本机全局)、写进 settings.jsonenv(跟配置走、跟启动方式无关);临时试探用第一种,长期生效推荐第三种。


03 settings.json 的四类文件:谁能管到、哪个进 git

上一节说 settings.jsonenv 是我最推荐的口子,但这里有个新手必踩的坑settings.json 不止一个文件,它有四类,写进不同的文件,这个变量管的「人」完全不一样。

这事第 31 篇专门拆过,这里就环境变量的角度再钉一遍——因为放错文件的后果很真实:你以为只给自己设的代理地址,一不小心提交进了 git,全团队都被你带跑偏了

类比:公司报销标准贴公告栏 vs 你自己记在便签。 财务把「打车 50 封顶」打印出来贴在公告栏,全公司都得照办,这是公开规矩;你自己嫌麻烦,在工位便签上写「这个月我自费的咖啡别报」,这是只管你自己的私人备注。环境变量写进哪个文件,就是在选「贴公告栏」还是「记便签」。

官方给的这张表,直接告诉你每类文件「管到谁」:

文件适用于
~/.claude/settings.json你,在每个项目中
.claude/settings.json在项目中工作的每个人,检入源代码控制
.claude/settings.local.json你,仅在此项目中,未检入
托管设置你组织中的每个人,由管理员部署

翻成大白话,四句话记住:

  • ~/.claude/settings.json——在你主目录下,「我自己,所有项目都这么来」。你个人偏好放这儿。
  • .claude/settings.json(项目根)——「这个项目里所有人都这么来」,而且它进 git,队友拉下来就带上。团队统一的规矩放这儿。
  • .claude/settings.local.json(项目根)——「只有我,只在这个项目」,而且它不进 git.local 后缀默认被忽略)。带私人凭据、只属于你的临时设置放这儿。
  • 托管设置——管理员给全组织统一下发的,你一般改不了,也轮不到你设。

这里有个不大不小的跟头很容易栽。接自建网关时,图省事把 ANTHROPIC_BASE_URL 连同一个带个人 token 的地址写进项目根的 .claude/settings.json,然后顺手 git commit——推之前要是没扫一眼 diff,就麻烦了:那玩意儿一旦推上去,等于把私有地址(还可能带凭据)公开给了所有能看到这个仓库的人。 所以有条铁律记死:凡是带「个人专属」性质的变量(私有地址、个人配置目录这种),一律进 .local 那个不上 git 的文件;只有「全队都该一样」的,才往 .claude/settings.json 里放。

这个变量的性质该写进哪个文件
我个人偏好,所有项目通用~/.claude/settings.json(主目录)
全队统一,要随项目共享.claude/settings.json(进 git)
我私人的、带凭据的、只这个项目.claude/settings.local.json(❌ 不进 git)

💡 一句话总结:settings.json 分四类文件,写进哪个决定这变量管「谁」——主目录管自己全局、项目根 settings.json 进 git 管全队、.local 不进 git 只管自己;带个人凭据的变量,死活别往进 git 的文件里放。


04 最该认识的那几个变量:连接、超时、隐私、目录

官方那张环境变量表,说实话,长得吓人——上百个,从 AWS Bedrock 到 OpenTelemetry 导出器,绝大多数你这辈子都用不上。所以这一节我不堆清单,只挑小白真实会碰到的那十来个,按用途分四组,每个给你说清「干啥的、默认多少、什么时候动它」。

一组:连接与认证(怎么连上模型)

这组是前面第 04、05 篇的底层。三个核心:

ANTHROPIC_API_KEY      # 你的 API 密钥
ANTHROPIC_BASE_URL     # 把请求改道到代理或网关
ANTHROPIC_MODEL        # 默认用哪个模型
  • ANTHROPIC_API_KEY——你的 API 密钥。这里有个特别容易踩的点,官方写得明明白白:一旦设了这个 key,即使你已经登录了订阅(Pro / Max / Team / Enterprise),也会改用这个 key。想换回订阅,得 unset ANTHROPIC_API_KEY 把它清掉。注意:交互模式下,Claude Code 会弹一次确认提示,让你批准或拒绝用这个 key,选择记住后续自动沿用;非交互模式(-p)则直接使用,不弹确认。 这个坑很容易踩——明明开了 Max 订阅,账单却走了 API 计费,查半天才发现是 ~/.zshrc 里残留了一行 export ANTHROPIC_API_KEY(第 04 篇详谈了订阅 vs API key 怎么选)。

  • ANTHROPIC_BASE_URL——把 API 请求改道到你的代理或网关。接国产模型、走自建中转,核心就是它(第 05 篇那套配置,主角就是这个变量)。

  • ANTHROPIC_MODEL——指定默认模型。注意它的优先级:--model 标志和会话里的 /model 命令会盖过它(下一节细讲)。

二组:超时(嫌它太快放弃就调这个)

网络慢、或者走代理绕远路时,最常调的就是超时。两个最常用:

变量管什么默认值
API_TIMEOUT_MS单次 API 请求的超时600000(10 分钟)
BASH_DEFAULT_TIMEOUT_MS长跑 bash 命令的默认超时120000(2 分钟)
  • API_TIMEOUT_MS——API 请求多久算超时。官方提示:网络慢或走代理时把它调大。但别瞎填——它有个上限 2147483647超过这个数会让底层计时器溢出,请求直接秒失败(手抖多打个 0 是常见情形,结果每次请求瞬间报错,排查半天才发现是溢出)。

  • BASH_DEFAULT_TIMEOUT_MS——Claude 跑那种长命令(比如装依赖、跑构建)默认给多久。默认 2 分钟,跑大型构建不够时调它。

三组:隐私与遥测(合规/强隐私场景)

第 21 篇讲安全时点过的几个,这组管「往外发不发数据」:

DISABLE_TELEMETRY=1      # 关掉遥测上报
DO_NOT_TRACK=1           # 同上,跨工具通用的约定
  • DISABLE_TELEMETRY——设成 1 退出遥测。官方明确说遥测数据不含你的代码、文件路径或 bash 命令;但合规要求严的环境,设上它图个干净。
  • DO_NOT_TRACK——设成 1等同于 DISABLE_TELEMETRY。这是个被很多开发者 CLI 共同遵守的跨工具约定,你设过一次,好些工具都认。

还有个一键全关的——CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1,官方说它等同于同时设了 DISABLE_AUTOUPDATERDISABLE_FEEDBACK_COMMANDDISABLE_ERROR_REPORTINGDISABLE_TELEMETRY。强隐私 / 隔离环境一个变量全关掉,省事。

四组:多账号与上下文(进阶但好用)

两个高频、强烈推荐你认识的:

  • CLAUDE_CONFIG_DIR——覆盖配置目录(默认 ~/.claude)。所有设置、凭证、会话历史、插件都存这底下。它最大的用处是并行跑多个账号——官方给的例子就很实用:
# 给工作账号开个独立配置目录,互不干扰
alias claude-work='CLAUDE_CONFIG_DIR=~/.claude-work claude'

工作号和个人号就可以这么分:平时 claude 走个人配置,敲 claude-work 走另一套完全隔离的设置和登录态,两边的历史、凭证、MCP 配置井水不犯河水

  • DISABLE_AUTO_COMPACT——设成 1 关掉「接近上下文上限时的自动压缩」(第 19 篇讲过 auto-compact 这个机制)。手动 /compact 仍然能用。想完全自己掌控什么时候压缩,才设它——多数人保持默认即可。

⚠️ 一句重要提醒:官方说得很死——Claude Code 只在「启动时」读环境变量。所以你改完任何变量(无论改 shell 还是改 settings.json),都得退出 claude 重开,新值才生效。改完没反应,十有八九是没重启。

💡 一句话总结:真正常碰的就四组——连接认证(ANTHROPIC_API_KEY/BASE_URL/MODEL)、超时(API_TIMEOUT_MS 默认 10 分钟)、隐私(DISABLE_TELEMETRY/DO_NOT_TRACK)、多账号(CLAUDE_CONFIG_DIR;改完务必重启 claude 才生效。


05 优先级:同一件事好几个地方都能设,到底谁说了算

学到这儿你会冒出一个很自然的疑问:模型既能用 ANTHROPIC_MODEL 设、又能用 /model 命令选、还能在 settings.json 里写 model 字段——三个都设了,听谁的?

这就是「优先级(precedence)」要回答的事。不搞清它,你会遇到「我明明设了啊怎么没用」的灵异现象。

先记住官方给的第一条总纲——环境变量 > 设置字段

当相同的行为同时具有环境变量和设置字段时,环境变量优先。例如,ANTHROPIC_MODEL 覆盖 model 设置。当环境变量未设置时,设置字段适用。

类比:老板当面那句话,压过员工手册。 员工手册(settings.json 的字段)白纸黑字写着「报销打车 50 封顶」;可老板今天当面跟你说「这趟远,你打车实报实销」(环境变量)——这一趟你当然听老板当面那句的。环境变量就是那句「当面交代」,比手册里写死的字段更优先。等老板没特别交代时(环境变量没设),才回去按手册(设置字段)办。

但这里有个反直觉的拐点,新手最容易栽:不是所有东西环境变量都压得住。 模型这件事,官方专门点了名:

--model/model 覆盖 ANTHROPIC_MODEL

也就是说,模型这条链是这样的:

/model 命令 / --model 标志   ←  最优先(你当场的选择)
        ↓ 盖过
ANTHROPIC_MODEL 环境变量      ←  其次
        ↓ 盖过
settings.json 的 model 字段   ←  兜底

为啥模型这儿反过来了?其实很合理——你在会话里手动 /model 切一下,是「我现在就想用这个」的明确当场意图,它当然该压过你之前设死的那个环境变量。 这跟「老板当面那句压过手册」是同一个逻辑:越「当场、越明确」的指令,优先级越高。

配置方式相对优先级一句话
/model 命令 / --model 标志最高你会话里/启动时当场的明确选择
ANTHROPIC_MODEL 环境变量你预先设死的默认
settings.jsonmodel 字段兜底都没设时才用

注意:这个「命令/标志盖过环境变量」是模型这类配置的规矩,不是放之四海皆准。官方原话提醒不同功能交互方式不一样——比如 CLAUDE_CODE_EFFORT_LEVEL 反而会覆盖 /effort 命令。所以拿不准某个具体变量时,回官方那张变量表查它那一行的说明,别想当然。

这条很容易栽一次:在 settings.json 里写死了 ANTHROPIC_MODEL,结果某次会话里随手 /model 切了个别的,切完就忘了——下半场一直在用临时切的那个,还纳闷怎么跟配置的不一样。其实道理很直白:/model 当场选的,本来就该压过预设的环境变量。这不是 bug,是设计。

💡 一句话总结:总纲是环境变量 > 设置字段(老板当面话压过员工手册);但模型这类有例外——/model/--model 这种「当场明确指令」反过来压过 ANTHROPIC_MODEL;规律是「越当场越明确,优先级越高」,拿不准就查官方那行说明。


06 动手:设一个变量,亲手验证它真的生效了

光看不练,环境变量这东西永远隔层纱。下面带你走一遍最小闭环:设一个变量 → 进会话 → 确认它真生效了。全程不依赖你任何已有的复杂配置,几分钟搞定。

我们拿 BASH_DEFAULT_TIMEOUT_MS(bash 命令默认超时)来练——选它是因为它安全、可观察、改错了也不影响连接

第一步:先看默认状态(在终端,启动 claude 之前)

什么都别设,直接开一个会话:

claude

进去后,让它跑一句话,问它当前的 bash 超时:

我现在的 bash 命令默认超时是多少毫秒?读一下你环境里的 BASH_DEFAULT_TIMEOUT_MS,没设的话就说默认值

预期:它会告诉你这个变量没显式设置,走默认 120000(2 分钟)。记住这个基线值,等会儿对照。然后退出会话(敲 /exit 或 Ctrl+C 两下)。

第二步:用 shell 临时设一个值,再开会话

回到终端,临时 export 一个不一样的值(设成 5 分钟),紧接着开会话:

export BASH_DEFAULT_TIMEOUT_MS="300000"
claude

Windows PowerShell 用:$env:BASH_DEFAULT_TIMEOUT_MS = "300000" 然后 claude

进去后,问同样的问题

我现在的 bash 命令默认超时是多少毫秒?

预期:这次它该读到 300000(5 分钟),而不是默认的 120000看到值从 120000 变成了 300000 = 你的临时设置真的被读进去了。 这就验证了「方式一:shell 临时设」确实管用。

第三步:验证「关掉终端就没了」

退出会话,完全关掉这个终端窗口,重新开一个新的,直接 claude(这次什么都不 export),再问一遍同样的问题。

预期:又变回 120000(默认值)。因为 export 只对那个已经关掉的终端有效——这就亲眼印证了第 02 节那条「shell 临时设,关掉终端就没了」。

第四步(可选):写进 settings.json,让它持久

如果你想让这个值长期生效、跟启动方式无关,把它写进 settings.json。最稳妥是写进只属于你、不上 git 的那个文件:

{
  "env": {
    "BASH_DEFAULT_TIMEOUT_MS": "300000"
  }
}

写进 .claude/settings.local.json(当前项目根、不进 git),或 ~/.claude/settings.json(你的主目录、所有项目通用),按你想要的范围选——参考第 03 节那张表。

存盘后,新开终端、直接 claude(不 export),再问一遍——这次该稳定读到 300000 了,而且无论你以后怎么启动 claude,它都在。这就是「方式三:写进 settings.json」相比 shell 临时设的好处:一次写好,不用回回 export。

跑完这四步,你就把环境变量「设 → 验证生效 → 验证范围 → 持久化」整条链路亲手走了一遍。以后设任何变量,本质都是这套:先临时试管不管用,确认了再挪进 settings.json 固化。

💡 一句话总结:验证一个变量生不生效,最稳的办法就是「问 Claude 它读到的值」;先 shell 临时 export 试探(关终端就没)、确认管用再写进 settings.json 持久化——亲手走一遍这条链路,环境变量就再也不玄了。


07 小结

这一篇我们钻到水面下,把控制 Claude Code 底层行为的那排「总开关」——环境变量——认全、拨明白了。

归纳一下,整篇讲的核心就五件事:它管什么、在哪设、写进哪个文件、常用的那几个长啥样、多处都设了听谁的。一张表串起来:

你要搞清的事答案关键点
环境变量管啥连接、认证、超时、隐私这些底层行为启动时读的键值对开关,「设一次长期生效」
在哪设shell 临时 / ~/.zshrc / settings.jsonenv按生效范围选,长期用推荐 settings.json
写进哪个 settings 文件主目录 / 项目根(进 git) / .local(不进 git)带凭据的别进 git
最常用哪几个ANTHROPIC_*API_TIMEOUT_MSDISABLE_TELEMETRYCLAUDE_CONFIG_DIR各有默认值,改完重启才生效
多处都设了听谁的环境变量 > 设置字段;但 /model 压过 ANTHROPIC_MODEL越当场越明确,优先级越高

你现在应该能: 看懂环境变量在 Claude Code 里到底管什么、知道三种设置方式各自的生效范围、清楚 settings.json 四类文件谁进 git 谁不进、认识连接/超时/隐私/多账号这几组最常用的变量、并且想明白当同一件事多处都能设时该听谁的。更重要的是——你亲手设了一个变量、验证了它真生效、还看到了「关掉终端就没」和「写进文件就持久」的区别。 这层窗户纸一旦捅破,环境变量就从「高阶玄学」变成了你随手能拨的开关。

回到开头那句话:环境变量从来不是「高阶才碰」,而是「一次拨好、终身受益」。 你前面四十一篇里那些「每次都得手动设一遍」的别扭,现在多半都能用一个变量一劳永逸地解决了。


下一篇 43「Git 工作流」——环境变量帮你把 Claude Code 的底层行为安顿明白了,接下来该让它真正融进你每天的开发节奏。说到开发,绕不开的就是 Git:让 Claude 帮你写提交信息、理清 diff、开 PR、处理冲突……它在 Git 这块到底能帮到哪一步、又有哪些坑得你自己盯着?下一篇好好聊聊。想想看:你愿意让 AI 替你 git commit,但 git push 到生产分支这一下,你敢撒手吗?