
Claude Code routines turn a labeled issue into a PR from a sandbox — but can't ask a follow-up
Two disposable GitHub issues test Claude Code's cloud routines: labeling one produces a real PR from a sandbox, but the routine has no AskUserQuestion tool.
On this page
Introduction
I’d heard that Claude Code now offers a cloud feature people call “cowork”: spin up a sandbox, hand it a GitHub issue, and watch the result from a phone without keeping a machine on. Before wiring anything real to it, I wanted to know what the workflow actually looks like day to day, not just what the pitch promises, since this blog already has a release pipeline with enough sharp edges that I did not want to hand a routine something it could get quietly wrong unsupervised. Two disposable GitHub issues later, the answer landed on one missing tool: a Claude Code routine cannot call AskUserQuestion at all, which is not what “label an issue and let it work” prepares you for. This article covers the setup friction that came first, a test that would have proved nothing had a bad design not been caught in time, the finding itself, a notification that arrived despite the docs saying it shouldn’t, and what is actually worth handing to a routine on this blog given the constraint.
The private repo that wouldn’t show up
The first snag had nothing to do with routines yet. This blog’s repo is private, and it simply did not appear in the repository picker at claude.ai/code: typing the name returned “No repos match.”

Private repos are supported; this repo just was not in scope for the app that grants access. The Claude GitHub App asks, at install time, whether it should see all repositories on the account or only a selected list, and this repo had not been added to that list.

Reconfiguring the app’s repository access at github.com/settings/installations and reconnecting fixed it. This is also a documented, recurring failure mode independent of that fix: several open issues on Anthropic’s own tracker describe a private repo the app genuinely has access to still not appearing, or dropping out intermittently, which reads as a backend indexing problem rather than anything wrong with the account’s settings.
A scratch file, labeled and merged
With the repo reachable, the first real test used a routine: a saved prompt plus a GitHub trigger, set up once at claude.ai/code/routines. Rather than writing a task-specific prompt, the routine’s instructions were deliberately generic: read whatever GitHub issue triggered the run, and do exactly what it says.

The agent proposed a disposable first task: create one throwaway file (docs/cloud-agent-shakedown.md) containing a fixed sentence, touch nothing else, run the repo’s own pnpm check, and open a pull request without merging it. That went into a GitHub issue, and applying a dedicated cloud-agent-test label to it fired the routine.
![A GitHub issue titled “[test] Cloud agent shakedown” with the labels panel open and the cloud-agent-test label about to be applied](/_astro/issue-166-apply-label.D6asaGIu_ZUV4UN.webp)
It worked cleanly, unattended, on the first try. The routine cloned the repo, created exactly the one file asked for, ran the validation suite, and opened a pull request with the real command output pasted into the description:
$ astro check && pnpm run check:types && pnpm run check:i18n …
05:57:16 [check] Getting diagnostics for Astro filesResult (244 files):- 0 errors- 0 warnings- 0 hintsIt also flagged something nobody had asked it to check: an unrelated, pre-existing Unsupported engine warning about the repo’s pinned Node version, noted in the pull request rather than silently ignored. That is a small thing, but it is also exactly the behavior this blog’s own tooling conventions ask for, and the routine did it without being told to.
Watching myself answer a question proves nothing about a routine
The next question was whether a routine could pause mid-task on a real decision and be resumed later by answering it from a phone, since that is the “hands-free” half of the pitch. The first design for testing that was wrong, and I am glad it was caught before it ran: the plan was to open a session directly from the phone, paste a prompt that forced an AskUserQuestion call, and answer it live.
A session I start myself and am already watching cannot test the unattended path. Answering a question in a conversation I am actively driving only proves that live conversation works, which was never in doubt. The thing actually worth knowing was a materially different claim: whether a run fired by a trigger, with nobody watching, could stop, wait, and later be resumed by a reply from a phone.
The redesign reused the same generic routine from the first test. A second disposable issue asked for the same kind of throwaway file, except this time the routine had to call AskUserQuestion and wait for an answer before creating anything, and the trigger was the label, not a session started by hand.
AskUserQuestion is not a tool a routine can call

Applying the label fired the routine, and it stopped almost immediately, before creating anything:

The run’s own words: “AskUserQuestion is not an available tool in this routine/trigger session. It’s absent from the tool list and ToolSearch finds nothing matching it… I stopped rather than fabricate an answer or guess between option A/B. No file was created, nothing was committed, no PR was opened.”
That is a stronger and more precise finding than Anthropic’s public documentation gives, which only says routines run with “no approval prompts during a run”: wording that reads as being about tool-permission prompts, not about a distinct, conversational, ask-the-user tool. The actual behavior settles it either way. The tool simply is not in a routine’s toolbox, so nothing “declines” to ask; there is nothing there to call. The failure mode when it hits that wall is the right one: it did not guess between the two options, and it did not silently pick a default. It stopped and reported, which is what unattended automation should do when it genuinely cannot proceed.
I do want this tool to exist here. A routine that could call AskUserQuestion, pause on a genuine decision, and resume from a phone reply the same way an ad hoc cloud session already does would remove the one reason a routine’s prompt has to be a complete spec with nothing left open. Until it does, that constraint is not a preference to work around; it is the design brief.
A third test, run on an ad hoc session instead
That comparison, “the same way an ad hoc cloud session already does,” was written on the strength of Anthropic’s own documentation, not verified firsthand: both tests so far had only ever exercised the routine path. A third test closed that gap, starting a session directly from a phone rather than through a labeled issue, with the same disposable task and the same forced AskUserQuestion call, but nothing routine about how it ran this time.

It worked, and the app pushed a notification the moment it needed one: “Claude has a question — Shakedown line.” Opening it showed a real, native question card, not a text workaround.

The question sat unanswered for twelve minutes, timestamps on the phone itself putting the prompt at 1:26 and the finished result at 1:38, long enough to rule out the live-conversation flaw the first routine-test design had.

Answering after the gap resumed the session correctly: it created the file with the chosen option, ran pnpm check clean, and opened a pull request against main, unmerged, exactly as asked. The constraint is specific to routines, not to cloud sessions in general. AskUserQuestion is a real, working, push-notified tool everywhere except inside a routine’s unattended run, which is one more reason the design brief above holds: write a routine’s prompt as if the tool will never be there, because for a routine, it never is.
A notification arrived anyway
Anthropic’s mobile documentation scopes push notifications narrowly: “When Remote Control is active, Claude can send push notifications to your phone… typically when a long-running task finishes or when it needs a decision from you.” Remote Control is a different feature from routines. It connects a phone to a session running live on your own machine, and it requires that machine to stay on, which defeats the point of a routine running in the cloud while a laptop is closed.
Despite that scoping, the blocked routine run above still pushed a notification to the phone, with no Remote Control session active anywhere. The docs and the observed behavior disagree here, and the practical read is the one that matters more: even without Remote Control, at least one class of routine event, a hard stop, reaches the phone. What remains untested is whether a routine that pauses mid-task waiting on something, rather than giving up outright, would push the same way. It could not be tested, because the tool that would have caused that pause does not exist.
What’s actually worth handing to a routine here
Four different surfaces let Claude Code work away from a terminal, and they trade the same two things against each other: whether the work needs a machine left on, and whether a human can steer it mid-task.
| Surface | Where it runs | Machine must stay on | Can pause and wait for input |
|---|---|---|---|
| Cloud session (ad hoc) | Anthropic’s cloud | No | Yes, sits idle until you reply |
| Routine | Anthropic’s cloud | No | No: the tool for it does not exist |
| Remote Control | Your own machine | Yes | Yes, and can push a notification |
| Dispatch | Desktop app on your machine | Yes | Yes, via the Desktop app |
Routines are the only row that is both unattended and free of the machine-on requirement, and also the only row that cannot ask anything back. That trade decides what belongs on a routine and what does not.
This blog’s own release skill orchestrates a full release end to end: choosing a title, picking labels, merging a pull request, tagging a version. It stays deliberately interactive at every one of those points, on purpose, and none of that is a good fit for a routine given what the two shakedown tests found. A routine can’t ask which title to use any more than it could ask which of two placeholder sentences to write.
What did survive both tests is anything with a procedure specific enough to need no judgment call at all. This blog’s changelog drifts whenever a dependency bot merges something outside the normal release flow, and the fix is a fixed, already-written sweep: read what landed since the last tag, add any missing entries, open a pull request touching only that one file. Nothing in that procedure has a branch point a routine would need to ask about, which is exactly the property this session spent two tests confirming actually matters.
Summary
Labeling a GitHub issue and letting a routine clone a repo, do the work, and open a pull request is real, and it worked on the first attempt with nothing to supervise. The limit that matters is narrower and more mechanical than “routines can’t be trusted with judgment calls”: AskUserQuestion is simply not a tool a routine session can call, confirmed by watching a run hit that exact wall and stop rather than guess. Getting to that finding took a discarded first test design, because a session started and answered by hand cannot stand in for an unattended trigger no matter how convincing it looks. Anthropic’s docs scope push notifications to a feature that requires a machine left on, and a blocked routine run still reached the phone anyway, which is one more place the written behavior and the observed behavior did not match. The practical rule that falls out of all of it: write a routine’s prompt as a complete spec with the uncertain cases already resolved, because there is no fallback where it asks and waits. A third test settled the one thing left open: on an ad hoc session, the same tool works correctly, pushing a notification and resuming after a real delay, which confirms the missing tool is a property of routines specifically, not of cloud sessions as a whole.

