×−+
命令行第 4 课 · Claude Code 教程
第 4 课 · CLI

命令行:
不进聊天界面,也能用 Claude

平时你输入 claude,进入聊天界面一问一答。其实它也是一条普通的终端命令:可以接在别的命令后面、写进脚本、放进 CI 里自动跑。

约 45 分钟 11 节 · 8 个动手练习 章末测验 改编自 luongnv89/claude-howto(MIT)
my-app — zsh
$
点命令里的任意一段
入门先用起来 原理弄懂为什么 实战动手练 深入进阶与避坑

时间紧就先看"入门"和"实战";"原理"讲清楚脚本里的权限和输出格式,决定你的自动化脚本能不能跑通。

01入门

两种用法:当面聊,还是发封信

不加 -p 是当面聊天,可以一来一回;加上 -p 是发一封信,Claude 回完信就走。

my-app — zsh

交互模式打印模式 -p
怎么启动claude 或 claude "开场白"claude -p "问题"
对话一直开着,多轮来回,/exit 或连按两下 Ctrl+D 退出回答完立刻退出,回到终端
要改文件时Manual 模式下弹窗问你;auto 模式下由安全员把关(第 9A 课)没人能点,没提前允许的就被拒绝(第 6 节)
斜杠命令全部可用你自己的 skill 能用;/login 这类界面命令不能用
适合日常写代码、边做边商量管道、脚本、CI、定时任务
名字的由来

-p 是 --print 的简写:把回答"打印"到屏幕上然后退出。官方把这种用法叫作"用程序调用 Claude Code"(programmatic),也常被叫作无头模式(headless)。

02入门

接着上次的对话

关了终端,对话并没有丢。-c 接上最近一次,-r 按名字或 ID 找回某一次。

命令做什么
claude -c接上当前目录里最近的一次对话(--continue)
claude -r 名字按名字或会话 ID 恢复某次对话(--resume);不写名字就弹出列表让你挑;已经在对话里时,输入 /resume 打开同一个列表
claude -n 名字开新对话时先起个名字,以后好找(--name);对话里也能用 /rename 改
--fork-session配合 -c 或 -r:复制一份接着聊,原来那次不动(和第 3 课的 /branch 一样)

试一试:这条命令会打开哪次对话?

你的电脑上有下面 3 次对话。点一条命令,看它会接上哪一次:

这台电脑上的对话
容易踩的坑:claude -c 找不到脚本跑出来的对话

交互模式的 claude -c 会跳过 claude -p 跑出来的对话。想接着脚本里的对话,用 claude -p "…" --continue,或者用 -r 加会话 ID。

03入门

常用选项速查

官方有好几十个选项,下面是最常用的 30 来个。不用背,知道有这些、用时回来查就行。

  • 短写和长写是同一个:-p 就是 --print,-c 就是 --continue。
  • 有些选项后面要跟值:--model haiku、--max-turns 3。值里有空格,就用引号括起来。
  • 标了 仅 -p 的,只在打印模式里有效。
选项做什么 · 例子

完整列表在官方 CLI reference,终端里也可以运行 claude --help 查看。

04入门

练一练:该用哪条命令?

每个场景选一个最合适的写法。

05原理

管道与脚本:-p 怎样接进别的命令

claude -p 和 grep、cat 一样守终端的规矩:从左边读输入,往右边写输出,结束时给一个退出码。

输入你写的提示词,加上用 | 管道送进来的内容,比如 git diff、cat error.log 的输出
→
claude -p读项目、调用工具、想答案。和交互模式是同一个 Claude,也会读 CLAUDE.md
→
输出回答打印到屏幕;用 > 写进文件,或用 | 交给下一个命令
成功:退出码 0 失败:退出码非 0,脚本可以据此判断 管道输入最多 10MB

三个现成的用法

看懂报错
cat build-error.txt | claude -p "简要解释这个构建报错的根本原因" > output.txt
package.json:用 Claude 当拼写检查
{
  "scripts": {
    "lint:claude": "git diff main | claude -p \"你是拼写检查器。对这段 diff 里的每个拼写错误,一行写 文件名:行号,下一行写问题。其他什么都不要输出。\""
  }
}

运行 npm run lint:claude。改动是用管道送进去的,所以 Claude 不需要 Bash 权限去自己读;引号用 \" 转义,Windows 上也能跑。

接着上一次问
claude -p "检查这个项目的性能问题"
claude -p "只看数据库查询部分" --continue
claude -p "把发现的问题汇总成一张表" --continue
-p 也会读你的项目配置

不加别的选项时,claude -p 加载的东西和交互模式一样:CLAUDE.md、skill、hook、MCP 服务器。想让脚本在每台机器上结果一致,加 --bare(第 10 节)。

06原理

-p 里没人点"允许"

交互模式里,Claude 要改文件、跑命令时会弹窗问你(auto 模式下由安全员把关)。打印模式默认是 Manual 模式,没人在屏幕前点允许,这些请求会直接被拒绝。所以要提前说好哪些可以做。

选项作用打个比方
--allowedTools列出的工具和命令不用问,直接做提前签好的授权书
--disallowedTools拒绝名单。只写工具名(如 "Edit")就把这个工具整个拿走;写成 Bash(rm *) 只拒绝匹配的命令黑名单
--tools只给 Claude 这几个内置工具,其他内置工具它根本看不到(MCP 工具不受影响)只发这几件工具
--permission-mode整体放宽或收紧:acceptEdits 改文件不用问;dontAsk 只做提前允许的,其余一律拒绝;auto 交给后台的"安全员"模型把关(第 9A 课)整体的授权级别

读文件和 ls、cat、git status、git diff 这类只读命令,本来就不用问。需要提前允许的,是改文件和其他命令。

规则怎么写

  • Bash(pnpm test):只匹配一模一样的 pnpm test。
  • Bash(pnpm run *):结尾是"空格 + 星号",匹配以 pnpm run 开头的所有命令,也包括光秃秃的 pnpm run。
  • 星号前面的空格很重要:Bash(git diff*) 连 git diff-index 也会匹配上。
  • 用 &&、;、| 连起来的命令会被拆开,每一段都要被允许,所以 pnpm test && git push 骗不过去。
  • 拒绝规则优先:只要有一段命中拒绝名单,整条都不执行。

试一试:这条命令会被放行吗?

假设你这样运行:claude -p "…" --allowedTools "Bash(pnpm run *)" "Bash(pnpm test)" "Bash(git commit *)" --disallowedTools "Bash(git push *)"。Claude 想执行下面的命令时:

Claude 想执行

这里只模拟规则匹配,只读命令也只认几个常见的。真实的 Claude Code 还会先去掉 timeout 这类包装命令,并检查 > 写入的目标文件,细节见官方权限文档。

--dangerously-skip-permissions

跳过权限确认,Claude 要做的事基本都直接执行。但你写的拒绝规则照样生效;删除 /、~ 这类关键路径也仍然要确认,在 -p 里就直接拒绝。官方只建议在容器或虚拟机里这样跑;在 Linux、macOS 上用 root 运行,它会直接拒绝启动。在你自己的电脑上,优先用 --allowedTools 列清楚要允许什么。

07原理

输出格式:给人看,还是给程序读

--output-format 决定回答长什么样:text 给人看,json 和 stream-json 给程序读。

格式长什么样什么时候用
text(默认)纯文字回答直接看,或写进文件
json结束时输出一个 JSON:回答在 result 里,另有会话 ID、花费、轮数等脚本要取会话 ID、判断成败、统计花费
stream-json边做边输出,每行一个 JSON 事件,最后一行是结果自己做界面,要实时显示进度

试一试:从 JSON 里取值

下面是 --output-format json 的输出(示意,字段名与官方一致)。点一个 jq 写法,看取出来的是什么:

输出
用 jq 取值
回答是一段文字,不是 JSON 对象

只加 --output-format json 时,Claude 的回答整个是 result 字段里的一个字符串。就算你在提示词里要求"用 JSON 回答",也得自己再解析一次,而且格式不保证。想要可靠的结构,加 --json-schema 给出格式,结果会放在 structured_output 字段里。

08实战

命令拼装器

勾选你要的效果,页面实时拼出命令,并用大白话解释它会做什么、哪里可能出问题。

从场景开始:
怎么跑
模式
对话
会话名
模型
让它做什么
管道输入
提示词
权限
权限模式
提前允许
输出与限制 仅 -p
输出格式
写到哪
最多轮数
花费上限
精简模式 --bare
拼出来的命令
这条命令会
    09实战

    终端演练:把 Claude 接进你的终端

    从查版本到写进脚本,9 步。点"下一步"回放,放完可以自己输入命令。

    my-app — zsh — 90×28
    $

    终端画面为教学示意,回答内容、版本号、花费都是虚构的;命令和选项的用法与真实的 Claude Code 一致。

    10深入

    进阶与避坑

    把 Claude 放进脚本和 CI 时,最常遇到的问题。

    脚本里为什么推荐 --bare
    --bare 跳过自动加载的 hook、skill、插件、MCP 服务器、自动记忆和 CLAUDE.md,启动更快,而且不管在谁的电脑上跑,结果都一样(同事 ~/.claude 里的 hook 不会混进来)。需要的东西用选项显式传:--append-system-prompt、--settings、--mcp-config 等。注意:bare 模式不读你的订阅登录,要设置环境变量 ANTHROPIC_API_KEY。官方说它以后会成为 -p 的默认行为。
    在别人的仓库里跑 claude -p 要小心
    不加 --bare 时,-p 会执行项目 .claude/settings.json 里的 hook、连接 .mcp.json 里的服务器,而且不弹"是否信任此文件夹"的确认框。在你没审过的仓库里(比如 CI 里跑外部贡献者的 PR),加 --bare。
    CI 里怎么登录
    两种办法:用 Claude Console 的 API key,放进 CI 的密钥(secret),以环境变量 ANTHROPIC_API_KEY 传入;或者在本机运行 claude setup-token,生成一个有效期一年的令牌(需要 Claude 订阅),存成 CI 密钥,以环境变量 CLAUDE_CODE_OAUTH_TOKEN 传入。注意 --bare 模式不读这类登录令牌,只认 ANTHROPIC_API_KEY。不要把 key 写进代码或 CLAUDE.md。
    --append-system-prompt 和 --system-prompt 选哪个
    绝大多数时候用 --append-system-prompt:在默认系统提示词后面追加你的要求,Claude 原有的工具用法、安全规则都还在。--system-prompt 是整个替换,这些默认内容全没了,只适合做和写代码无关的专用工具。两者都有从文件读取的版本(-file 结尾),交互模式和 -p 都能用。长期要遵守的规矩还是写进 CLAUDE.md(第 2 课)。
    --max-turns 到了会怎样
    Claude 每走一步(调用工具、拿到结果)算一轮。到了上限,命令以错误退出(JSON 里 subtype 是 error_max_turns),活可能只干了一半。脚本里要检查退出码。--max-budget-usd 同理,按花费封顶,子代理的花费也算在内。
    管道送进去的内容太大
    管道输入上限 10MB,超了会报错退出。大文件先存到磁盘,在提示词里写文件路径,让 Claude 自己去读。
    装好了但命令不对劲
    claude --version 看版本;claude doctor 不进对话、只读地检查安装和设置文件;进了对话用 /doctor,还能帮你修。claude auth status 看登录状态(已登录退出码 0,否则 1),适合放在脚本开头。升级用 claude update,想装指定版本用 claude install 2.1.118 或 claude install stable。
    老教程里的写法和官方不一样
    1. 说 --system-prompt-file 只能用在 -p 里:官方说五个系统提示词选项在两种模式下都能用。
    2. claude -p --output-format json "…" | jq '.endpoints[]':取不到东西,回答在 .result 这个字符串里。要结构化数据,用 --json-schema 再取 .structured_output。
    3. 权限规则 Bash(git log:*):还能用,和 Bash(git log *) 等价;官方和权限弹窗现在都写成空格加星号。
    11检验

    小测验

    8 道题,每题选完会立刻看到解析。