ORANGE BOOK · CLAUDE CODE

第九章 自动化与定时任务(/loop 与 Hooks)


一、自动化的本质:把"按需触发"变成"自动触发"

我们先不谈 /loop,也不谈 Hooks,先想一个更朴素的问题——为什么需要"自动化"

1.1 一个普通人的"被触发"清单

你可能没意识到,你这一天的大部分时间,都被"触发"消耗掉了。

早上 7:00 你的闹钟响,你起床——这是时间触发。 9:30 同事在群里 @ 你,你停下手头的事去回——这是事件触发。 12:00 公司微信群弹"今天饭堂吃啥",你看到才决定要不要订外卖——这是条件触发。 晚上 6:30 钉钉提醒你"该健身了",你犹豫一下出门——又是时间触发。 睡前你刷一眼银行 APP,看到这个月已经花了 8000,你叹一口气——这是事件触发

我们一天 24 小时,被各种"提示音"、"通知"、"推送"切片成了无数小段。每一段你都要从"做事"切换到"被打扰再决定"再切换回"做事"——大脑这种切换的成本极高,心理学叫任务切换损耗,平均切换一次要花 23 分钟才能彻底回到深度工作状态。

自动化的本质,就是把这些"被触发"的事,一次性教给一个员工,让员工替你听见、替你想、替你做。你不用再被打扰,你只在最后看一眼"员工产出"。

这就是 Claude Code 的 /loop 和 Hooks 真正想做的事——不是炫技,不是省代码,而是把你大脑从无数小切换中解放出来

1.2 你每天在做的"重复触发"

打开你的手机,看一下日历、闹钟、提醒事项,把"每天会重复发生的事"挑出来:

时间 你的动作 重复频率
早上 7:00 看天气、看新闻、看日程 每天
早上 8:30 看一遍邮箱新邮件 每天
早上 9:30 看一眼股票/基金 工作日
中午 12:00 决定今天吃什么 每天
下午 5:00 看下今天还有什么没干完 工作日
周日晚上 复盘一下这一周 每周
月初 看一下上个月花了多少钱 每月

你看,"重复"就是规律。所有规律都可以自动化。但在 Claude Code 出来之前,你只有两种自动化方式:

  • 苹果/安卓的"快捷指令":能跑,但只能跑死板的命令,不会"思考"。
  • 写脚本 + 系统 cron:能思考,但要会写代码,普通人完全没门。

Claude Code 把这两件事合并了:你只要会写一句中文,剩下的"会思考 + 自动触发"它都帮你搞定。

1.3 自动化的三种触发模式

不管什么工具,自动化只有三种触发方式,记住这三种,你就抓住了所有自动化的本质:

触发模式 关键词 对应工具 例子
时间触发 "什么时候" /loop 每天早上 8 点跑一次
事件触发 "发生什么" Hooks 文件被修改后立即跑
条件触发 "满足什么" Hook + 脚本判断 服务器 CPU > 80% 时报警

第三种"条件触发"本质上是前两种的组合——你要么用时间去轮询条件(每分钟检查一次),要么用事件去判断条件(数据来了就比对)。所以掌握 /loop 和 Hooks 这两件,等于覆盖了所有自动化场景。

把这三种模式落到生活里,你会发现它们的用途完全不一样:

模式 适合什么场景 不适合什么场景
时间触发 周期性产出(早报、周报、月报)、固定的轮询(每天看一次股票) 紧急的、不确定何时发生的事(如服务器突然宕机)
事件触发 发生了就要立刻反应的事(代码改完立即测试、Bash 跑前先审核) 周期性的事(你不会"代码每天 8 点改一次")
条件触发 "满足条件才动"(CPU > 80% 报警、新邮件含某关键词推送) 简单时间事项(直接用时间触发更省)

你也可以这么记——时间触发是日历,事件触发是耳朵,条件触发是嗅觉

1.4 Claude Code 的两件武器

武器 触发方式 配置方式 你说的"指令"
/loop 时间(Cron 表达式) 命令行注册 一段中文提示词
Hooks 事件(工具调用、会话生命周期) JSON 配置文件 一段 shell 脚本/命令

把它们放在一张大图里:

                       Claude Code 自动化双轮
        ┌──────────────────────────┬──────────────────────────┐
        │      /loop(时间)        │        Hooks(事件)      │
        ├──────────────────────────┼──────────────────────────┤
        │  闹钟:到点了,干活!      │  反射弧:发生了,干活!    │
        │                          │                          │
        │  例:每天 8:00 出早报     │  例:你改了文件,自动 lint │
        │  例:每周一 9:00 写周报   │  例:你跑了 rm,先警告     │
        │  例:每 5 分钟查健康       │  例:会话结束自动备份      │
        │                          │                          │
        │  控制权:在 Claude 这边    │  控制权:在你这边          │
        │  适合:周期性产出          │  适合:工程纪律 / 守门员    │
        └──────────────────────────┴──────────────────────────┘
                          ↓                      ↓
                    "员工自己上班"          "员工的肌肉记忆"

记住这个隐喻:/loop 是给 AI 设的闹钟,Hooks 是给 AI 长的反射弧。一个让它"按时上班",一个让它"看见就反应"。


二、/loop 详解:把 Claude 变成 24 小时员工

2.1 /loop 是什么

/loop 是 Claude Code 在 2026 年 2 月 正式上线的内置定时任务功能。你只需要两样东西:

  1. 一个 Cron 表达式——告诉它"什么时候触发"。
  2. 一段中文提示词——告诉它"触发后干什么"。

注册成功后,Claude Code 的后台守护进程会按照 Cron 表达式定时启动一个新的会话,把提示词喂给 Claude,让它在你不在场的情况下自己跑完任务。

/loop 出来之前,要做同样的事,普通人需要:写 Python 脚本 + 配置系统 cron + 处理 token + 调试错误。整套下来初学者至少 3 天起步。/loop 把这件事压缩成 30 秒。

2.2 Cron 表达式速查(5 分钟搞懂)

Cron 表达式是一段 5 个字段的字符串,专门用来表达"什么时候"。它的样子是这样的:

*  *  *  *  *
│  │  │  │  │
│  │  │  │  └── 星期 (0-7,0 和 7 都是周日)
│  │  │  └───── 月 (1-12)
│  │  └──────── 日 (1-31)
│  └─────────── 时 (0-23)
└────────────── 分 (0-59)

关键规则只有 4 条:

  1. *:表示"任意值",等于"每"。
  2. 数字:表示"那个具体值"。
  3. */n:表示"每隔 n",比如 */5 在分钟位就是"每 5 分钟"。
  4. a-b:表示"范围",比如 1-5 在星期位就是"周一到周五"。

下面是普通人最常用的 Cron 表达式速查表,记住这一张表,你 95% 的需求都能套

表达式 中文含义
0 8 * * * 每天早上 8:00
30 7 * * * 每天早上 7:30
*/30 * * * * 每 30 分钟一次
*/5 * * * * 每 5 分钟一次
0 9 * * 1-5 工作日(周一到周五)早上 9:00
0 17 * * 5 每周五下午 5:00
0 21 * * 0 每周日晚上 9:00
0 22 1 * * 每月 1 号晚上 10:00
0 0 1 1 * 每年 1 月 1 日凌晨(新年钟声)
0 9,18 * * * 每天 9:00 和 18:00 各一次
0 */2 * * * 每 2 小时一次(0:00、2:00、4:00…)
15 14 * * 3 每周三下午 2:15

小知识:Cron 表达式的"时区"用的是你电脑所在系统的时区,不是 UTC。所以 0 8 * * * 在你电脑上就是"本地时间早上 8 点",不用换算。

2.3 三个写 Cron 的小技巧

写 Cron 表达式如果还是不熟,给你三个万试万灵的小技巧:

技巧 1:先想"几点几分",再想"周几"。比如"每天 7:30",先写出 30 7(分时),再考虑天和周——都不限制就用 * * *,组合成 30 7 * * *

技巧 2:不会写的,去 crontab.guru 在线测。这是个免费小网站,你输入表达式,它实时告诉你"对应中文是什么",还会列出"下 5 次会在哪天哪时触发"。每个 Claude Code 老用户的浏览器收藏夹里都有这个网址。

技巧 3:让 Claude 自己写。你最简单的办法——直接和 Claude 说"我想每周三下午两点半触发,cron 是什么",它会回答 30 14 * * 3,并解释清楚。

写完后一定要在 crontab.guru 复核一遍——Cron 表达式只要错一位数字,触发时间就完全不同,而你看着自己写的字符串往往看不出问题。

2.4 第一个 /loop 任务

打开 Claude Code,输入:

/loop "0 8 * * *" "请生成今日早报,包括:天气、日程、邮件简报、新闻 5 条,发到我的微信"

回车后你会看到:

[OK] Loop 任务已注册
   ID:        loop_a7c3f1
   Cron:      0 8 * * *  (每天 8:00)
   下次运行:  明天 08:00
   状态:      enabled
   日志路径:  ~/.claude/loops/loop_a7c3f1/

到此为止,你已经"雇佣"了一个员工——它每天 8:00 准时上班,干完这件事就下班,不要工资。

注意几个细节:

  • ID 是系统自动生成的,叫 loop_xxxx 这种,记下来——后面所有管理操作都靠它。
  • 下次运行时间是基于你注册的那一刻计算的,所以如果你 8:30 注册了"每天 8:00",第一次跑会是明天 8:00,不是今天。
  • 状态默认是 enabled(启用)。注册后立即生效,没有"待审核"环节。
  • 日志路径会保存这个任务每次跑的完整记录,包括输入提示词、用了哪些工具、token 消耗、最终输出。

第一次注册时 Claude Code 可能会问你"是否授予该任务调用 MCP 的权限?"——因为生成早报需要调天气、日历、邮件、新闻的 MCP。回答 yes 即可。第十章会专门讲这种"前置授权"的安全机制。

2.5 注册成功后会立刻发生什么

很多新手以为注册完就万事大吉,其实不是。/loop 注册成功的瞬间,背后会发生这几件事:

你按下回车
    ↓
Claude Code CLI 把 /loop 命令转成 JSON
    ↓
JSON 写入 ~/.claude/loops/loop_xxxx/config.json
    ↓
通知后台守护进程 claude-coded
    ↓
守护进程把任务加入"待运行"队列
    ↓
守护进程根据 Cron 计算下一次触发时间
    ↓
返回成功 → 你看到 "[OK] Loop 任务已注册"

这意味着——只要你电脑开着 + claude-coded 在跑,任务就会按时触发。如果你电脑关机了,错过的那次就直接跳过(不会补跑)。

如果你不希望"错过就跳过",注册时加 --catch-up

/loop "0 8 * * *" "..." --catch-up

这样开机后会自动补跑当天还没跑过的那次。但慎用——如果你电脑关了 7 天,开机后会一次性跑 7 次,token 会爆。

2.6 管理 /loop 任务

/loop 自带 4 个管理子命令,全部都可以记成"动词 + ID":

命令 作用
/loop list 列出所有已注册的 /loop 任务
/loop disable <id> 暂停某个任务(不删除,可以重新启用)
/loop enable <id> 重新启用一个被暂停的任务
/loop remove <id> 删除任务(不可恢复)
/loop logs <id> 查看任务的运行日志
/loop run <id> 手动触发一次(调试时用)

举个完整的例子。第一次跑出来的早报你嫌新闻太多了,想改成 3 条,操作流程是:

你 →  /loop list

Claude →
ID            Cron          下次运行       提示词预览
loop_a7c3f1   0 8 * * *     明天 08:00    请生成今日早报,包括:天气、日程…
loop_b8d2e5   30 7 * * 1-5  明天 07:30    工作日邮件汇总…

你 →  /loop remove loop_a7c3f1

Claude →
确认删除 loop_a7c3f1? (y/n)

你 →  y

Claude →
[OK] 已删除

你 →  /loop "0 8 * * *" "请生成今日早报,包括:天气、日程、邮件简报、新闻 3 条,发到我的微信"

Claude →
[OK] Loop 任务已注册
   ID:        loop_e9f4d2
   ...

整个过程不到 30 秒。

2.7 /loop 背后发生了什么

为了让你更安心地把任务交给它,简单讲一下 /loop 的"幕后机制":

  1. 后台守护进程:Claude Code 安装时会在你电脑上注册一个轻量级常驻进程(macOS 上是 claude-coded、Windows 上是后台服务)。这个进程开机自动启动,每分钟检查一次有没有 /loop 任务到点。
  2. 独立会话:每次触发时,它会启动一个全新的会话——不会和你当前的对话混在一起。所以即便你正在用 Claude,定时任务也不会打断你。
  3. 独立 token 计费:每次跑都会消耗 token(订阅用户走配额,API 用户走 API key),所以请务必看 2.6 的"成本控制"。
  4. 错误自动重试:默认重试 1 次,第 2 次失败会写错误日志但不再重试。可以通过 --retry 3 改成最多 3 次。
  5. 日志保留 30 天:自动滚动清理。

2.8 成本控制:别让 /loop 一个月烧光你的钱

/loop 最大的"坑"是——它默默在后台烧 token,你不打开日志可能根本不知道。务必加上下面三个参数中的至少一个:

/loop "0 8 * * *" "..." --max-tokens 50000
/loop "0 8 * * *" "..." --timeout 600
/loop "0 8 * * *" "..." --max-cost 0.5
参数 作用 推荐值
--max-tokens N 单次任务最多消耗 N 个 token 普通任务 50000,复杂任务 200000
--timeout N 单次任务最多跑 N 秒 5–10 分钟
--max-cost X 单次任务最多花 X 美元 重要任务 0.5–2,玩具任务 0.1

真实事故:本书作者第一次试 /loop 时设了一个 "每 5 分钟检查一下 GitHub 有没有新 PR",没设上限,结果在睡觉的 8 个小时里跑了 96 次,每次消耗 8000 token,一晚上烧掉 $4.6。第二天早上看到账单差点哭出来。

预算速算公式

月成本 ≈ 单次 token × 日触发次数 × 30 × 单价

举几个例子(按 Sonnet 4.5 单价 $3/百万输入 + $15/百万输出 估算):

任务 单次 token 频率 月成本估算
每天早报(30K) 30,000 1 次/天 ~ $4
每周月报(80K) 80,000 4 次/月 ~ $3
每天竞品(100K) 100,000 1 次/天 ~ $14
每 5 分钟健康检查(5K) 5,000 288 次/天 ~ $20

如果你装了 5-10 个 /loop,月成本可能就来到 $50-100。务必每月初看一次总账。


三、11 个开箱即用的 /loop 模板

下面 11 个模板都是经过实战的,直接复制到 Claude Code 就能用。每个模板的格式是:

  • Cron 表达式 + 中文解释
  • 完整提示词(你照抄就能跑)
  • 前置依赖(需要装哪些 MCP 或 Skill)
  • 预计 token 消耗(按 Sonnet 4.5 估算)

关于"提示词写多长":注意观察下面 11 个模板,提示词都比较"啰嗦"——不是因为 Claude 听不懂简短指令,而是因为 /loop 是无人值守的,你不能在场补充说明。所以你要在第一句话就把所有约束、口味、格式、分发渠道写清楚,让它一个人也能跑出"你想要"的结果。

每个模板下面都有"调优建议"——告诉你跑了一周后通常会想改的点,提前节省你的时间。

模板 1:每日早报(每天 7:30)

/loop "30 7 * * *" "请生成今日早报,按顺序输出:

1. 【天气】今天本地天气、最高最低温、是否带伞,一句话;
2. 【日程】查我今天日历的全部事项,列出时间、地点、与会人;
3. 【邮件】查我邮箱过去 12 小时的未读邮件,挑出 3 封最重要的,每封一句话总结;
4. 【新闻】给我 5 条今天我应该知道的全球大事,每条一行;
5. 【提醒】查我的 Todo 清单,挑出今天到期的任务。

全部内容用中文,控制在 600 字以内,最后通过 wechat MCP 发到我的微信文件传输助手。" --max-tokens 80000
  • Cron30 7 * * * = 每天早上 7:30
  • 依赖weather / gcal / gmail / news / todoist / wechat 这 6 个 MCP
  • 预计 token:每次约 30K,月成本约 $4
  • 调优建议:跑一周后大概率会想——"新闻太多了改成 3 条"、"邮件挑选算法不够准(漏了真正重要的)"、"周末的早报省略掉"。逐个调整即可。

模板 2:每周一周报草稿(每周一上午 9:00)

/loop "0 9 * * 1" "请生成上周周报草稿,覆盖周一到周日:

1. 【完成事项】查我上周的日历、邮件 sent 文件夹、Notion 工作日志,提取我做完的事,分类列出;
2. 【未完成事项】查我的 Todo 清单,列出还没勾掉的、属于上周的任务;
3. 【数据指标】查飞书表格 'XXX 项目周指标',输出关键数字的环比;
4. 【下周计划】基于本周未完成 + 已知排期,列出下周 5 件最重要的事;
5. 【风险提示】我有没有什么任务超过 2 周还在 in_progress?

输出格式按公司模板:标题《Cassius 周报 - 第 N 周》,存到 Notion 的'我的周报'数据库下,状态设为 draft,最后给我发一条提醒。" --max-tokens 100000
  • Cron0 9 * * 1 = 每周一上午 9:00
  • 依赖gcal / gmail / notion / todoist / feishu
  • 预计 token:每次约 60K,月成本约 $6(4 周)
  • 调优建议:你大概率想加"截图本周飞书表格的关键图表附进去"。这一点用 feishu-screenshot MCP 可以做到。

模板 3:每周日周回顾(每周日晚 21:00)

/loop "0 21 * * 0" "请帮我做本周个人复盘,但不要变成长篇大论:

1. 【数字盘点】这一周我跑步几公里?读书几页?睡眠平均几小时?读取健康 MCP 和 Notion 阅读日志;
2. 【关键回忆】查我这周的微信收藏 + Notion 日记,挑出 3 件让我印象最深的事;
3. 【目标进度】我月度目标完成了百分之多少?列出每个目标的进度条;
4. 【下周建议】基于本周表现,给我 3 条下周可以改进的具体建议(不要鸡汤);
5. 【一句话】用一句话评价这一周。

输出存到 Notion 的'周复盘'数据库,封面颜色根据本周自评:好=绿、一般=黄、差=红。" --max-tokens 80000
  • Cron0 21 * * 0 = 每周日晚上 9:00
  • 依赖apple-health / notion / wechat
  • 预计 token:每次约 50K

模板 4:每月账单分析(每月 1 号上午 9:00)

/loop "0 9 1 * *" "请帮我分析上个月的账单:

1. 【收入】查招商银行 + 支付宝 + 微信的入账,分类汇总;
2. 【支出】把所有支出按以下大类分组:餐饮、交通、住房、订阅、购物、娱乐、医疗、其他;
3. 【对比】每个大类的金额,相比上上个月(环比)和去年同月(同比)的变化百分比;
4. 【异常】挑出本月 3 笔最大的单笔支出,每笔说明发生了什么;
5. 【建议】根据消费结构,给我 3 条具体的省钱建议,不要鸡汤。

输出做成一张表格 + 一段总结,存到 Notion 'XX 年家庭账本'数据库下'202X 年 X 月'页面。" --max-tokens 150000
  • Cron0 9 1 * * = 每月 1 号上午 9:00
  • 依赖bank-mcp(如有)/ alipay-mcp(如有)/ notion
  • 预计 token:每次约 80K,因为月度账单数据量大,建议设 max-tokens 为 150K

模板 5:竞品监控(每天 9:00)

/loop "0 9 * * *" "请帮我监控以下 5 家竞品:[竞品 1 主页 URL]、[竞品 2]、[竞品 3]、[竞品 4]、[竞品 5],看看过去 24 小时有没有:

1. 官网首页有没有改版/换文案/新功能;
2. 公众号有没有发新文章(用 wechat-public MCP 查);
3. Twitter/X 账号有没有新推文;
4. GitHub 仓库有没有新 release;
5. 招聘网站上有没有发新岗位(侧面看战略方向)。

每家公司的变化输出一段不超过 50 字的总结,没有变化就写'无更新'。
最后整体合并发到我们公司的 Slack #竞品监控 频道,并加密到 Notion 备份。" --max-tokens 200000
  • Cron0 9 * * * = 每天早上 9:00
  • 依赖browser / wechat-public / twitter / github / slack / notion
  • 预计 token:每次约 100K,月成本约 $15

模板 6:邮件三句话简报(每天 8:30)

/loop "30 8 * * *" "请打开我的 Gmail 收件箱,处理过去 24 小时所有未读邮件:

1. 自动归档掉所有营销/促销/订阅类邮件(标 'Marketing' 标签);
2. 把剩下的'真邮件'按发件人分组;
3. 每封邮件用 3 句话总结:发件人是谁、说了什么、需不需要我回;
4. 如果邮件含会议邀请,自动加到我的 Google Calendar;
5. 整理成一份'今晨待办邮件清单',按紧急程度排序,发到我的 Telegram。

不要自动回邮件,只总结。" --max-tokens 100000
  • Cron30 8 * * * = 每天早上 8:30
  • 依赖gmail / gcal / telegram
  • 预计 token:每次约 60K(邮件多的人会更高)

模板 7:股票/基金涨跌提醒(工作日 9:30)

/loop "30 9 * * 1-5" "请帮我查以下持仓的实时行情:

A 股:[股票代码 1]、[代码 2]、[代码 3]
基金:[基金代码 1]、[基金代码 2]
港股:[港股代码 1]
美股盘前:[美股代码 1]、[代码 2]

输出表格:代码、名称、最新价、涨跌幅、相对我的成本价的盈亏百分比。

如果任何一个标的当日涨跌超过 5%,触发醒目提示(开头加 '【异动】')。
如果整体持仓亏损超过 -3%,自动追加一段 100 字的'冷静建议',避免我冲动操作。

发到我的微信。" --max-tokens 50000
  • Cron30 9 * * 1-5 = 工作日早上 9:30(A 股开盘)
  • 依赖stock-mcp(雪球/同花顺等)/ wechat
  • 预计 token:每次约 20K,月成本约 $2

模板 8:天气和出行建议(每天 6:30)

/loop "30 6 * * *" "请帮我查今天的本地天气和明日预报,给出:

1. 今天气温(最高/最低)、降水概率、空气质量指数;
2. 通勤建议:是否带伞、穿什么厚度的衣服、要不要戴口罩;
3. 如果今天空气质量 AQI > 100,建议关窗开净化器;
4. 如果今天有降水,提前 1 小时告诉我(再触发一次提醒);
5. 顺便看一眼日历,今天有没有外出行程,如果有,特别提醒一下天气。

简短一些,控制在 100 字以内,发到 iOS 通知(用 ntfy MCP)。" --max-tokens 30000
  • Cron30 6 * * * = 每天早上 6:30
  • 依赖weather / gcal / ntfy
  • 预计 token:每次约 15K

模板 9:待读文章自动整理(每天 22:00)

/loop "0 22 * * *" "请帮我整理今天收藏的所有文章:

1. 查 Pocket / Instapaper / 微信收藏 / 浏览器书签 这 4 个来源,找今天新增的内容;
2. 去重;
3. 按主题分类(科技 / 商业 / 生活 / 学术 / 其他);
4. 每篇用 50 字总结核心观点;
5. 标记'必读'(与我的 5 个长期关注主题强相关)和'选读';
6. 保存到 Notion 数据库 '今日待读',标签按主题分。

输出最后一句话告诉我:'今晚共收 X 篇,必读 X 篇,预计花你 X 分钟。'" --max-tokens 100000
  • Cron0 22 * * * = 每天晚上 10:00
  • 依赖pocket / wechat / chrome-bookmarks / notion
  • 预计 token:每次约 60K

模板 10:自媒体涨粉跟踪(每天 23:00)

/loop "0 23 * * *" "请帮我每天晚上跑一次自媒体数据统计:

1. 抖音:粉丝总数、今日新增、今日播放、今日点赞;
2. 公众号:阅读总数、新关注、最新一篇阅读量;
3. 小红书:粉丝、笔记总曝光、今日新笔记数据;
4. B 站:粉丝、播放、收藏;
5. YouTube:subs、views、watch hours。

输出格式:每个平台一行,'当日数字 (环比 +/- X%)'。
最后追加一句'你的内容今天表现:好/一般/差',依据是综合点赞率。

存到 Notion '自媒体日报'数据库,并发到我的 Telegram。" --max-tokens 80000
  • Cron0 23 * * * = 每天晚上 11:00
  • 依赖douyin / wechat-public / xhs / bilibili / youtube / notion / telegram
  • 预计 token:每次约 50K

模板 11:服务器/网站健康检查(每 5 分钟)

这是 11 个模板里最关键的一个——一旦你有任何对外服务(哪怕只是个人博客),你都需要它。它的本质是把"凌晨 3 点的电话告警"自动化掉。

/loop "*/5 * * * *" "请检查以下 5 个服务的健康状态:

1. https://api.example.com/health  期望 200 OK
2. https://www.example.com         期望 200 OK + 响应时间 < 2 秒
3. https://blog.example.com        期望 200 OK
4. SSH 到 server-1,跑 'df -h',磁盘使用率 < 85%
5. SSH 到 server-2,跑 'free -m',内存使用率 < 90%

如果**任何**一项失败,立即:
- 发短信到我手机(twilio MCP)
- 发到 Slack #alerts 频道
- 写一条记录到 PagerDuty

如果全部正常,**什么都不做**(不要每 5 分钟刷屏)。" --max-tokens 30000 --timeout 120
  • Cron*/5 * * * * = 每 5 分钟一次
  • 依赖http / ssh / twilio / slack / pagerduty
  • 预计 token:每次约 5K(无故障时),月成本约 $20

注意:模板 11 是高频任务,务必加 --timeout 120 避免某次卡死把后面的任务也堵住。

11 个模板的"分发渠道"对照表

如果你不熟悉每个推送渠道的特性,下面这张表帮你挑:

渠道 触达速度 适合场景 缺点
微信文件传输助手 1-2 秒 个人轻量内容(早报、提醒) 长内容容易没人看完
微信群 1-2 秒 团队同步(销售日报) 信息流式,容易刷掉
邮件 1-5 分钟 长篇报告(周报、月报) 容易塞进"重要"或"垃圾"
Slack 1-2 秒 工作消息 + 富格式 国内访问需要代理
Telegram 1-2 秒 个人通知,可以写 Bot 国内访问需要代理
Notion 5-10 秒 长期沉淀的内容(周报、月报) 不主动推送,要打开才看到
ntfy.sh 1-2 秒 紧急告警(服务器宕机) 只能推短文,没格式
iOS 通知(PushOver) 1-2 秒 强提醒,会震动 收费
企业微信 1-2 秒 国内企业内部 API 配置麻烦

经验法则

  • "我主动看就行"的内容(早报、周报)→ Notion + 邮件
  • "我必须立刻知道"的内容(告警、付款异常)→ ntfy + 微信
  • "团队都需要看"的内容(销售日报)→ 企业微信群 + Slack

四、Hooks 详解:事件触发的自动化

讲完了"按时间触发",我们来讲"按事件触发"。

4.1 Hook 是什么

Hook(钩子)的概念来自传统编程——"当某个事件发生时,自动执行某段预定义的代码"。Claude Code 的 Hook 把这个概念用在了 AI 工作流上:每当 Claude 干了某件事(或者要干某件事),系统会自动执行你定义的 Hook 脚本

用一个生活化的比喻:Hook 就像你给家里安装的"门铃 + 摄像头 + 自动开关"组合——

  • 有人按门铃(事件发生),摄像头自动录像(你定义的脚本跑起来)
  • 屋里没人时(条件判断),自动播放"主人不在"录音(脚本输出反馈)
  • 客人是你认识的(PreToolUse 拦截),开门;不认识的,拒绝并报警(exit 2)

Hook 就是 AI 世界的"智能门禁系统"——你不用每次都在场,事情自己会按你定的规矩发生。

举一个最直白的例子:

不用 Hook:
  你 → "帮我改 main.js 里的这个 bug"
  Claude → [改了文件]
  你 → 然后你手动跑 eslint 检查,发现新引入了 2 处规范问题
  你 → 跟 Claude 说"上面有 lint 问题,改一下"
  Claude → 改

用了 Hook(PostToolUse Edit):
  你 → "帮我改 main.js 里的这个 bug"
  Claude → [改了文件]
  → 系统自动跑 eslint --fix
  → 自动检查通过,结束
  你 → 完事

省掉了"手动检查 + 反馈给 Claude + Claude 再改"这三步。

4.2 Hook 的 7 大事件

Claude Code 目前支持 7 种 Hook 事件,按"什么时候触发"可以画成一条会话生命周期:

SessionStart
    ↓
UserPromptSubmit  ← 每次你按回车
    ↓
   ┌─────────────────────────────┐
   │  Claude 思考...              │
   │  ┌───────────────────┐      │
   │  │  PreToolUse        │      │ ← 工具执行前(可拦截!)
   │  │  Tool 执行         │      │
   │  │  PostToolUse       │      │ ← 工具执行后
   │  └───────────────────┘      │
   │  (以上可能循环 N 次)        │
   └─────────────────────────────┘
    ↓
Stop  ← Claude 这一轮答完
    ↓
(用户继续提问,回到 UserPromptSubmit)
    ↓
SessionEnd  ← 会话结束(关闭/退出/Crashed)

Notification ← 任意时刻,Claude 想"通知你一下"

每个事件的用途:

事件 触发时机 典型用途
SessionStart 会话开启时 拉最新 git、加载环境变量、打印欢迎语
UserPromptSubmit 你提交一条消息后 记录 Prompt、敏感词过滤、注入上下文
PreToolUse Claude 要调一个工具之前 拦截危险命令、确认、记录
PostToolUse Claude 调完一个工具之后 自动 lint、自动 format、写日志
Stop Claude 这一轮回复结束 桌面通知、播放声音
Notification Claude 主动提示用户 转推到手机、邮件
SessionEnd 会话关闭时 备份、汇总、清理

最常用的两个PreToolUsePostToolUse——前者是"门神"(拦截),后者是"清洁工"(善后)。

4.3 Hook 配置文件位置

Hook 用 JSON 写,放在 3 个文件之一:

文件路径 作用域 是否进 Git 典型用途
~/.claude/settings.json 全局(所有项目) 否(在 home 目录) 个人通用 Hook:审计日志、API key 检测
<项目>/.claude/settings.json 项目(团队共享) (一定要进 Git) 团队规范 Hook:lint、test、format
<项目>/.claude/settings.local.json 项目(仅自己) 否(gitignored) 个人在项目里的私货:本地路径、个人偏好

优先级:项目 local > 项目 settings > 全局 settings。多个文件里都定义了同一个事件的 Hook 时,会全部跑(不是覆盖),但顺序是 local 先、全局后。

4.4 Hook 配置语法

最小的 Hook 配置长这样:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "echo '文件改了' >> ~/log.txt" }
        ]
      }
    ]
  }
}

逐行拆解:

字段 作用
"hooks" 顶层固定 key
"PostToolUse" 事件名(来自上面 7 大事件)
"matcher" 工具名匹配(正则),Edit|Write 表示对 Edit 和 Write 工具都触发
"hooks" 内层 一个数组,可以挂多个动作
"type": "command" 动作类型,目前主要是 command(跑命令)
"command" 真正要跑的 shell 命令

matcher 的常用写法

matcher 字段是个正则表达式,匹配工具名。你只要记住下面这几种写法就够:

matcher 写法 匹配的工具
"Bash" 只匹配 Bash
"Edit|Write" Edit 或 Write
"Edit|Write|MultiEdit" 三种文件改动
".*" 所有工具(用于全量审计)
"WebFetch|WebSearch" 任何联网请求
"mcp__github__.*" 所有 github MCP 的工具(按命名约定 mcp__<服务>__<工具>

注意 JSON 里的 \| 实际写成 |,但因为这里是文本表格我加了转义。在真实 JSON 文件里直接写 "Edit|Write" 即可。

多个 Hook 是什么执行顺序

如果一个事件挂了多个 Hook,Claude Code 的执行规则是:

  1. 同一文件内:按 JSON 数组顺序,从上到下串行执行。
  2. 跨文件:项目 local 先跑,项目 settings 次之,全局 settings 最后。
  3. 任何一个 Hook exit 2(仅 PreToolUse):立即停止后续 Hook,并阻止工具执行。
  4. Hook 之间相互独立:上一个的输出不会自动传给下一个,要靠文件/环境变量串。

举个例子:你给 Edit 挂了两个 PostToolUse Hook(自动 lint + 自动备份),它们会先 lint 后备份——这正是你想要的(备份的是已经 lint 过的版本)。

4.5 Hook 能拿到的环境变量

Hook 跑起来时,Claude Code 会自动注入下面这些环境变量,这就是 Hook 的"输入"——你可以在脚本里随便用:

变量 含义 示例值
$CLAUDE_TOOL_NAME 当前触发 Hook 的工具名 EditWriteBash
$CLAUDE_TOOL_INPUT 工具的输入参数(JSON 字符串) {"file":"/x.js","content":"..."}
$CLAUDE_TOOL_OUTPUT 工具的输出(仅 PostToolUse 时有) "已写入 50 行"
$CLAUDE_TOOL_OUTPUT_FILE 工具刚刚改的文件路径(仅 Edit/Write 时有) /Users/x/main.js
$CLAUDE_SESSION_ID 本次会话的唯一 ID sess_a7b3c1d9
$CLAUDE_PROJECT_DIR 当前项目根目录 /Users/x/code/myapp
$CLAUDE_USER_PROMPT 用户最近一条原文(仅 UserPromptSubmit) "帮我改这个 bug"
$CLAUDE_EXIT_REASON 会话结束原因(仅 SessionEnd) user_quit / error

懂代码的同学可以用这些变量做任何事;不懂代码的同学也别慌,下面 10 个模板里都给了"你直接复制就能用"的版本。

4.6 Hook 怎么"拒绝"工具运行

PreToolUse 是唯一一个有"否决权"的 Hook——它可以阻止Claude 真正执行那个工具。具体做法是让你的脚本退出码非 0:

exit 0  # 放行(默认)
exit 1  # 拒绝(Claude 收到错误,不再执行)
exit 2  # 拒绝并把 stdout 作为错误信息反馈给 Claude(让它"理解"原因)

三者的区别用一张表说清:

退出码 工具是否执行 Claude 是否收到反馈 适合场景
exit 0 否(静默放行) 日常通过、纯审计
exit 1 是(看到一个普通错误) 你不想让它知道太多
exit 2 是(stdout 内容会变成给 Claude 的反馈 想"教育" Claude 改用别的办法

举例,你想阻止 Claude 跑 rm -rf,脚本可以写成:

#!/bin/bash
input="$CLAUDE_TOOL_INPUT"
if echo "$input" | grep -q "rm -rf"; then
  echo "禁止跑 rm -rf!请改用 trash 命令,trash 是 macOS 的安全删除工具"
  exit 2
fi
exit 0

Claude 看到 stdout 里的"禁止跑 rm -rf!请改用 trash 命令",会主动改用 trash 重新尝试——这就是 Hook 的"训狗"威力。

Hook 不要影响正常工作流

写 Hook 的最高境界是——它存在但你感受不到。如果 Hook 经常报错、误拦、卡住 Claude,你会很快关掉它,整个自动化就崩了。所以记住三条防呆原则:

  1. 能 silent 就 silent:用 2>/dev/null 把 stderr 屏蔽,避免无关错误被 Claude 看到当成事。
  2. || true|| true:让脚本永远成功退出,避免某次工具失败连带 Hook 失败。
  3. 超时要短:Hook 默认会阻塞工具执行,超过 5 秒就会让 Claude 体验明显变卡。复杂逻辑改成 nohup ... & 异步跑。

举例:

# 不好:lint 失败会让 Claude 一直收到错误反馈
npx eslint --fix "$f"

# 好:失败也假装成功,不打扰 Claude
npx eslint --fix "$f" 2>/dev/null || true

# 更好:异步跑,不阻塞工具执行
(npx eslint --fix "$f" 2>/dev/null) &

五、10 个高价值 Hook 模板

下面 10 个都是真实场景下高频使用的。你只需要把对应 JSON 段拷到 ~/.claude/settings.json"hooks" 字段下,重启 Claude Code 即可生效。

模板 1:自动 lint(PostToolUse Edit)

每次 Claude 改了 JS/TS 文件,自动跑一次 ESLint 修复格式问题。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "if [[ \"$CLAUDE_TOOL_OUTPUT_FILE\" =~ \\.(js|ts|jsx|tsx)$ ]]; then npx eslint --fix \"$CLAUDE_TOOL_OUTPUT_FILE\" 2>/dev/null || true; fi"
          }
        ]
      }
    ]
  }
}

那个 || true 很关键——如果 ESLint 报错,不让这个错误传给 Claude,避免它"看到错误又改一次又触发又改…"陷入死循环。

模板 2:自动 prettier(PostToolUse Edit)

跟模板 1 一样思路,但格式化所有支持的文件类型:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write \"$CLAUDE_TOOL_OUTPUT_FILE\" 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}

模板 3:阻止危险 Bash(PreToolUse Bash)

最重要的一个 Hook——拦截可能毁掉系统的命令。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "cmd=$(echo \"$CLAUDE_TOOL_INPUT\" | python3 -c 'import sys,json; print(json.load(sys.stdin).get(\"command\",\"\"))'); if echo \"$cmd\" | grep -E '(rm -rf /|rm -rf ~|rm -rf \\*|sudo rm|> /etc/|mkfs|dd if=|:(){ :|:& };:)' > /dev/null; then echo '检测到危险命令,已拦截:'$cmd; exit 2; fi; exit 0"
          }
        ]
      }
    ]
  }
}

它会检查这些绝对不该跑的命令模式:

  • rm -rf /:删根目录
  • rm -rf ~:删主目录
  • rm -rf *:删当前目录全部
  • sudo rm:以管理员删
  • > /etc/:覆写系统配置
  • mkfs:格式化磁盘
  • dd if=:底层磁盘写
  • :(){ :|:& };::fork 炸弹

被拦截后 Claude 会主动改用 trash 或者放弃,不会硬来。

模板 4:自动备份(SessionEnd)

每次会话结束,自动把项目当前状态打个 zip 包到备份目录。

{
  "hooks": {
    "SessionEnd": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "mkdir -p ~/claude-backups && cd \"$CLAUDE_PROJECT_DIR\" && tar --exclude=node_modules --exclude=.git -czf ~/claude-backups/$(basename $PWD)-$(date +%Y%m%d-%H%M%S).tar.gz . 2>/dev/null"
          }
        ]
      }
    ]
  }
}

备份目录建议用 iCloud / Dropbox / OneDrive 同步过的目录,万一硬盘炸了还有云端兜底。

模板 5:审计日志(PostToolUse 全部)

把 Claude 跑过的所有 Bash 命令写到一份审计日志里,方便事后追溯。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"[$(date '+%Y-%m-%d %H:%M:%S')] [session:$CLAUDE_SESSION_ID] $CLAUDE_TOOL_INPUT\" >> ~/claude-audit.log"
          }
        ]
      }
    ]
  }
}

跑了一阵后你打开 ~/claude-audit.log,会看到:

[2026-04-19 09:23:15] [session:sess_a7b3] {"command":"ls -la"}
[2026-04-19 09:23:48] [session:sess_a7b3] {"command":"git status"}
[2026-04-19 09:24:02] [session:sess_a7b3] {"command":"npm install lodash"}
...

这是企业用户必装的 Hook——合规、追责、训练 SIEM 都靠它。

模板 6:自动跑测试(PostToolUse Edit)

改了源文件后自动跑相关测试,避免引入回归。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "if [[ \"$CLAUDE_TOOL_OUTPUT_FILE\" =~ src/.*\\.(js|ts)$ ]]; then npx jest --findRelatedTests \"$CLAUDE_TOOL_OUTPUT_FILE\" --silent 2>&1 | tail -20; fi"
          }
        ]
      }
    ]
  }
}

只对 src/ 下的 JS/TS 文件触发,跑 jest 找相关的测试。tail -20 确保只把最后 20 行反馈给 Claude,避免输出爆炸。

模板 7:API Key 检测(PreToolUse Write)

在 Claude 写文件之前,扫描内容里有没有像 API Key 的字符串,如果有就拦截。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "content=$(echo \"$CLAUDE_TOOL_INPUT\" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d.get(\"content\",\"\")+d.get(\"new_string\",\"\"))'); if echo \"$content\" | grep -E '(sk-[a-zA-Z0-9]{20,}|ghp_[a-zA-Z0-9]{30,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35}|xox[baprs]-[a-zA-Z0-9-]+|-----BEGIN.*PRIVATE KEY-----)' > /dev/null; then echo '检测到疑似 API Key 或私钥,拒绝写入。请使用环境变量。'; exit 2; fi; exit 0"
          }
        ]
      }
    ]
  }
}

它检测:

正则 对应密钥类型
sk-[a-zA-Z0-9]{20,} OpenAI / Anthropic
ghp_[a-zA-Z0-9]{30,} GitHub Personal Token
AKIA[0-9A-Z]{16} AWS Access Key
AIza[0-9A-Za-z_-]{35} Google API Key
xox[baprs]-... Slack Token
-----BEGIN.*PRIVATE KEY----- 私钥文件

实测能拦下 95% 以上的"密钥被误提交"事故。

模板 8:长任务桌面通知(Stop)

Claude 跑完一轮就给你一个桌面通知,方便你"开会去了,回来不用守屏幕"。

macOS 版本:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude 已完成本轮任务\" with title \"Claude Code\" sound name \"Glass\"'"
          }
        ]
      }
    ]
  }
}

Linux 版本(需要 notify-send):

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "notify-send 'Claude Code' '已完成本轮任务'" }
        ]
      }
    ]
  }
}

Windows(PowerShell)版本:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "powershell -Command \"[System.Windows.MessageBox]::Show('Claude 已完成本轮任务')\""
          }
        ]
      }
    ]
  }
}

模板 9:会话开始自动 git pull(SessionStart)

每次进项目,自动拉一下最新代码,避免在过期分支上瞎改。

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "cd \"$CLAUDE_PROJECT_DIR\" && if [ -d .git ]; then git fetch --quiet 2>/dev/null && git status -sb | head -5; fi"
          }
        ]
      }
    ]
  }
}

效果:每次启动会话,会自动看到当前分支和远端的对比信息:

## main...origin/main [behind 3]
 M src/api.ts
?? notes.md

Claude 看到 "behind 3" 就会主动建议你先 pull 再开始改代码。

模板 10:阻止操作生产数据库(PreToolUse Bash)

最严重的事故之一——Claude 误把 dev SQL 跑到 prod。这个 Hook 是双保险。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "cmd=$(echo \"$CLAUDE_TOOL_INPUT\" | python3 -c 'import sys,json; print(json.load(sys.stdin).get(\"command\",\"\"))'); if echo \"$cmd\" | grep -iE '(prod|production)\\.db|prod-db|--env=prod|DROP DATABASE|TRUNCATE.*production' > /dev/null; then echo '检测到生产数据库操作,已拦截。如确需操作,请人工到生产服务器执行。'; exit 2; fi; exit 0"
          }
        ]
      }
    ]
  }
}

匹配规则(关键词触发):

  • prod.db / prod-db / production.db
  • --env=prod
  • DROP DATABASE
  • TRUNCATE 后跟 production 字样

任何企业用户都必须装这条 Hook——这是不可商量的安全底线。


六、综合案例:搭一个"个人早报"全流程

讲了这么多,我们用一个完整的案例把所有知识点串起来。

6.1 目标

每天早上 7:00,Claude 自动生成一份"个人早报",发到 3 个渠道(微信、邮件、Notion)。任务失败时自动告警。

6.2 架构图

                       06:55 提前 5 分钟唤起
                             ↓
                    ┌────────────────┐
                    │   /loop 触发    │
                    │   07:00 每天   │
                    └────────┬───────┘
                             ↓
                    ┌────────────────┐
                    │   主 Claude     │
                    └────────┬───────┘
                             ↓
        ┌──────┬──────┬──────┴──────┬──────┬──────┐
        ↓      ↓      ↓             ↓      ↓      ↓
     weather  gcal  gmail         news   stock  todoist
       MCP    MCP   MCP            MCP    MCP    MCP
        │      │      │             │      │      │
        └──────┴──────┴──────┬──────┴──────┴──────┘
                             ↓
                    ┌────────────────┐
                    │  整合成早报      │
                    └────────┬───────┘
                             ↓
                ┌────────────┼────────────┐
                ↓            ↓            ↓
            wechat MCP    gmail MCP    notion MCP
                ↓            ↓            ↓
           你的微信      你的邮箱      你的 Notion
                             ↓
                    ┌────────────────┐
                    │ Hook: SessionEnd│
                    │  失败则 ntfy 推送│
                    └────────────────┘

6.3 三步搭建

第 1 步:注册 /loop

/loop "0 7 * * *" "你是我的'早报员工',请按以下流程生成今日早报:

【数据采集】
1. 调 weather MCP 获取本地天气:今日最高/最低温、降水概率、空气质量
2. 调 gcal MCP 获取我今天日历的全部事项
3. 调 gmail MCP 获取过去 12 小时未读邮件,挑出 3 封最重要的
4. 调 news MCP 获取 5 条今天必看的全球大事
5. 调 stock MCP 查我的 5 只持仓股票今日预期
6. 调 todoist MCP 查今天到期的任务

【整合输出】
按以下结构组织(中文,不要 emoji):

═══════════════════════════
 Cassius 的今日早报 - 2026-04-19
═══════════════════════════

【天气】今日 12-18℃,多云转小雨,建议带伞,AQI 35(优)

【日程】
  • 09:30  团队晨会(Zoom)
  • 14:00  和 ACME 客户演示
  • 18:30  健身

【邮件三件事】
  1. (重要) ACME John 确认了演示时间
  2. (一般) 财务报销审批
  3. (告知) AWS 账单到达

【今日要闻】
  1. ...
  2. ...
  ...

【持仓提示】昨夜美股小幅上涨 0.5%

【今日待办】
  • 提交季度报告
  • 给 PM 反馈方案
═══════════════════════════

【分发渠道】
1. 调 wechat MCP 发到我的微信文件传输助手
2. 调 gmail MCP 发到 cassius@example.com(标题:'早报 2026-04-19')
3. 调 notion MCP 在 '我的早报' 数据库下创建一个新页面

完成后回复'早报已发送'。" --max-tokens 200000 --timeout 600 --max-cost 0.3

关键参数解释

  • 0 7 * * *:每天 7:00 触发
  • --max-tokens 200000:上限 20 万 token(早报 6 个 MCP 加起来不会超)
  • --timeout 600:上限 10 分钟(避免某个 MCP 卡死)
  • --max-cost 0.3:单次最多花 $0.3,月成本上限约 $9

第 2 步:加 Hook 监控失败

打开 ~/.claude/settings.json,加上:

{
  "hooks": {
    "SessionEnd": [
      {
        "matcher": ".*loop_e9f4d2.*",
        "hooks": [
          {
            "type": "command",
            "command": "if [ \"$CLAUDE_EXIT_REASON\" != \"normal\" ]; then curl -d '早报任务失败!原因: '\"$CLAUDE_EXIT_REASON\" ntfy.sh/cassius-claude-alerts; fi"
          }
        ]
      }
    ]
  }
}

loop_e9f4d2 是你 /loop 注册成功后系统给的 ID,要换成你自己的。ntfy.sh 是一个免费的推送服务(手机装 ntfy app,订阅同名频道即可收到推送),第八章已经介绍过。

第 3 步:先手动跑一次验证

/loop run loop_e9f4d2

然后等 1-3 分钟,看微信、邮箱、Notion 三处有没有同时收到早报。如果有,恭喜,自动化雇佣完成。如果某一处没收到,按 /loop logs loop_e9f4d2 看错误日志。

6.4 调试过程中遇到的真实坑

第一次跑这个早报,本书作者实际遇到了下面 5 个坑,每一个都可能在你身上重演:

坑 1:第一次 7:00 没收到推送

打开 /loop logs loop_e9f4d2 --tail 50,看到:

[07:00:01] 启动会话
[07:00:02] 调用 weather.get_forecast - OK
[07:00:05] 调用 gmail.list_messages - ERROR: token 过期

Gmail 的 OAuth token 过期了。解决:手动重新跑一次 gmail mcp 的 OAuth 授权流程。

坑 2:早报里的"今日要闻"和真实日期对不上

发现 Claude 输出的新闻是昨天的——因为 news MCP 默认返回过去 24 小时,但它的"24 小时"是 UTC 时区。改提示词加一句"请只挑选北京时间今天的新闻"。

坑 3:微信发送失败但 Claude 报告"成功"

wechat MCP 的内部错误处理有 bug,发送失败后返回 {"status": "ok"}。Claude 当真了。解决:在提示词里加"发送后请回查这条消息是否真的出现在我的微信,未确认前不要标记成功"。

坑 4:每天 7:00 触发,但通知到 7:03 才到

Claude Code 的守护进程不是 100% 准时——它有 ±60 秒漂移。如果你需要严格准时(比如开盘前 5 分钟提醒),把触发时间提前 1 分钟,比如 */5 9 * * 1-5 改成 1-59/5 9 * * 1-5

坑 5:Hook 通知没生效

SessionEnd Hook 写好了,但没收到推送。原因:matcher 写错了,应该是 loop_e9f4d2.* 而不是 .*loop_e9f4d2.*——matcher 默认会全匹配。改一下就好。

每个坑后面都跟着一次"啊原来这样"的恍然大悟。第一次搭自动化,预期至少要踩 3-5 个坑。这是正常的,不是你的问题。

6.5 第一次成功运行的输出样本

═══════════════════════════
 Cassius 的今日早报 - 2026-04-19
═══════════════════════════

【天气】今日 12-18℃,多云转小雨,建议带伞,AQI 35(优)。
今晚可能有雷阵雨,外出请提前关窗。

【日程】
  • 09:30  团队晨会(Zoom)
  • 14:00  和 ACME 客户演示(重要!上周演示效果很好,今天主要谈合同)
  • 18:30  健身(教练张老师,胸推日)

【邮件三件事】
  1. (重要) ACME John 确认了今天 14:00 的演示
     建议:提前 10 分钟开会议,提前测试一下分享屏幕
  2. (一般) 财务报销审批 - 上次报销已批,钱周五到账
  3. (告知) AWS 账单 4 月份 $124,比上月降 12%

【今日要闻】
  1. 美联储宣布维持利率不变,市场反应平淡
  2. OpenAI 发布 GPT-5.5,长上下文支持 1000 万 token
  3. A 股开盘大涨 1.5%,新能源板块领涨
  4. 国家发改委:上半年 GDP 同比 +5.2%
  5. NASA 宣布载人登月推迟到 2027 年

【持仓提示】
  昨夜美股小幅上涨 0.5%,你的 NVDA 涨 1.2%,AAPL 跌 0.3%
  建议:今天早盘 A 股开盘后留意是否有跟涨机会

【今日待办】
  • 提交 Q1 季度报告(截止今天,紧急)
  • 给 PM 反馈方案 v2 修改意见
  • 取快递(菜鸟驿站)

═══════════════════════════
 来自 Claude Code · 用时 1 分 47 秒 · 消耗 28K tokens
═══════════════════════════

整个流程完全无人干预——你早上一睁眼,3 个渠道里都已经躺着这份早报。

6.6 跑了一周后的"调优清单"

跑了一周,你大概率会想做下面这些调整。提前预告,让你少走弯路

不爽的地方 怎么调
邮件挑选不准(重要被漏掉) 在提示词里加"我和 ACME / XYZ / John 等关键人的邮件务必标'重要'"
新闻太美国化 加"国内新闻至少 2 条,国际 3 条"
持仓信息太长 加"如果当日波动 < 1%,只用一行总结即可"
想看周环比/月环比 加"用昨天/上周同期/上月同期数据做对比"
微信和邮件重复推送 取消邮件渠道,只保留微信和 Notion
周末早报不需要 Cron 改成 0 7 * * 1-5(仅工作日)
出差时区不对 --timezone Asia/Tokyo(去东京时)
想加昨天的支出明细 接入 alipay-mcp,加"昨日总支出 + Top 3 类别"

核心心法:早报系统不是一次写好的,是用 1-2 周时间和 Claude 共同打磨出来的。每次发现"不太对"就改一下提示词,几次迭代后它就完全是你想要的样子。


七、定时任务的 5 大注意

熟练度上来后,你可能会越注册越多 /loop 任务。这一节是给"老用户"的——这 5 件事不做,迟早翻车。

7.1 设上限(每个任务都要)

重申一遍——每个 /loop 任务都要至少设置一个上限。最稳妥的组合:

--max-tokens 100000 --timeout 300 --max-cost 0.5

哪怕这个任务你测试过、稳定如老狗,也要设。原因:

  • MCP 可能突然变慢导致 token 暴涨
  • 上游 API 改动可能让 Claude 反复重试
  • 你自己改了提示词后忘了重新评估成本

一个反面教材:本书测试期间有人写了"每天监控 GitHub 5 个仓库"的 /loop,没设上限。某仓库突然多了 3000 个 issue,Claude 就吭哧吭哧把 3000 个全读了一遍,单次烧掉 $80。从此作者每个任务都要 --max-cost

7.2 加超时(防卡死)

--timeout 不是为了节省时间,而是为了让卡死的任务死掉,避免堵塞后续任务。建议:

任务类型 推荐 timeout
简单查询(天气、股价) 60-120 秒
中等任务(邮件汇总、新闻) 300-600 秒
复杂任务(月报、竞品分析) 600-1200 秒
高频任务(每 5 分钟) 60-120 秒(必须短)

7.3 dry-run 先(危险任务必做)

任何会"动钱、动文件、动外部世界"的任务,第一次跑都要先 --dry-run

/loop "0 22 * * *" "..." --dry-run

--dry-run 模式下,Claude 会走完所有逻辑,但不会真正调用副作用 MCP(不会发邮件、不会扣钱、不会改文件)。它会输出"如果真跑,我会做这些事"的列表,让你 review。

建议新任务前 3 天都用 --dry-run,第 4 天再去掉。

7.4 错误告警(永远不要"默默失败")

最危险的不是任务跑错,而是任务默默挂掉。两个推荐做法:

方法 1:Hook 监听 SessionEnd

如六章案例所示,用 SessionEnd Hook 把失败推到 ntfy / 微信 / 邮件。

方法 2:内建的 --on-failure 参数

/loop "..." --on-failure "curl -d 'fail' ntfy.sh/my-alerts"

任务失败时直接跑这条命令。简单粗暴。

7.5 日志保留与清理

/loop 默认保留 30 天日志,老日志会自动滚动删除。你可以:

/loop logs loop_xxx --since 7d   # 看最近 7 天
/loop logs loop_xxx --tail 100   # 看最近 100 行
/loop logs --clean --older-than 7d  # 清理 7 天前的所有日志

建议每月 1 号手动跑一次清理——把整个 ~/.claude/loops/ 目录瘦下来,加快下次启动速度。


八、调试自动化任务的 5 个工具

凡是自动化都会出问题。这一节给你 5 个调试武器。

8.1 /loop logs <id> 看输出

第一招永远是"看日志"。日志会告诉你:

[2026-04-19 07:00:00] Loop triggered
[2026-04-19 07:00:01] Calling MCP: weather.get_forecast
[2026-04-19 07:00:03] Result: {temp_high: 18, ...}
[2026-04-19 07:00:04] Calling MCP: gcal.list_events
[2026-04-19 07:00:08] ERROR: gcal.list_events timeout (5s)
[2026-04-19 07:00:08] Retrying...
[2026-04-19 07:00:14] ERROR: gcal.list_events timeout again
[2026-04-19 07:00:14] Skipping gcal, continuing...
[2026-04-19 07:00:50] Done. Tokens: 23K, Cost: $0.06

看就能看出问题:gcal MCP 有问题。这时候就该去检查它的 token 是不是过期了。

8.2 claude --debug 启动调试模式

如果某次跑挂在你不知道的环节,可以手动用 debug 模式重跑:

claude --debug
> /loop run loop_xxx

debug 模式下你会看到每一次工具调用的完整请求和响应,包括内部的 thinking。

8.3 Hook 调试:临时打印环境变量

Hook 出问题时(比如不触发、触发了没效果),把它临时改成"只打印环境变量":

{
  "type": "command",
  "command": "env | grep CLAUDE >> /tmp/claude-debug.log; echo '---' >> /tmp/claude-debug.log"
}

跑一次,然后 cat /tmp/claude-debug.log 看到所有 CLAUDE_* 变量的值,就能知道原本的 Hook 为什么没生效。

8.4 ntfy.sh 推送通知到手机

调试自动化最痛苦的是"任务在你不在场时跑挂了"。给你的 Hook 和 /loop 都接上 ntfy.sh,让失败信息推到你手机:

curl -d "调试信息:xxx" ntfy.sh/your-channel-name

手机装 ntfy app,订阅 your-channel-name 这个频道,3 秒内收到推送。完全免费、不用注册、随便用

8.5 把任务先在前台跑通再放后台

最重要的一条原则:任何自动化任务,都先在 Claude Code 的前台手动跑一次完整的,确认 OK 再注册成 /loop

你 → "你试着按这段提示词跑一次:[完整提示词]"
Claude → [真的跑了一次]
你 → 检查结果是不是想要的
你 → 如果 OK,再 /loop "0 7 * * *" "完整提示词"

不要直接写 /loop 注册一个从未在前台跑通的提示词。

8.6 自动化任务的"健康度仪表盘"

如果你装的 /loop 超过 5 个,强烈建议自己写一个 meta /loop 来监控所有任务的健康度:

/loop "0 23 * * *" "请帮我盘点一下今天所有 /loop 任务的运行状况:

1. 跑 'claude loop list --json' 拿到所有任务列表
2. 对每个任务,跑 'claude loop logs <id> --since 24h --json' 获取今日日志
3. 统计:总计跑了多少次、成功多少、失败多少、平均耗时、平均 token
4. 标红:任何今天有失败的任务,列出错误原因
5. 标黄:任何耗时比上周平均高 50% 的任务(可能在变慢)
6. 输出一份 markdown 报告,发到我的微信

如果有任何标红,加一行'今晚一定要看这条消息'。" --max-tokens 50000

这就是用 /loop 监控 /loop 的"递归技巧"——AI 自己监督自己。

跑了一段时间,你会有一份这样的"自动化体检表":

═══════════════════════════
 你的自动化每日体检 - 2026-04-19
═══════════════════════════

[正常] loop_a7c3f1 早报           今日 1 次    平均 1m45s   ~28K tokens
[正常] loop_b8d2e5 邮件汇总        今日 1 次    平均 2m10s   ~62K tokens
[正常] loop_c9e3f7 股票提醒        今日 1 次    平均 0m32s   ~18K tokens
[警告] loop_d2f8a3 健康检查        今日 288 次  失败 12 次   原因: HTTP 504
[红色] loop_e3a9b6 竞品监控        今日 0 次    任务挂了!    原因: gmail token 过期

总成本:今日 $0.84,月累计 $18.50(预算 $50)
═══════════════════════════

这就是"自动化的自动化"——你只需要每天看这一份就够了。


九、自动化的 3 个进阶玩法

会跑 /loop 和 Hook 之后,你已经超过 99% 的 Claude Code 用户了。这一节给真正的进阶用户——把多种机制组合起来

9.1 Hook 链:一个 Hook 触发另一个

Hooks 之间是可以串起来的——一个事件的 Hook 写日志,另一个事件的 Hook 读日志做汇总。

例子:让 Claude 每次跑 Bash 命令都记录,会话结束时把当天所有命令汇总发邮件。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$(date '+%H:%M:%S') $CLAUDE_TOOL_INPUT\" >> /tmp/claude-cmds-$CLAUDE_SESSION_ID.log"
          }
        ]
      }
    ],
    "SessionEnd": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "f=/tmp/claude-cmds-$CLAUDE_SESSION_ID.log; if [ -f $f ]; then mail -s 'Claude 本次会话命令汇总' you@example.com < $f && rm $f; fi"
          }
        ]
      }
    ]
  }
}

逻辑链:

Bash 执行 → PostToolUse → 写到临时文件
   ↓
   ↓ (循环 N 次)
   ↓
会话结束 → SessionEnd → 读临时文件 → 发邮件 → 删文件

这就是Hook 链——把多个事件用文件系统串起来。

9.2 /loop + Subagent:并行批量任务

第六章讲过 Subagent(并行小弟)。把它和 /loop 组合,能并发跑批量任务。

例子:每周一早上 9:00,并行处理 10 个客户的周报。

/loop "0 9 * * 1" "你现在要为我处理 10 个客户的周报。

客户列表:[客户 1]、[客户 2]、...、[客户 10]

请用 10 个 subagent 并发处理,每个 subagent:
1. 接收一个客户名称
2. 查这个客户上周的会议纪要、邮件来往、合同进展
3. 生成 200 字的周报段落
4. 返回给主 agent

主 agent 收齐 10 段后合并成一份完整周报,发到我的邮箱。

预算:每个 subagent max-tokens 30K,总 timeout 1200 秒。" --max-tokens 500000 --timeout 1500

执行图:

                      /loop 触发
                          ↓
                    主 Claude 启动
                          ↓
        ┌──────────┬──────────┬──────────┬──────────┐
        ↓          ↓          ↓          ↓          ↓
    Subagent 1  Subagent 2  ...     Subagent 9   Subagent 10
    (客户 A)    (客户 B)            (客户 I)     (客户 J)
        │          │          │          │          │
        └──────────┴──────────┼──────────┴──────────┘
                              ↓
                     主 Claude 收齐 10 段
                              ↓
                          合并成周报
                              ↓
                          发邮件

10 个客户串行要跑 10 分钟,并行只要 1.5 分钟。

9.3 /loop 之间的"任务编排"

复杂场景下你会有多个 /loop 任务有先后依赖关系——比如"先采数据,再做分析,最后发报告"。Claude Code 没有内建的 DAG 编排器,但你可以用文件信号量简单实现:

# 任务 A:每天 6:55 跑,负责采集原始数据,写到 ~/data/today.json
/loop "55 6 * * *" "采集今天的原始数据..."  --on-success "touch ~/data/.ready"

# 任务 B:每天 7:00 跑,但如果 A 没完成就跳过
/loop "0 7 * * *" "如果 ~/data/.ready 存在则继续做分析;不存在则报警并退出"

# 任务 C:每天 7:30 跑,发报告,跑完清理信号量
/loop "30 7 * * *" "..." --on-success "rm ~/data/.ready"

--on-success 是任务成功完成后跑的命令,--on-failure 是失败后跑的命令。这俩参数能让你把多个 /loop 串成简单的流水线。

如果场景非常复杂(5+ 个有依赖关系的任务),这时候就别用 /loop——直接上 Airflow / Prefect / Dagster 这种正经的工作流编排器,把 Claude Code 当成其中一个 step 调用。

9.4 用 Hook 做"准 IDE"功能

Hook 的真正威力是——它能让 Claude Code 模拟出很多 IDE 才有的功能。

例 1:保存即 commit

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "cd \"$CLAUDE_PROJECT_DIR\" && git add \"$CLAUDE_TOOL_OUTPUT_FILE\" && git commit -m \"WIP: auto-commit by Claude $(date '+%H:%M:%S')\" --quiet 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}

实验性功能,建议在专门的"实验分支"上玩,否则你的主分支会被 100 条 "WIP: auto-commit" 刷屏。

例 2:读了文件就更新 README

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Read",
        "hooks": [
          {
            "type": "command",
            "command": "f=$(echo \"$CLAUDE_TOOL_INPUT\" | python3 -c 'import sys,json; print(json.load(sys.stdin).get(\"path\",\"\"))'); if [[ \"$f\" =~ src/.*\\.py$ ]]; then echo \"[$(date '+%Y-%m-%d')] $f\" >> .claude/recent-reads.log; fi"
          }
        ]
      }
    ]
  }
}

记录最近读过哪些源文件,下次启动会话时 Claude 自动加载这份"近期关注列表"作为上下文。等于让 AI 有了注意力记忆

例 3:模拟 IDE 的"问题面板"

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "if [[ \"$CLAUDE_TOOL_OUTPUT_FILE\" =~ \\.py$ ]]; then mypy --no-error-summary \"$CLAUDE_TOOL_OUTPUT_FILE\" 2>&1 | head -10 > /tmp/claude-problems.txt && cat /tmp/claude-problems.txt; fi"
          }
        ]
      }
    ]
  }
}

这个 Hook 让 Claude 改完 Python 文件后立刻看到自己引入的类型错误,相当于 PyCharm 的红色波浪线实时反馈。Claude 会在下一轮自动修。

9.5 把 Hook 和 /loop 联动

最进阶的玩法——用 Hook 触发 /loop

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "mcp__github__create_pr",
        "hooks": [
          {
            "type": "command",
            "command": "claude loop run loop_pr_review --once  # 创建 PR 后立即触发 PR review 任务"
          }
        ]
      }
    ]
  }
}

含义:每次 Claude 在 GitHub 上创建一个 PR,自动触发"PR Review" 这个 /loop 任务跑一次(不等到下次定时触发)。这样你的 PR 在创建那一刻就有自动 review。

这种"事件 → 触发定时任务"的联动,是 Claude Code 自动化能力的最高级形态。


十、避坑:自动化的 8 条红线

把自动化从"工具"变成"灾难",往往就是这 8 条没守住。严肃看一遍,每条背后都有真实事故。

每条红线后面我都会附一个真实事故复盘——不是吓你,是想让你看到"如果不守,会发生什么"。

红线 1:不要让 /loop 自动付款

任何会扣钱的操作(自动续费、付款、转账、买股票)都不要让 /loop 自动跑。即便它"看起来稳定",AI 偶尔会幻觉、偶尔会被诱导。

错误示范

/loop "0 0 1 * *" "查看我的 SaaS 订阅,自动续费即将到期的"

正确做法

/loop "0 0 1 * *" "列出我所有即将到期的 SaaS 订阅,发到我邮箱让我自己决定续不续"

真实事故:某用户给 /loop 装了"自动续订快到期的 SaaS",本意是省心。某月该任务把一个已经不用的 $99/月服务给续了 12 个月(一次性扣 $1188),还把一个Anthropic 已经放弃的合作伙伴 Codeium 给续了。退款流程花了 3 周。AI 不会替你判断"这个东西你还需不需要"——这是只有你能做的决定。

红线 2:不要让 /loop 自动发消息给客户

发给同事、内部群、自己——可以。发给外部客户——绝对不要。AI 一句口误可能丢掉一个项目。

错误示范

/loop "0 9 * * 1" "给上周客户发感谢邮件"

正确做法

/loop "0 9 * * 1" "给上周客户起草感谢邮件,存到 Gmail Drafts 让我自己审一遍再发"

真实事故:某创业团队让 /loop 自动给"过去 30 天没回复的客户"发跟进邮件。Claude 认真做了,结果给一个已经在两年前去世的客户 发了"想念你的好评"。家属看到后联系过来,企业声誉掉了一大块。AI 没有"基本人情"概念,"已离职"、"已去世"、"已撕破脸"这些它统统不知道。

红线 3:Hook 永远不要无限递归

最经典的事故——你写了个 PostToolUse Edit Hook 自动改文件,结果 Hook 改完又触发 Hook,死循环。

错误示范

{
  "matcher": "Edit",
  "hooks": [
    { "type": "command", "command": "sed -i 's/foo/bar/' \"$CLAUDE_TOOL_OUTPUT_FILE\"" }
  ]
}

每次 Edit 后改文件 → 系统认为又是一次 Edit → 又触发 Hook → ...

保险做法

  • || true 让脚本永远成功,不让 Hook 输出反馈给 Claude
  • 自动化文件改动用 git hooks,不用 Claude Code 的 PostToolUse Hook
  • 改完后用 touch -t 让文件 mtime 不变,避免再次触发

真实事故:某用户写了个 PostToolUse Hook:"Claude 改了 README,自动追加 '更新于 X'"。但追加这个动作又触发了 PostToolUse,于是 README 在 0.3 秒内被追加了 1700 行 "更新于 X",磁盘瞬间多了 800MB。

红线 4:不要让 /loop 频率超过 1 分钟

* * * * *

每分钟一次。除非你非常清楚自己在干什么(高可用监控),否则不要这么干。原因:

  • token 烧得飞快
  • 上游 API 限速会被打满
  • 一旦某次卡住,下一次还在等前一次结束(Claude Code 默认串行)
  • 调试时你根本来不及看日志

安全频率上限:5 分钟一次(*/5 * * * *),且单次任务 timeout < 60 秒。

真实事故:某 SRE 把网站健康检查设成 * * * * *(每分钟),共 20 个站点。有一次 DNS 暂时挂了,每次任务因为 timeout 跑了 90 秒,第二次任务来时第一次还没结束。30 分钟后队列堆了 30 个待跑任务,电脑风扇狂转,token 飞涨。教训:高频任务timeout 必须 < 频率间隔

红线 5:自动化任务永远要有"紧急刹车"

你要确保任何时候都能 1 秒内停掉所有 /loop。最简单的刹车开关:

# 启用所有 loop(开机时跑)
claude loop enable-all

# 禁用所有 loop(紧急情况)
claude loop disable-all

强烈建议:在 Mac 的菜单栏 / Windows 的任务栏放一个一键脚本,遇到不对劲(账单异常、Claude 行为奇怪)就一键 disable-all。

具体怎么做(macOS 示范):

# 1. 写一个紧急刹车脚本
cat > ~/bin/claude-emergency-stop.sh <<'EOF'
#!/bin/bash
claude loop disable-all
osascript -e 'display notification "所有 /loop 已紧急停止" with title "Claude Code"'
EOF
chmod +x ~/bin/claude-emergency-stop.sh

# 2. 用 Apple Shortcuts 加到菜单栏,或者绑定到 Karabiner 全局快捷键

绑完之后,发现"Claude 在乱跑"——按一下就停。

红线 6:不要把 ANTHROPIC_API_KEY 写进 Hook 脚本

Hook 脚本会被你 commit 进 Git。把 API Key 写在里面 = 上传 GitHub。

错误示范

{
  "command": "curl -H 'Authorization: Bearer sk-ant-api03-xxxx' ..."
}

正确做法——用环境变量:

{
  "command": "curl -H \"Authorization: Bearer $ANTHROPIC_API_KEY\" ..."
}

Key 存在 ~/.zshrc~/.bashrc 里,不进 Git。

真实事故:某 GitHub 用户把项目级 .claude/settings.json 推了上去,里面有一行 Authorization: Bearer sk-ant-...。8 分钟后 Anthropic 的扫描器发现了,自动撤销 Key,给他发了一封"我们已经替你救火"的邮件。换 Key + 改提交历史 + 走公司合规流程花了整整一天。

红线 7:/loop 任务要定期 review

Claude 会"漂"。你今天写好的提示词,3 个月后可能输出已经不对了——可能是 MCP 升级、上游 API 改字段、提示词过时。

建议

  • 每月 1 号花 30 分钟看一遍所有 /loop 的输出,确认还是你想要的
  • 给每个 /loop 任务设一个 expiration(如 90 天后自动 disable,要重新审过才再启)
  • 重要任务输出抽样存到 Notion,方便对比"以前 vs 现在"

真实事故:某用户的"每周分析竞品"/loop 跑了 4 个月没看,期间一家被监控的公司悄悄换了官网域名。Claude 找不到旧域名 → 提示词没写"找不到怎么办" → Claude 编了一段"该公司本周无更新"的话蒙过去。用户一直被蒙了 4 个月,直到偶然在新闻里看到该公司新功能发布才发现 /loop 已经"失明"了。

红线 8:多设备只在一台跑同一个 /loop

如果你 Mac、办公电脑、家里 PC 都装了 Claude Code 并配了同一份 settings,同一个 /loop 会被三台机器同时触发——你早上会收到 3 份一模一样的早报,账单也会乘 3。

解决办法

  • /loop list 看一下是不是只有一台机器有这个 ID
  • 注册时加 --device-pin <设备名>,绑定到具体设备
  • 或者干脆把 /loop 全部统一在一台"自动化主机"上跑
/loop "0 7 * * *" "..." --device-pin laptop-mac

真实事故:某团队 5 人都把 /loop 配置同步到云端,每个人电脑都跑同一个"每天 8:00 出销售日报"。结果销售总监每天 8:00 在群里收到 5 份一模一样的日报,一年后才发现是这个原因——账单也乘了 5。教训:自动化任务只能有一个"指定的执行人",绝不能 N 台机器同时跑。


十一、给团队管理员的特别建议

如果你不只是个人用 Claude Code,还在团队/公司里推广,这一节专门给你。

11.1 团队级 Hook 怎么设

团队的 Hook 应该放在项目仓库的 .claude/settings.json 里,进 Git,所有成员共享。这样新人 clone 项目就自动有相同的工程纪律。

推荐的"团队基础 Hook 套餐":

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "scripts/claude-hooks/check-dangerous-cmd.sh" }
        ]
      },
      {
        "matcher": "Write|Edit",
        "hooks": [
          { "type": "command", "command": "scripts/claude-hooks/check-secrets.sh" }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "scripts/claude-hooks/auto-format.sh" },
          { "type": "command", "command": "scripts/claude-hooks/run-related-tests.sh" }
        ]
      },
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "scripts/claude-hooks/audit-log.sh" }
        ]
      }
    ]
  }
}

把所有 Hook 脚本放在 scripts/claude-hooks/ 目录下,每个脚本独立、注释清晰、可独立测试。这样新成员一看就懂"为什么会自动跑这个"。

11.2 团队的 /loop 怎么管

/loop 是设备级的,不像 Hook 能跨成员同步。团队推荐做法:

  1. 指定一台"自动化主机"——可能是公司的小服务器、共享 Mac mini、或者一台云主机。
  2. 所有团队级 /loop(销售日报、监控、周报)都注册在这台主机上。
  3. 每个成员的个人 /loop(自己的早报、个人提醒)注册在自己电脑上。
  4. 每月一次"自动化主机 review 会"——15 分钟过一遍所有任务,看哪些该 disable、哪些要更新。

11.3 给团队的"自动化白名单"和"黑名单"

把组织对自动化的态度写成 markdown 文档,放进项目根目录 AUTOMATION_POLICY.md

# 自动化白名单(这些可以自动跑)
- 拉取 git 最新代码
- 跑 lint / format
- 跑测试
- 收集指标到内部 Slack
- 整理本周的 PR / Issue

# 自动化黑名单(绝对不能自动跑)
- 给客户发邮件(必须人工 review)
- 部署到生产环境
- 任何涉及付款的操作
- 修改主分支
- 删除任何文件(包括 build 产物)

这份文档比一切技术防护都重要——它定义了"我们公司对 AI 的信任边界"。


本章一图回顾

                       ╔═══════════════════════════════════╗
                       ║     Claude Code 自动化双轮         ║
                       ╠═══════════════════════════════════╣

                  时间触发                       事件触发
                ┌──────────┐                ┌─────────────┐
                │  /loop    │                │   Hooks     │
                │  闹钟     │                │  反射弧     │
                └────┬──────┘                └──────┬──────┘
                     │                              │
                     ↓                              ↓
              ┌──────────────┐              ┌──────────────┐
              │ Cron 表达式   │              │  7 大事件    │
              │ "什么时候"    │              │  PreToolUse  │
              │              │              │  PostToolUse │
              │ 0 8 * * *    │              │  SessionStart│
              │ */5 * * * *  │              │  SessionEnd  │
              │ 0 9 * * 1-5  │              │  UserPrompt  │
              └──────┬───────┘              │  Stop        │
                     │                      │  Notification│
                     ↓                      └──────┬───────┘
              ┌──────────────┐                     │
              │ 11 个模板:    │                     ↓
              │ 早报 周报 月报 │              ┌──────────────┐
              │ 竞品 邮件     │              │ 10 个模板:    │
              │ 股票 天气     │              │ lint format  │
              │ 文章 涨粉     │              │ 拦危险命令    │
              │ 健康检查      │              │ 备份 审计     │
              └──────┬───────┘              │ 测试 密钥检测 │
                     │                      │ 桌面通知      │
                     │                      │ git pull      │
                     │                      │ 阻止生产数据库 │
                     │                      └──────┬───────┘
                     │                             │
                     └──────────────┬──────────────┘
                                    ↓
                         ┌─────────────────────┐
                         │   综合案例:         │
                         │   每日个人早报       │
                         │   /loop + 6 MCP +   │
                         │   Hook 失败告警      │
                         └─────────┬───────────┘
                                   ↓
                         ┌─────────────────────┐
                         │ 5 大注意:           │
                         │ 设上限 加超时        │
                         │ dry-run 错误告警     │
                         │ 日志清理            │
                         ├─────────────────────┤
                         │ 8 条红线:           │
                         │ 不付款 不发外部       │
                         │ 不递归 频率不超 1 min │
                         │ 急刹车 不裸 Key      │
                         │ 定期 review 单机跑    │
                         └─────────────────────┘

                       ╚═══════════════════════════════════╝

把这张图记住——左边是闹钟,右边是反射弧,中间是案例,下面是注意事项。这 4 块就是"个人 AI 自动化"的全部。


下章预告

到这一章为止,你的 Claude Code 已经能:

  • 听到指令做事(前八章)
  • 按时自己上班(/loop
  • 看见就反应(Hooks)

但能力越大,潜在风险越大。当 AI 能 24 小时自己动手,安全边界就成了不可回避的话题——它会不会把不该读的文件读了?会不会把 API Key 传到云上?会不会被钓鱼攻击劫持?被恶意 MCP 偷走数据?

下一章 第十章 安全与隐私 会把"保命"这件事讲透:

  • 默认安全护栏:Claude Code 自带的 4 道防线是什么?
  • 沙箱隔离:怎么让危险任务跑在"封闭笼子"里?
  • 提示词注入:恶意网页/文档如何劫持 Claude?怎么防?
  • API Key 管理:放哪里、怎么轮换、泄露了怎么办?
  • 数据出境:哪些数据会上传 Anthropic?哪些不会?怎么完全本地化?
  • 企业合规:HIPAA / GDPR / 等保 / 涉密单位怎么用?
  • 应急处置:发现 Claude 干了不该干的事,5 分钟止损步骤

自动化做到位 = 你睡觉时有人替你工作;安全做到位 = 你睡觉时不会被人偷家。下一章我们就把"安全"这层底裤穿好。