Feature request: a producer-initiated "resume session" signal — a clean one-shot wake for background/external events

Resolved 💬 2 comments Opened Jun 9, 2026 by qiankunli Closed Jun 12, 2026

Context / use case

I maintain a Claude Code plugin — devloop — that runs background monitors which perceive external state changes: CI results, PR/MR merges, deploy completion, eval/verdict runs. These events happen outside the agent's own actions. When one occurs, I want the idle session woken so the agent can react (read the new state, decide a next step).

The agent + plugin already own the policy — is this change relevant? what to do? proceed automatically vs. ask the user? What's missing is the plumbing: a clean, programmatic way for a background producer to wake an idle session exactly once.

The gap

None of today's levers cover a producer-initiated one-shot wake:

  1. Monitor stdout → notification — the only producer→session push, but a long-lived task's notification is re-delivered ~every turn (#66219 — measured ~5×/min, 362 deliveries from a single event over 69 min). Unusable as a wake; we ship it muted.
  2. run_in_background task exit does re-invoke the session cleanly, exactly once (verified). But it's session-initiated — the session must pre-arm a poller that exits on a condition; it can't represent an unsolicited external event, and needs a separate armed waiter per pending intent.
  3. Hooks fire on Claude Code's own lifecycle, not external state.
  4. Scheduled wakeups / loops = polling: laggy, and burn turns/cache re-checking rarely-changing state.

The only clean path is (2), which proves the mechanism already exists internally (a background task's exit re-invokes the session once) — but it's only reachable by arming a task from inside a turn.

What we'd like

A first-class resume signal: a way for a background process to ask the runtime to start exactly one turn for a given idle session, carrying a short reason, deduplicated (delivered once, not re-rendered per turn). e.g. a small CLI a monitor can call:

claude session resume --session <id> --reason "PR #972 merged"

(or a file/socket the runtime watches). Conceptually this splits two things the notification channel conflates: ambient toast (a status line that may re-render each turn) vs. actionable wake ("act on this now" — delivered once, starts a turn).

Explicitly out of scope

We are not asking Claude Code to decide whether/what to auto-run. Relevance filtering, permission/mode gating, and the next action are the agent's + plugin's job — auto-continue is our policy to get right, not yours. We only need the wake.

Concrete implementation (in devloop)

The full perceive → wake → execute design, and the one-shot-exit workaround above, are written up in docs/event-driven-resume.md. The monitor is scripts/poll_pr_status.py; the verified one-shot waiter (snapshots state, exits on change → re-invokes the session) is scripts/wait_for_pr_change.py. A proper resume signal would let us drop the armed-waiter workaround entirely.

Related

  • #66219 — the symptom: per-turn re-delivery makes the one existing push channel unusable here. A "deliver once" fix is one route; a dedicated resume signal is the more direct one.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗