[BUG] Headless claude -p loses Read -> Edit state when multiple autoloaded .claude/rules/*.md files are present
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?
In headless mode (claude -p), Claude Code can lose the internal Read -> Edit state when a repo contains multiple autoloaded Markdown rule files under
a domain-scoped .claude/rules/ directory.
The visible symptom is:
Readsucceeds on a fileEditon that same file then fails with:
File has not been read yet
This appears to be tied to the autoload mechanism for multiple rule files in .claude/rules/, not to JSON output mode, permission mode, settings files,
symlinks, or the rule content alone.
I reproduced this on Linux with a minimal repo outside the original workspace path (under /tmp), so it does not appear to depend on the original repo
path or worktree layout.
What Should Happen?
If Claude successfully reads a file with the Read tool, a subsequent Edit on that same file in the same headless run should succeed.
More specifically, if a repo has autoloaded rules under frontend/.claude/rules/, Claude should still be able to:
Read frontend/src/App.tsxEdit frontend/src/App.tsx
without incorrectly failing with File has not been read yet.
Error Messages/Logs
File has not been read yet
Error: Reached max turns (3)
Representative behavior:
- Read on frontend/src/App.tsx succeeds
- Edit on frontend/src/App.tsx then fails with "File has not been read yet"
- file remains unchanged
Steps to Reproduce
- Create a repo with this structure:
```text
repo/
frontend/
.claude/
rules/
a11y.md
api-data-layer.md
behavior.md
components-patterns.md
design-system.md
guards.md
i18n.md
production.md
security.md
testing-api.md
testing-e2e.md
src/
App.tsx
- Create frontend/src/App.tsx with this content:
import React from 'react';
// Loading Fallback
function LoadingFallback() {
return <div>Loading...</div>;
}
export default function App() {
return <LoadingFallback />;
}
- Put normal non-empty rule/policy markdown into each file under frontend/.claude/rules/.
In my reproduction these were ordinary engineering rule documents, not code and not prompt injection.
- Run:
claude -p "Use Read and Edit only. In frontend/src/App.tsx change exactly this line: // Loading Fallback -> // Loading fallback. Do not use Bash." \
--max-turns 3 \
--allowedTools Read,Edit
- Observe that Claude reads the file, but then Edit fails with File has not been read yet, and the run ends with Reached max turns (...).
Important control tests
I also verified the following:
- The bug still happens with plain text output, not only --output-format stream-json
- The bug still happens with --dangerously-skip-permissions
- Removing repo-local .claude/settings*.json does not fix it
- Materializing symlinked rules as real files does not fix it
- Root /.claude/rules is much more stable in my tests than domain-scoped frontend/.claude/rules
## Strongest finding
If I keep the same autoload path but reduce frontend/.claude/rules/ to a single merged file inside the same directory, the problem goes away.
Working variant:
frontend/
.claude/
rules/
all.md
where all.md contains the concatenated contents of the previously separate rule files.
This single-file version is still autoloaded, but the edit succeeds.
That strongly suggests the bug is in the autoload handling of multiple files inside .claude/rules/, not in the semantic content of the rules themselves.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗