How to Use Your .claude Directory in Claude Code
A maintained guide to CLAUDE.md, settings, skills, rules, subagents, hooks, and local overrides, with a project tree that stays legible.
Last verified July 17, 2026 against the official Claude Code directory guide, configuration reference, and extension guide. The URL stays because this began as Devlog #2. The page is now maintained documentation.
Most projects need only a root CLAUDE.md and .claude/settings.json. Add rules or skills after a repeated need appears. Add a subagent when isolated context or narrower permissions matter. Configure hooks inside settings.json. Keep machine-specific overrides out of git.
I learned that by building more than sixty specialist agents before realizing the setup was spending attention on its own configuration. This is the version I wish I had started with.
A clean project tree
repo/
├── CLAUDE.md
├── CLAUDE.local.md # private project instructions; gitignored
├── .mcp.json # project MCP servers live at the repo root
└── .claude/
├── settings.json # shared permissions, env, hooks, plugins
├── settings.local.json # private machine overrides; gitignored
├── rules/
│ └── testing.md # narrower instructions, optionally path-scoped
├── skills/
│ └── release/
│ ├── SKILL.md # the required entrypoint
│ ├── references/
│ └── scripts/
├── agents/
│ └── security-reviewer.md # custom isolated reviewer, if you need one
└── hooks/
└── check-protected.sh # optional script referenced by settings.json
The hooks/ folder above is only a place to keep scripts. Claude Code does not read a standalone project hooks file. Hook configuration belongs under the hooks key in settings.json.
The official guide also supports .claude/CLAUDE.md. I prefer CLAUDE.md at the repository root because people see the contract before they inspect tool-specific folders.
What belongs where
| Need | Put it here | Why |
|---|---|---|
| Rules needed on almost every task | CLAUDE.md | Loads as persistent project context |
| Instructions for one part of a monorepo | nested CLAUDE.md or .claude/rules/*.md | Keeps local rules near their scope |
| Permissions, environment, hooks, or shared plugins | .claude/settings.json | Project configuration, committed for the team |
| Private machine or project override | .claude/settings.local.json or CLAUDE.local.md | Local-only and kept out of version control |
| Reusable procedure or reference | .claude/skills/<name>/SKILL.md | Full instructions load when the skill is used |
| Work needing isolated context or custom tools | .claude/agents/<name>.md | Runs a separate agent loop |
| External service or tool connection | .mcp.json at the repo root | Project MCP configuration does not live inside .claude/ |
| Automatic action at a lifecycle event | hooks in settings.json | Runs code, a prompt, an agent, HTTP, or an MCP tool on a defined event |
Legacy files under .claude/commands/ still work. Claude Code now treats custom commands and skills as the same command surface, and Anthropic recommends skills because they can carry supporting files and load automatically when relevant.
1. Start with CLAUDE.md
CLAUDE.md is for the few facts and rules that deserve to follow every task:
- how to build and test the repository;
- the source-of-truth documents that must be read;
- safety constraints and protected paths;
- the tracker and delivery policy;
- a short map to deeper references.
Keep procedures out. A release checklist, incident runbook, or migration method belongs in a skill that loads when invoked.
Claude Code's current guidance is to keep CLAUDE.md under 200 lines. I use a stricter test: if a rule does not change behavior on most tasks, move it behind a link or a skill.
One more loading detail matters. Files from the working directory and its parents load at startup. A CLAUDE.md deeper in the tree loads when Claude reads files in that area. Do not assume every nested instruction was present from the first prompt.
2. Put policy in settings.json
Use .claude/settings.json for shared project configuration:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": ["Bash(npm run test *)", "Bash(npm run lint)"],
"deny": ["Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)"]
}
}
The schema gives editors autocomplete. The deny rules provide an explicit boundary around sensitive files. Review allowed shell commands carefully; a convenient wildcard can grant more authority than its label suggests.
Use .claude/settings.local.json for a path, tool, or permission that works only on your machine. Local settings override project settings. Project settings override user settings. Managed policy stays above both.
3. Add skills for repeated work
A skill is a directory with SKILL.md as its entrypoint:
.claude/skills/database-migration/
├── SKILL.md
├── references/
│ └── rollback-policy.md
└── scripts/
└── verify-migration.sh
The name and description are visible so Claude can decide when the skill applies. The full body loads only when the skill is invoked or selected. You can also run it directly with /database-migration.
Create a skill when you keep pasting the same procedure, checklist, or reference into chat. Keep one-off task instructions in the issue. Keep universal rules in CLAUDE.md.
Good project skills have a concrete trigger and a receipt:
- release this package, then verify the published artifact;
- investigate a failed CI job, then report the failing check and source line;
- migrate this database, then prove the rollback path;
- review this change against the repository's security boundary.
"Be a database expert" is a persona. "Verify this migration and its rollback" is a job.
4. Use subagents for isolation
Custom subagents live under .claude/agents/. They get their own context, prompt, and tool policy. That makes them useful for an independent review, a narrow research task, or work that should not inherit the main session's clutter.
Do not create a custom agent merely because a topic has a name. Start with the built-in agent, a focused prompt, and the exact evidence it needs. Add a file only when the prompt and permissions are worth maintaining across tasks.
My original setup had specialist agents for every discipline. Most became skills, references, or ordinary review prompts. The agents that survived had a real isolation requirement.
5. Use hooks for deterministic edges
Hooks fire on defined lifecycle events. They are good for work that should happen because an event occurred, not because the model remembered a paragraph.
Examples:
- block edits to a protected file before the tool runs;
- format a changed file after an edit;
- run a fast check after a tool batch;
- record configuration changes;
- load environment state when the working directory changes.
Configure them in settings.json, then inspect the resolved setup with /hooks. Hook matchers are case-sensitive. A Bash matcher works; bash does not.
Hooks are executable policy. Keep scripts small, fail loudly, quote inputs, and make the exit behavior obvious. If a hook needs a long natural-language judgment, consider whether it belongs in a skill or a deliberate validation step instead.
How the pieces cost context
The important distinction is when content loads.
| Extension | When it loads | What enters context |
|---|---|---|
CLAUDE.md | Session start, plus nested discovery | Full instructions |
| Skill | Description at startup; full body when used | Small listing, then the selected procedure |
| Subagent | When spawned | Fresh isolated context with its assigned prompt and skills |
| Hook | On its event | Nothing by default unless the hook returns context |
| MCP server | Session start, then tool use | Tool names first; schemas when needed |
This is why a small CLAUDE.md plus on-demand skills works better than a giant universal manual. The goal is not a magic utilization percentage. The goal is to keep always-on context reserved for rules that truly apply everywhere.
A setup that can grow
If I were starting a new repository today, I would ship this in order:
- A root
CLAUDE.mdwith build, test, safety, tracker, and source-of-truth pointers. .claude/settings.jsonwith explicit read and shell boundaries.- One skill for the workflow the team repeats most often.
- A local settings file for machine-specific differences.
- No custom subagents until one task needs isolated context or permissions.
- No hooks until a missed deterministic edge repeats.
Then I would inspect the setup from the runtime:
/config show resolved settings
/skills show discovered skills and invocation policy
/hooks show hook source, event, matcher, and handler
/mcp show project MCP status and approvals
When something appears ignored, check scope and precedence before rewriting the file. The official configuration debugger covers the common traps, including misplaced MCP servers, lowercase hook matchers, and skills missing their SKILL.md directory.
The cleanup rule
Configuration should earn its maintenance cost.
Delete a rule when the repository itself makes it obvious. Fold duplicate procedures into one skill. Remove an agent when a normal fresh review produces the same result. Keep historical experiments in git history instead of loading them into every future session.
My first cleanup took the setup from a zoo of specialists to a smaller operating loop. The exact files have changed since January. The direction held: persistent rules stay small, procedures load on demand, and judgment gets isolated when independence matters.
Want the maintained loop?
The workflow that grew from this cleanup is AgentOps: portable skills plus a Go CLI for one bounded Plan, Implement, and fresh Validate cycle.
For Claude Code, install the managed plugin bundle:
claude plugin marketplace add boshu2/agentops
claude plugin install agentops@agentops-marketplace
Or read 12-Factor AgentOps for the vendor-neutral operating principles.