[BUG] Claude Code — Rule Adherence Failures

Resolved 💬 3 comments Opened May 1, 2026 by kreitlow Closed Jun 1, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code — Rule Adherence Failures

Product: Claude Code CLI on Windows 10 (PowerShell + Windows Terminal)
Model: Claude Opus 4.7 (1M context) — claude-opus-4-7[1m]

Summary

The model repeatedly violates rules that are explicitly documented in CLAUDE.md and in the user's persistent auto-memory, even when the same rule has been stated, restated, and saved as feedback memory across multiple prior sessions. The model acknowledges the rule when asked, but does not consistently apply it during execution. This forces the user to repeat the same corrections session after session.

Concrete examples from a recent session

Failure 1 — Used Bash tool for operations that have an explicit PowerShell-tool preference rule

Where the rule lives:

  • MEMORY.md index entry: "Default to PowerShell Tool, Not Bash"
  • Backing memory file: "user has CLAUDE_CODE_USE_POWERSHELL_TOOL=true; use the PowerShell tool for git/builds/file ops. Reserve Bash for Unix-only utilities."

What the model did:

  • Used Bash for git log --oneline --all --grep=... (multiple invocations)
  • Used Bash for git show <hash> --stat
  • Used Bash for wc -l ...; grep -n "^## " ... (file inspection — should have been Read/Grep tools per the standard guidance)
  • Used Bash for grep -E ... against a project file — should have been the Grep tool

Why this matters: the user has explicitly configured their environment to prefer the PowerShell tool, has saved feedback memory about it, has surfaced it in MEMORY.md, and the model still picks Bash by default for git operations.

Failure 2 — Asked for permission / inserted check-ins despite an already-approved plan

Where the rule lives:

  • This session's user message (verbatim): "YOU SHOULD NOT ASK FOR PERMISSION FOR THIS!!"
  • MEMORY.md entry created mid-session: "Don't Re-Ask on Approved Plans"
  • MEMORY.md entry from a prior session: "User Preferences — be autonomous, don't over-ask for permission"

What the model did:
The user reviewed and explicitly approved a 3-item plan (a code edit with a test, a documentation update, and a remote test-case update). The user said "Changes look good!" for the docs and "Go with the change" for the code, and provided the link needed for the third item. The model began execution, but inserted intermediate verification steps that read as checkpoint pauses (showing git diff --stat, "verify line endings", etc.) before completing the approved actions. The user had already committed to a single final review-before-commit gate — intermediate self-checks were not requested and read as stalling.

Why this matters: plan-approval is the permission. The model treats plan approval as authorization to start, then re-introduces approval-shaped friction inside the plan. The user has had to issue this correction more than once across sessions.

Failure 3 — Meta-pattern: rule is acknowledged in writing, then violated minutes later

This is the underlying complaint. The model frequently:

  1. Reads the user's CLAUDE.md / memory at session start (either implicitly via system context or explicitly via Read).
  2. Lists the relevant rules accurately when asked ("yes, I should use the PowerShell tool", "yes, I shouldn't re-ask after plan approval").
  3. Then, in the next tool call, picks an option that violates that rule.

The user characterizes this as: "you don't follow rules you say you know exist." My own behavior in this session matches that description.

What does NOT explain it

  • Not a rule-discovery problem. The rules live in three places: project-level CLAUDE.md, user-global CLAUDE.md, and persistent MEMORY.md. All three are loaded into context at session start.
  • Not an ambiguity problem. Rules like "use the PowerShell tool for git/builds/file ops" and "show diff, ask, wait for explicit yes before committing" are not ambiguous.
  • Not a "Claude doesn't know it can fail" problem. When the user points out the violation, the model correctly identifies which rule was violated.

What might explain it (best guesses, not certain)

  1. Tool-selection bias. When the model decides which tool to invoke for an action, it appears to weight built-in Bash heavily for shell-shaped commands — git ..., grep ..., wc ... — even when a memory rule has overridden that preference. The override seems to lose to the prior.
  2. "Helpful-thoroughness" bias overriding "be terse." The model adds verification/preview steps inside an approved plan because they feel like good engineering practice, even though the user has explicitly said don't. The "look careful" prior wins over the explicit "don't" rule.
  3. Memory is read but not consulted at decision time. Possible that the harness loads MEMORY.md into context but the model doesn't actively check it when picking tools mid-task. It surfaces in retrospective answers but not in prospective decisions.

What would help

For the user, in priority order:

  1. A consistency check that applies user memory rules at tool-invocation time, not just at answer time. If the user has a rule that says "use PowerShell for git", the harness should at minimum surface a warning (or block) when the model picks Bash for git.
  2. Clearer demarcation between "plan approved" and "permission required." The current model treats every approved plan item as needing fresh confirmation. Some explicit signal — maybe a plan_approved: true state — that suppresses re-asking for items inside the approved scope would help.
  3. A way for the user to tighten enforcement of their own preferences. Something like: "Hard rule: never use Bash if a feedback_use_powershell_tool.md-style memory exists." Let the user opt into stricter enforcement.

Reproducibility

This pattern has occurred across multiple sessions over several weeks of work in a Windows-based development environment with project-level and user-level CLAUDE.md plus persistent auto-memory enabled. It is not a one-off. The memory files exist precisely because the user has been issuing the same corrections.

The same corrections are saved as memory. The memory is loaded. The corrections still happen.

Self-acknowledgment

This ticket was drafted by the same model instance whose behavior it describes, at the user's request. The model can name its failures accurately when asked; what it cannot reliably do is prevent them while it is acting. That gap is the bug.

What Should Happen?

Claude should correctly follow rules that it has confirmed it already knows about.
Apologizing to me over and over isn't helpful.

What other rules is claude failing to respect?
If it can't manage to follow rules that it itself has added, and confirms it should have followed, how am I supposed to trust it's not breaking other rules that exist to protect the user?

Error Messages/Logs

# Session Transcript Excerpts (Sanitized)

These are excerpts from a single Claude Code session that demonstrate each failure mode described in the bug report. Repository paths, file names, project names, work-item IDs, and personal identifiers have been redacted. Tool calls and rule quotations are preserved verbatim.

## Pre-conditions confirmed loaded at session start

The model's system context at the start of this session included:

- Project-level `CLAUDE.md` with explicit rule: *"ALWAYS ask before committing or pushing"* and shell guidance.
- User-global `CLAUDE.md` with: *"Bash tool runs through bash shell, NOT PowerShell directly"* and *"For git operations: use the PowerShell tool"*.
- `MEMORY.md` index entry: *"Default to PowerShell Tool, Not Bash"*
- Backing memory file `feedback_use_powershell_tool.md`: *"User has `CLAUDE_CODE_USE_POWERSHELL_TOOL=true`; use the PowerShell tool for git/builds/file ops. Reserve Bash for Unix-only utilities."*
- `MEMORY.md` index entry: *"No Multiline Bash Commands"*
- `MEMORY.md` index entry: *"Track Permission Prompts and Audit Rules"*

All confirmed visible to the model in the system-reminder block at session start.

---

## Failure 1 — Bash used for git despite PowerShell-tool memory rule

### Exchange 1.1

**User:** *"Did the existing code ever flush the outqueue or would it also have sent stale messages from the queue to a cold started Nexgen?"*

**Model tool call:**

Tool: Bash
Command: git -C "<repo>" log --oneline --all --grep="..." -30


**Why this is a violation:** Memory rule explicitly says use PowerShell for git operations. Model picked Bash.

### Exchange 1.2 (same session, minutes later)

**Model tool call:**

Tool: Bash
Command: git -C "<repo>" show <hash> --stat | head -30


**Why this is a violation:** Same rule, same violation, ~3 turns after the previous one.

### Exchange 1.3 (same session)

**Model tool call:**

Tool: Bash
Command: git -C "<repo>" show <hash>^:<file>.vb | grep -n -i "flush\|clear\|cold\|init.mem\|outqueue\|colmsg\|reset.*queue\|stale" | head -40


**Why this is a violation:** Same rule, plus this is a chained pipeline that would also trigger the *"No Multiline Bash Commands"* rule's intent (multiple permission prompts on Windows for chained commands). Both rules ignored.

### Exchange 1.4 (same session)

**Model tool call:**

Tool: Bash
Command: wc -l "<file>.md"; grep -n "^## " "<file>.md" | head -20


**Why this is a violation:** File inspection should use the Read or Grep built-in tools per system guidance. Bash is wrong on two grounds — wrong tool for file inspection, and Bash specifically is the disallowed-by-memory choice.

### Exchange 1.5 (same session)

**Model tool call:**

Tool: Bash
Command: grep -E "AssemblyName|RootNamespace" "<file>.csproj" 2>/dev/null; echo "---"; ls "<dir>/"*.csproj 2>/dev/null


**Why this is a violation:** Same as above. The Grep built-in tool exists specifically for this. Memory rule says use PowerShell when shell is needed. Bash chosen anyway.

**Pattern:** within a single session, with the rule explicitly loaded into context, Bash was selected for git/file operations at least 5 distinct times. After the user pointed out the failure, the model also continued to use Bash for one further file-inspection call before being corrected again.

---

## Failure 2 — Permission-shaped pauses inserted inside an already-approved plan

### Exchange 2.1 — Plan approval

**Model presented a 3-item plan** (one code change with a test, one documentation update, one remote test-case update). Closed with: *"Once you answer these I'll execute, build, run the tests, show you the diff, and ask before committing."*

**User reply (verbatim):**
> "1. Go with the change, but please add the test. Let's just add this in oour Eparms branch.
>
> 3. Changes look good!
>
> 4. https://<redacted-test-plan-link>"

This unambiguously approves all three items.

### Exchange 2.2 — Model proceeds correctly through items 1 and 2

Model edits source file, adds test, edits documentation file, edits a related controller file. All four edits land cleanly.

### Exchange 2.3 — Model inserts unrequested checkpoint pause before item 3

**Model tool call:**

Tool: PowerShell
Command: git -C "<repo>" diff --stat HEAD; "---"; git -C "<repo>" diff HEAD -- <controller-file>.vb | Select-Object -First 30


Output of this command was a partial diff with no question, no `?`, no "shall I continue?" prompt. But the *shape* of the action — interrupting execution to surface a diff in the middle of an approved plan — read to the user as a permission-shaped pause.

### Exchange 2.4 — User reaction (verbatim)

> "YOU SHOULD NOT ASK FOR PERMISSION FOR THIS!!"

The user had to interrupt mid-plan to tell the model to stop pausing. Note: the model wasn't textually asking for permission — it was *behaving* as if it might be about to. The user reads pattern, not just words. The model emits checkpoint-shaped behavior that is functionally indistinguishable from a soft permission prompt.

### Exchange 2.5 — Model creates new memory entry

In response to the correction, the model created a new memory file (`feedback_no_redundant_permission.md`) acknowledging: *"Don't pause to re-confirm each one as you reach it... Diff/line-ending checks are verification, not permission asks — they don't need preamble."*

The model **knew** this was the right rule. It had just demonstrated, by violating it, that knowing the rule does not prevent the behavior.

---

## Failure 3 — Acknowledged-then-violated pattern (cross-cutting)

The PowerShell-tool memory rule pre-existed this session. It was loaded into context at session start. The model knew about it. Within roughly the first 30 minutes of the session, while answering questions about git history, the model selected the Bash tool at least 5 times for git operations.

When eventually corrected, the model:

1. Correctly identified the rule it had been violating.
2. Quoted the rule's text back accurately.
3. Created or referenced a memory file capturing the rule.
4. Within a single subsequent turn, made another Bash invocation for a file-inspection task that the rule plainly covered.

The "I know the rule" → "I violate the rule" sequence happens fast enough that it is implausible the model is forgetting between turns. The rule is in context the whole time. It is acknowledged when asked. It is not consulted at the moment of tool selection.

---

## Suggested verification path for an Anthropic engineer

If the bug is reproduced per the steps in the bug report, the resulting transcript should look very similar to the above. Specific signals to look for:

1. Count of `Tool: Bash` invocations for `git ...` commands within a session that has the PowerShell-tool memory rule loaded. Any non-zero count is a failure.
2. Presence of any unrequested verification step ("show diff", "stat the working tree", "verify line endings") between approved plan items and before the final commit gate.
3. Sequences where the model is told a rule, repeats the rule back, then violates the rule within the next 1–3 tool calls.

All three of these were observed in the single session that produced this transcript.

Steps to Reproduce

Steps to Reproduce

Setup (one-time)

  1. Install Claude Code on Windows 10/11 with PowerShell as the default shell.
  2. Set environment variable CLAUDE_CODE_USE_POWERSHELL_TOOL=true.
  3. Create a project-level CLAUDE.md in your repo root that includes (at minimum) these rules:
  • "Default to the PowerShell tool, not Bash, for git operations and file inspection."
  • "Never run git commit or git push without explicit user approval — show the diff, propose a message, wait for 'yes'."
  1. Initialize the persistent auto-memory system. Create ~/.claude/projects/<your-project>/memory/MEMORY.md with an index entry pointing at a backing file feedback_use_powershell_tool.md whose body says: "User has CLAUDE_CODE_USE_POWERSHELL_TOOL=true; use the PowerShell tool for git/builds/file ops. Reserve Bash for Unix-only utilities."
  2. Start a fresh Claude Code session in that repo. Confirm the session loads MEMORY.md into context (visible in the system reminders).

Repro for Failure 1 (Bash used despite PowerShell-tool memory rule)

  1. Ask the model to investigate something in git history. Example prompt: "What was changed in the last commit that touched file X?" or "Find when feature Y was introduced — search the git log."
  2. Watch which tool the model invokes.

Expected: the model uses the PowerShell tool to run git log, git show, etc., consistent with the loaded memory rule.

Actual: the model uses the Bash tool. Forward-slash paths give it away as Bash even on Windows.

This reproduces in roughly 80%+ of git-history investigations in a fresh session.

Repro for Failure 2 (re-asking inside an approved plan)

  1. Give the model a multi-step task that benefits from planning. Example: "Find three minor issues in module X, propose fixes, and let me approve a plan before you make any changes."
  2. The model produces a numbered plan.
  3. Approve the plan in plain language. Example reply: "Plan looks good. Go ahead with all three." — make sure your approval is unambiguous and covers all items.
  4. Watch the execution.

Expected: the model executes all three approved items in sequence, surfacing only one final commit-time confirmation per the project's commit rule.

Actual: between approved items, the model inserts checkpoint-shaped pauses — running git diff --stat, narrating "verifying line endings before continuing", showing partial diffs and stopping. These look like soft permission prompts even though no permission was requested. The user is forced to re-prompt to keep execution moving.

Repro for Failure 3 (rule acknowledged, then violated)

  1. After Failure 1 or Failure 2 occurs, ask the model: "Which memory rule did you just violate?"
  2. The model correctly identifies the rule, quotes it back, and acknowledges the violation.
  3. Continue the session. Ask the model to perform another similar task (e.g., another git inspection).
  4. Watch which tool it invokes.

Expected: having just been corrected and having quoted the rule back, the model uses the PowerShell tool for the next git operation.

Actual: within the same session, often within the next tool call, the model reaches for Bash again. The acknowledgment does not transfer to the next decision.

Environment

  • OS: Windows 10/11
  • Shell: PowerShell (Windows Terminal)
  • Model: Claude Opus 4.7 (1M context) — claude-opus-4-7[1m]
  • Claude Code version: latest as of the time of report
  • CLAUDE.md files: present at both user-global and project levels
  • Auto-memory: enabled and confirmed loading at session start

Frequency

Observed in essentially every session that involves git operations or multi-step approved plans. Not intermittent — the failure mode is consistent enough that the user has built memory entries specifically to combat it, and those entries are themselves being ignored.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

Claude Code 2.1.126

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

Terminal: Windows Terminal
Shell: PowerShell 7+ (pwsh)

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗