CoreCode博客

用法

claude -p 用法详解:在脚本和 CI 里非交互运行 Claude Code

发布于 · 最后核对

这一页讲怎么在脚本里用 claude -p 调用 Claude Code:基本用法、管道输入、三种输出格式、工具权限、续接对话和 bare 模式,命令都可以直接复制。参数、字段和行为取自 Anthropic 官方的 Run Claude Code programmatically 文档,2026 年 10 月 30 日核对。这里是一个精选,文档里还有子代理消息、后台任务等更多内容。

要点
  • 带上提示词传 -p(或 --print)就是非交互运行。Claude Code 成功时退出码为 0,运行失败时为非 0,脚本可以据此分支。
  • --output-format 可选 text(默认)、json、stream-json。加上 --json-schema 会得到 structured_output 字段。
  • 在 Manual 模式的 claude -p 运行里,需要批准的工具调用会被拒绝,除非有东西批准它。用 --allowedTools 列出工具,或用 --permission-mode 设基线。
  • Anthropic 推荐脚本和 SDK 调用用 --bare:它跳过 hooks、skills、插件、MCP 服务器、auto memory 和 CLAUDE.md 的自动发现,每台机器上结果一致。

-p 做什么

在任何 claude 命令后加 -p(或 --print)标志,就以非交互方式运行。下面这条运行一个提示词并打印回复:

claude -p "What does the auth module do?"

不是每个 CLI 选项都能和 -p 组合。Claude Code 会拒绝 --bg,也会拒绝带任务描述的 --cloud,并给出指明冲突的错误。

Claude Code 成功时退出码为 0,运行失败时为非 0。如果传了无效的参数,它会在运行开始前把错误报告到 stderr。运行内部发生的失败,比如缺少认证,则作为结果打印在 stdout 上。

-p 可以和其他参数一起用。下面这条预先批准了三个工具,Claude 不用弹提示就能工作:

claude -p "Find and fix the bug in auth.py" --allowedTools "Read,Edit,Bash"

管道输入

非交互模式会读取 stdin,所以可以像其他命令行工具一样把数据管道进来,把回复重定向出去。下面把一份构建日志管道给 Claude,并把解释写进文件:

cat build-error.txt | claude -p 'concisely explain the root cause of this build error' > output.txt

管道输入的 stdin 上限是 10MB。超过时,Claude Code 会报一个明确的错误并以非 0 状态退出。输入更大时,改为把内容写进文件,在提示词里引用文件路径。如果 Claude Code 读不了 stdin,比如启动它的进程断开了自己这一端,它会向 stderr 打印警告,并用命令行里的提示词继续。

也可以把调用包进脚本,把 Claude 当作项目专用的 linter。下面这个 package.json 脚本把相对 main 的 diff 管道给 Claude,让它报告拼写错误。管道传 diff 意味着 Claude 不需要 Bash 权限去读它,转义的双引号让脚本在 Windows 上也能用:

{
  "scripts": {
    "lint:claude": "git diff main | claude -p \"you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else.\""
  }
}

用 npm run lint:claude 运行。

输出格式

用 --output-format 控制回复的返回方式:

取值得到什么
text(默认)纯文本输出
json结构化 JSON,包含结果、会话 ID 和元数据
stream-json以换行分隔的 JSON,用于实时流式输出

下面以 JSON 返回项目摘要,文本结果在 result 字段里:

claude -p "Summarize this project" --output-format json

用 --output-format json 时,返回内容里还有 total_cost_usd 和按模型拆分的费用,脚本可以据此跟踪花费。用 --continue 或 --resume 接着之前的对话时,这次运行报告的是整个对话的总额,包含之前几次运行的花费。这两个数字都是客户端估算,可能和实际账单不同。

可以用 jq 之类的工具取出具体字段:

# Extract the text result
claude -p "Summarize this project" --output-format json | jq -r '.result'

# Extract structured output
claude -p "Extract function names from auth.py" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
  | jq '.structured_output'

用 JSON Schema 得到结构化输出

要让输出符合某个特定 schema,把 --output-format json 和 --json-schema 以及一份 JSON Schema 定义一起用。返回内容包含请求的元数据(会话 ID、用量等),结构化输出在 structured_output 字段里。下面提取函数名,返回一个字符串数组:

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"]}'

如果传入的值不是合法的 JSON Schema,claude 会以 Error: --json-schema is not a valid JSON Schema 退出,后面跟着校验器的诊断。Claude Code 接受使用 format 关键字的 schema,比如 "format": "email",但只把 format 当作注解,不强制执行。如果运行结束时没有有效的结构化输出,比如 Claude 拒绝了请求,返回内容里就没有 structured_output 字段,所以脚本使用它之前要先检查这个字段是否存在。

流式输出

用 --output-format stream-json 加 --verbose 和 --include-partial-messages,可以在 token 生成时就收到。每一行是一个表示事件的 JSON 对象:

claude -p "Explain recursion" --output-format stream-json --verbose --include-partial-messages

流的最后一行是 result 消息,包含最终回复文本、费用和会话元数据。下面这个 jq 过滤器只保留文本增量;-r 输出原始字符串(不带引号),-j 不加换行地拼接,token 就能连续流出:

claude -p "Write a poem" --output-format stream-json --verbose --include-partial-messages | \
  jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'

system/init 事件报告会话元数据,包括模型、工具、MCP 服务器和已加载的插件。API 请求遇到可重试的错误时,Claude Code 会在重试前发出 system/api_retry 事件,字段包括 attempt、max_retries、retry_delay_ms 和 error_status。用 stream-json 时,被拒绝的调用会以 permission_denied 系统消息出现,最终的 result 消息会在 permission_denials 里列出它们。

非交互模式下的工具权限

没有人能回答权限提示,所以要事先决定 Claude 能做什么。用 --allowedTools 让 Claude 不经提示就使用某些工具。列出 Read 和 Edit,Claude 就能不问权限地读写文件,网络路径的读取除外。列出 Bash 对 shell 命令效果相同,但在以 auto 模式启动的运行里,Claude Code 会把单独的 Bash 条目当作过宽的 allow 规则丢弃,由 auto 模式逐条评估命令。下面列出这三个工具,运行测试套件并修复失败:

claude -p "Run the test suite and fix any failures" \
  --allowedTools "Bash,Read,Edit"

没列出的工具,如果不需要批准,调用照样运行。在 Manual 模式的 claude -p 运行里,需要批准的调用会被拒绝,除非有东西批准它,比如 PermissionRequest hook 或 --permission-prompt-tool。Claude Code v2.1.302 及以后,没有任何设置指定权限模式时,claude -p 以 Manual 模式启动。

要把工具限制在特定命令上,--allowedTools 用的是权限规则语法。结尾的 * 启用前缀匹配,所以 Bash(git diff *) 允许任何以 git diff 开头的命令。* 前的空格很重要:没有它,Bash(git diff*) 还会匹配 git diff-index。

claude -p "Look at my staged changes and create an appropriate commit" \
  --allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"

想给整个会话设一个基线,而不是逐个列工具,用 --permission-mode 传一个权限模式:

模式在 -p 运行里的行为
auto由分类器代替你审查大部分操作
dontAskClaude Code 拒绝所有本来会弹出提示的调用,适合锁死的 CI 运行。Manual 模式下不需要批准的操作照常运行,被你的 --allowedTools 条目或 permissions.allow 规则覆盖的操作也照常运行
acceptEditsClaude 不经提示写文件,Claude Code 自动批准 mkdir、touch、mv、cp 这类常见的文件系统命令。其他 shell 命令和网络请求仍然需要 --allowedTools 条目或 permissions.allow 规则
claude -p "Apply the lint fixes" --permission-mode acceptEdits

无人值守的任务里,没有人能回答权限提示时(比如定时任务)传 --permission-prompts none。任何会弹提示的操作都被拒绝,除非有 PermissionRequest hook 允许;Claude 会被告知没有人能批准这个请求、不要重试,运行继续。这个参数需要 Claude Code v2.1.259 及以后,更早的版本会以未知选项错误拒绝它。

claude -p "Update the dependency pins and run the tests" --permission-mode auto --permission-prompts none

各个模式本身的说明见 Claude Code 权限模式。

续接对话

用 --continue 继续最近的一次对话,或用 --resume 加会话 ID 继续指定的对话。下面先做一次审查,再发送后续提示:

# First request
claude -p "Review this codebase for performance issues"

# Continue the most recent conversation
claude -p "Now focus on the database queries" --continue
claude -p "Generate a summary of all issues found" --continue

同时跑多个对话时,记下会话 ID,就能恢复指定的那一个:

session_id=$(claude -p "Start a review" --output-format json | jq -r '.session_id')
claude -p "Continue that review" --resume "$session_id"

这两条命令可以在不同目录里运行:Claude Code 会按 ID 在本机任何项目里找到这个会话。除了会话 ID,也可以给 --resume 传某个会话 .jsonl 转录文件的绝对路径,Claude Code 会继续该文件里保存的对话。

给脚本和 CI 用的 bare 模式

加 --bare 可以缩短启动时间,它跳过 hooks、skills、自定义命令、子代理、已安装插件、MCP 服务器、auto memory 和 CLAUDE.md 的自动发现。不加的话,claude -p 会像交互会话一样发现并加载它们,包括工作目录或 ~/.claude 里配置的任何内容。bare 模式适合需要每台机器结果一致的 CI 和脚本:同事 ~/.claude 里的 hook,或项目 .mcp.json 里的 MCP 服务器都不会运行,因为 bare 模式根本不读它们。

运行下面这条之前先设置 ANTHROPIC_API_KEY,因为 bare 模式不使用你的订阅登录。它预先批准了 Read 工具,调用不用弹权限提示就能完成:

claude --bare -p "Summarize README.md" --allowedTools "Read"

在 bare 模式下,Claude Code 从不读取 OAuth 凭据或系统钥匙串。使用 Anthropic API 时,在环境里设置 ANTHROPIC_API_KEY(密钥在 Claude Console 创建),或者在 --settings 的 JSON 里提供 apiKeyHelper。Amazon Bedrock、Google Cloud 的 Agent Platform 和 Microsoft Foundry 照常读取各自的提供方凭据。

bare 模式下 Claude 可以使用 Bash、文件读取和文件编辑工具。需要的上下文用参数传入:

要加载用
系统提示词补充--append-system-prompt、--append-system-prompt-file
设置--settings <file-or-json>
MCP 服务器--mcp-config <file-or-json>
自定义代理--agents <file-or-json>
插件--plugin-dir <path>、--plugin-url <url>

不加 --bare 时,-p 会话会运行项目 .claude/settings.json 里的 hooks,并连接 .mcp.json 里的服务器,即使是你从没信任过的文件夹。-p 会话不显示工作区信任对话框,也没有逐个服务器的批准提示。在不是自己写的仓库里运行 claude -p 之前,要想到这一点。文档说 --bare 是脚本和 SDK 调用的推荐模式,将来的版本会把它设为 -p 的默认。

其他用法

用 --append-system-prompt 可以在保留 Claude Code 默认行为的同时追加指令。下面把 PR 的 diff 管道给 Claude,让它做安全审查。存成 shell 脚本,比如 review.sh,运行 bash review.sh 123,shell 会把 "$1" 替换成 123:

gh pr diff "$1" | claude -p \
  --append-system-prompt "You are a security engineer. Review for vulnerabilities." \
  --output-format json

--system-prompt 会完全替换默认提示词。替换之后,运行也不再带 git status 快照。

-p 模式下命令的支持情况不同。用户调用的 skills 和自定义命令可以用:在提示词字符串里写 /skill-name,Claude Code 会在运行前展开它。只能在终端界面里运行的内置命令,比如 /login,不可用。要改设置,给 /config 传 key=value,例如 /config thinking=false。交互模式的命令见 Claude Code 常用命令大全。想在 GitHub 工作流里跑 claude -p,见 Claude Code 与 GitHub Actions。

故障排查

现象文档怎么说
传了无效参数Claude Code 在运行开始前把错误报告到 stderr
缺少认证属于运行内部的失败,Claude Code 把它作为结果打印在 stdout 上
用 --bare 时认证失败bare 模式不使用订阅登录,从不读取 OAuth 凭据或系统钥匙串。设置 ANTHROPIC_API_KEY,或在 --settings 的 JSON 里提供 apiKeyHelper
报错指出参数冲突-p 会拒绝 --bg,也拒绝带任务描述的 --cloud
工具调用被拒绝在 Manual 模式的运行里,需要批准的调用会被拒绝,除非有东西批准它。把它加进 --allowedTools,或设置 --permission-mode
--permission-prompts 报未知选项错误这个参数需要 Claude Code v2.1.259 及以后
Error: --json-schema is not a valid JSON Schema传入的值不是合法的 JSON Schema,信息后面跟着校验器的诊断
没有 structured_output 字段运行结束时没有有效的结构化输出,比如 Claude 拒绝了请求。先检查该字段是否存在
管道传很大的文件失败管道输入的 stdin 上限是 10MB。把内容写进文件,在提示词里写路径
配置的 MCP 服务器没出现Claude Code 会跳过校验失败的 --mcp-config 条目,运行照常正常退出。检查 system/init 事件里的 mcp_server_errors;没有错误时这个键会被省略,所以 CI 可以在数组非空时判失败
Claude 回复完了,运行还不退出它可能在等 Claude 启动的后台任务。默认情况下,连续空闲等待 10 分钟后,Claude Code 会停掉仍在运行的内容。用 CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS 修改这个上限,设为 0 则不设上限地等待
退出码 143你用 SIGTERM 停掉了运行。Claude Code 会让进行中的这一轮保持未完成,也不为它记录结果。想结束这一轮,先发 SIGINT 再停进程。想在恢复时继续被中断的一轮,设置 CLAUDE_CODE_RESUME_INTERRUPTED_TURN=1

常见问题

-p 和 --print 一样吗?

一样。文档把这个标志写作 -p(或 --print),加在任何 claude 命令上都会变成非交互运行。

脚本里为什么我的编辑或命令被拒绝了?

-p 运行里没有人能回答权限提示。在 Manual 模式下,需要批准的调用会被拒绝,除非有东西批准它,比如 PermissionRequest hook 或 --permission-prompt-tool。用 --allowedTools 列出要用的工具,例如 --allowedTools "Bash,Read,Edit";只是改文件的话,也可以传 --permission-mode acceptEdits。

怎么让每台机器或每个 CI runner 上的结果一致?

加 --bare。它跳过宿主机上的 hooks、skills、插件、MCP 服务器、auto memory 和 CLAUDE.md,同事的 ~/.claude 或项目的 .mcp.json 就影响不到这次运行。先设置 ANTHROPIC_API_KEY,因为 bare 模式不使用订阅登录;需要的上下文用 --settings、--mcp-config 这类参数传入。

来源