[OPUS4.7] Read tool returns different content for ~/.claude/settings.json across calls within the same session — effective-view rendering or bug?

Resolved 💬 1 comment Opened Apr 30, 2026 by champagne-papa Closed May 31, 2026

Preflight Checklist

  • [x] I have searched existing issues for similar behavior reports
  • [x] This report does NOT contain sensitive information (API keys, passwords, etc.)

Type of Behavior Issue

Claude modified files I didn't ask it to modify

What You Asked Claude to Do

I observed the following behavior in Claude Code v2.1.123 (Opus 4.7, 1M context, WSL on Windows):
Within a single Claude Code session, two Read tool calls against the same path (~/.claude/settings.json = /home/philc/.claude/settings.json) returned materially different content with no on-disk changes between them.

First Read (session-start, pre-flight verification): returned 131 lines including a permissions block with curated allow, ask, and deny arrays, defaultMode: "acceptEdits", and disableBypassPermissionsMode: "disable". The deny array contained Bash(curl:*) at line 109.
Subsequent Read (mid-session, root-cause investigation): returned 24 lines containing only enabledPlugins and statusLine. No permissions block at all.

Verified from a fresh WSL terminal (not from inside Claude Code):

On-disk file is 892 bytes, 24 lines, mtime Apr 29 18:42 — matches the second Read.
Pre-session backup (settings.json.bak.20260429T163945Z, mtime Apr 29 09:41) is also 892 bytes — disk has been the 24-line skeleton continuously since before the session opened.
CLAUDE_CONFIG_DIR is unset on both WSL and Windows sides.
Windows-side %USERPROFILE%\.claude\settings.json is a separate 23-line / 743-byte file with mtime 2026-04-10 (different content, different machine, three weeks stale; not the source of either Read).

Behavior consistent with the 24-line skeleton being the actual substrate: a curl https://example.com invocation prompted with the generic "This command requires approval" wording rather than refusing with "Permission to use Bash with command curl https://example.com/ has been denied" wording — i.e., defaultMode fallthrough rather than deny-rule firing.
Trying to determine which of the following is happening:

Claude Code renders an effective-config view at session-start (raw user config merged with built-in defaults) and the Read tool returned that view; subsequent Reads return raw on-disk bytes. If so, is there a documented way to inspect the effective view from inside a running session (e.g., a slash command, CLI flag, or canonical Read path)?
The Read tool returned cached or otherwise incorrect content at session-start. Tool-level bug.
Something else.

The answer affects how I draft permission-related briefs going forward — specifically, whether file-content audits of ~/.claude/settings.json can be trusted as a basis for permission-state reasoning, or whether substrate verification needs to drive through runtime behavior probes instead.
Happy to provide additional context (session ID, full transcripts of both Reads, the project-layer config that was active during the second Read) if useful.

What Claude Actually Did

Here's the "Actual behavior" field text:

Actual behavior:
Two Read tool calls against ~/.claude/settings.json within the same session returned materially different content despite no on-disk changes between them.
The first Read (early in the session) returned 131 lines including a full permissions block with curated allow, ask, and deny arrays (Bash(curl:*) was in the deny array at line 109), defaultMode: "acceptEdits", and disableBypassPermissionsMode: "disable".
A subsequent Read (later in the same session) of the same path returned only 24 lines containing enabledPlugins and statusLine — no permissions block at all.
Verified from a fresh WSL terminal outside Claude Code that the on-disk file is 892 bytes / 24 lines / mtime Apr 29 18:42, matching the second Read. The pre-session backup is also 892 bytes, confirming the file has been the 24-line skeleton continuously since before the session opened. The first Read returned content that does not correspond to the on-disk file at any point in the session window.
Runtime permission behavior matches the 24-line on-disk content rather than the 131-line first-Read content: a curl https://example.com attempt prompted with the generic "This command requires approval" wording rather than refusing with deny-rule wording, indicating the curated deny array seen in the first Read is not actually active at runtime.

Expected Behavior

Two Read tool calls against the same file path within a single session, with no on-disk changes between them, should return identical content. Either both should return the raw on-disk bytes (24 lines, the actual file content), or both should return an effective-config view if Claude Code renders one — but the behavior should be consistent across calls within a session.
If effective-config rendering is an intentional feature (raw user config merged with Claude Code's built-in defaults), this should be documented, and there should be a documented way to inspect the effective view from inside a running session.

Files Affected

Permission Mode

Accept Edits was ON (auto-accepting changes)

Can You Reproduce This?

Yes, every time with the same prompt

Steps to Reproduce

_No response_

Claude Model

Sonnet

Relevant Conversation

Impact

Critical - Data loss or corrupted project

Claude Code Version

Opus 4.7

Platform

Anthropic API

Additional Context

_No response_

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗