白色卡片上的赭紅色 Claude 星形標誌與黑色字樣

用 Claude Code 的 routine 把已標記的 Issue 變成沙箱裡的 PR — 但無法追問

用兩個用完即丟的 GitHub Issue 測試 Claude Code 的雲端 routine:標記一個就能從沙箱拿到真正的 PR,但 routine 沒有 AskUserQuestion 這個工具。

更新

本頁目錄

引言

我聽說 Claude Code 現在提供一種大家稱為「cowork」的雲端功能:啟動一個沙箱,交給它一個 GitHub Issue,就算不讓機器保持開機,也能從手機上看到結果。在真的把重要的事交給它之前,我想知道這個工作流程實際上每天是怎麼運作的,而不只是宣傳詞說的那樣,因為這個部落格已經有一套發布流程,裡面藏著不少陷阱,我不想在沒人看著的情況下讓 routine 悄悄把事情做錯。經過兩個用完即丟的 GitHub Issue,答案落在一個缺少的工具上:Claude Code 的 routine 完全無法呼叫 AskUserQuestion,而這正是「幫 Issue 加標籤、剩下的交給它」這句話沒有告訴你的事。這篇文章會談到最先遇到的設定摩擦、一個原本設計錯誤、要是沒被抓出來就什麼也證明不了的測試、這個發現本身、一個明明文件說不該出現卻還是到來的通知,以及在這個限制之下,這個部落格真正值得交給 routine 去做的事。

沒有出現的私有 repo

第一個卡關的地方,其實還跟 routine 無關。這個部落格的 repo 是私有的,在 claude.ai/code 的 repo 選單裡完全沒有出現:輸入名稱只換來一句「No repos match」。

Claude Code on the web 的 repo 選單,輸入部分 repo 名稱後顯示「No repos match」

在重新設定 GitHub App 的存取權之前,repo 搜尋什麼都找不到。

私有 repo 本身是支援的,這個 repo 只是不在授權存取的 app 範圍裡而已。 Claude GitHub App 在安裝時會問,要看到帳號底下的所有 repo,還是只看選定的清單,而這個 repo 當時並不在那份清單裡。

GitHub 的「Install & Authorize Claude」畫面,有 All repositories 和 Only select repositories 兩個選項,目前選的是 All repositories

決定 app(以及 Claude Code on the web)能存取哪些 repo 的安裝畫面。

github.com/settings/installations 重新設定 app 的 repo 存取權並重新連接後就解決了。這也是一個獨立於這次修正之外、有紀錄可查的常見問題。 Anthropic 自己的 issue tracker 上有好幾筆回報,說明明 app 確實有存取權的私有 repo,還是不會出現,或是會斷斷續續消失,讀起來比較像後端索引的問題,而不是帳號設定哪裡出錯。

貼上標籤就合併的用完即丟檔案

repo 可以存取之後,第一次正式測試用的是 routine:一份儲存好的提示詞加上一個 GitHub 觸發條件,在 claude.ai/code/routines 設定一次就好。這次沒有寫針對單一任務的提示詞,routine 的指示刻意寫得很通用:讀取觸發這次執行的 GitHub Issue,並且完全照著它說的做。

Claude Code 的 routine 建立表單,Instructions 欄位寫著「讀取觸發這次執行的 GitHub Issue,並且完全照著它說的做」,觸發條件是 Issue: Labeled,並且設定了 cloud-agent-test 標籤的篩選條件

每次測試都重複使用同一個 routine:任務寫在 Issue 裡,不是寫在 routine 自己的設定裡。

agent 提出了一個用完即丟的第一個任務:建立一個只包含固定句子的檔案(docs/cloud-agent-shakedown.md),不動其他任何東西,執行 repo 自己的 pnpm check,開出 PR 但不合併。這些內容寫進了一個 GitHub Issue,幫它加上專用的 cloud-agent-test 標籤,就觸發了這個 routine。

標題為「[test] Cloud agent shakedown」的 GitHub Issue,標籤面板打開著,正要加上 cloud-agent-test 標籤

加上標籤就是整個觸發條件,沒有其他步驟會啟動這次執行。

完全無人值守,第一次嘗試就乾淨俐落地成功了。 routine 複製了 repo,剛好只建立了被要求的那一個檔案,跑完了驗證流程,還開出一個把實際指令輸出貼進說明欄的 PR:

$ astro check && pnpm run check:types && pnpm run check:i18n …
05:57:16 [check] Getting diagnostics for Astro files
Result (244 files):
- 0 errors
- 0 warnings
- 0 hints

它還回報了一件沒人要求它檢查的事:一個跟這次改動無關、原本就存在的 Unsupported engine 警告,是關於 repo 釘住的 Node 版本,它把這件事寫進 PR 裡,而不是悄悄忽略。這是件小事,但也正是這個部落格自己的工具慣例所要求的行為,而 routine 在沒被要求的情況下就做到了。

自己回答問題,證明不了 routine 什麼

接下來的問題是,routine 能不能在任務進行到一半時,真的因為需要判斷而暫停,之後再靠手機上的回覆繼續,因為這正是「不用人在旁邊看著」這句宣傳詞的另一半。測試這件事的第一版設計是錯的,很慶幸在真的執行之前就被抓出來了:原本的計畫是直接從手機開一個 session,貼上一段會強迫呼叫 AskUserQuestion 的提示詞,然後當場回答。

自己開的、自己盯著看的 session,沒辦法驗證無人值守的路徑。 在自己主動推進的對話裡回答問題,只能證明即時對話可以運作,而這件事從來就沒有人懷疑過。真正值得知道的是一個性質完全不同的主張:一個由觸發條件啟動、沒有人看著的執行,能不能停下來等待,之後再靠手機上的一則回覆繼續。

重新設計後的測試,重複使用了第一次測試的同一個通用 routine。第二個用完即丟的 Issue 要求同樣類型的用完即丟檔案,只是這次 routine 必須先呼叫 AskUserQuestion 並等待回答,才能建立任何東西,而觸發條件也換成了標籤,而不是手動開啟的 session。

AskUserQuestion 不是 routine 能呼叫的工具

標題為「Cloud agent shakedown 2, question path」的 Issue,標籤面板打開著,正要加上 cloud-agent-test 標籤

同一個標籤、同一個 routine,Issue 裡的任務不一樣:這次要求先問問題才能做任何事。

加上標籤觸發了 routine,它幾乎立刻就停下來了,什麼都還沒建立:

一次已完成的 Claude Code routine 執行,回報 AskUserQuestion 在這個 routine session 裡不是可用的工具,所以它停下來而不是用猜的

與其在兩個選項之間亂猜,這次執行選擇拒絕猜測。

這是執行本身的原話:「AskUserQuestion 在這個 routine/trigger session 裡不是可用的工具,不在工具清單裡,ToolSearch 也找不到任何相符的東西……我選擇停下來,而不是捏造答案或在選項 A、B 之間亂猜。沒有建立任何檔案,沒有任何提交,也沒有開出任何 PR。」

這是比 Anthropic 公開文件更強、也更精確的發現。 文件只寫了 routine 執行時「完全沒有核准提示」,這句話讀起來像在講工具權限提示,而不是一個完全不同、用來對話式詢問使用者的工具。實際的行為兩邊都說清楚了:這個工具根本不在 routine 的工具箱裡,所以不是「拒絕」詢問,而是根本沒有東西可以呼叫。碰到這道牆的失敗方式是對的:它沒有在兩個選項之間亂猜,也沒有悄悄選一個預設值。它停下來並且回報了,這正是無人值守的自動化在真的無法繼續時該有的樣子。

我確實希望這個工具能存在。如果 routine 能呼叫 AskUserQuestion,在真正需要判斷時暫停,並且像現在的隨選雲端 session 已經做到的那樣,靠手機上的回覆繼續,就能消除 routine 的提示詞必須寫成一份完全沒有留白的完整規格的唯一理由。在這件事實現之前,這個限制不是可以繞過的偏好,而是設計上必須遵守的前提。

第三次測試改用隨選 session

「就跟現在的隨選雲端 session 已經做到的那樣」這句比較,其實是憑著 Anthropic 自己的文件寫的,並沒有實際驗證過:目前為止的兩次測試都只試過 routine 這條路徑。第三次測試補上了這個缺口,這次直接從手機開啟 session,而不是透過加了標籤的 Issue,用的是同樣用完即丟的任務、同樣被強制呼叫的 AskUserQuestion,但這一次的執行過程完全跟 routine 無關。

一則標題為「Claude has a question」的 iOS 推播通知,待處理的問題名稱顯示為「Shakedown line」

隨選 session 需要答案的那一刻,通知就送到了。

確實成功了,app 在需要的那一刻推播了通知:「Claude has a question — Shakedown line」。打開之後看到的是真正原生的問題卡片,不是文字湊合出來的替代方案。

標題為「Which line should be used in docs/cloud-agent-shakedown-3.md?」的行動裝置 AskUserQuestion 卡片,有 Option A、Option B、Other 欄位和 Submit 按鈕

routine session 完全碰不到的互動工具,在手機上以原生 UI 呈現。

這個問題就這樣懸在那裡十二分鐘沒人回答,手機上的時間戳記顯示,提示出現在 1:26,完成的結果則是 1:38,這段時間長到足以排除第一版 routine 測試設計裡「即時對話」那個瑕疵。

十二分鐘後的同一個 session,已經提交了選定的檔案、乾淨地跑完 pnpm check,並對 main 開出了 pull request

隔了一段時間才回答之後,session 自己恢復執行,並且正確地完成了。

隔了一段時間才回答,session 正確地繼續執行:用選定的選項建立檔案、乾淨地跑完 pnpm check,並照要求對 main 開出未合併的 pull request。這個限制是 routine 特有的,不是雲端 session 整體的問題。 AskUserQuestion 除了在 routine 的無人執行裡之外,到處都是真正能用、會推播通知的工具,這也是上面那個設計前提成立的另一個理由:routine 的提示詞要當作這個工具永遠不存在來寫,因為對 routine 來說,它確實從來就不存在。

通知還是送到了

Anthropic 的行動裝置文件把推播通知的範圍限定得很窄:「當 Remote Control 啟用時,Claude 可以把推播通知送到手機上……通常是在長時間執行的任務結束時,或是需要你做決定時。」 Remote Control 是跟 routine 不一樣的功能,它把手機連到一個在自己機器上即時執行的 session,需要那台機器保持開機,而這正好抵消了 routine 能在雲端執行、讓筆電闔上也沒關係的優點。

儘管文件這樣限定範圍,上面那個卡住的 routine 執行,在完全沒有任何 Remote Control session 在跑的情況下,還是把通知送到了手機。文件跟實際觀察到的行為在這裡對不上,而比較重要的實務判讀是:就算沒有 Remote Control,至少有一類 routine 事件,也就是徹底卡死,還是會送到手機上。還沒測試到的是,一個不是完全放棄、而是卡在等待某件事的 routine,會不會用同樣的方式推播。因為會造成那種暫停的工具根本不存在,這件事沒有辦法測試。

在這個部落格,真正值得交給 routine 的是什麼

讓 Claude Code 離開終端機工作有四種不同的方式,它們互相拿同樣兩件事做取捨:工作是不是需要機器保持開機,以及人能不能在中途介入操作。

方式 執行位置 機器是否要保持開機 能不能暫停等待輸入
隨選雲端 session Anthropic 的雲端 不用 可以,閒置直到你回覆
routine Anthropic 的雲端 不用 不行:對應的工具根本不存在
Remote Control 自己的機器 可以,還能推播通知
Dispatch 自己機器上的 Desktop app 可以,透過 Desktop app

routine 是唯一一種既無人值守、又不需要機器保持開機的方式,同時也是唯一一種完全無法反過來問你任何事的方式。 這個取捨就是整個發現的核心,也決定了什麼該交給 routine,什麼不該。

這個部落格自己的 release skill 會一路處理完整個發布流程:決定標題、選標籤、合併 PR、幫版本打標籤。它刻意在每一個判斷點都保持互動,考量到這兩次測試的結果,這些判斷點沒有一個適合交給 routine。routine 沒辦法問該用哪個標題,就跟它沒辦法問該用兩句佔位句子中的哪一句一樣。

兩次測試都撐過去的,是那種流程具體到完全不需要任何判斷的工作。這個部落格的 changelog,每次有依賴套件更新機器人在正常發布流程之外合併東西,就會跟著漂移,而修正方式是一套已經寫好、固定不變的整理流程:讀出上次打標籤之後進來的內容,補上漏掉的項目,開一個只碰那一個檔案的 PR。這個流程裡完全沒有需要 routine 開口詢問的分岐點,而這正是這次的兩次測試花力氣確認、真正重要的性質。

總結

幫 GitHub Issue 加標籤,讓 routine 複製 repo、完成工作、開出 pull request 是真實可行的,而且第一次嘗試就成功,完全不用人在旁邊盯著。真正重要的限制,比「routine 不能被交付判斷」更窄、也更機械化:AskUserQuestion 就是不在 routine session 能呼叫的工具清單裡,這一點透過看著執行真的撞上那道牆、停下來而不是用猜的,得到了確認。要走到這個發現,得先捨棄第一版的測試設計,因為不管看起來多有說服力,一個自己開啟、自己回答的 session,都無法取代一個無人值守的觸發條件。Anthropic 的文件把推播通知限定在需要機器保持開機的功能上,但一個卡住的 routine 執行還是把通知送到了手機,這是文件寫的行為和實際觀察到的行為對不上的又一個地方。從這一切導出的實務規則是:routine 的提示詞要寫成一份把不確定的情況都先解決好的完整規格,因為不存在開口詢問、等待回覆這種退路。第三次測試把僅剩的一個疑問也解決了:在隨選 session 上,同一個工具能正確運作,會推播通知,也能在真正延遲之後恢復執行,這證實了缺少的這個工具是 routine 特有的性質,而不是整體雲端 session 的性質。

參考連結

分享這篇文章