Claude Code 結構化輸出完整教學:別再用 grep 硬撈 AI 的回答,讓它吐 JSON
以前想在腳本裡用 Claude Code,流程大概是這樣:claude -p 丟一個 prompt 進去,它吐回一段文字,然後你寫一串 grep 加 sed,從那段文字裡把你真正要的那個答案撈出來。
能跑。但每次跑起來心臟都懸著。因為那段文字是「講給人聽的」——它今天回「結果是 42」,明天心情好一點回「經過分析,我認為結果應該是 42 喔」,你的 grep '結果是 ([0-9]+)' 就當場失效。你不是在解析資料,你是在猜 AI 這次會怎麼講話。
這篇要講的,就是怎麼把這件事從「猜」變成「讀」。
口頭報告 vs 填好的表格
先用一個生活場景把問題講清楚。
你向路人問路,他跟你講一長串:「你先直走,看到那個很大的全家左轉,走一小段有間麵店再右轉……」你得一邊聽一邊在腦子裡記路口。他要是換個講法、順序調一下,你就記錯。這是純文字。
換個方式:他直接給你一張紙,上面第一格寫「第 1 個路口:左轉」、第二格寫「第 2 個路口:右轉」。你不用聽懂他整段話,你只要看第幾格。這就是結構化輸出。每個資訊有固定的位置,你按位置去取,不管對方今天話多話少,那一格永遠在那裡。
Claude Code 預設吐的是口頭報告,--output-format 這個旗標,就是叫它改填表格給你。
三種格式,對應三種場景
--output-format 吃三個值,先把地圖攤開:
text(預設):純文字,講給人聽的。你在終端機裡互動、或只是想看它講什麼,用這個。json:一次吐一個完整的 JSON 物件。腳本要拿結果、要記帳、要接 CI,用這個。stream-json:逐行吐 NDJSON(一行一個 JSON),邊算邊吐。你要做即時介面、想看它一個字一個字冒出來、或監控長任務的進度,用這個。
九成的自動化場景,你要的是中間那個 json。來看它到底給你什麼。
json 模式:一次拿到你需要的每一格
把旗標加上去跑一次:
1 | claude -p "用三個重點總結這個專案" --output-format json |
回來的不再是一段話,是一個 JSON 物件。裡面幾個關鍵欄位:
.result:AI 的回應文字本體。這是你以前要用 grep 硬撈的東西,現在它自己躺在一個固定欄位裡。.session_id:這次對話的識別碼。記下來,等一下要拿它接續對話。.total_cost_usd:這一次呼叫花了你多少錢(美金)。跑排程最怕帳單失控,這欄直接告訴你。.usage:token 用量的細節,input、output 各用了多少。
配上 jq,撈資料就一行的事:
1 | claude -p "用三個重點總結這個專案" --output-format json | \ |
注意這裡的心態轉變。你不再需要「讀懂它說了什麼再想辦法抓」,你只要說「給我 .result 這一格」。AI 講話的方式再怎麼變,欄位名不會變。這就是把猜謎換成定址。
讓對話接得下去:session_id + –resume
腳本化最常卡住的一點,是多輪對話。互動模式裡你一句我一句很自然,但在腳本裡,每個 claude -p 都是一次獨立呼叫,講完就忘。
解法就是剛剛那個 .session_id。先把它抓下來,下一輪用 --resume 帶回去:
1 | # 第一輪:開一個 code review,順手記住 session |
(要從同一個工作目錄跑,--resume 才找得到那個 session。如果只是想接最近一次、懶得記 id,用 --continue 也行。)
有了這個,你可以在一支 shell script 裡串出一整段有上下文的對話,而不是每次都從零開始重新解釋。
stream-json:想看它邊想邊吐
如果你要做的是即時介面、或想監控一個跑很久的任務,json 會讓你乾等到最後才一次看到全部。這時候換 stream-json:
1 | claude -p "寫一首關於 debug 的俳句" \ |
它會逐行吐 NDJSON,每一行是一個事件:開頭有個 system 的 init 事件(帶著這次用了哪個 model、哪些工具)、中間一連串 stream_event(文字一段一段的 delta)、最後一行是 result,成本跟 session_id 都在那最後一行。要即時把字印出來,就挑 stream_event 裡的 text_delta 事件來接。
代價是它比較囉嗦,得配 --verbose 跟 --include-partial-messages 才會吐 delta。做即時體驗時很值得,純粹要結果時就不必。
進階:用 –json-schema 把它當成一個回傳固定結構的函式
json 模式保證你拿得到 .result,但 .result 裡面 AI 寫了什麼,還是它自由發揮。如果你要的是「一定給我一個 JSON 陣列,每個元素有 name 跟 score 兩個欄位」,可以再上一層,用 --json-schema 把回應的形狀也鎖死:
1 | claude -p "評估這三個方案" \ |
符合 schema 的結果會放在 .structured_output 這一格。到這一步,Claude Code 在你眼裡就跟一個普通的 API 端點沒兩樣了——你給輸入、給契約,它回一個保證符合契約的結構。下游程式可以直接吃,不用再寫任何防呆去接一段不受控的文字。
真正改變的,是 AI 在你系統裡的身分
回到開頭那個用 grep 硬撈的畫面。表面上,我們只是多加了一個 --output-format 旗標、少寫了幾行 sed。
但真正變的不是這個。是 AI 在你的系統裡的身分變了。
以前它是一個「你要盯著看、還要讀懂它在講什麼」的對話框——你是它的讀者。加上結構化輸出之後,它變成一個「你可以放心串進管線、像呼叫任何 API 一樣呼叫」的元件——你是它的呼叫方。你不再消化它的文字,你定址它的欄位;你不再猜它這次會怎麼回,你檢查它是否符合契約。
從讀者變成呼叫方,這一步跨過去,Claude Code 才真正從一個聊天工具,變成一塊能塞進 CI、cron、任何 pipeline 的積木。下次要把 AI 接進你的系統,先問自己一句:我到底是要跟它對話,還是要呼叫它?想清楚這個,你就知道那個旗標該不該加。














































































































































