CLAUDE.md and Settings
- 1 Installing Claude Code
- 2 Using the Claude Code TUI
- 3 CLAUDE.md and Settings
- 4 Skills, Agents, and MCP Servers
- 5 Hooks
- 6 Plugins and Marketplaces
- 7 Agent Teams
Introduction
Claude Code has two configuration mechanisms: CLAUDE.md files that give Claude persistent context about your project, and settings.json files that control permissions and behaviour. Together they let you tailor Claude to your codebase without repeating yourself every session.
If you haven’t set up Claude Code yet, start from Installing Claude Code. If you want a walkthrough of the TUI itself, see Using the Claude Code TUI.
The CLAUDE.md Hierarchy
CLAUDE.md files can exist at five different levels. Claude loads and merges them all, with more specific files adding to (not replacing) broader ones:
| Level | Path | Scope |
|---|---|---|
| Enterprise | /etc/claude-code/CLAUDE.md | Organisation-wide policies |
| User | ~/.claude/CLAUDE.md | Your personal defaults across all projects |
| Project | ./CLAUDE.md | Project root — the main one |
| Subdirectory | ./subdir/CLAUDE.md | Scoped context for a specific directory |
| Local | ./CLAUDE.local.md | Personal overrides, gitignored |
CLAUDE.local.md for personal preferences that shouldn’t be committed — things like “I prefer verbose explanations” or “always use bun instead of npm.” Add it to your .gitignore.What to Put in CLAUDE.md
A good CLAUDE.md gives Claude the same context a new team member would need on their first day. Here’s the kind of information that works well:
- Project overview — What the project is, what tech stack it uses
- Build and run commands — How to build, test, lint, and run the project
- Key paths — Where the important files and directories are
- Conventions — Coding style, naming conventions, patterns to follow
- Rules — Things Claude should always or never do
Here’s an example:
CLAUDE.md
# CLAUDE.md
## Project Overview
A REST API built with Go and Chi router, backed by PostgreSQL.
## Commands
- `make run` — Start the dev server
- `make test` — Run all tests
- `make lint` — Run golangci-lint
## Key Paths
- `cmd/api/` — Entry point and server setup
- `internal/handlers/` — HTTP handlers
- `internal/store/` — Database layer (sqlc generated)
- `migrations/` — SQL migration files
## Conventions
- Use structured logging via slog
- Errors wrap with fmt.Errorf("context: %w", err)
- All handlers return (response, error) — the middleware handles error responses
- Tests use testcontainers for database integration tests
## Rules
- Never modify generated files in internal/store/db/
- Always run make lint before suggesting a commitYou may also see references to AGENTS.md — this is an emerging cross-tool convention that serves the same purpose as CLAUDE.md but is recognised by multiple AI coding tools. Claude Code only reads CLAUDE.md natively, but you can pull in an AGENTS.md by adding @AGENTS.md to your CLAUDE.md or by symlinking it with ln -s AGENTS.md CLAUDE.md.
Nesting CLAUDE.md Files
For larger projects, you can place CLAUDE.md files in subdirectories to provide scoped context. Claude only loads a subdirectory’s CLAUDE.md when it’s working with files in that directory.
Consider a project structure like this:
my-project/
CLAUDE.md # Project-wide context
src/
api/
CLAUDE.md # API-specific conventions
handlers/
middleware/
frontend/
CLAUDE.md # Frontend-specific conventions
components/
pages/
migrations/
CLAUDE.md # Migration-specific rulesThe root CLAUDE.md covers the whole project. The subdirectory files add specifics:
src/api/CLAUDE.md
# API Conventions
- All handlers follow the func(w, r) signature pattern
- Use chi.URLParam(r, "id") for path parameters
- Validate request bodies with the validator package
- Return JSON errors with the errorResponse helpersrc/frontend/CLAUDE.md
# Frontend Conventions
- Components use PascalCase filenames
- State management through Zustand stores in stores/
- All API calls go through the client in lib/api.ts
- Use the cn() utility for conditional classnamesWhen Claude is editing a file in src/api/handlers/, it sees the root CLAUDE.md and the src/api/CLAUDE.md. When it’s working on the frontend, it picks up the frontend-specific context instead. This keeps each CLAUDE.md focused and avoids bloating the context with irrelevant information.
Anti-Patterns
A few things to avoid:
- Don’t paste your entire README — CLAUDE.md should be curated context, not a documentation dump. Claude doesn’t need your project’s marketing copy or contribution guidelines.
- Don’t duplicate other config — Don’t restate things Claude can read from
package.json,tsconfig.json, or other config files. Just tell it where to look. - Don’t make it huge — If your CLAUDE.md is over 200 lines, it’s eating into the context window that Claude needs for actual work. Split it into subdirectory files or trim it down.
- Don’t include volatile information — Don’t put things that change frequently (current sprint goals, ticket numbers). CLAUDE.md should be relatively stable.
Writing Effective Rules
Rules in CLAUDE.md work best when they have clear boundaries. I use these levels:
- IMPORTANT — Things you want Claude to always keep in mind and consider. “IMPORTANT: This project uses a monorepo — changes in shared/ affect all services.”
- ALWAYS — Things Claude must do every time, no exceptions. “ALWAYS run
make lintbefore suggesting a commit.” - ASK — Things Claude should check with you before doing. “ASK before modifying any migration files.”
- NEVER — Hard lines Claude must not cross. “NEVER modify generated files in
internal/store/db/.”
Being explicit with these keywords helps Claude understand the weight of each instruction. A vague “try not to modify generated files” is much weaker than “NEVER modify generated files.”
CLAUDE.md
## Rules
- ALWAYS run tests before suggesting changes are complete
- ALWAYS use structured logging via slog, never fmt.Println
- ASK before adding new dependencies
- ASK before modifying the CI pipeline
- NEVER modify generated files in internal/store/db/
- NEVER commit directly to mainsettings.json rather than CLAUDE.md rules. A settings-level deny is enforced by the permission system and cannot be bypassed. A CLAUDE.md rule is just an instruction — Claude follows it most of the time, but it’s not a hard guarantee.Importing Files with @
You can reference files directly in your CLAUDE.md using the @ import syntax:
CLAUDE.md
# Project Overview
A REST API built with Go and Chi router.
## Architecture
For a detailed overview of the system architecture, see @docs/architecture.md
## API Conventions
See @docs/api-conventions.md for request/response patterns and error handling.When Claude reads the CLAUDE.md it will pull in the contents of the referenced files. This is powerful because it means your CLAUDE.md stays short and readable while still giving Claude access to detailed documentation when it needs it.
You can use this to reference any file in your project — markdown docs, config files, even source files that contain important patterns you want Claude to follow.
Progressive Disclosure
Progressive disclosure is the idea that Claude shouldn’t load everything into context at once, but instead only load what it needs for the current task.
The key insight is that your CLAUDE.md should be an index, not an encyclopedia. Instead of including all of your documentation inline, describe what each document covers and where to find it. Claude is smart enough to go read the relevant files when it’s working on a task that needs that context.
Here’s what this looks like in practice:
CLAUDE.md
# Project Overview
A microservices platform with three services: auth, billing, and notifications.
## Documentation
Topic-specific documentation is in the docs/ directory:
- docs/architecture.md — System architecture, service boundaries, data flow
- docs/database.md — Schema conventions, migration process, query patterns
- docs/testing.md — Test strategy, fixtures, integration test setup
- docs/deployment.md — CI/CD pipeline, environment config, rollback process
- docs/api-design.md — Endpoint naming, versioning, error response format
Read the relevant doc before making changes in that area.Claude sees this on every session — it’s only a few lines in the context window. But when it needs to work on the database layer, it knows to read docs/database.md first. When it’s working on deployment config, it pulls in docs/deployment.md. The information is available on demand without eating into the context budget permanently.
This approach scales well. You can have extensive documentation for a large project without any of it impacting Claude’s context window until it’s actually needed. The CLAUDE.md acts as a table of contents, and Claude reads the chapters it needs.
Settings Files
While CLAUDE.md handles context, settings.json handles permissions and behaviour. There are four levels:
| Level | Path | Committed? |
|---|---|---|
| Enterprise | /etc/claude-code/settings.json | N/A (system) |
| User | ~/.claude/settings.json | No |
| Project | .claude/settings.json | Yes |
| Local | .claude/settings.local.json | No (gitignored) |
Here’s what a typical project settings file looks like:
.claude/settings.json
{
"permissions": {
"allow": [
"Bash(git status)",
"Bash(git diff:*)",
"Bash(git log:*)",
"Bash(just *)",
"Bash(go test:*)",
"Bash(go build:*)",
"Read(*)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push *)",
"Bash(git reset --hard*)"
]
}
}The project settings file (.claude/settings.json) should be committed to your repo so the whole team shares the same permission baseline. Use .claude/settings.local.json for personal overrides.
Permission Rules in Detail
The allow and deny arrays accept patterns for specific tools:
Bash(pattern)— Match shell commands.Bash(git status)matches exactly,Bash(git diff:*)matchesgit diffwith any arguments.Read(pattern)— Control file read access.Read(*)allows reading everything.Write(pattern)— Control file write access.Write(src/*)allows writes only withinsrc/.- Glob patterns — Use
*for wildcards.Bash(just *)matches anyjustcommand.
allow and a deny rule, the deny takes precedence. This is by design — deny rules are your safety net. Put destructive commands in deny and you can be more generous with allow patterns.Some practical examples:
{
"permissions": {
"allow": [
"Bash(npm test:*)",
"Bash(npm run lint:*)",
"Bash(docker compose *)",
"Write(src/*)",
"Write(tests/*)"
],
"deny": [
"Bash(npm publish*)",
"Bash(docker compose down*)",
"Write(*.env*)",
"Write(.claude/settings.json)"
]
}
}This setup lets Claude run tests, lint, and manage Docker containers, but blocks it from publishing packages, tearing down containers, touching env files, or modifying its own permission settings.
Enterprise Configuration
For organisations, the /etc/claude-code/ directory provides system-level configuration that applies to all users on the machine:
/etc/claude-code/CLAUDE.md— Organisation-wide instructions (coding standards, security policies)/etc/claude-code/settings.json— Organisation-wide permission rules
Enterprise settings cascade the same way — they combine with user and project settings, with deny rules always taking precedence regardless of level. This means a security team can set organisation-wide deny rules (like blocking access to production credentials or preventing certain destructive commands) that individual users and projects cannot override.
Typical enterprise use cases include enforcing code review policies, restricting access to sensitive directories, mandating specific linting or testing commands before any commit suggestions, and ensuring compliance with internal security standards.
Practical Setup Walkthrough
Setting up Claude Code configuration for a new project takes about two minutes:
1. Create your CLAUDE.md at the project root with your project overview, commands, key paths, and conventions.
2. Create the settings directory and file:
3. Add a .claude/settings.json with your permission rules — start permissive with reads and common commands, add deny rules for anything destructive.
4. Add local files to .gitignore:
.gitignore
CLAUDE.local.md
.claude/settings.local.json5. Commit .claude/settings.json and CLAUDE.md so your team shares the same baseline.
Real-World Example
Here’s the CLAUDE.md from this blog — it’s a Hugo static site with a custom cyberpunk theme. This gives you an idea of what a real, working CLAUDE.md looks like in practice:
CLAUDE.md
# CLAUDE.md
## Project Overview
This is a Hugo static site blog with a custom cyberpunk theme.
The Hugo project lives in `src/wildev/` (not the repo root).
## Commands
just dev # Start dev server with drafts and live reload
just build # Production build with minification
just clean # Remove public/ and resources/
just new-post TITLE # Create new post
## Key Paths
- src/wildev/hugo.toml — Hugo config
- src/wildev/assets/css/main.css — Complete theme CSS
- src/wildev/assets/js/main.js — Interactive JS
- src/wildev/layouts/shortcodes/ — Custom shortcodes
- src/wildev/content/ — All markdown content
## Architecture Notes
- No external Hugo theme — everything is custom
- CSS uses custom properties sourced from hugo.toml params
- All assets are minified and fingerprinted through Hugo PipesNotice how it’s focused on what Claude needs to know to work effectively in the codebase — not a comprehensive README, just the practical essentials.
Wrapping Up
Start simple: a short CLAUDE.md with your project overview and build commands, a basic settings.json with sensible permission rules. Iterate from there as you notice patterns — if you keep telling Claude the same thing, put it in CLAUDE.md. If you keep approving the same command, add it to your allow list.
The next guide in this series covers the extensibility layer — skills, agents, and MCP servers.