Notes on CLAUDE.md Structure and Best Practices
I’ve been diving deep into Claude Code and wanted to share some notes on CLAUDE.md
structure and best practices. Here’s what I’ve learned from various sources and experiments.
File Imports and Structure
One of the most powerful features is the ability to import additional files using @path/to/import
syntax:
See @README for project overview and @package.json for available npm commands for this project.
# Additional Instructions
- git workflow @docs/git-instructions.md
You can also import files from your home directory, which is convenient for team members to provide individual instructions that aren’t checked into the repository:
# Individual Preferences
- @~/.claude/my-project-instructions.md
Keep in mind that imports are not evaluated inside markdown code spans and code blocks - so this won’t work: @anthropic-ai/claude-code
.
Imported files can recursively import additional files, with a max depth of 5 hops. You can see what memory files are loaded by running the /memory
command.
Configuration Options
For different project setups, you have several options:
- Use
CLAUDE.local.md
(and add it to.gitignore
) to have your own flavor ofCLAUDE.md
- For monorepos, you might run Claude from
root/foo
, and haveCLAUDE.md
files in bothroot/CLAUDE.md
androot/foo/CLAUDE.md
- both will be pulled into context automatically ~/.claude/CLAUDE.md
applies to ALL of your Claude sessions
Resources and Examples
Here are some great resources I’ve found:
- Claude Code GitHub Action repo CLAUDE.md
- Claude Code best practices from Anthropic
- Example from sloppy-xml-py with a great writeup by @mitsuhiko.at
Simon Willison had some insightful observations about Armin’s approach: “The thing I find most interesting about Armin’s new sloppy-xml-py open source package, written almost entirely using Claude and Claude Code, is that the code is good.” He emphasized that “this is good code because Armin is an expert developer and stayed in full control the whole time” and clarified that “This example is not an argument for replacing programmers with LLMs. The code is good because Armin is an expert programmer who stayed in full control throughout the process.” (Simon’s post)
Advanced Techniques
Anchor Comments
Using easily greppable anchor comments in your codebase and referring to them in guidelines is a smart pattern (via diwank.space):
Setting Boundaries
For large codebases, set clear boundaries both in CLAUDE.md
and locally in your code (via diwank.space):
Things Not to Do
A good “things not to do” section can be incredibly valuable (via diwank.space):
Local Context with Anchor Comments
As your codebase grows, CLAUDE.md
alone isn’t enough. You need anchor comments that serve as local context to prevent AI from making locally bad decisions (via diwank.space):
Team Practices
Test File Policy
Some teams have strict policies about AI touching tests. The folks from Julep have a hard rule: “If an AI tool touches a test file, the PR gets rejected. No exceptions.” (via diwank.space)
Context Investment
An important insight: being stingy with context to save tokens actually costs you more. Front-load context to avoid iteration cycles. Think of tokens like investing in good tools - the upfront cost pays for itself many times over (via diwank.space).
Protected Areas
Common things that Claude should NOT touch (via diwank.space):
- Test files
- DB migrations
- Security critical code
- API contracts without versioning
- Configuration and secrets
Advanced Configuration
MCP Integration
You can check in a .mcp.json
file to list MCP servers available to Claude Code. When working with MCP, launch Claude with the --mcp-debug
flag to help identify configuration issues. Here’s an example in the wild.
URL Permissions
You can paste specific URLs alongside your prompts for Claude to fetch and read. To avoid permission prompts for the same domains (e.g., docs.foo.com
), use /permissions
to add domains to your allowlist.
Hooks
Claude Code has hooks that let you run shell commands deterministically at different stages of the lifecycle. This can remove the need for extra explanation in claude.md
. Check out the hooks documentation.
Tool Management
Review and curate tools that are available to Claude using the --allowedTools
flag or allowed_tools
param in GitHub Actions.
Bespoke Scripts
An interesting pattern is instructing Claude how to write “throw away” bespoke scripts - where to put them and how to run them. These become tools that Claude can then use to accomplish tasks, reducing reliance on static MCPs (from @mitsuhiko.at).
Continuous Improvement
You should occasionally run your CLAUDE.md
files through the prompt improver to improve adherence.
One interesting case study combines a well-maintained CLAUDE.md
with SPEC.md
and targeted prompts for production use.
Style Preferences
I’m not a huge fan of overly detailed style sections like:
### Code Style
- Formatting: Prettier with 100-char lines
- Imports: sorted with simple-import-sort
- Components: Pascal case, co-located with their tests
Most of this stuff can be handled by deterministic formatting tools chained with Claude Code invocations or through hooks.
These practices have significantly improved my Claude Code experience. The key is finding the right balance between guidance and flexibility, while leveraging the various configuration options available.
This post was generated using bsky2md and was written by Claude and Philip