---
title: "11 - 非互動模式與腳本化"
type: note
specialty: Programming
tags: [claude-code-cli從0開始使用教學, 11-headless, scripting, ci]
created: 2026-08-04
updated: "2026"
modified: 2026-08-04
---

# 11 - 非互動模式與腳本化

← [[10-MCP與外部工具]] | [[00-Index]] | 下一篇 → [[12-設定檔與CLI旗標速查]]

---

## 基本：`-p`

任何 `claude` 指令加上 `-p`（`--print`）就變成非互動：

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

- **成功 exit 0，失敗非零** → 腳本可以用 exit status 分支
- 傳了無效 flag → 錯誤印到 stderr，執行前就中止
- 執行中的失敗（例如沒登入）→ 當成結果印到 **stdout**

所有 [CLI 選項](12-設定檔與CLI旗標速查) 都能跟 `-p` 一起用。

---

## `--bare`：腳本應該用的模式 ⭐

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

`--bare` **跳過自動探索**：hooks、skills、plugins、MCP servers、auto memory、CLAUDE.md 全部不載入。啟動更快，而且**每台機器結果一致**。

> ⚠️ **重要副作用**：bare mode **不讀 OAuth 憑證也不讀系統 keychain**。要用 Anthropic API 就得設 `ANTHROPIC_API_KEY`，或在 `--settings` JSON 裡給 `apiKeyHelper`。**也就是說 bare mode 用不到你的 Claude Pro 訂閱登入。**

Bare mode 下 Claude 有 Bash、讀檔、改檔工具。要載入其他東西用 flag：

| 要載入 | 用 |
|---|---|
| System prompt 補充 | `--append-system-prompt` / `--append-system-prompt-file` |
| 設定 | `--settings <file-or-json>` |
| MCP servers | `--mcp-config <file-or-json>` |
| 自訂 agent | `--agents <json>` |
| Plugin | `--plugin-dir <path>` / `--plugin-url <url>` |

> 📌 官方說 `--bare` 是腳本和 SDK 呼叫的**建議模式**，未來會變成 `-p` 的預設。

---

## Pipe 進去

非互動模式會讀 stdin：

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

```bash
git diff main --name-only | claude -p "review these changed files for security issues"
```

```bash
tail -200 app.log | claude -p "if you see any anomalies, summarize them"
```

⚠️ **stdin 上限 10MB**。超過會用非零狀態退出。更大的內容寫成檔案、在 prompt 裡提檔案路徑。

---

## 輸出格式

```bash
claude -p "query" --output-format text          # 預設，純文字
claude -p "query" --output-format json          # 結構化 JSON（含 result、session_id、metadata）
claude -p "query" --output-format stream-json    # NDJSON 即時串流
```

`--output-format json` 的 payload 含 **`total_cost_usd`** 和每個模型的成本細分——腳本可以自己追蹤花費。

### 用 JSON Schema 拿保證格式的輸出 ⭐

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

結果在 `structured_output` 欄位。用 `jq` 取：

```bash
claude -p "..." --output-format json | jq -r '.result'
claude -p "..." --output-format json --json-schema '...' | jq '.structured_output'
```

> ⚠️ Schema 無效會直接錯誤退出。`format` 關鍵字（如 `"format": "email"`）會被接受但**只當註解，不做驗證**。

### 串流

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

最後一行是 `result` 訊息，含最終文字、成本、session metadata。

只顯示串流文字：
```bash
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'
```

---

## 自動核准工具

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

比較精細的版本用權限規則語法：

```bash
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 *)"
```

⚠️ **尾巴 ` *` 前面那個空格很重要**：`Bash(git diff *)` 只比對 `git diff ` 開頭；`Bash(git diff*)` 會連 `git diff-index` 一起中。

或者設整個 session 的基準模式：

```bash
claude -p "Apply the lint fixes" --permission-mode acceptEdits
claude -p "..." --permission-mode dontAsk     # 鎖死的 CI：只跑你 allow 過的
```

---

## 接續對話

```bash
claude -p "Review this codebase for performance issues"
claude -p "Now focus on the database queries" --continue
claude -p "Generate a summary of all issues found" --continue
```

多條對話並行時，抓 session ID：

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

⚠️ **兩個指令要在同一個目錄跑**——session ID 查詢是以目前專案目錄（和它的 git worktree）為範圍。

---

## 幾個實用的護欄 flag

| Flag | 作用 |
|---|---|
| `--max-turns N` | 限制 agentic 輪數（print mode）。到上限會**錯誤退出** |
| `--max-budget-usd 5.00` | 花超過就停（print mode）。**subagent 的花費也算進去**；到上限後再生 subagent 會以 `Budget limit reached` 失敗，並停掉還在跑的背景 subagent |
| `--no-session-persistence` | 不存 session、不可 resume（print mode）|
| `--fallback-model sonnet,haiku` | 主模型過載或不可用時依序 fallback |
| `--tools "Bash,Edit,Read"` | 限制可用的內建工具（`""` 全關、`"default"` 全開）。**不影響 MCP 工具**——要一起擋加 `--disallowedTools "mcp__*"` |

> 💡 **`--max-budget-usd` 對「不小心跑一整晚」是很便宜的保險。** CI 腳本裡建議一律加。

---

## 實用範例

### 當專案的 linter

`package.json`：
```json
{
  "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.\""
  }
}
```

### 安全審查腳本

```bash
#!/usr/bin/env bash
# review.sh <PR-number>
gh pr diff "$1" | claude -p \
  --append-system-prompt "You are a security engineer. Review for vulnerabilities." \
  --output-format json
```

### 給你 vault 的範例：批次盤點 frontmatter

```bash
#!/usr/bin/env bash
set -euo pipefail
for dir in "Nephrology(NEP)" "Cardiology(CV)" "Endocrinology(ENDO)"; do
  claude --bare -p "掃描 '$dir' 底下所有 *_overview.md 的 YAML frontmatter，
列出缺少 modified 欄位、或 YAML 不合法的檔案。只回報，不要改檔。" \
    --allowedTools "Read,Glob,Grep" \
    --max-budget-usd 1.00 \
    --output-format json \
    --json-schema '{"type":"object","properties":{"problems":{"type":"array","items":{"type":"object","properties":{"file":{"type":"string"},"issue":{"type":"string"}},"required":["file","issue"]}}},"required":["problems"]}' \
  | jq -r --arg d "$dir" '.structured_output.problems[] | "\($d)\t\(.file)\t\(.issue)"'
done
```

**設計重點**：`--bare` 保證一致、`--allowedTools` 限制成唯讀、`--max-budget-usd` 設上限、`--json-schema` 保證輸出可被 `jq` 解析。

> ⚠️ 記得 `--bare` 需要 `ANTHROPIC_API_KEY`（走 API 計費）。想用訂閱登入就拿掉 `--bare`，代價是會載入你的 hooks / skills / CLAUDE.md。

---

## 幾個容易踩的行為

- **背景 bash 任務**：`claude -p` 期間 Claude 起的背景 shell（dev server、watch build），會在最終結果回傳且 stdin 關閉後**約 5 秒**被終止。
- **背景 subagent 和 workflow 不受那 5 秒限制**（它們的結果是最終輸出的一部分），但預設**最多等 10 分鐘**（`CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS` 可調，`0` = 不限）。
- **SIGTERM**：中止當輪、終止 bash 指令的整個 process tree、跑 `SessionEnd` hook、以 **exit code 143** 結束。
- **`-p` 裡可以用 skill**：prompt 字串裡放 `/skill-name`，Claude Code 會先展開。但只在終端介面能用的內建指令（如 `/login`）在 `-p` 模式不可用。`/model`、`/effort`、`/fast`、`/color`、`/rename` 可以帶值（`/model sonnet`），`/config` 可以 `key=value`。

---

## 🔗 相關筆記

- [[10-MCP與外部工具]] — 上一步
- [[12-設定檔與CLI旗標速查]] — 下一步：完整旗標表
- [[05-權限模式與安全]] — `dontAsk` 是 CI 的正確模式
- [[Programming/Codex/Codex-CLI從0開始使用教學/06-非互動模式codex-exec|Codex CLI 06 - codex exec]] — Codex 那邊的對應功能
- [[Programming/Python/07-實戰自動化範例|Python 07 - 實戰自動化範例]] — 可以被包成 pipeline 的既有腳本

---

*最後更新：2026-08-04*
