a Bun preload that turns agent_summary off · by Flamerix AI, flamerix.ai · MIT · GitHub

by Flamerix AI · MIT License
Tested on Linux, Claude Code 2.1.257–2.1.312 (see Tested variations). The binary isn’t modified (
BUN_OPTIONS=--preload). An replace can silently undo it, so see Verify.
curl -fsSL https://gist.githubusercontent.com/flamerix-ai/c3905705cc4205e5de3011fa2e74efce/raw/no-agent-summary.js -o ~/.native/share/no-agent-summary.js
claude daemon cease --any
BUN_OPTIONS="${BUN_OPTIONS:+$BUN_OPTIONS }--preload $HOME/.native/share/no-agent-summary.js" claude
To make it everlasting for each Claude Code course of, see Install.
Every ~30 seconds, for each background agent, Claude Code sends that agent’s complete
transcript to the agent’s personal mannequin (normally Opus) and asks it to “describe your most up-to-date
motion in 3-5 phrases”. The reply solely updates the agent’s standing line within the brokers panel; it
by no means reaches the mannequin or your dialog. There is not any setting that turns it off, and since
2.1.232 (August 2026) it has been on by default.
The anomaly was detected by DRIM in Claude Code’s OpenTelemetry export:
grouping claude_code.api_request occasions by query_source confirmed agent_summary costing greater than the principle dialog itself.
query_source = agent_summary |
week earlier than the hook | 2 days after |
|---|---|---|
| share of all Claude Code spend | 16.4 % (principal dialog: 15.7 %) | 0 % |
| share of all API requests | 19.7 %, about 1 in 5 | 0 % |
| a part of that spend on Opus | 96 % | — |
| enter tokens per output token | ≈ 9,000 : 1 | — |
Spend right here means Claude Code’s personal per-request estimate (cost_usd), not an bill: on a
subscription, what you lose is rate-limit headroom. We are usually not the one ones who measured it:
#86879 collects 4 unbiased
measurements of 18–26 %.
no-agent-summary.js is a Bun preload (~80 strains of code). It wraps setTimeout/setInterval;
when a callback’s supply textual content accommodates a summarizer anchor (e.g. the [AgentSummary] Timer fired
log line), it returns an inert deal with as an alternative of arming the timer. Every different timer passes
by untouched. In the OpenTelemetry export the suppressed requests are
claude_code.api_request occasions with query_source = agent_summary.
Why a timer hook moderately than one thing easier: the module ships as precompiled Bun bytecode, so
modifying its JS textual content contained in the binary modifications nothing, and the API consumer doesn’t undergo a
wrapped worldThis.fetch. But Function.prototype.toString nonetheless returns a callback’s supply
even when it runs from bytecode, so the timer will be recognised by a string inside it. The inert
timer makes use of precisely 2³¹−1 ms: Node and Bun deal with a bigger delay as 1 ms, so an “infinite” delay
would fireplace directly.
-
Put
no-agent-summary.jssomeplace steady; word its absolute path. -
Set
BUN_OPTIONSglobally so each Claude Code course of will get it. One of:# ~/.profile, ~/.bashrc, ~/.zshrc export BUN_OPTIONS="${BUN_OPTIONS:+$BUN_OPTIONS }--preload /abs/path/no-agent-summary.js"
# ~/.config/fish/config.fish set -gx BUN_OPTIONS "--preload /abs/path/no-agent-summary.js"
# ~/.config/setting.d/50-no-agent-summary.conf (systemd consumer env; additionally reaches # consumer companies and timers; applies when the consumer supervisor subsequent begins, normally subsequent login) BUN_OPTIONS=--preload /abs/path/no-agent-summary.js
Or a wrapper named
claudeearlier onPATH(thecaseretains it idempotent when one Claude
Code course of begins one other):#!/bin/sh HOOK=/abs/path/no-agent-summary.js case " ${BUN_OPTIONS-} " in *" --preload $HOOK "*) ;; *) export BUN_OPTIONS="${BUN_OPTIONS:+$BUN_OPTIONS }--preload $HOOK" ;; esac : "${CC_AGENT_SUMMARY_LOG:=${XDG_RUNTIME_DIR:-/tmp}/no-agent-summary.log}" export CC_AGENT_SUMMARY_LOG exec /path/to/the/actual/claude "$@"
-
Restart the daemon and each already-running session, then begin Claude Code from an
setting that hasBUN_OPTIONS:
| variable | values | impact |
|---|---|---|
CC_AGENT_SUMMARY_MODE |
off (default), go |
off suppresses the abstract timer. go is the A/B management: masses and logs, arms each timer untouched. Any different worth warns on stderr and acts as off. |
CC_AGENT_SUMMARY_LOG |
file path, non-compulsory | Appends preload energetic mode=… bun=… hooked=… on load, one line per matched timer (first 20), and an exit rely. |
CC_AGENT_SUMMARY_MARKER |
file path, non-compulsory | Overwritten on load with the preload energetic … line. |
- Restart the daemon after set up. The daemon, pty host and pre-warmed
bg-spareclasses
inherit the setting of the consumer that began the daemon, so a daemon began earlier than
BUN_OPTIONSwas set retains spawning unhooked classes. Henceclaude daemon cease --any. - Headless runs want it too:
claude -p, cron, CI, editor integrations. - Platform: Linux examined, macOS and Windows untested. On Windows the
/$bunfs/gate most
seemingly by no means installs the hook. - A/B:
CC_AGENT_SUMMARY_MODE=gomasses the hook however arms each timer; the summaries come again, which reveals theoffresult’s the hook’s doing. - Background processes: daemon, pty host and
bg-spareshould carry--preloadof their setting (/proc/on Linux); if not, restart the daemon./environ
-
Preload masses:
BUN_OPTIONS="--preload $HOME/.native/share/no-agent-summary.js" CC_AGENT_SUMMARY_LOG=/tmp/nas.log claude --version && cat /tmp/nas.log
Expect
preload energetic mode=off …. No line:BUN_OPTIONSdidn’t attain the method, or the
path isn’t absolute. -
Timer suppressed: with the identical
BUN_OPTIONSandCC_AGENT_SUMMARY_LOG=/tmp/nas.log, run
a background subagent for a minute or two. The log reveals
abstract timer #1 suppressed (setTimeout, delay=30000)and the agent’s panel standing stops
updating. If you export OpenTelemetry,query_source = agent_summaryought to keep at zero; this
is the one verify that catches each failure mode.
Matching is by supply textual content: an anchor should sit contained in the callback handed to the timer. If an
replace breaks that, the hook matches nothing and summaries silently come again. Ways it may possibly occur:
- the log line or query-source id is renamed;
- the callback is handed by way of
fn.bind(...)(no supply intoString) or one other wrapper; - the strings transfer to a shared fixed exterior the callback;
- the timer strikes to an unwrapped API (
timers/guarantees, a scheduler loop).
So re-run Verify after each replace.
- We run it below each Claude Code course of on our machine (2.1.301). Since then there have been
zeroagent_summaryrequests, and no different aspect question grew to take its place. - Subagents, background brokers, forked abilities and background classes run usually; solely the
abstract fork is skipped. - Visible change: the per-agent panel standing stops updating; SDK
task_progresshas noabstract. - Overhead: one
Function.prototype.toStringper distinct timer callback, cached in aWeakMap.
claude --version: ~10 ms → ~17 ms (one measurement).
Linux x64 binary from npm @anthropic-ai/claude-code-linux-x64 (its sha256 equals the native
installer’s manifest.json checksum). Static: the extracted bundle’s abstract timer callback
carries a hook anchor. Live: claude -p --model haiku with
CLAUDE_CODE_AGENT_PROGRESS_SUMMARIES=1, one subagent doing 8 steps of ~20 s, counting
[AgentSummary] Forking in --debug-file.
| model | revealed | sha256 | static | abstract forks in a ~2.5-min agent run: no hook / hook go / hook off |
notes |
|---|---|---|---|---|---|
| 2.1.312 | 2026-10-27 | 4f4178ce41d8 |
OK | 5 / 5 / 0 | newest on 2026-10-28; interactive: 6 no hook, 0 off |
| 2.1.310 | 2026-10-23 | b73676430af1 |
OK | 5 / 5 / 0 | |
| 2.1.308 | 2026-10-22 | 356733f185fa |
OK | 5 / 6 / 0 | steady on 2026-10-28; the go run’s agent took 9 steps as an alternative of 8 |
| 2.1.301 | 2026-10-15 | bc1aad9982c7 |
OK | 5 / 5 / 0 | identical with earlier hook builds; interactive off additionally 0; in each day use since 2026-10-26, 0 agent_summary requests in telemetry |
| 2.1.280 | 2026-09-22 | 1e08503dbdf3 |
OK | 1 / 1 / 0 (timer fired 11 / 11 / 0) | interactive: -p can’t allow summaries on this model. The agent sat at a permission immediate, so later timers skipped the unchanged transcript |
| 2.1.257 | 2026-09-01 | 9a64bda9d872 |
OK | 1 / 1 / 0 (timer fired 11 / 11 / 0) | identical as 2.1.280 |
5 / 5 / 0 = the fork occurs on this model, merely loading the hook modifications nothing, and off
removes it.
- The documented swap solely turns it on. The SDK possibility
agentProgressSummariesdefaults to
false, however within the bundle it’s one time period of an OR, and each code path that writes it units
true. Sofalsemodifications nothing, and the undocumentedCLAUDE_CODE_AGENT_PROGRESS_SUMMARIES
can solely allow summaries too. - The interval belongs to the server. It comes from a per-model-family server flag and is
clamped to 30–240 s. The default is already the minimal, and no worth disables the timer. - The apparent env vars miss.
DISABLE_NON_ESSENTIAL_MODEL_CALLS, which some packagers set,
doesn’t happen within the binary in any respect.CLAUDE_CODE_FORK_SUBAGENT=0and
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1do cease it, however solely by taking fork subagents or
background brokers with it. - The immediate cache makes it cheaper, not low-cost. About 98 % of those calls re-read the
transcript from cache; the ~2 % that hit a chilly cache carry over a 3rd of its price. - Cost instruments that learn transcripts do not see it. These requests are usually not written to the
session logs on disk (#104358); solely
the OpenTelemetry export reveals them. The docs part on background token utilization would not record it
both, whereas Agent View’s row summaries are documented as a Haiku-class mannequin refreshing each
couple of minutes. - A less expensive variant already exists, switched off. 2.1.310 ships a
quickmode: about 2k
tokens of notes as an alternative of the complete transcript, optionally written by a smaller mannequin. The
default remains to be the complete transcript, and solely server flags can change it.
| model (revealed) | what modified |
|---|---|
| 2.1.32 (Feb 5) | the code first seems; useless in public builds |
| 2.1.72 (Mar 9) | reachable as an SDK opt-in |
| 2.1.117 (Apr 21) | reachable within the interactive CLI behind the fork gate or a server rollout |
| ≤ 2.1.220 (Jul 24) | forked abilities are at all times summarized |
| 2.1.232 (Aug 13) | on by default for interactive background brokers |
| 2.1.300 (Oct 14) | interval turns into server-tunable, 30–240 s |
| 2.1.310 (Oct 23) | the cheaper quick mode lands, switched off |
In our telemetry its weekly share of spend went from 3.5–7 % in July (the fork gate was already
open for us) to 7.3 % after which 11.8 % within the week we picked up 2.1.233, and to about 16 % by
mid-October.
MIT © 2026 Flamerix AI. Provided as is, with out guarantee of any type;
you employ it at your personal danger. Flamerix AI isn’t answerable for any harm, knowledge loss or account
motion arising from its use. Changing a consumer’s runtime behaviour could dispute with the phrases of
the service you employ it with; checking that’s on you.
“Claude” and “Claude Code” are logos of Anthropic, PBC. This venture is unbiased and is
not affiliated with, sponsored or endorsed by Anthropic.
