[BUG] ScheduleWakeup in --print/headless mode is a silent no-op

Status Closed — not planned
Reported on v2.1.201
Maintainer reply ✓ Yes — bcherny
Activity 4 comments · opened Jul 6, 2026 · closed Sep 13, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

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_

View original on GitHub ↗

4 Comments

zwrose · 2 months ago

Still reproduces on 2.1.219 (this report was filed against 2.1.201), and the same silent-no-op
shape extends past ScheduleWakeup to harness-tracked background Bash tasks. Receipts from three
probes run today — claude -p --permission-mode acceptEdits, model claude-sonnet-5, in a scratch
directory with no project config.

1. ScheduleWakeup — confirming the original report on 2.1.219

The tool returns success with a concrete time:

Next wakeup scheduled for 23:01:00 (in 67s)... the harness re-invokes you when the wakeup fires.

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_background Bash

A session was asked to start a background Bash task and then deliberately end its turn:

date +%s > started.txt; sleep 45; date +%s > finished.txt

Observed: started.txt was written at t+8s, so the task genuinely launched. The session exited at
t+15s. finished.txt never appeared — not at its due time, not 60 seconds later — and no
surviving 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:

you'll be notified when it finishes — do not poll

3. Why this reads as a model failure when it isn't

In -p, three separate surfaces affirmatively promise re-invocation:

  • the Bash tool description ("you'll be notified when it finishes"),
  • the ScheduleWakeup tool description ("when harness-tracked work finishes, you are re-invoked

automatically, so polling is wasted"),

  • and 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 have
two separate receipts of that happening mid-flight. The failure is specific to work the harness
owns
— run_in_background tasks and scheduled wakeups.

Suggested resolution

Either honor these in -p (keep the process alive until tracked work completes or the wakeup
fires), or fail loudly: have ScheduleWakeup and run_in_background return an explicit error in
print 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.

bcherny collaborator · 2 months ago

Reproduced on v2.1.233 (macOS, Anthropic API, Opus).

Steps:

  1. In an empty directory, run:

claude --print --dangerously-skip-permissions "Sleep for 1 minute and then wake up. Use the ScheduleWakeup tool. After this wakeup, run: touch woke.txt"

  1. Wait past the scheduled wakeup time and check the directory.

Observed: the ScheduleWakeup call succeeds and its result tells the model:

Next wakeup scheduled for 10:26:00 (in 81s). Nothing more to do this turn — the harness re-invokes you when the wakeup fires or a task-notification arrives.

The model then prints "Wakeup scheduled for 10:26:00 ... When it fires, I'll run touch woke.txt" and the process exits with result: success after about 7 seconds. The wakeup never fires, woke.txt is never created, and no process is left running. Same with --output-format stream-json --verbose.

Expected: either -p stays 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 -p terminates 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

github-actions[bot] · 1 month ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

marcindulak · 1 month ago

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.