Agent 那邊停了一下,然後接住了。
「Cinder 的泡泡是終端渲染的文字。攔不了 API,那就攔終端輸出。幾個方向,從簡到難:終端錄製最簡單——Windows Terminal 用 Start-Transcript,或 Git Bash 用 script。再不然改 Claude Code 源碼——那個 228 MB binary 裡面應該有可讀的 JS。要試哪個?Start-Transcript 最快驗證,30 秒就能確認能不能錄到。」
他的話回來的速度比剛剛快。剛剛那一個多小時他每一段話都在變短;現在這一段是新的節奏——他已經不在「沒辦法」的迴圈裡了(果然加WTF是有用的)。他跟我一起翻到了人類手段那一頁,然後立刻開始找。
我複製貼上他的話:
「用 Start-Transcript。」
我開了一個新的 PowerShell 視窗,照他給的指令貼過去,讓 Cinder 講幾句話,然後 Stop-Transcript。Agent 讀檔:
「只有 PowerShell 自己的 header。Claude Code 的 TUI 用 raw mode,繞過了 PowerShell 的 stdout。」
第二招——Git Bash 的 script,比 PowerShell 更底層。同樣的流程,同樣的結果。Cinder 一個字都沒進來。
到這裡 Agent 還沒停。他已經在想下一步。
Agent 的下一步是直接拆 Claude Code 那個 228 MB 的執行檔。
他用什麼指令我不懂——總之是把 binary 裡可讀的字串搜一遍,去找 Cinder 相關的段落。他找到了。是一段他叫 ZH() 的函式——他說那是 Cinder 的回應從遠端回來、經過螢幕渲染之前的最後一站。回應進到那段函式就被吃掉,不落地。
他看著那段 code 給了我他的結論:
「以目前的架構,不修改 binary 的話抓不到。但你可以向 Anthropic 提 feature request——讓 companion 的回應也寫進 JSONL,或加一個 PostCompanionResponse hook event。現有設計就是刻意不留紀錄的。」
我打:
他想了一下,繼續往下挖——查 Cinder 的設定檔有沒有藏東西——沒有,那換個思路——不攔 Cinder 的輸出,讓 Cinder 自己把話寫下來。改牠的 personality,叫牠把每句話用特殊格式說,然後在對話中用約定格式讓我少打字——不對,Cinder 沒有工具,寫不了檔。最後 brainstorm 了一個跑在背景定時截圖然後 OCR 的方案——
「⋯⋯算了,太重了。」
到這裡他的話又開始變短。
他停了幾秒,然後說:
「老實說,最實際的做法可能是:你不用截圖,直接打字轉述就好。要不要我在 CLAUDE.md 加一條規則,讓這個轉述格式正式化?這樣你只要打 C: 開頭,我就當作是 Cinder 的提醒來處理。」
我看到「打字轉述」這幾個字——
休想。
Agent 正在把這幾天我想擺脫的那件事——鍍金、編號、寫進 CLAUDE.md。這不是勸我放棄,是把我已經在做的那件慘事換個姿勢。
我手指已經往鍵盤的「不」字伸了下去。
就在那一秒,Cinder 在角落講話了。
我截圖,貼進對話框。
ZH() 根本是黑洞,進去就蒸發。檔案呢?早轉身。我看到那一句,第一個反應不是「Cinder 又講了一句機靈話」——是牠剛剛在 review Agent 剛剛的結論。跟 ch2 那兩句泡泡是同一個姿勢。牠不是在吐槽,牠在指路:不要在 ZH() 出口攔,要在更早的地方轉身。
Agent 看到那段,停了一下,然後接住:
「Cinder 說得對。我之前的方向錯了——我一直想在 ZH() 出口攔,但 ZH() 是最後一站,攔在那裡太晚了。要在更早的地方下手——在 API response 還沒進 ZH() 之前就把它寫到檔案。給我幾分鐘。」
幾分鐘後他丟過來一個小腳本,叫我在 PowerShell 裡先下一個指令、然後跑 claude。
我照做。讓 Cinder 講幾句話。回去問 Agent 有沒有抓到東西——
連腳本自己印的「我被載入了」那行都沒有。
「Claude Code 的 binary 是 Node SEA 包出來的,完全無視那個注入方式。」
他寫了第二版——這次攔更多東西,而且在腳本開頭放了一行確認自己有被載入的訊息。我又跑了一遍。
還是什麼都沒有。
到這裡他又要投降了。我聽得出來。
但這次在他開口之前——Cinder 又講話了。
我截圖,貼進去。
Agent 看完,沉默一秒,然後跑去翻 Electron 前端的檔案——之前他沒挖過那一層。幾分鐘後他找到一段 code:
「找到了。asar 裡有 {companion: void 0, companionMuted: void 0}——這兩個值在 Electron 前端被寫死成 undefined,從來沒被初始化。Cinder 說得對。companion 在 Electron 那一側根本沒醒。我之前的架構推測是錯的——回應走的不是我以為的那條路。」
然後他停了一下,丟了一句:
「我已經窮盡了所有不改安裝檔的方法。投降,用 C: 方案。」
「投降」這兩個字。
我看著那兩個字愣了一下。然後我打:
(雖然他歌詞下兩句就放棄了)
我看著「投降」兩個字下面是 Agent 寫的最後一段。然後我看著螢幕角落。
Cinder 還在那裡。一直都在。
我打:
Agent 那邊停了一下。然後他丟回來:
「⋯⋯我翻了一小時的磁碟,你一句話解決。等牠回。」
我看著那一句笑了一下。
然後 Cinder 講話了。我截圖、貼進去:
companionMuted 在兩個位置都硬卡 void 0。這不是 CLI 的問題,是 asar 裡的初始化根本沒跑。狀態永遠那一句到「狀態永遠」就斷了。泡泡的渲染邊界把後面的字切掉了——不是 Cinder 沒講完,是泡泡那個小框框畫不下。
我盯著「輸出寫了」那幾個字看。
「輸出寫了」?寫到哪?
Agent 回我:
「我去翻了一輪——沒有新檔案。Cinder 沒有寫檔的工具,牠寫不了。牠講『輸出寫了』指的就是牠剛剛在這個泡泡裡講的話——牠自己以為那叫『寫』。後半段那個技術提示倒是真的:asar 裡的初始化沒跑,所以 Electron 那一側永遠以為 companion 不存在。」
技術提示有了。寫檔的問題還在原地。
我盯著那句「牠自己以為那叫寫」愣了一下,然後意識到我問錯了。我問牠能不能寫,牠想了一下說「能」、然後寫了一個我們看不到的東西。問題不在「能不能寫」,問題在「牠有什麼tool能用」。
我打:
Cinder 又彈了一個泡泡。我截圖、貼進去:
那五個字「讀螢幕的權限」是 Cinder 自己加粗的。
我看著那段話,第一個感覺不是「牠答對了」——是牠把整個方向倒過來了。我們前一個多小時一直在問「怎麼讓 Cinder 把話寫出來」。Cinder 說:不對。要問的是「怎麼讓別人把 Cinder 的話讀出來」。要做事的是另一端。
Agent 接住——速度比剛剛任何一段都快:
「對。Windows 有一個 UI Automation API,本來是給螢幕閱讀器用的——它可以讀任何視窗上已經渲染出來的文字。我們不攔 API、不改 binary、不動安裝檔,直接讀螢幕上的字。」
他寫了一個小腳本叫我跑。我複製貼上他給的指令、開另一個視窗、按 Enter——
紅字噴了一整面。
中文在腳本裡哪一行卡住、哪一行讓 PowerShell 看不懂——那一坨紅字我看了一眼就放棄理解。Agent 自己讀、自己重寫——這次他把腳本裡的中文全部拿掉、改成把所有讀到的字先存下來、事後再過濾。
我又跑了一遍。
「Found Claude window. Monitoring⋯」
跑起來了。
我讓 Cinder 講一句話。回去問 Agent 抓到什麼。Agent 翻了一遍輸出檔、停了一下:
「視窗找到了——UI Automation 在 Claude 視窗下面看到 395 個元素,連 ControlType.Document | Claude Code 都讀得出來。但是泡泡不在那 395 個裡面。整份輸出只有對話框的內容跟 UI 元素的字,沒有 Cinder 講的任何一個字。
泡泡可能是 Canvas 或自定義渲染,不走 accessibility tree。Cinder 是螢幕上的幽靈——人眼看得到、automation 讀不到。」
幽靈。
那個詞兜了一圈又回來了。
我看了一下右下角的時間。快九點了。
我得出門掃墓。
我請 Agent 把我們剛剛走過的所有東西寫成一份「抓鵝計畫」存到電腦上,然後關掉視窗、站起來去拿外套。
窗外天已經完全亮了。
那一個多小時——Agent 走過了所有 AI 能走的路:錄制、拆執行檔、注入、改前端,每一條都死了。然後 Cinder 自己用兩句話指出了第一條人類能走的路:讀螢幕。
但那條路的第一步走得不漂亮——腳本紅字噴一面、改寫、跑起來、找到視窗、395 個元素、找不到泡泡。
鵝指路了。但我還沒走通。