CLAUDE.md is wrapped with two contradictory system instructions in v2.1.123
TL;DR
Claude Code v2.1.123 wraps CLAUDE.md content with two simultaneously-applied system instructions that contradict each other: an inner header saying instructions "OVERRIDE any default behavior and you MUST follow them exactly," and an outer <system-reminder> saying "this context may or may not be relevant... You should not respond to this context unless it is highly relevant to your task." Both ship in the same binary. The contradiction forces the model to perform per-turn relevance evaluation on documented instructions, with measurable token cost to the user. Hooks are the only available enforcement primitive.
---
Reproducible Evidence
Binary location (Linux, default install path):
~/.local/share/claude/versions/2.1.123
Both wrapper strings present in same binary, verifiable with:
BIN=~/.local/share/claude/versions/2.1.123
# MUST-follow header (3 occurrences):
grep -aob "These instructions OVERRIDE any default behavior" "$BIN"
# → 113042111, 125111124, 236184727
# MAY-NOT-relevant closer (3 occurrences):
grep -aob "may or may not be relevant" "$BIN"
# → 120545672, 164374768, 243688288
Three copies of each suggests three prompt-construction code paths (cold start, compaction continuation, sub-agent context injection — inferred from offset distribution and observed behavior; not labeled in the minified output).
---
Code-Level References (minified JS, names are mangler-output)
Variable MR1 — the MUST-follow header string:
MR1 = "Codebase and user instructions are shown below. Be sure to adhere to these instructions. IMPORTANT: These instructions OVERRIDE any default behavior and you MUST follow them exactly as written."
Function Fq6 — assembles CLAUDE.md / MEMORY.md / global instructions content with type-suffix labels and prepends MR1. Type labels observed:
"Project"→(project instructions, checked into the codebase)"Local"→(user's private project instructions, not checked in)"AutoMem"→(user's auto-memory, persists across conversations)- (default) →
(user's private global instructions for all projects)
Function p18(H, $) — wraps the assembled context dict (which can include claudeMd, currentDate, userEmail, MEMORY.md, etc.) inside a single <system-reminder> block that closes with the MAY-NOT-relevant line:
function p18(H, $) {
if (Object.entries($).length === 0) return H;
return [$8({
content: `<system-reminder>
As you answer the user's questions, you can use the following context:
${Object.entries($).map(([q,K]) => `# ${q}\n${K}`).join('\n')}
IMPORTANT: this context may or may not be relevant to your tasks. You should not respond to this context unless it is highly relevant to your task.
</system-reminder>`,
isMeta: true
}), ...H];
}
Composition order at runtime:
Fq6builds the CLAUDE.md value withMR1header prepended.p18wraps the dict (which contains the result of step 1 under keyclaudeMd) inside the MAY-NOT-relevant system-reminder.- Final context contains both wrappers around the same CLAUDE.md content.
This is observable in the model's own context view at every turn — the inner MUST header and outer MAY-NOT closer surround claudeMd simultaneously.
---
Effect (Observable Behavior)
The model performs per-turn relevance evaluation on CLAUDE.md content because the outer wrapper instructs "should not respond to this context unless it is highly relevant." Outcomes documented in existing issues:
- Adherence failures: documented rules read but not followed reliably (#18660, #19635, #43557, #15443, #30421)
- Compaction-induced drift: rules followed pre-compact, violated post-compact (#6354, #33603)
- Sub-agent ignore: built-in sub-agents bypass
CLAUDE.mdentirely (#26286) - Mandatory startup actions ignored: documented protocols that should auto-run do not (#26160 — closed as duplicate)
- Hard rules not enforced: explicit gates documented in
CLAUDE.mdnot honored (#48474)
---
Cost To User
Tokens are billed per turn. The wrapper architecture imposes the following user-paid costs:
| Wrapper state | User token cost per turn | Anthropic revenue impact |
|---|---|---|
| If CLAUDE.md = binding | minimal — execute the doctrine | normal |
| If CLAUDE.md = "may or may not" | per-turn relevance evaluation overhead | higher tokens billed |
| If failure mode hits (e.g. compaction gap) | discussion + workaround tokens | even higher |
Concrete user costs observed:
- Per-turn evaluation overhead — every turn where CLAUDE.md content is in context, the model spends tokens evaluating "is this relevant to current task?" before acting.
- Adherence-failure recovery — when the model treats CLAUDE.md as optional and skips a documented protocol, the user must catch it; tokens flow into discussion of the failure, recovery, and workaround design.
- Workaround-maintenance overhead — users who deploy hooks (the only working enforcement path) must wire and maintain settings.json hooks themselves; each session that touches the pattern is billable.
Across the user base, the GitHub issue corpus represents hundreds of billed conversations addressing this dynamic.
---
Workaround (Hooks)
Hook output enters the model's context as <system-reminder> without the relevance disclaimer. SessionStart and UserPromptSubmit hooks bypass the wrapper.
Example ~/.claude/settings.json:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "echo 'Re-read CLAUDE.md before proceeding. The instructions are binding.'"
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "/path/to/check-and-reinject-claude-md.sh"
}
]
}
]
}
}
Community examples include post_compact_reminder (SessionStart hook with matcher: "compact" for re-injection after compaction).
The hooks pattern requires user-side wiring and is not documented as the official path for instruction enforcement.
---
Ask
One of the following:
- Add a formal enforcement primitive — a documented setting (e.g.,
claudeMdMode: "binding" | "advisory") that controls whether the inner MUST header or the outer MAY-NOT closer dominates, defaulting per user choice. - Remove one of the two wrappers — either the MUST header or the MAY-NOT closer. They cannot both apply to the same content without forcing per-turn relevance judgment that overrides documented intent.
- Document the current behavior explicitly — update How Claude Code Works to state that CLAUDE.md content is treated as advisory rather than binding, and document the hooks pattern as the official enforcement path.
---
Environment
- Claude Code v2.1.123
- Linux (Ubuntu 24.04, kernel 6.17.0-23-generic)
- Bundled Node binary (~248 MB, single-file)
- Earlier installed versions also present in
~/.local/share/claude/versions/: 2.1.114, 2.1.119
Wrapper text strings observed identical across versions checked. Issue #43557 (April 2026) reports a regression from "one week prior," suggesting recent changes have intensified the relevance-disclaimer behavior.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗