Build1 distinct publisher3 min readUpdated
One developer's LaunchAgent fleet hit Claude Code's weekly limit and kept firing. His fix is a shared circuit breaker with a state file, not better error handling inside each job.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
The arithmetic in the writeup is on the low side. The author prices the outage at 6 hours x 15 jobs = 90 jobs' worth of work [7], which only holds if each job runs once an hour [3]. He also says these LaunchAgent entries fire every 5 minutes or every hour [8]. A five-minute job gets 72 attempts inside a six-hour window [1], so fifteen of them on that cadence would produce 1,080 invocations with no chance of succeeding [2]. Each one forked a process, made the call, was told the weekly limit was reached [2], exited 1, and was rescheduled by launchd [3].
Per-job error handling cannot close that loop, and not because the handling is sloppy. Each invocation is a short-lived process that knows nothing about the run before it or about its fourteen siblings, while the quota is a property of the account rather than of the job. The guard's answer is the cheapest shared memory available: one JSON file, an fcntl.LOCK_EX lock, and os.replace() to swap it in so concurrent writers cannot tear it [11]. That is the entire difference between fifteen jobs each finding the wall and one job finding it on behalf of the rest.
What the design trades away is detection quality. There is no exit code to key on, because Claude Code returns 0, 1, or other values depending on the situation [5], and the error text goes to stderr in a /tmp log nobody tails [6]. So the guard reads prose: seven case-insensitive regexes over the last 131,072 bytes of combined stdout and stderr [10]. Two of them, "rate limit" and "resets? (at|in|on|tomorrow)", will match output that has nothing to do with quota [10], and the penalty for a wrong match is six hours of stopped automation [9] until someone runs --reset or open_until expires [12]. The 128KB tail fails in the opposite direction: a chatty run that pushes the limit message out of the window passes as healthy.
Then there is the window itself. The limit being defended is weekly [2], while the circuit opens for 21,600 seconds and then closes on its own [9][12]. A seven-day limit period has room for twenty-eight of those windows [4], so if the reset has not arrived, the fifteen jobs wake up, trip the breaker again, and keep cycling, at a cost of one real invocation per job per reopening. That is much better than 1,080 blind attempts, but it is a rate limiter on your own retries, not a stop, and the state file never learns when the quota actually returns.
One caveat on sourcing: this is a single developer's account of his own machine, published on dev.to, and the Y1.2M/month attached to the stack is his stated revenue, not a measured loss [1]. The mechanism travels regardless. A scheduler that treats quota exhaustion as a transient error will retry at whatever cadence you configured, for as long as the quota lasts, and will file every attempt as an ordinary failure.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The author's 15 LaunchAgent jobs, behind an autonomous stack he says earns Y1.2M/month, hit Claude Code's weekly quota ceiling and then spent six hours swallowing errors while appearing to work; he discovered it the next morning by checking by hand.
Fifteen Claude-invoking jobs run in parallel in the author's environment, so hitting the limit skips all of them at once; he counts the loss as 6 hours x 15 jobs = 90 jobs' worth of work.
Claude Code has a weekly usage limit; when it is hit, API calls come back with an error message containing the text "weekly usage limit".
Automation scripts running under LaunchAgent mostly emit exit 1 and terminate when they receive that error; launchd records exit 1 as a failed job but runs it again on the next cycle as if nothing happened.
macOS launchd does not notify the operator by default when a job fails; ThrottleInterval controls the retry interval, but a plist cannot express "hit the quota, do not run at all until the next limit reset".
The quota error message goes to stderr; LaunchAgent dumps stdout and stderr into logs under /tmp, which almost nobody watches continuously.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
One self-published account with code excerpts, no external verification
The mechanism is documented well enough to inspect: the post shows QUOTA_PATTERNS, the 131,072-byte tail slice, EXIT_CIRCUIT_OPEN = 75, the cooldown/window/threshold defaults, and the lock-plus-os.replace write path. Everything else -- the six-hour outage, the 90 lost runs, the varying Claude exit codes, the ¥1.2M/month stack -- is single-source self-report with no logs, screenshots, repository, or vendor documentation, and the cluster contains no second publisher to corroborate any of it.
One operator's own machine
The only disclosed usage is the author's own stack: the guard fronting 15 LaunchAgent jobs on one macOS host. There is no published repository, package, star count, downstream user, or organizational deployment, and the cluster reports no one else adopting the pattern.
Real failure mode, oversold fix
The underlying problem -- quota exhaustion presenting as ordinary retry noise under launchd -- is well described and plausibly generalizes. The framing overstates the solution: detection relies on matching human-readable error strings, including patterns as broad as 'rate limit' and 'resets? (at|in|on|tomorrow)', the six-hour cooldown comes from a rule of thumb about Japan-time resets rather than a published reset schedule, and a breaker that auto-closes every six hours can reopen up to 28 times inside one weekly quota window. The headline cost figure also only reconciles with the slower hourly cadence. None of these limits are acknowledged in the post, and the revenue framing adds stakes the evidence does not carry.
Personal-brand and revenue-narrative incentive
The post is self-published on a developer platform and structured around the author's monthly income progression from ¥100K to ¥600K to ¥1.2M, framing the incident as a lesson from an 'autonomous stack' he markets as his own achievement. That creates an incentive to present the failure as dramatic and the homemade fix as decisive. No vendor sponsorship, commercial product, or affiliation is disclosed, and no competing outlet's incentives are present in the cluster.
Mechanism credible, magnitude and generality unverified
Confidence is moderate for the code-level facts, which are quoted and internally consistent, and low for anything about scale or platform behaviour: one publisher, one author, no corroboration, no vendor documentation of the weekly limit or exit-code semantics, and adoption limited to a single machine.
build
The 46GB Leak Your RSS Alert Cannot See: macOS Compressed Memory Breaks Threshold Monitoring1 distinct publisher
build
Exit 0 is not a health check: three weeks of macOS backups that copied nothing1 distinct publisher
build
A cost monitor overcounted 4.9x, then went dark for a week when set -e did its job1 distinct publisher
build
Your script exited 0 because the file no longer existed: macOS evicted it to iCloud1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 22, 2026