Claude Code 自动化与排错
Claude Code 自动化与排错
定时执行提示任务
3 分钟阅读
定时执行提示任务
用 /loop 和 cron 调度工具反复运行提示词、轮询状态,或在 Claude Code 会话内设置一次性提醒。
定时任务需要 Claude Code v2.1.72 或更高版本。用 claude --version 检查你的版本。
定时任务能让 Claude 按固定间隔自动重新运行某个提示词。可以用它们轮询一次部署、盯着一个 PR、回头查看一个长期运行的构建,或者提醒你在会话稍后的时间做某件事。要在事件发生时立即响应,而不是轮询,请参阅Channels:你的 CI 可以直接把失败信息推送进会话。要让会话逐轮持续工作直到满足某个条件,而不是按固定间隔运行,请参阅/goal。
任务的范围限定于会话:它们存在于当前对话中,你开始一个新对话时就会停止。用 --resume 或 --continue 恢复会话,会带回任何尚未过期的任务:即最近 7 天内创建的循环任务,或触发时间尚未到达的一次性任务。要让调度独立于任何会话持续存在,请用例行任务(Routines)在 Anthropic 托管的基础设施上创建一个例行任务,搭建一个桌面端定时任务,或使用GitHub Actions。
比较各种调度方式
Claude Code 提供三种调度循环或一次性工作的方式:
| 云端 | 桌面端 | /loop | |
|---|---|---|---|
| 运行位置 | Anthropic 云端 | 你的机器 | 你的机器 |
| 是否需要机器开机 | 否 | 是 | 是 |
| 是否需要打开的会话 | 否 | 否 | 是 |
| 重启后是否持续存在 | 是 | 是 | 未过期时随 --resume 恢复 |
| 是否能访问本地文件 | 否(全新克隆) | 是 | 是 |
| MCP 服务器 | 按任务配置的连接器 | 配置文件和连接器 | 继承自会话 |
| 权限提示 | 无(自主运行) | 可按任务配置 | 继承自会话 |
| 可自定义调度计划 | 通过 CLI 中的 /schedule | 是 | 是 |
| 最短间隔 | 1 小时 | 1 分钟 | 1 分钟 |
用 /loop 反复运行一个提示词
/loop 这个内置技能是在会话保持打开期间反复运行某个提示词的最快方式。间隔和提示词都是可选的,你提供的内容决定了该循环的行为。
| 你提供的内容 | 示例 | 会发生什么 |
|---|---|---|
| 间隔和提示词 | /loop 5m check the deploy | 你的提示词会按固定计划运行 |
| 仅提示词 | /loop check the deploy | 你的提示词会在每次迭代时按Claude 选择的间隔运行 |
| 仅间隔,或什么都不提供 | /loop | 运行内置的维护提示词,或你的 loop.md(如果存在) |
你也可以把某个技能作为提示词传入,例如 /loop 20m /review-pr 1234,让每次迭代都重新运行该技能。从 v2.1.196 开始,一次定时触发只会运行 Claude被允许自行调用的技能。以下内容会以纯文本形式送达 Claude,而不会被执行:
- 内置命令,例如
/permissions、/model或/clear - 被标记为
disable-model-invocation: true的技能 - 被
skillOverrides设置或Skill拒绝规则对 Claude 隐藏的技能 - MCP 提示词,例如
/mcp__github__list_prs;由 MCP 服务器暴露的技能仍会运行
按固定间隔运行
当你提供一个间隔时,Claude 会将其转换为一个 cron 表达式,调度该任务,并确认运行节奏和任务 ID。
该间隔可以作为一个孤立的令牌放在提示词前面,例如 30m,也可以作为一个从句放在提示词后面,例如 every 2 hours。支持的单位是 s(秒)、m(分钟)、h(小时)和 d(天)。
由于 cron 的精度是一分钟,秒数会被向上取整为最近的一分钟。像 7m 或 90m 这样无法对应到一个整齐 cron 步长的间隔,会被四舍五入到最接近的可用间隔,Claude 会告诉你它选定的值。
让 Claude 选择间隔
当你省略间隔时,Claude 会动态选择一个,而不是按固定的 cron 计划运行。每次迭代后,它会根据观察到的情况,在一分钟到一小时之间选择一个延迟:当某次构建即将完成或某个 PR 处于活跃状态时,等待较短;当没有待处理事项时,等待较长。所选的延迟以及选择它的原因,会在每次迭代结束时打印出来。
以下示例检查 CI 和审查评论,一旦该 PR 安静下来,Claude 会在各次迭代之间等待更长时间:
当你要求一个动态的 /loop 调度时,Claude 可能会直接使用监视器工具。监视器会运行一个后台脚本,并把每一行输出流式传回,这完全避免了轮询,通常比按固定间隔重新运行提示词更节省 Token、响应更快。
一个动态调度的循环会像任何其他任务一样出现在你的定时任务列表中,因此你可以用同样的方式列出或取消它。抖动规则不适用于它,但七天过期规则适用:该循环会在你启动它七天后自动结束。
在 Amazon Bedrock、Google Cloud 的 Agent Platform 和 Microsoft Foundry 上,不带间隔的提示词会改为按固定的 10 分钟计划运行。
运行内置的维护提示词
当你省略提示词时,Claude 会使用一个内置的维护提示词,而不是你提供的提示词。每次迭代它会按顺序处理以下内容:
- 继续对话中任何未完成的工作
- 处理当前分支 pull request 的事务:审查评论、失败的 CI 运行、合并冲突
- 当没有其他待处理事项时,运行清理性任务,例如查找 bug 或做简化
Claude 不会在这个范围之外启动新的工作,像推送或删除这样不可逆的操作,只有在记录中已经授权的工作延续时才会继续执行。
一个孤立的 /loop 会以动态选择的间隔运行这个提示词。添加一个间隔,例如 /loop 15m,可改为按固定计划运行它。要用你自己的默认提示词替换这个内置提示词,请参阅用 loop.md 自定义默认提示词。
在 Amazon Bedrock、Google Cloud 的 Agent Platform 和 Microsoft Foundry 上,不带提示词的 /loop 会打印用法说明,而不会运行维护提示词。
用 loop.md 自定义默认提示词
一个 loop.md 文件会用你自己的指令替换内置的维护提示词。它为孤立的 /loop 定义了单一的默认提示词,而不是一份独立定时任务的列表,并且只要你在命令行上提供了提示词,它就会被忽略。要在它之外调度额外的提示词,请使用 /loop <prompt>,或直接询问 Claude。
Claude 会在两个位置查找该文件,使用它找到的第一个。
| 路径 | 范围 |
|---|---|
.claude/loop.md | 项目级。当两个文件都存在时优先。 |
~/.claude/loop.md | 用户级。适用于任何没有定义自己文件的项目。 |
该文件是没有任何强制结构的纯 Markdown。像你直接输入 /loop 提示词一样撰写它。以下示例保持一个发布分支的健康:
对 loop.md 的编辑会在下一次迭代时生效,因此你可以在循环运行期间不断打磨这些指令。当这两个位置都不存在 loop.md 时,该循环会回退到内置的维护提示词。请保持该文件简洁:超过 25,000 字节的内容会被截断。
在 Amazon Bedrock、Google Cloud 的 Agent Platform 和 Microsoft Foundry 上,不会读取 loop.md,不带提示词的 /loop 会改为打印用法说明。
停止一个循环
要在一个 /loop 正等待下一次迭代时停止它,按 Esc。这会清除待处理的唤醒,使该循环不再触发。你通过直接询问 Claude调度的任务不受 Esc 影响,会一直保留,直到你删除它们。
在自主节奏模式下,一旦任务完成,Claude 也可以自行结束该循环。Claude 会调用带 stop: true 的ScheduleWakeup 工具,立即取消待处理的唤醒。如果某次迭代结束时既没有重新调度也没有停止,Claude Code 会安排一次约 20 分钟后的后备唤醒,如果那次迭代同样没有重新调度,就会结束该循环。在 v2.1.202 之前,不重新调度是 Claude 唯一能自行结束循环的方式。
按固定间隔运行的循环会持续运行,直到你停止它们,或七天过去。
设置一次性提醒
对于一次性提醒,用自然语言描述你想要的内容,而不是使用 /loop。Claude 会调度一个单次触发的任务,运行后自行删除。
Claude 会用一个 cron 表达式把触发时间固定到具体的分钟和小时,并确认它将在何时触发。
管理定时任务
用自然语言让 Claude 列出或取消任务,也可以直接引用底层工具。
在底层,Claude 使用以下工具:
| 工具 | 用途 |
|---|---|
CronCreate | 调度一个新任务。接受一个 5 字段的 cron 表达式、要运行的提示词,以及它是循环执行还是只触发一次。 |
CronList | 列出所有定时任务及其 ID、计划和提示词。 |
CronDelete | 按 ID 取消某个任务。 |
每个定时任务都有一个 8 字符的 ID,可以传给 CronDelete。一个会话最多可同时保留 50 个定时任务。
定时任务如何运行
调度器每秒检查一次是否有到期的任务,并将其以低优先级加入队列。一个定时提示词会在你各轮次之间触发,而不会在 Claude 正在回复的过程中触发。如果某个任务到期时 Claude 正忙,该提示词会等到当前轮次结束。
所有时间都按你的本地时区解读。像 0 9 * * * 这样的 cron 表达式,指的是你运行 Claude Code 所在地的上午 9 点,而不是 UTC 时间。
抖动
为了避免所有会话在同一时刻集中调用 API,调度器会为触发时间添加一个确定性的偏移量:
- 循环任务会在计划时间之后最多 30 分钟内触发(对于运行频率高于每小时一次的任务,则是间隔的一半以内)。一个计划在
:00触发的每小时任务,可能会在:00到:30之间的任意时刻触发。 - 计划在整点或半点触发的一次性任务,会最多提前 90 秒触发。
这个偏移量由任务 ID 推导得出,因此同一个任务总会得到相同的偏移量。如果精确的时间很重要,请选择一个不是 :00 或 :30 的分钟,例如用 3 9 * * * 代替 0 9 * * *,这样一次性任务的抖动就不会生效。
七天过期
循环任务会在创建 7 天后自动过期。该任务会最后触发一次,然后自行删除。这限制了一个被遗忘的循环最长能运行多久。如果你需要一个循环任务持续更久,请在它过期前取消并重新创建,或使用例行任务(Routines)或桌面端定时任务实现持久化调度。
Cron 表达式参考
CronCreate 接受标准的 5 字段 cron 表达式:分钟 小时 日 月 星期。所有字段都支持通配符(*)、单一值(5)、步长(*/15)、范围(1-5)和逗号分隔的列表(1,15,30)。
| 示例 | 含义 |
|---|---|
*/5 * * * * | 每 5 分钟一次 |
0 * * * * | 每小时整点 |
7 * * * * | 每小时的第 7 分钟 |
0 9 * * * | 每天本地时间上午 9 点 |
0 9 * * 1-5 | 工作日本地时间上午 9 点 |
30 14 15 3 * | 3 月 15 日本地时间下午 2:30 |
星期字段用 0 或 7 表示星期日,6 表示星期六。不支持像 L、W、? 这样的扩展语法,以及像 MON 或 JAN 这样的名称别名。
当日和星期两个字段都被限定时,只要其中一个字段匹配,该日期就算匹配。这遵循标准的 vixie-cron 语义。
关闭定时任务
在你的环境中设置 CLAUDE_CODE_DISABLE_CRON=1,即可完全关闭调度器。cron 工具和 /loop 会变得不可用,任何已经调度的任务都会停止触发。完整的关闭标志列表,请参阅环境变量。
限制
会话范围的调度存在固有的限制:
- 任务只在 Claude Code 处于运行且闲置状态时触发。关闭终端或让会话退出会阻止它们触发。将会话转入后台会把
/loop任务带到该后台会话中,让它在没有终端的情况下继续运行。 - 错过的触发不会补跑。如果某个任务的计划时间在 Claude 忙于处理一个长时间请求期间过去了,它会在 Claude 变为闲置时触发一次,而不是为每个错过的间隔各触发一次。
- 开始一个全新的对话会清除所有会话范围的任务。用
claude --resume或claude --continue恢复会话,会恢复尚未过期的任务:创建于七天以内的循环任务,以及计划时间尚未到达的一次性任务。后台 Bash 和监视器任务在恢复时永远不会被恢复。
对于需要无人值守运行的、由 cron 驱动的自动化:
- 例行任务(Routines):在 Anthropic 托管的基础设施上,按计划、通过 API 调用,或在 GitHub 事件触发下运行
- GitHub Actions:在 CI 中使用
schedule触发器 - 桌面端定时任务:在你的机器上本地运行