The Problem: Claude “Remembers” Nothing Between Sessions
I started using Claude Code for a Python project about three months ago. Every time I opened a terminal, I’d have to explain everything from scratch: “this project uses FastAPI, the database is PostgreSQL, naming follows snake_case, don’t create separate test files…” It was genuinely exhausting.
After struggling for a few weeks, I realized I had been completely ignoring the .claude/ directory — the thing designed specifically to solve this problem.
Classic symptoms of not configuring .claude/ properly:
- Having to remind Claude of the same code style rules every day
- Claude suggesting libraries the project already has
- Every team member using Claude differently, leading to inconsistent output
- Claude not knowing how to run tests or build the project
The Root Cause: Claude Code Works on Context, With No Built-in “Long-Term Memory”
Claude Code doesn’t automatically remember previous conversations. Every session starts with a blank slate. Unlike a new engineer joining a team — who can read the README, ask colleagues, and gradually learn the project — Claude needs a structured briefing at the start of every session.
When launched inside a directory, Claude Code automatically reads configuration files in priority order: CLAUDE.md in the home directory → CLAUDE.md in the project root → files inside .claude/. All of that “long-term memory” — from code rules to frequently used shortcuts — lives right there.
The .claude/ Structure: From Simple to Complex
Level 1: Personal Projects (Solo)
For a one-person project, a single CLAUDE.md file at the root is enough. Claude reads this file first, automatically, without any prompting.
# Minimal structure
my-project/
├── CLAUDE.md ← Main file, Claude reads automatically
├── src/
└── ...
Sample CLAUDE.md content for a small project:
# Project Context
## Stack
- Python 3.11, FastAPI, SQLAlchemy 2.0
- PostgreSQL (local: localhost:5432/mydb)
- Alembic for migrations
## Conventions
- Variables/functions: snake_case
- Classes: PascalCase
- No `print()` — use the `logging` module
- All API endpoints must have complete type hints
## Common Commands
- Run dev server: `uvicorn app.main:app --reload`
- Run tests: `pytest tests/ -v`
- Create migration: `alembic revision --autogenerate -m "description"`
Concise but sufficient to keep Claude from suggesting the wrong stack or generating code outside the project’s conventions.
Level 2: Mid-Size Projects (Adding Settings and Commands)
More complex projects benefit from a settings.json to control Claude’s behavior, and a commands/ directory to store custom slash commands.
# Level 2 structure
my-project/
├── CLAUDE.md
├── .claude/
│ ├── settings.json ← Permissions and hooks configuration
│ └── commands/
│ ├── review.md ← /project:review
│ └── deploy.md ← /project:deploy
The .claude/settings.json file lets you restrict what Claude is allowed to execute:
{
"permissions": {
"allow": [
"Bash(git:*)",
"Bash(pytest:*)",
"Bash(uvicorn:*)"
],
"deny": [
"Bash(rm -rf:*)",
"Bash(sudo:*)"
]
}
}
Custom command in .claude/commands/review.md:
---
description: Review code changes before committing
---
Please review the changes in `git diff HEAD` against these criteria:
1. Are there any naming convention violations?
2. Where is error handling missing?
3. Are there any N+1 queries?
4. Are type hints complete?
Only report real issues — don't suggest unnecessary refactors.
Invoke it with /project:review in Claude Code — no need to retype the entire prompt every time. For more advanced reusable workflows, you can also create custom skills that go beyond simple slash commands.
Level 3: Team Projects (Multiple Environments, Multiple Contributors)
This is the level I see most teams skip, which leads to inconsistent Claude output across developers.
# Team-scale structure
my-project/
├── CLAUDE.md ← Shared context for the whole team (commit to git)
├── .claude/
│ ├── settings.json ← Shared permissions (commit to git)
│ ├── settings.local.json ← Personal overrides (add to .gitignore)
│ └── commands/
│ ├── review.md
│ ├── test.md
│ ├── migration.md
│ └── deploy-staging.md
The key distinction: settings.json is committed to git so the whole team shares it. settings.local.json lets each person override settings for their own machine — personal API keys, local paths — without affecting anyone else.
# Add to .gitignore
.claude/settings.local.json
.claude/memory/ # If using auto memory
The team CLAUDE.md should include a clear onboarding section:
# Project: E-commerce Platform
## Architecture Overview
- Backend: FastAPI (port 8000)
- Frontend: Next.js (port 3000)
- Database: PostgreSQL + Redis
- Message queue: RabbitMQ
## IMPORTANT Rules
- Do NOT modify the database schema directly — always create a migration
- Do NOT hardcode credentials — use environment variables
- Every new endpoint must have an integration test
- PRs must pass CI before merging
## Environments
- Dev: `docker-compose up -d`
- Test: `pytest tests/ --cov=app --cov-report=term`
- Staging deploy: `/project:deploy-staging`
## Contacts
- DB schema questions: ask @dbteam on Slack
- Infrastructure: see docs/infrastructure.md
Best Practice: Build .claude/ Incrementally
Setting up the full structure on day one isn’t a good idea — it wastes time and you won’t know what you actually need yet. A better approach is to follow this order:
- Week 1: Create
CLAUDE.mdwith your stack and the 3–5 most important rules. That’s it. - After 2–3 weeks: Notice what you keep repeating to Claude → add it to
CLAUDE.md. - When patterns emerge: Create custom commands instead of typing the same prompts by hand.
- When teammates join: Split out
settings.local.jsonand add an onboarding section toCLAUDE.md.
A tip I use regularly: at the end of each sprint, spend 10 minutes reviewing what Claude got wrong or needed repeated reminders about, then update CLAUDE.md right away. Treat this file as a living document like your README — when it goes stale, Claude’s output goes stale with it. If you’re working on automating IT workflows with AI agents, keeping this context file sharp becomes even more critical.
Verifying That .claude/ Is Working
# Check whether Claude is reading CLAUDE.md
# Ask directly in Claude Code:
"What stack does this project use? What's the command to run tests?"
# If Claude answers correctly → CLAUDE.md is being read
# If Claude doesn't know → check the file location and encoding (must be UTF-8)
Common Mistakes
- CLAUDE.md is too long: Claude can handle a 500+ line file, but the context gets diluted — important information sinks to the bottom. Prioritize putting critical rules at the top.
- Using vague language: “Write clean code” does nothing. Replace it with “Maximum 50 lines per function, each function does exactly one thing.”
- Forgetting .gitignore:
settings.local.jsoncontains personal information — committing it exposes that data. - Not version-controlling CLAUDE.md: This file evolves with the project. Track its history like any other piece of code.
Real-World Results
After setting up .claude/ properly, the time spent briefing Claude dropped from 5–10 minutes per session to nearly zero. Output became noticeably more consistent — fewer corrections for convention violations, and Claude stopped suggesting things that made no sense for the project’s context.
The .claude/ directory is small — sometimes just a single markdown file with a few dozen lines. But that file is what determines whether Claude Code is a genuinely useful tool or just a chatbot that needs constant babysitting.

