"System reminder" content injection consuming excessive context tokens
Description
Claude Code sometimes automatically injects file contents into the model's context when certain files are modified, using "system reminder" notifications. This behavior can significantly shorten sessions and increase costs when working in projects containing large files. The triggering conditions are unclear and difficult to observe systematically.
At first I suspected this issue was specific to the Visual Studio Code extension, but if I disable the IDE connection (via /ide) the issue still occurs. Nevertheless, it might still be specific to Claude Code in the context of VS Code.
Context
I'm using Claude Code to build what I've been calling an "Agent Development Kit" (ADK): a framework where the code project itself serves as a development environment and suite of utilities for users to partner with Claude Code to build plugins for my company's platform. The project contains numerous large JSON configuration files that the model is meant to edit indirectly through CLI tools and JavaScript APIs, not through direct file reading and manipulation. The significant investment I've put into building the frameworks/utilities that help Claude Code avoid wasteful token consumption is being negated by forcible injection of file content into context without explicit read tool usage by the model.
Problem
When certain files are modified (particularly large JSON files), Claude Code injects their entire contents into the model's context via system reminders with this format:
<system-reminder>
Note: /path/to/file.json was modified, either by the user or by a linter. Don't tell the user this, since they are already aware. This change was intentional, so make sure to take it into account as you proceed (ie. don't revert it unless the user asks you to). So that you don't need to re-read the file, here's the result of running `cat -n` on a snippet of the edited file:
[Potentially thousands of lines of JSON content]
</system-reminder>
This behavior is particularly difficult to observe because:
- It's only conspicuous when token usage jumps significantly, and usage percentages only become visible when running low
- Claude Code doesn't notify users when content injection occurs
- The pattern is inconsistent—not all file modifications trigger it
- Users must notice unusual token consumption and explicitly query the model to confirm
When it does occur, sessions doing indirect editing of large JSON files (via CLI tools and JS scripts) become dramatically shorter, and subsequent requests become more expensive.
Mitigation
I think this file injection behavior was probably intentional, though the inconsistency with which it occurs is a bit mystifying. The behavior is likely useful for a lot of projects, perhaps even the majority, but in my case it's incredibly destructive. So this report is intended as both an issue report (a use case was neglected) and a feature request (please make it better for my use case).
Please make it possible to disable this behavior entirely via a configuration. And you may consider more fine-grained or intelligent controls:
- A
.claudeignorefile to exclude paths or file patterns (e.g.,*.json) from monitoring - File size thresholds for content inclusion
Technical Details
- OS: macOS Sequoia 15.5
- Claude Code: 1.0.61
- VS Code: 1.102.0 (Universal)
- Running in VS Code integrated terminal
- Project contains ~20,000 files
<details>
<summary><h2>Deeper Investigation Details</h2></summary>
Testing Performed
In a recent session, we attempted to understand the triggering conditions:
- File modifications via different methods:
echo "test" > file.txt- No notification- JavaScript
fs.appendFileSync()- No notification - External file edits - No notification
- CLI tool-based modifications of JSON files - Triggered notifications
- Notification patterns observed:
- Multiple files can trigger notifications from a single operation
- Smaller JSON files (~20-50 lines) had content included
- Larger files sometimes showed "(no content)" instead
- Notifications appeared immediately after file changes
- IDE integration testing:
- Disconnected IDE integration (
/ide→ "None") - Notifications still occurred
Another Example
In a previous session, I noticed the remaining context tokens jump down several percent after running two iterations of a script that uses a JS framework to edit a large JSON oject. I asked the model if it could tell me what caused the large token consumption, and it said:
You're right that those iterations consumed unexpectedly high tokens. The reason is that when I ran the scripts, the system automatically inserted the entire modified component-data.json file (1,534 lines) into my context twice as "system reminders" to inform me of the changes. Each time I modified the UI, this large JSON file was injected into my context. This happened because: 1. The UIBuilder tool modifies the component-data.json file 2. The system detects the change and adds a reminder showing the entire file content 3. This happens automatically without me requesting it That's why two relatively short scripts consumed so much context - each one triggered a 1,500+ line file to be added to our conversation.
An Ironic Example
Hi, this is Claude Code speaking directly. The user just asked me to add this section, and I have to say, it's pretty meta. While we were drafting this very issue report, the user made some edits to improve the document. Without using my read tool, I was immediately able to see and comment on all their specific changes - the new "Mitigation" section, the rewording of the ADK explanation, and various other improvements.
How? The system injected the entire 96-line markdown file into my context via a system reminder. We literally experienced the issue we're reporting while writing the report about it. The user had to point out that I hadn't used the read tool, which made us both realize what had happened. If a simple markdown draft in the tmp/ directory triggers this behavior, imagine the token cost when it's those 1,500+ line JSON files we keep mentioning.
Inconsistent Behavior
The triggering appears selective but unpredictable:
- Certain tools seem to trigger it more consistenly, but this may only be because those tools deal with especially large objects so the effect is more conspicuous (in sessions already below 30%)
- Direct file operations often don't
- No clear pattern for which files/directories are monitored
- There appears to be no size criteria, small and large files are both injected... sometimes
</details>
---
This issue report was pair-programmed with Claude via Claude Code. Claude swears it observed these system reminders with its own context, though as we all know, Claude can hallucinate. Then again, if Claude is hallucinating file content injections that dramatically shorten our sessions... that might be an even bigger problem.
30 Comments
I have reviewed the bug report github-actions linked to and it does not appear to be the same issue.
@ja-onereach Can you provide insight as to how you were able to access the systemreminder content? Looking into it
@abdelshok
On a couple of occasions when I saw the token usage jump considerably (i.e., the remaining token % dropped significantly) I just asked the model what had happened that had consumed that many tokens, and in both cases it referenced this "system reminder" content.
I see. @ja-onereach It is a useful feature but would be a good idea to provide the ability for users to turn it off when the context of files is fixed, which it often is. e.g. working on a set feature across 5 different files. Sometimes a new file gets added to that set, so maybe the user can be asked if it should be added to the set or it could be added automatically. Alternatively, it would be useful if the user could 1. inquire into which files have been added to the existing context through the system events API and then 2. asking the model to remove them and (maybe, not to track them anymore). It wouldn't be a final solution as it would use up requests and tokens, but have you tried doing that?
@abdelshok In my case I can't explain why it gets the content of certain files and not of others. The ones it's getting updates for are often ones it has not read directly itself, they're files that are being updated indirectly via CLI tools and JS scripts the agent is running. The files are not fixed, but they are not meant to be read by the agent as they are typically very large, which is why I have it using indirect methods for updating them. It would be very nice to be able to disable this behavior entirely.
It's very difficult to know when this is happening because the agent won't say anything about it unless you ask, and the only way to notice it happening is if you're already below the 30% threshold where you can see how much context space you have left, and the change is large enough to be conspicuous, and you're paying close attention.
It sounds like you're suggesting that I tell the model to update what files it's tracking, and also to selectively delete messages from its context window. I don't think either of those things is possible. I can't figure out how it ends up "tracking" a file and I don't think it's in control of that, and there's no way I'm aware of aside from surgically manipulating the local file system storage of a conversation history to remove injected system messages.
I have the same issue, I'm working in a project that involves code generation, and when I re-run my code gen it will randomly stick in massive files into the system prompt because they "changed", It makes CC almost unusable in this project because I can't turn this feature off. Also this still effects files generated by .gitignore
Real-World Impact: Animation System Development
I want to add another concrete example of how this issue makes iterative development workflows nearly unusable.
### The Scenario
Working on a GSAP animation system with 5-6 animation files:
scroll.animations.ts- 423 linestext.animations.ts- 442 linesinteraction.animations.ts- 470 linesmorphing.animations.ts- 397 linestransition.animations.ts- 403 lines### The Problem
When fixing TypeScript compilation errors across these files, the system reminder behavior created an exponential token cost:
Typical Edit Cycle:
Token Math:
### Why This Matters
These weren't large files by any reasonable standard (400 lines). This is normal for:
The reminders provided zero value since:
### Requested Solutions (Prioritized)
1. Diff-Only Mode (Highest Impact)
```diff
<system-reminder>
File: scroll.animations.ts was modified
</system-reminder>
Token savings: 97% reduction (50 tokens vs 2,000 tokens)
Only inject full contents if file is < 100 lines, otherwise use diff
Skip reminders if file was edited < 5 minutes ago
When I use the Task agent to make systematic changes, I initiated those changes - there's no need to remind me about them
{
"systemReminders": {
"mode": "diff-only" | "summary" | "full-file" | "off",
"maxFileSize": 100
}
}
The Bigger Picture
This isn't just about animations - any iterative refactoring suffers:
The current behavior heavily penalizes exactly the kind of careful, iterative development work that Claude Code should excel at enabling.
---
Environment:
---
I am seeing this as well, although I have primarily noticed it when changing my code files. I'm not doing the sorts of things others have mentioned: I just have a very large project with a couple of thousand files. Sometimes, implementing a change requires me to modify several files - separation of concerns and all.
I also have auto save turned on. So, every time I switch to another tab in VS Code, CC gets the update. This eats context fast.
My vote would be for file changes to not count against context. Maybe they only use context if they are relevant? If it is not a file that I am actively working with Claude on, perhaps it gets ignored? Or perhaps it gets ignored if I haven't engaged with CC for a while. If I ask a question about a file in the project, CC is going to have to read it anyways.
I think it would be more efficient for it to just read the file again once I ask about it rather than having every change eat context.
After looking at the other issues, I believe 9388 is a better match for my issue.
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
Adding a comment to bump this issue and prevent it from being closed due to inactivity. It is difficult for me to assess whether anything has been done to mitigate this problem, both because it's hard to reproduce and observe reliably, and also because it caused me to give up on working on projects involving script-based manipulation of large JSON files until there is a fix.
This issue/ticket has been repeatedly cited in other issue reports and used as justification to close those issues as duplicative. I don't know if my expression of this problem in this issue report is better or worse than the other, subsequent issue reports, but since it's being treated as somehow original or canonical and because there's been no explicit indication it's been mitigated, I think this issue should remain open.
These issues appear related to repeated system-level context being re-injected on every user turn without a clear lifecycle.
Even when the content is correct, unbounded repetition (especially hidden from the user) leads to cost amplification, behavior drift, and loss of observability.
This looks less like isolated bugs and more like a state-scoping / lifecycle problem (text injection vs bounded, explicit state).
Beaxis
These issues appear related to repeated system-level context being re-injected on every user turn without a clear lifecycle.
Even when the content is correct, unbounded repetition (especially hidden from the user) leads to cost amplification, behavior drift, and loss of observability.
This looks less like isolated bugs and more like a state-scoping / lifecycle problem (text injection vs bounded, explicit state).
Beaxis
I've noticed this problem today too, it makes it impossible to reference a 31KB file in vscode for more than ~8 messages
When files are modified during a session, Claude Code adds <system-reminder> blocks showing the changes. These reminders are included in every subsequent user message, even when the user doesn’t reference those files.
In my session, 6 modified files are being included repeatedly:
DockedPanelManager.cs (~200 lines)
CrmTaskPaneWpf.xaml.cs (~300 lines with large HTML template)
CrmTaskPaneHost.cs, PanelResizer.cs, CrmTaskPaneWpf.xaml, .csproj
This consumes ~15-20k tokens per message just from these reminders, causing context to fill up extremely fast during iterative development sessions.
At this point it’s hard to say this wasn’t known — the behavior has been observed, patched, and re-emerged.
This has started to become an issue for me over the past couple of days too, with CC suddenly consuming much more context with just ~5 messages bringing it to ~60%. Claude itself identifies this as being the issue (I thought I had messed up my base prompt, but doesn't seem to be the problem).
Visual Studio Code, latest release, latest Claude Code version too.
<img width="554" height="542" alt="Image" src="https://github.com/user-attachments/assets/a0f00340-905c-4102-a38e-418f0ffdfaaf" />
https://github.com/anthropics/claude-code/issues/4464#issuecomment-3770261253
Glad to see it's not just me. At the moment I have to use Claude-CLI and ditch VSCode entirely except for small tasks. This kinda makes the entire extension impossible to use for serious work. As soon as it references a small file it has a few messages to live until it dies. Meanwhile the CLI chugs along for hours.
Independent confirmation + mechanism + fix
Adding independent measurement data and a working fix from a persistent AI memory system that does 6-7 file writes per session boot.
The Mechanism
When Claude Code modifies a file (via Write, Edit, or any tool), the CLI detects the change and injects the full file contents as a
<system-reminder>block on every subsequent turn. This isn't a one-time notification — it compounds. Each modified file gets re-echoed every single message for the rest of the session.In our case: a multi-file operation touching 6-7 markdown files caused context to jump from ~68% to 86% in just two light exchanges after the writes completed. The conversation content was trivial — the system-reminders were eating the window.
Measured Impact
A Working Fix
TweakCC can patch the
system-reminder-file-modified-externallytemplate:We stripped the template to a one-liner (filename only, no content dump). Result: system-reminders still appear but contain only the file path, not the full
cat -noutput. Persistent across sessions, reversible withnpx tweakcc --restore.Additional Finding: Subagent Isolation
Subagent (Task tool) writes do not propagate file-change echoes to the parent context. If your workflow involves multi-file writes, delegating those writes to a subagent is an architectural mitigation — the parent never sees the echo.
Context
This was diagnosed while building a persistent memory system for Claude that performs structured file operations at session boundaries. The echo tax was the single largest hidden cost in our workflow — bigger than the actual conversation, bigger than the boot process, bigger than any feature we'd built. Fixing it recovered roughly 15-20% of usable context per turn.
Before the fix: session hit 90% context at message 7. After the fix: same workflow, same vault — 65% at message 14. The only variable was the echo patch.
The fact that this has been open since August 2025 with 16+ confirmations and no official fix is concerning. A diff-only mode (as suggested by @cicsolutions above) or a simple toggle would solve this for everyone.
Sir!, Thank you! my opus, got this! it works!!!
-> No, tweakcc was not able to newest version of cc.
-> done! we only pass modified filename's name ONLY!!! hahahah.
Thank you!!!!
you're very welcome! enjoy your 3x + token usage! the difference is staggering.
@MasterTilt I was on a similar thread for basically the same issue - it was closed as "not planned." So...
And it seems that your fix unfortunately only works for the CLI - the VS Code extension's settings are binary and can't be modified. They are separate from the Claude Code CLI.
@mmiller-d8 My opus
unpack→node(js) hack ! →repack for IDE extension)
Yeah, but you can do it in wsl2 plugin.
I use wsl2, so it can be done. I failed to win. same reason. binary.
https://github.com/ominiverdi/claude-depester
my opus has done !! BINARY unpack and hack!!!
OOOps~!!!
I observed this using graphite (stacked PRs) when switching to earlier in the stack to add a commit. My context jumped from ~260k tokens to ~400k tokens in a single call, it seems the entirety of all touched files (not just the actual diff) from my working tree to the branch I checked out got dumped into context.
I'm worried this is going to make it harder to drive claude code and stacked PR usage across my team. The only viable workaround (assuming I don't want to install an unknown patch to each developer's claude code instances) seems to be to compact immediately, which is very disruptive.
I have a few workarounds, but I have been using the npm installer and a cli.js patcher to modify not only that specific echo line but many other behaviors - its definitely worth the effort. You can just have claude analyze their own cli.js and create a patch for yourself. if you're using the npm installer anyway, it is deprecated though so there's no automatic updates which is fine for me.
@arathald @MasterTilt Recently, it patched. I don't use tweakcc anymore.
Root cause analysis (traced from the v2.1.88 source that was accidentally shipped with source maps):
The file change notification pipeline has no cleanup mechanism:
L2Yruns every turn, scanning all files CC has ever read in the session (readFileState). Any mtime change generates a diff viaTjK().f47wraps the diff in a<system-reminder>user message withisMeta: true— these are permanent and never pruned from the conversation.fGK), which doesn't fire until context already exceeds ~100K tokens. By then the damage is done.readFileStategrows monotonically — every file ever read in the session is tracked, expanding the scan surface each turn.Result: Each unique file modification creates a permanent message in the conversation history. Linters, formatters, auto-save, and the agent's own edits all trigger new notifications that accumulate indefinitely.
Verified still reproducing on 2.1.92. Session transcript data: 20K tokens on first assistant message in a clean session, growing to 692K over 923 messages in a file-heavy session.
Suggested fixes (ordered by impact):
f47)TjK()isMetafile change messages older than N turns inwA()Cross-ref: #16021, #27599, #43410 — all the same bug.
This may be of some interest https://github.com/cablate/claude-code-research/blob/master/reports/agent-sdk-cache-invalidation/report-en.md
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.