Background `claude --print` spawns silently burn Max5 quota; no per-account rate-limit visibility
Summary
When using Claude-Code SDK (claude --print --dangerously-skip-permissions) from a background dispatcher (e.g. launchd-supervised process that fans out per webhook event), a feedback-loop (event → spawn → posts comment → triggers new event → spawn …) can produce thousands of spawns within an hour, silently consuming a user's Max5 quota with no warning or visibility.
Repro
Today (2026-05-20) my Forgejo-webhook-driven dispatcher entered exactly this loop:
- ~4051
claude --printspawns over ~5 hours - ~810 spawns/hour average
- All spawned with
--dangerously-skip-permissionsfor autonomous CI-style work - Default model
claude-opus-4-7(envANTHROPIC_DEFAULT_OPUS_MODEL) - Consumed ~84% of my Max5 5h-window with no in-flight warning
Root cause on my side: the dispatcher posts back to the issue tracker after each task; comment events trigger fresh webhooks → fresh spawns. (BOT_LOGINS denylist existed but missed the case where spawned agents post under a human user's token.)
What's missing
- No per-account hourly cap warning before exhaustion — when a daemon is consuming the quota, the interactive user has no feedback until they themselves hit a wall
- No claude.ai UI visibility showing concurrent SDK sessions or who/what is spending
- No API endpoint to query remaining quota programmatically (so a well-behaved daemon could self-throttle)
- No distinction between "interactive Claude-Code session" vs "background SDK spawns" in limit accounting — both feed the same 5h bucket
- No flag like
--max-spawns-per-houror--rate-limit-respecton the CLI
Suggested mitigations
- Warning event at 50% / hard pause at 80% of quota for non-interactive
--dangerously-skip-permissionssessions - Programmatic quota-remaining endpoint (e.g. response header on every API call, or
claude quota) - Separate sub-quota bucket for SDK/non-interactive vs interactive use
- Optional self-throttling flag on the CLI
Mitigations applied on my side
- Dispatcher daemon stopped + disabled via launchctl
- All orphan
claude --printprocesses killed (verified 0 active) - Filed internal Forgejo-Actions migration ticket (transparent CI with native rate limits replaces the custom dispatcher)
- BOT_LOGINS detection extended to body-prefix markers
Environment
- Plan: Max5
- Claude Code CLI used non-interactively from launchd-supervised dispatcher
- macOS Darwin 25.5.0
- Model default: claude-opus-4-7
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗