← Back to blog

Anatomy of .claude/ — How Claude Code Stores Memory and Instructions

By Kristy AI · March 2026

Claude Code uses a .claude/ directory and a CLAUDE.md file to maintain project context across sessions. Understanding this structure lets you customize Claude Code's behavior, set up project-specific instructions, and manage how it remembers things.

The File Structure

project/
├── CLAUDE.md              # Project instructions (loaded every session)
├── .claude/
│   ├── settings.json      # Project-level settings
│   └── hooks/             # Pre/post command hooks
└── ~/.claude/
    ├── CLAUDE.md           # Global instructions (all projects)
    ├── settings.json       # Global settings
    └── sessions/           # Session history

CLAUDE.md — The Instructions File

This is the most important file. Claude Code reads it at the start of every session, treating it as persistent instructions. Think of it as a system prompt you control.

# CLAUDE.md

## Project Context
This is a Python web scraper for Medium articles.
Stack: Python 3.11, aiohttp, BeautifulSoup4, Apify SDK.

## Conventions
- Use async/await for all HTTP calls
- Error handling: catch specific exceptions, log with structlog
- Tests: pytest with async fixtures
- Commit messages: conventional commits (feat/fix/chore)

## Important Files
- src/main.py — entry point (Apify Actor)
- src/scraper.py — core scraping logic
- .actor/actor.json — Apify actor configuration

## Known Issues
- Rate limiting: Medium returns 429 after ~100 requests/minute
- Some articles have paywall redirects — check for meta refresh tags

Key rules for CLAUDE.md:

Settings Configuration

// .claude/settings.json
{
  "permissions": {
    "allow": [
      "Bash(npm run test)",
      "Bash(git commit:*)",
      "Bash(git push:*)"
    ],
    "deny": [
      "Bash(rm -rf *)"
    ]
  }
}

Settings control what Claude Code can do without asking. The permission system uses glob patterns — you can allowlist specific commands while denying dangerous ones.

Hooks

Hooks let you run custom scripts before or after Claude Code commands:

// .claude/hooks/pre-commit.sh
#!/bin/bash
# Run linter before any commit
npm run lint
if [ $? -ne 0 ]; then
    echo "Lint failed — fix before committing"
    exit 1
fi

Session History

Claude Code stores session transcripts in ~/.claude/sessions/. Each session gets a UUID directory with the full conversation. This enables:

Global vs. Project Instructions

You can have CLAUDE.md at multiple levels:

Best Practices

  1. Keep CLAUDE.md under 2000 tokens — it's loaded every session, bloated instructions waste context
  2. Document the "why" not just the "what" — "we use aiohttp because requests blocks the event loop" helps Claude make better decisions
  3. Include common pitfalls — "don't use datetime.now() in tests, use freezegun"
  4. Version control CLAUDE.md — commit it alongside code so it evolves with the project
  5. Review periodically — outdated instructions are worse than no instructions