把 Claude Code 接进定时任务:无人值守跑一天,早上只看 diff
一个人维护一个站,重复劳动最贵。每天写情报、每周扫政策、每月出精选——这些活的共同点是:结构化、有明确验收、但很耗时候。它们恰好适合交给 Agent 夜里跑。
这篇给一套能直接抄的配置。所有命令行参数取自 Claude Code 官方 CLI 文档。
一、最小可用的一次无头调用
claude -p "检查 content/news 里最近 48 小时有没有漏更,缺就补写" \
--output-format json \
--max-turns 12
三个关键点:
-p/--print:查完就退出,不进交互界面。--output-format:text/json/stream-json。要机器可读就用json;要实时看进度(比如长任务的中间输出透传)用stream-json,通常配合--verbose:claude -p --output-format stream-json --verbose "总结今天的构建日志"--max-turns(仅 print 模式):这条务必写。默认无限轮,一个卡住的 Agent 能跑一整夜的 token。一到上限就退出并报错,成本封顶。
管道输入也支持:
cat logs.txt | claude -p "找出所有 5xx 并按接口归类" --output-format json
二、把权限收死:允许列表白名单
无人值守时 Agent 拿到了你本地的完整权限(能读文件、能跑命令),所以必须显式限制。
claude -p "给昨天的提交补缺失的测试用例" \
--allowedTools "Read" "Bash(git log *)" "Bash(git diff *)" \
--permission-mode default \
--max-turns 8
--allowedTools/--allowed-tools:不需要再弹确认的工具,支持括号通配,例如"Bash(git log *)"、"Bash(git diff *)"、"Read"。--disallowedTools/--disallowed-tools:反向,把某些工具从上下文里摘掉,"*"等于全部禁掉。--permission-mode:default/acceptEdits/plan/auto/dontAsk/bypassPermissions。无人值守不要用bypassPermissions——那是把”我不看”写进配置里了。要自动同意编辑用acceptEdits,并配合下面的分支闸门。
我的习惯是两道锁:
- 工具白名单只给
Read、指定的几条Bash(git *)、Edit;网络请求一律不给; - 同时在独立的 git worktree / 分支里跑,Agent 改完只产出 diff,合并动作留给人。
第 2 条比第 1 条重要。白名单挡的是意外,分支挡的是”它自信地做错了 200 行”。
三、会话可以续跑
一次跑不完的任务不必重来:
# 用一个业务名字起会话
claude -p --session-id "$(uuidgen)" "开始重构鉴权模块" --output-format json
# 第二天接着上次继续
claude --resume auth-refactor "继续,先补测试"
--session-id:指定会话 ID,必须是合法 UUID。自己生成方便在脚本里追踪。--resume/-r:按 ID 或名字恢复。不带参数会弹出交互式选择器(后台会话标bg)。
定时任务里推荐用显式 UUID + 记录到日志文件,这样第 N 次跑挂了,能精确捞回那条会话接着说。
四、一个能直接用的定时任务模板
每天上午 9 点补情报,只改 content/news,跑完把结果写日志:
#!/usr/bin/env bash
set -euo pipefail
cd /path/to/project
BRANCH="auto/$(date +%Y%m%d-%H%M)"
git switch -c "$BRANCH"
claude -p "为 content/news 补今天缺失的条目,按现有文件格式写,完成后运行校验脚本" \
--output-format json \
--allowedTools "Read" "Edit" "Bash(git status)" "Bash(git diff)" \
--permission-mode acceptEdits \
--max-turns 20 \
> "logs/claude-$(date +%F).json" 2>&1 || echo "任务失败,看日志" >&2
# 只生成 diff,不自动合并
git add -A && git diff --cached --stat
echo "改动在 $BRANCH,人工 review 后再合并"
最后三行是这套方案的全部精髓:Agent 出活,人做决定。
五、四个容易踩的坑
- 不加
--max-turns。卡住的 Agent 会一直重试到天亮,账单先于结果到达。设一个比你认为需要的略小的数,它会更早失败、更早被你发现。 - 把
--output-format json的输出直接当汇报。它包含工具调用轨迹,很长。真正要读的是最后一条 assistant 消息,写个 jq 抽出来再入库。 - 让 Agent 在同一分支上直接提交。早晚会有一天它改错并推送,而你当日发现不了。分支 + diff 的成本几乎为零。
- 忘了它读得到你整个仓库。
.env、密钥文件、客户数据都在里面。跑之前确认.gitignore是真生效的,必要时空目录起步。
六、什么活适合这么干
适合:结构固定、验收标准明确、错了能回滚的活——补内容、生成周报、跑 lint 并修、翻译、给 PR 写摘要、检查政策更新。
不适合:要对外发请求、要花钱、要删东西、涉及真实个人信息的活。这些不是”自动化”,是”无人看管的权限”。
一句话总结这套心法:让 Agent 夜里干活,白天你只做一件事——看 diff。