开始之前
你需要 Claude Code、一个终端,以及运行 JSON 示例用的 jq。如果对权限规则还不熟,先读设置那一课,因为无头运行里没人回答提示,全靠规则来决定。
Anthropic 为此写的页面叫 Run Claude Code programmatically。页面把 claude -p 称作 Agent SDK 的命令行形式,第 4 课就建立在 Agent SDK 之上。下面的参数来自这个页面和命令行参考,读于 2026 年 11 月 4 日,无头运行页面在本课更新时又核对过一遍。
跑一条提示词,把数据管道进去,检查退出码
非交互模式会读取 stdin,所以 Claude Code 用起来和任何命令行过滤器一样。下面是 Anthropic 的示例:构建日志送进去,解释以文件的形式出来。
cat build-error.txt | claude -p 'concisely explain the root cause of this build error' > output.txt- 运行
claude -p "What does the auth module do?"。Claude Code 打印回答然后退出。-p是--print的缩写。 - 用上面那条命令把构建日志管道进去。管道输入 stdin 的上限是 10MB,更大的内容请写进文件,并在提示词里写明路径。
- 用
echo $?读退出码。成功是 0,运行失败是非 0。无效的参数会在运行开始之前报到 stderr。 - 故意让运行在内部失败,比如在没有认证的情况下运行。Claude Code 会把失败信息当作结果打印到 stdout,所以脚本应该先检查退出状态,再相信 stdout。
- 点名工具,让 Claude 修改文件:
claude -p "Find and fix the bug in auth.py" --allowedTools "Read,Edit,Bash"。
没人来批准:工具、模式和提示
在 Claude Code v2.1.302 或更高版本里,没设权限模式的 -p 运行从 Manual 模式开始。需要批准的调用会被拒绝,除非有 allow 规则、hook、canUseTool 回调或 --permission-prompt-tool 批准它。所以要做的事,是提前说清楚什么可以运行。
在 CI 里,Anthropic 的权限模式页面给了一个配合 dontAsk 的精确白名单。凡是会弹提示的调用都被拒绝,只有列出的那条命令和文件读取能运行。
claude -p "run the test suite" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"| 参数 | 效果 | 适合 |
|---|---|---|
--allowedTools "Read,Edit" | 列出的工具不经提示直接运行。它用权限规则语法,所以 Bash(git diff *) 放行任何以 git diff 开头的命令 | 命令都已知的任务 |
--permission-mode acceptEdits | 文件写入和 mkdir、touch、mv、cp 这类常见文件系统命令直接运行。其他 shell 命令仍然需要 allow 条目 | lint 修复和重构 |
--permission-mode dontAsk | 凡是会弹提示的调用都被拒绝。工作目录里的读取和已放行的工具仍然运行 | 严格锁定的 CI |
--permission-mode auto | 由分类器代替你审查大多数操作 | 没人盯着的宽泛任务 |
--permission-prompts none | 凡是会弹提示的调用都被拒绝,并告诉 Claude 不要重试。需要 v2.1.259 或更高版本 | 带权限宿主的定时任务 |
输出格式:text、json 和 stream-json
默认的 text 输出适合人在终端里看。脚本要的是 json:它返回一个对象,答案在 result 里,另有 session_id、用量元数据、total_cost_usd 和按模型拆分的费用。Anthropic 把这个费用称为客户端估算,可能和账单不一致。
想让数据按你定的形状出来,就加上 --json-schema 并给一个 JSON Schema。校验过的数据出现在 structured_output 字段里。schema 无效时运行会停下,并报 Error: --json-schema is not a valid JSON Schema,而 format 关键字只当注释读,从不强制执行。
claude -p "Extract the main function names from auth.py" \
--output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
| jq '.structured_output'| 格式 | 你得到什么 | 怎么读 |
|---|---|---|
text | 纯文本,默认值 | 重定向到文件 |
json | 一个对象,含 result、session_id、用量和费用。配合 --json-schema 还多一个 structured_output 字段 | jq -r '.result' |
stream-json | 按行分隔的 JSON 事件,最后是一条 result 消息。加 --verbose 和 --include-partial-messages 才有逐词的增量 | 用 jq 逐行处理 |
继续一段对话,不用猜是哪一段
--continue 加载当前目录里最近的一段对话。单独的 --continue 会跳过 claude -p 产生的会话,而 claude -p --continue 把它们算进来。凡是会运行不止一次的任务,都应该从 JSON 输出里取出 ID,恢复那一个确切的会话。
--resume 还接受会话名,或者会话 .jsonl 记录文件的绝对路径。Claude Code 能在这台机器的任何项目里找到某个 ID,所以两条命令可以在不同目录里运行。继续对话时,total_cost_usd 报告的是整段对话的花费,前面几次运行也算在内。--fork-session 从旧对话派生出一个新 ID,--no-session-persistence 则什么都不保存。
session_id=$(claude -p "Start a review" --output-format json | jq -r '.session_id')
claude -p "Continue that review" --resume "$session_id"用 --bare 让 CI 可重复
普通的 claude -p 会加载交互会话加载的东西:hooks、技能、插件、MCP 服务器、自动记忆和 CLAUDE.md,来自工作目录,也来自 ~/.claude。队友的某个 hook 或者一个游离的 .mcp.json 就是这样跑进你的 CI 任务里的。加上 --bare,Claude Code 把这些全部跳过,Claude 保留 Bash、文件读取和文件编辑工具。
bare 模式从不读取 OAuth 凭据或系统钥匙串。请设置 ANTHROPIC_API_KEY,或者在 --settings 的 JSON 里提供 apiKeyHelper。Amazon Bedrock、Google Cloud 的 Agent Platform 和 Microsoft Foundry 仍然读取各自的凭据。v2.1.286 之前这些限制只部分成立,所以请核对你的版本。
没有
--bare时,-p会话会运行项目.claude/settings.json里的 hooks,并连接其.mcp.json里的服务器,即使这个文件夹你从未信任过。
claude --bare -p "Summarize README.md" --allowedTools "Read"| 要加载 | 用 |
|---|---|
| 系统提示词的追加内容 | --append-system-prompt、--append-system-prompt-file |
| 设置 | --settings,后面跟文件路径或内联 JSON |
| MCP 服务器 | --mcp-config |
| 自定义智能体 | --agents |
| 插件 | --plugin-dir、--plugin-url |
写进脚本,并给它设上限
页面里的这个脚本把一个拉取请求的 diff 管道进 Claude,请它做安全审查。把它存成 review.sh,运行 bash review.sh 123。shell 会把 "$1" 换成 123,审查结果以 JSON 返回,文字在 result 里。
脚本还需要几道上限。文档里写到的有这些。
脚本也离不开它运行时的版本。九月以来有四个版本改了 -p 运行的行为,所以在相信一段旧脚本之前,先在运行器上跑 claude --version,和这些版本对一对。
gh pr diff "$1" | claude -p \
--append-system-prompt "You are a security engineer. Review for vulnerabilities." \
--output-format json--max-turns限制打印模式下的智能体回合数,默认没有上限。--max-budget-usd在估算花费达到这个金额时停止运行。子智能体的花费也计入,而且花费可能超过上限,所以要留出余量。- SIGTERM 会让运行以退出码 143 结束,并且不为正在进行的回合记录结果。想干净地结束回合,先发 SIGINT,或者调用 SDK 的
interrupt()。 - 给出答案之后,运行还会为它启动的后台工作保持打开。空闲等待默认 10 分钟后停止,
CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS可以改这个上限。 stream-json输出里的system/init事件列出已加载的插件和 MCP 服务器。mcp_server_errors数组非空,说明有服务器根本没加载,所以 CI 关卡可以据此判失败。
v2.1.259 新增
--permission-prompts none凡是会弹出提示的操作都直接拒绝,其余的仍由你设定的权限模式决定。
来源:Claude Code release v2.1.259 on GitHub (2026年11月5日 查阅)
v2.1.286 让
--bare完全生效bare 运行只连接命令行上点名的 MCP 服务器,不发系统提醒,也不启动后台任务。
来源:Claude Code release v2.1.286 on GitHub (2026年11月5日 查阅)
v2.1.314 修好一个无声的启动失败
启动就失败的
claude -p运行,以前可能以 0 退出且没有任何输出,现在会打印错误并以 1 退出。来源:Claude Code changelog (2026年11月5日 查阅)
v2.1.318 不再乱改
~/.claude.json无人值守的运行,也就是
claude -p和 SDK 应用,在文件内容没变时不再重写它。来源:Claude Code changelog (2026年11月5日 查阅)
Claude Code 的作者为什么要每个脚本都加 --bare
Boris Cherny 是 Claude Code 的作者,他在 X 上的一串技巧里,把 --bare 列为第 12 条。
默认情况下,claude -p 以及 TypeScript 和 Python SDK 会去找本地的 CLAUDE.md、设置和 MCP 服务器。脚本通常更想自己点名要加载什么。
他说这样启动最多能快十倍,还把旧的默认行为称作 SDK 早期的一个设计疏忽。
他在帖子里说,将来的版本会把默认改成 --bare。这一步至今还没到来。无头运行页面仍把它称为脚本的推荐模式和将来的默认值,所以这个参数还得你自己加。
现在就把它加进每一条 CI 调用。默认值改掉的那天,你的任务行为不变。在那之前,队友的 hook 或者随手留下的 .mcp.json 也混不进运行里。
不过在非交互使用时,大多数情况下你会想通过
--system-prompt、--mcp-config、--settings等参数明确指定要加载什么。
X 官方嵌入卡片的截图,拍摄于 2026 年 11 月 5 日,时间为 UTC。X 用“Show more”截断了这条帖子。点击截图可到 X 上打开原帖。
常见错误
- 用了
--bare却没有 API 密钥。bare 模式跳过订阅登录,所以在设置ANTHROPIC_API_KEY之前运行会认证失败。 - 没检查
structured_output是否存在就去读它。运行结束时没有有效的结构化输出,比如 Claude 拒绝了请求,就没有这个字段。 - 在不是你写的仓库里运行
claude -p。没有--bare时,它会运行那个项目的 hooks,并在没有信任对话框的情况下连接它.mcp.json里的服务器。请用--bare启动,或者传--setting-sources user。 - 在共用的目录里依赖
--continue。它选的是那里最近的一段对话,第二个任务一来就变了。请记下会话 ID。 - 用 SIGTERM 停掉任务,却指望拿到结果。正在进行的回合会被留在未完成的状态。
动手试试
- 把
git diff main管道进claude -p,用--append-system-prompt设一份审查员的说明。分别用text和json各跑一次,比较脚本能拿它们做什么。 - 写一段 shell,用
--output-format json运行一条提示词,退出码不是 0 就停下,并用jq打印.result和.total_cost_usd。 - 用
--output-format stream-json --verbose运行一条提示词,找到system/init事件。列出它的插件和 MCP 服务器,再加上--bare重复一遍并比较。 - 在需要更多回合的任务上设
--max-turns 3,记下你的脚本收到了什么。
下一课:GitHub Actions 里的 Claude Code
在 CI 的 runner 上,没人盯着运行,密钥还放在它的环境里,上面的一切都会更难。下一课 GitHub Actions 里的 Claude Code 会搭好官方 action,以及围绕它的密钥、权限和费用限制。
hooks 会在会话的固定节点运行你自己的命令,而 --bare 会跳过它们。hooks 一课列出了 hook 能响应的事件。
自测一下
一个 CI 任务在 v2.1.302 或更高版本的 Claude Code 里运行 claude -p,没设权限模式,也没放行 Bash。Claude 想运行的 shell 命令会怎样?
查看答案
B. 被拒绝,因为运行从 Manual 模式开始,没人能批准 这个版本里没设模式的 -p 运行从 Manual 模式开始,需要批准的调用会被拒绝,除非规则、hook 或回调批准它。
哪种输出格式返回一个对象,答案在 result 里,并带有 session_id?
查看答案
C. json json 格式返回带有结果、会话 ID 和元数据的结构化 JSON,而 stream-json 发送的是按行分隔的事件。
一个任务运行 claude --bare -p "Summarize README.md",认证失败了。最可能的原因是什么?
查看答案
A. bare 模式从不读取 OAuth 凭据或钥匙串,而且没设置 ANTHROPIC_API_KEY bare 模式跳过订阅登录,所以需要环境里的 API 密钥,或者设置 JSON 里的 apiKeyHelper。
两个任务在同一个目录里运行,第二个必须接着第一个的对话继续。最稳妥的办法是什么?
查看答案
D. 从 JSON 输出里读出 session_id,传给 --resume --continue 选的是目录里最近的对话,而带着记下的会话 ID 的 --resume 指明了确切的那一个。
常见问题
什么时候该用 Python 或 TypeScript 包,而不是 claude -p?
当脚本需要的东西,是 shell 给不了的。Anthropic 的页面把工具批准回调和原生消息对象,连同结构化输出,列为这些包额外提供的能力。这门课的最后一节就建立在它们之上。
怎样为某一次运行更换模型或系统提示词?
用 --model 传入 sonnet、opus 或 haiku 这样的别名,或者完整的模型名。--append-system-prompt 把文字追加到默认提示词之后,多数脚本用它就够了,而 --system-prompt 会替换整个默认提示词。
怎样让 claude -p 输出 JSON?
加上 --output-format json。答案在 result 字段里,旁边是 session_id 和费用数据。想要固定的结构,就加 --json-schema 再读 structured_output,运行结束时没有有效的结构化输出,这个字段就不存在。
在 -p 运行里能用技能和斜杠命令吗?
用户调用的技能和自定义命令可以用:在提示词里写 /skill-name,Claude Code 会展开它。只能在终端界面里运行的内置命令,比如 /login,则不可用。/model 等少数几个命令把值当作参数。
怎样追踪一次无头运行花了多少钱?
读 JSON 输出里的 total_cost_usd,里面还有按模型拆分的明细。Anthropic 把这两个数字都称为客户端估算,可能和账单不同。加上 --max-budget-usd,可以在达到上限时停止运行。
能在另一个目录里恢复无头会话吗?
能。--resume 带上会话 ID,会先搜当前项目和它的 git 工作树,再搜这台机器上的所有其他项目。你也可以传入会话 .jsonl 记录文件的绝对路径。
资料来源
- Claude Code docs: Run Claude Code programmatically https://code.claude.com/docs/en/headless
- Claude Code docs: CLI reference https://code.claude.com/docs/en/cli-reference
- Claude Code docs: Permission modes https://code.claude.com/docs/en/permission-modes
- Claude Code release v2.1.259 on GitHub https://github.com/anthropics/claude-code/releases/tag/v2.1.259
- Claude Code release v2.1.286 on GitHub https://github.com/anthropics/claude-code/releases/tag/v2.1.286
- Claude Code changelog https://code.claude.com/docs/en/changelog
- Boris Cherny on X: use --bare to speed up SDK startup https://x.com/bcherny/status/2038454357088457168

