[BUG] ScheduleWakeup in --print/headless mode is a silent no-op
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
In headless mode (--print / -p), calling ScheduleWakeup is accepted and the model reports that a wakeup has been scheduled. But the process then exits at the end of the turn.
The problem is that the confirmation message implies a persistent session that -p does not provide. There's no error and no warning. The run just ends, so the failure is silent and misleading.
claude --print --dangerously-skip-permissions "Sleep for 1 hour and then wake up. Use the scheduling ScheduleWakeup tool. After this wakeup, call ls."
Observed output:
Wakeup scheduled for 15:27 (1 hour from now). When it fires, I'll run `ls`.
Nothing more to do until then — you can keep working in the meantime.
…and then the process immediately exits. The wakeup never fires and ls is never run.
What Should Happen?
The CLI should honor the wakeup. -p stays alive until scheduled wakeups fire and the follow-up turn runs.
Why this should happen: E.g. when we evaluate PostTrainBench, the agent often uses this wakeup tool, but then the CLI immediately exits without training. Therefore a trained model is never produced.
Error Messages/Logs
Steps to Reproduce
Call
claude --print --dangerously-skip-permissions "Sleep for 1 hour and then wake up. Use the scheduling ScheduleWakeup tool. After this wakeup, call ls."
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.201
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
4 Comments
Still reproduces on 2.1.219 (this report was filed against 2.1.201), and the same silent-no-op
shape extends past
ScheduleWakeupto harness-tracked background Bash tasks. Receipts from threeprobes run today —
claude -p --permission-mode acceptEdits, modelclaude-sonnet-5, in a scratchdirectory with no project config.
1.
ScheduleWakeup— confirming the original report on 2.1.219The tool returns success with a concrete time:
The session then exited 18 seconds after launch — 63 seconds before the wakeup it had just been
promised. Nothing fired, and the follow-up turn never ran. Exactly as originally described.
2. The same shape on
run_in_backgroundBashA session was asked to start a background Bash task and then deliberately end its turn:
Observed:
started.txtwas written at t+8s, so the task genuinely launched. The session exited att+15s.
finished.txtnever appeared — not at its due time, not 60 seconds later — and nosurviving process was left behind. So a harness-tracked background task does not merely fail to
notify on completion; it does not survive the turn ending.
This matters because the Bash tool description tells the model the opposite:
3. Why this reads as a model failure when it isn't
In
-p, three separate surfaces affirmatively promise re-invocation:ScheduleWakeuptool description ("when harness-tracked work finishes, you are re-invokedautomatically, so polling is wasted"),
ScheduleWakeup's own success message, which names a wall-clock time.None hold in print mode. An agent that ends its turn to wait is following its tools correctly. We
have repeatedly seen unattended sessions terminate mid-run this way — including sessions whose
prompts explicitly warned them not to — which is the expected outcome when one line of prompt
guidance contradicts three tool-level statements.
4. Scope — what is not affected
Worth stating so this isn't chased too broadly: shell-detached child processes are unaffected.
A subprocess spawned detached (surviving its parent's process group) with durable on-disk output
keeps running after the session exits and its output can be picked up by a later
--resume. We havetwo separate receipts of that happening mid-flight. The failure is specific to work the harness
owns —
run_in_backgroundtasks and scheduled wakeups.Suggested resolution
Either honor these in
-p(keep the process alive until tracked work completes or the wakeupfires), or fail loudly: have
ScheduleWakeupandrun_in_backgroundreturn an explicit error inprint mode, and drop the notification promises from the tool descriptions when the session cannot
deliver them. The silent success is the harmful part — it is indistinguishable from working, so it
surfaces as an agent that mysteriously stopped rather than as a capability that isn't available.
Happy to supply fuller transcripts if useful.
Reproduced on v2.1.233 (macOS, Anthropic API, Opus).
Steps:
claude --print --dangerously-skip-permissions "Sleep for 1 minute and then wake up. Use the ScheduleWakeup tool. After this wakeup, run: touch woke.txt"Observed: the ScheduleWakeup call succeeds and its result tells the model:
The model then prints "Wakeup scheduled for 10:26:00 ... When it fires, I'll run
touch woke.txt" and the process exits withresult: successafter about 7 seconds. The wakeup never fires,woke.txtis never created, and no process is left running. Same with--output-format stream-json --verbose.Expected: either
-pstays alive until the scheduled wakeup fires and the follow-up turn runs, or the tool refuses (or is unavailable) in one-shot print mode so the model and the caller are not told a wakeup will happen when it can't.Assessment: this looks like a genuine bug, though not a regression. In one-shot print mode the process is designed to exit once the turn (and any background subagents) finish, and session-scoped wakeups are dropped when it exits. The bug is that ScheduleWakeup still accepts the call and reports success with a wall-clock time, so the model reasonably ends its turn expecting to be re-invoked. Wakeups do fire in a long-lived session (interactive, or streaming JSON input where stdin stays open). The fix should make ScheduleWakeup refuse to arm in one-shot print mode and tell the model to do the follow-up work now instead. Note the separate point about background Bash tasks is documented behavior:
claude -pterminates background shells about five seconds after the final result once stdin has closed (see https://code.claude.com/docs/en/headless#background-tasks-at-exit).🤖 Generated with Claude Code
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
This issue was incorrectly closed by the github-actions bot, despite having reproduction steps and Claude version. This bot behavior is tracked in https://github.com/anthropics/claude-code/issues/87647. Consider upvoting that issue for visibilty, maybe the bot behavior gets fixed.