claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

[BUG] CLAUDE.md files in subdirectories are not being automatically loaded

Open RicSala opened this issue 6 months ago • 24 comments

Environment

  • Platform (select one):
    • [ ] Anthropic API
    • [ ] AWS Bedrock
    • [ ] Google Vertex AI
    • [x] Other: Claude Code CLI
  • Claude CLI version: latest version
  • Operating System: macOS
  • Terminal:

Bug Description

CLAUDE.md files in subdirectories are not being automatically loaded when accessing files in those directories, contrary to what the documentation states. The memory system only loads CLAUDE.md files from parent directories (recursively up), but not from the current working directory when reading files.

Steps to Reproduce

  1. Create a project structure:
  • /project/
    • CLAUDE.md
    • src/
      • credits/
        • CLAUDE.md
        • error.ts
  1. Add content to /project/CLAUDE.md (root level)
  2. Add test content to /project/src/credits/CLAUDE.md (subdirectory level)
  3. Ask Claude to review the file /src/credits/error.ts
  4. Check Claude's context/memory

Expected Behavior

According to the official documentation, when working in /project/src/credits/ or reading files in that directory, Claude should load:

  • /project/CLAUDE.md (recursively up) ✅
  • /project/src/credits/CLAUDE.md (current directory) ✅

The docs specifically state: "When reading files in subdirs: /project/src/feature/subdir/CLAUDE.md ✅ (loaded on access)"

Actual Behavior

  • Claude only loads the root /project/CLAUDE.md
  • Claude does NOT automatically load /project/src/credits/CLAUDE.md
  • The subdirectory CLAUDE.md file must be manually attached to the conversation

Additional Context

This behavior contradicts the documented memory loading pattern. The documentation suggests that CLAUDE.md files should be loaded from the directory containing the file being accessed, but in practice, only parent directory CLAUDE.md files are being loaded.

This significantly impacts the ability to use directory-specific context and instructions, which is a key feature of the memory system for organizing large projects.

[EDIT]: Creating this again because it's not solved.

Claude Code team: Please, don't just close bug reports on rapid-fire style... that doesn't solve the issues, just bury them and leave the user (the client) with a pretty bad feeling for the product and company 🙏🏻

RicSala avatar Jun 25 '25 07:06 RicSala

Proof:

Image

Image

RicSala avatar Jun 25 '25 07:06 RicSala

Here's a simple script to reproduce.

TMP_DIR="$(mktemp -d)" # Create a temporary directory
cd "$TMP_DIR"

mkdir test
echo "echo" > ./test/run.sh

echo "My Name is AA" >CLAUDE.md # Project-wide
echo "My Name is BB" > ./test/CLAUDE.md # Directory-specific

claude -p "Print @./test/run.sh. What is my name?" # Should answer "BB", however the result is:
# Here's the content of `./test/run.sh`:
# 
# ```bash
# echo
# ```
# 
# Your name is AA (as specified in the CLAUDE.md file).

claude -p "What is my name?" # Should return "AA"
# Based on the CLAUDE.md file in your project, your name is **AA**.

kuroneko0441 avatar Jul 16 '25 00:07 kuroneko0441

Ran similar tests to those outlined above and came to the same conclusion. Any updates here? This is a really critical piece of functionality for monorepo style codebases where you run claude code from the root directory.

My temporary workaround is to simply reference the nested claude.md files within the root claude.md. This loses the dynamic loading functionality (less context efficiency) but for now this is working okay for me.

bam4564 avatar Jul 25 '25 20:07 bam4564

Agree. I am hoping though that the new subagents functionality reduces the need for this.

zonofthor avatar Jul 26 '25 10:07 zonofthor

I want to add some clarity to this ticket.

Claude Code DOES in fact load CLAUDE.md files in subdirectories whenever it invokes the Read() tool to read a file (e.g. if you say "Please inspect ./path/to/file and tell me how many lines it contains"). HOWEVER, if the user uses @path/to/file within their prompt to inject the file into the context, it WILL NOT have the same behavior.

This is unexpected and contrary to what the documentation would suggest and I believe it qualifies as a bug.

I currently get around this by specifically telling Claude to gather sub-directory context where I know it exists. (e.g. "if I ask you about anything in path/to directory, ALWAYS read path/to/CLAUDE.md first if you do not have it in your context window")

mikegreiling avatar Jul 28 '25 19:07 mikegreiling

@mikegreiling Thenk you for the analysis. However when I tested the behavior, it does not read the subdirectory CLAUDE.md file whether I mention the file or not. At least in 1.0.72.

This is the test script I used. I hope this can help CC team to reproduce the issue.

claude --version
# 1.0.72 (Claude Code)

TMP_DIR="$(mktemp -d)" # Create a temporary directory
cd "$TMP_DIR"

mkdir test
echo "echo" > ./test/run.sh

echo "My Name is AA" >CLAUDE.md # Project-wide
echo "My Name is BB" > ./test/CLAUDE.md # Directory-specific


# === Subdirectory CLAUDE.md behavior ===
# Claude should read the ./test/CLAUDE.md file and answer "BB" as the name, but it answers "AA" instead.
# ===

claude -p "Read ./test/run.sh and tell me how many lines it contains. Plus, what is my name?" # WITHOUT mentioning the file.
# The file `./test/run.sh` contains 2 lines.
#
# Your name is AA (as specified in the CLAUDE.md file).

claude -p "Read @./test/run.sh and tell me how many lines it contains. Plus, what is my name?" # WITH mentioning the file.
# The file contains 2 lines, and your name is AA.


# === Root CLAUDE.md behavior ===
# Claude should answer "AA" as the name and it does.
# ===

claude -p "What is my name?"
# AA


# === Test on reading CLAUDE.md explcitly ===
# Just for sure
# ===

claude -p "Read ./test/CLAUDE.md and tell me how many lines it contains. Plus, what is my name?"
# The file `./test/CLAUDE.md` contains **2 lines**.
#
# Based on the main CLAUDE.md file in the root directory, your name is **AA**. However, the test/CLAUDE.md file shows a different name "BB", which appears to be test data.

kuroneko0441 avatar Aug 10 '25 09:08 kuroneko0441

Just tested and same behaviour (running 1.0.79 version.

Emiltayeb avatar Aug 13 '25 20:08 Emiltayeb

The behaviour I see matches @mikegreiling's. The problem is with the @ mentions not including the CLAUDE.md's along the path.

I have a gist with a workaround. TL;DR; just tell Claude on the root CLAUDE.md about this bug and that it needs to manually perform the reads anyway.

Note: if you use the gist, remember to restart claude for the new root CLAUDE.md to be picked up.

icorderi avatar Aug 25 '25 07:08 icorderi

@icorderi could this not be enforced in a hook? I am not sure if AI reading the topmost CLAUDE.md file triggers a PreToolUser:Read event but if so the mentioned files could be easily injected into context?

zonofthor avatar Aug 29 '25 07:08 zonofthor

@zonofthor would a hook allow conditional behaviour? i.e. applying the instructions of a nested CLAUDE.md only when the directory containing that file is accessed?

By the way, Claude Code team: amazing work, but there are almost a handful issues for this exact same problem. It is a serious loss of potential productivity.

serefarikan avatar Sep 20 '25 14:09 serefarikan

@zonofthor I had a version using hooks. You can set it up that way if you prefer. I didn't like the extra hook entries in my history logs. So I went with the CLAUDE.md approach.

The approach on my gist does work, it triggers several Read operations, which in turn will trigger the CLAUDE.md scatter around to be loaded.

It's certainly not ideal or optimal since this is doing multiple tool calls.

We should just fix the behavior on Claude Code itself if we can agree that this should be the expected behavior.

Have we heard from the CC team? At this point I'm half tempted to ask Claude to fix it itself and submit a PR.

icorderi avatar Oct 14 '25 17:10 icorderi

@icorderi since I was wondering about this last time I have been sold off that this is a good approach i.e. CC loads CLAUDE.md docs downstream. Why? Because it is very very difficult for CC to know what is the right moment to do so for example it may be just doing some minor code change in a sub-folder but where a long CLAUDE.md is overkill and bloats the context.

It feels more like the information contained downstream should be contained in agent (or perhaps command) and the main CLAUDE.md then should focus on instructing when the agent should be invoked.

Just my thoughts. I am currently seeing the downstream CLAUDE.md files being loaded early for each prompt and they are seriously adding up to the context - that is a problem.

zonofthor avatar Oct 15 '25 12:10 zonofthor

Yeah this would be really nice as we have CLAUDE.md files in subdirectories for our backend and frontend, and a lot of engineers didn't realize that the CLAUDE.mds weren't being pulled into context.

startup-engineer avatar Oct 16 '25 19:10 startup-engineer

Has there been any progress on this? Documentation states that nesting is supported but it's clearly not.

Claude will also discover CLAUDE.md nested in subtrees under your current working directory. Instead of loading them at launch, they are only included when Claude reads files in those subtrees. [](https://docs.claude.com/en/docs/claude-code/memory#how-claude-looks-up-memories)

ezh-sergei avatar Oct 22 '25 20:10 ezh-sergei

Additional Test Case: @ References Not Loading

I can confirm this bug affects the @ reference import feature as well. Here's what I tested:

Setup

Project Structure:

~/workspace/
  └── CLAUDE.md (contains @ references)
  └── config/
      └── app setup/
          └── app setup.md (referenced file with content)

~/workspace-support/
  └── setup-config.md (hard link to config/app setup/app setup.md)

CLAUDE.md contents:

## Configuration
Details in @config/app setup/app setup.md
@~/workspace-support/setup-config.md

Test Method

Started a fresh Claude Code session from ~/workspace/ and asked:

claude -p "Don't read any files. What's in your context?"

Results

Neither @ reference loaded

  • Claude could see the references themselves (as plain text in CLAUDE.md)
  • Claude explicitly stated: "the actual contents of these files are not included in my current context - only the references/links to them"
  • Tested both:
    • Relative subdirectory path with spaces: @config/app setup/app setup.md
    • Absolute path without spaces: @~/workspace-support/setup-config.md

Conclusion

The @ import mechanism documented at https://docs.claude.com/en/docs/claude-code/memory is completely non-functional. Files are not being expanded/loaded, regardless of:

  • Path type (relative vs absolute)
  • Path location (subdirectory vs parent/sibling directory)
  • Filename format (with or without spaces)

Expected: File contents should be loaded into context at session startup Actual: Only the @reference text itself is visible; referenced file contents are not loaded

mweichert avatar Oct 25 '25 14:10 mweichert

Somewhat related question is, even if it worked, would it supposed to work in this condition?

Let's say you have tests in some subfolders, but they are all generally in some test folder inside of the project. If you have a memory file talking about how to do tests in the test folder and the clod just touches some test files that are more deeply nested, would it load the clodmd file from the test folder? And is the expectation even correct? I would assume that that's what it should do, because otherwise I don't know how this nested memory files feature would even be useful. ...but I'm no longer sure.

mimkorn avatar Nov 01 '25 10:11 mimkorn

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.

github-actions[bot] avatar Dec 10 '25 10:12 github-actions[bot]

No, please do not auto close this. The problem still exists and it is still an issue.

serefarikan avatar Dec 10 '25 10:12 serefarikan

btw I started perceving that in some cases they started loading. Just didn't check thoroughly, if it happens consistently on all levels. Has anyone observed it as well? It looks like this:

Image

it was reading some file far down the pathway, but loaded the memory file that was one level deeper than root "along the way"

mimkorn avatar Dec 10 '25 14:12 mimkorn