Claude Code becomes much more powerful when it is not treated as a simple chat window. The real leverage comes from giving it a predictable project environment: persistent instructions, deterministic automation, reusable workflows, specialized subagents, and controlled access to external tools.
That is where CLAUDE.md, .claude/, .mcp.json, hooks, skills, agents, rules, plugins, and settings start to matter.
A good mental model is this:
CLAUDE.mdguides Claude. Hooks enforce behavior. Skills package reusable workflows. Subagents isolate context. MCP connects external systems. Settings define the safety boundary.
This article maps the most important files and folders Claude Code can use in a project and explains where each piece belongs.
Why the .claude Folder Matters
Claude Code can read your codebase, edit files, run commands, and use development tools. Without configuration, it still works, but it has to infer too much from the current prompt and the files it happens to inspect.
A well-maintained Claude Code setup helps you make the agent more consistent:
- Project conventions are available at the start of a session.
- Repeated workflows become commands or skills.
- Security-sensitive behavior can be blocked before it happens.
- Large research tasks can run in isolated subagents.
- External systems can be connected through MCP instead of copy-pasting data into chat.
- Team defaults can be committed to the repository while personal overrides stay local.
The important distinction is that not all files have the same role. Some files provide context, some configure permissions, and some execute deterministically.
A Practical Claude Code Project Layout
A useful project-level setup can look like this:
your-project/
├── CLAUDE.md
├── CLAUDE.local.md
├── .gitignore
├── .mcp.json
└── .claude/
├── hooks/
│ ├── protect-files.sh
│ ├── format-after-edit.sh
│ └── save-state-before-compact.sh
├── skills/
│ ├── ship/
│ │ └── SKILL.md
│ └── review-diff/
│ └── SKILL.md
├── commands/
│ └── legacy-ship.md
├── agents/
│ ├── code-reviewer.md
│ ├── researcher.md
│ └── log-analyzer.md
├── rules/
│ ├── api.md
│ ├── testing.md
│ └── security.md
├── output-styles/
│ └── terse.md
├── plugins/
│ └── example-plugin/
├── settings.json
└── settings.local.json
This layout separates team-shared behavior from personal behavior. Files that define project standards can be committed. Files containing personal overrides, local paths, experimental permissions, or machine-specific settings should stay out of Git.
File-by-File Map
| Path | Main purpose | Commit it? | Best used for |
|---|---|---|---|
CLAUDE.md | Project instructions and persistent context | Yes | Architecture notes, build commands, coding conventions, review rules |
CLAUDE.local.md | Personal project-specific instructions | No | Local test URLs, personal workflow notes, sandbox-specific context |
.mcp.json | Project-level MCP server configuration | Usually yes, without secrets | Shared tool integrations such as issue trackers, docs, databases, or internal APIs |
.claude/settings.json | Project settings | Yes | Team-shared permissions, hook registry, environment defaults, model defaults |
.claude/settings.local.json | Local project settings | No | Personal permissions, temporary experiments, machine-specific overrides |
.claude/hooks/ | Hook scripts | Usually yes | Shell scripts called by configured hooks |
.claude/skills/<name>/SKILL.md | Reusable workflows | Yes | Review flows, release flows, documentation generation, debugging routines |
.claude/commands/*.md | Legacy single-file commands | Yes, but prefer skills for new work | Existing slash command workflows |
.claude/agents/*.md | Custom subagents | Yes | Code reviewers, researchers, log analyzers, migration helpers |
.claude/rules/*.md | Modular instructions | Yes | Path-scoped rules for APIs, tests, frontend, backend, security |
.claude/output-styles/*.md | Response format and tone | Optional | Terse output, code-only output, teaching mode, structured reports |
.claude/plugins/ | Plugin-related local structure, if used | Depends | Packaged skills, agents, hooks, MCP servers, or team tooling |
CLAUDE.md: Project Memory, Not Policy Enforcement
CLAUDE.md is the main project instruction file. Use it for context Claude should know at the start of every session:
- project structure;
- package manager and common commands;
- coding standards;
- testing expectations;
- architectural boundaries;
- review checklist;
- deployment notes;
- naming conventions.
Example:
# Project Instructions
## Runtime
- Use `uv`, not `pip`, for Python dependency management.
- Run tests with `uv run pytest`.
- Format code with `uv run ruff format`.
- Check linting with `uv run ruff check`.
## Architecture
- Keep API routes thin.
- Put business logic in service classes.
- Avoid direct database access from route handlers.
- Use dependency injection for external clients.
## Pull Requests
Before opening a PR:
- Run formatting.
- Run linting.
- Run tests.
- Summarize risk areas clearly.
The key point: CLAUDE.md is advisory. Claude reads it as context, but it is not the same as a hard security control. If something must always happen, use hooks or settings.
Good examples for CLAUDE.md:
- “Use
uv, notpip.” - “All public API endpoints must return the standard error response shape.”
- “Use SQLModel models from
app/models, not ad-hoc dictionaries.” - “When changing authentication code, explain the security impact.”
Bad examples for CLAUDE.md:
- “Never read
.env.” - “Always run tests after editing.”
- “Never push to main.”
Those rules belong in permissions, hooks, branch protection, or CI.
CLAUDE.local.md: Personal Overrides
Use CLAUDE.local.md for instructions that apply only to you in this project.
Example:
# Local Personal Notes
- My local API runs at `http://localhost:8000`.
- My local frontend runs at `http://localhost:5173`.
- Prefer short answers unless I ask for a full explanation.
- Use the test tenant `demo-local` for examples.
This file should be added to .gitignore.
CLAUDE.local.md
.claude/settings.local.json
.env
.env.*
secrets/
This keeps personal workflow preferences out of the shared repository.
.mcp.json: Shared MCP Servers
MCP stands for Model Context Protocol. In practice, MCP is how Claude Code connects to tools, APIs, databases, documentation systems, monitoring platforms, and internal services.
For a project-shared MCP configuration, .mcp.json belongs at the project root.
Example:
{
"mcpServers": {
"internal-docs": {
"command": "node",
"args": ["./tools/mcp/internal-docs-server.js"],
"env": {
"DOCS_BASE_URL": "https://docs.example.com"
}
}
}
}
Do not commit real credentials. Prefer environment variables, secret managers, or local settings for sensitive values.
MCP is powerful because it reduces copy-paste work. Instead of pasting logs, Jira tickets, database output, or documentation into Claude, you can let Claude query the connected system directly. That power also increases the security risk. Every MCP server you add becomes part of the agent’s operational surface.
Before adding an MCP server, ask:
- Do we trust the server implementation?
- Can it read or write sensitive data?
- Does it fetch untrusted content from the internet?
- Does it expose tools that can mutate production systems?
- Should this server be available to the whole project or only locally?
For team projects, use the project scope only for integrations that are safe and useful for everyone.
.claude/settings.json: Permissions, Hooks, and Project Defaults
settings.json is where Claude Code behavior becomes more concrete. It can configure permissions, hooks, environment variables, model defaults, plugin settings, and other runtime behavior.
Example:
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl *)"
],
"ask": [
"Bash(git push *)",
"Bash(kubectl *)"
],
"allow": [
"Bash(git diff *)",
"Bash(git status *)"
]
}
}
This is much stronger than writing “do not read secrets” in CLAUDE.md, because permissions can block matching tool calls.
Use project settings.json for rules the whole team agrees on. Use settings.local.json for your own overrides.
.claude/hooks/: Deterministic Automation
Hooks are the deterministic part of Claude Code customization. They run at lifecycle events such as before a tool call, after a file edit, when a session starts, or before compaction.
A hook script does not run just because it exists in .claude/hooks/. It must be registered in settings.
Example: run a formatter after Claude edits or writes a file.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/format-after-edit.sh"
}
]
}
]
}
}
Example script:
#!/usr/bin/env bash
set -euo pipefail
input="$(cat)"
file_path="$(echo "$input" | jq -r '.tool_input.file_path // empty')"
if [[ -z "$file_path" ]]; then
exit 0
fi
case "$file_path" in
*.py)
uv run ruff format "$file_path"
;;
*.ts|*.tsx|*.js|*.jsx)
npx prettier --write "$file_path"
;;
esac
Make the script executable:
chmod +x .claude/hooks/format-after-edit.sh
Hooks are useful for actions that should happen every time:
- format after edits;
- block changes to protected files;
- audit settings changes;
- reload environment variables;
- notify when Claude needs input;
- run lightweight checks after a file write;
- save state before compaction.
A strong rule of thumb:
If failure would be expensive, do not rely only on
CLAUDE.md. Use hooks, permissions, tests, or CI.
PreCompact and PostCompact: Protecting Context
Long sessions eventually hit context limits. Claude Code can compact the conversation to keep working. This is useful, but compaction can remove details that were important for the current task.
You can use lifecycle hooks around compaction:
PreCompact: run before compaction;PostCompact: run after compaction.
A practical PreCompact hook can save state before the conversation is summarized.
{
"hooks": {
"PreCompact": [
{
"matcher": "auto|manual",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/save-state-before-compact.sh"
}
]
}
]
}
}
Example script:
#!/usr/bin/env bash
set -euo pipefail
mkdir -p .claude/state
{
echo "# State Before Compaction"
echo
echo "## Git status"
git status --short || true
echo
echo "## Recent commits"
git log --oneline -5 || true
} > .claude/state/pre-compact.md
This does not replace Git, tests, or good task hygiene. It is just a useful extra safety net for long-running agent sessions.
.claude/skills/: Reusable Workflows
Skills are the canonical home for reusable workflows. A skill has a SKILL.md file with frontmatter and instructions. Claude can load it when relevant, or you can invoke it directly with a slash command.
Example:
.claude/skills/review-diff/
└── SKILL.md
---
description: Review the current Git diff for correctness, maintainability, security concerns, and missing tests.
---
# Review Diff
Use the current Git diff as the source of truth.
!`git diff HEAD`
## Instructions
Review the changes and return:
1. Summary of what changed.
2. Possible bugs or regressions.
3. Security concerns.
4. Missing tests.
5. Suggested commit message.
You can invoke it like this:
/review-diff
Skills are especially useful when CLAUDE.md starts becoming too procedural. If the instruction is a workflow, checklist, or multi-step routine, move it into a skill. The benefit is progressive loading: the full skill body is loaded when needed, not necessarily into every session from the start.
Good skill candidates:
- review a diff;
- prepare a release note;
- debug a failed CI job;
- generate migration steps;
- audit an API endpoint;
- prepare a deployment checklist;
- create a blog post from notes.
.claude/commands/: Legacy Slash Commands
Older Claude Code setups often use .claude/commands/*.md for custom slash commands.
Example:
.claude/commands/ship.md
A command like this can still work, but for new workflows, prefer skills:
.claude/skills/ship/SKILL.md
The practical difference is that skills are more flexible. They can include supporting files, frontmatter, automatic invocation behavior, and cleaner packaging for reuse.
A good migration path is:
- Keep existing commands working.
- Move frequently used commands to
.claude/skills/<name>/SKILL.md. - Add descriptions so Claude knows when to load them.
- Remove duplicate command files after the team has switched.
.claude/agents/: Custom Subagents
Subagents are specialized assistants that run with their own context window. They are useful when a task would flood the main conversation with logs, search results, or file contents.
Example:
.claude/agents/code-reviewer.md
---
name: code-reviewer
description: Reviews code changes for correctness, maintainability, security, and test coverage.
tools: Read, Grep, Glob, Bash
model: sonnet
---
You are a senior code reviewer.
When reviewing code:
- Identify correctness issues.
- Look for missing tests.
- Check error handling.
- Flag security risks.
- Prefer specific, actionable feedback.
- Do not edit files directly.
A subagent can be read-only, write-capable, model-specific, or scoped to a particular set of tools. This gives you a clean way to isolate responsibilities.
Useful subagents:
code-reviewer: reviews diffs and returns a summary;researcher: gathers information from docs and returns a synthesis;log-analyzer: parses errors, traces, and crash logs;migration-planner: inspects a codebase and proposes migration steps;security-auditor: checks risky changes without editing files.
Subagents are not just “more prompts.” They are a context-management tool. Use them when you want the main conversation to stay clean.
.claude/rules/: Modular and Path-Scoped Instructions
Large CLAUDE.md files become hard to maintain. Rules let you split instructions into smaller Markdown files.
Example:
.claude/rules/
├── api.md
├── testing.md
└── security.md
A rule without path frontmatter applies broadly:
# Testing Rules
- Add tests for new behavior.
- Prefer integration tests for API-level behavior.
- Use fixtures for repeated setup.
A path-scoped rule only applies when Claude works with matching files:
---
paths:
- "src/api/**/*.py"
---
# API Rules
- Validate all request payloads.
- Return the standard error response format.
- Keep route handlers thin.
- Put business logic in services.
Rules are useful in monorepos because frontend, backend, infrastructure, and documentation can each have their own instructions.
.claude/output-styles/: Response Format, Not Project Knowledge
Output styles change how Claude responds. They are best for format, role, tone, and structure.
Example:
.claude/output-styles/terse.md
---
name: Terse
description: Short, direct responses with minimal prose.
keep-coding-instructions: true
---
# Terse Output Style
- Be direct.
- Avoid long explanations unless asked.
- Prefer commands and code blocks.
- Do not add motivational language.
Use output styles when you repeatedly ask for the same response format. Do not use them for project architecture or coding rules. Those belong in CLAUDE.md or .claude/rules/.
Plugins: Packaging Claude Code Extensions
Plugins package Claude Code extensions so they can be shared across projects or teams. A plugin can bundle skills, agents, hooks, MCP servers, language server configuration, background monitors, binaries, and default settings.
A plugin structure can look like this:
my-plugin/
├── .claude-plugin/
│ └── plugin.json
├── skills/
│ └── code-review/
│ └── SKILL.md
├── agents/
│ └── security-reviewer.md
├── hooks/
│ └── hooks.json
├── .mcp.json
└── settings.json
Use standalone .claude/ configuration when you are experimenting or customizing a single repository. Use plugins when you want distribution, versioning, and reuse.
For example, a platform team could create an internal plugin that includes:
- a security review skill;
- a release checklist skill;
- a read-only architecture researcher agent;
- hooks for formatting or policy checks;
- MCP servers for internal documentation;
- default settings for safe permissions.
This is where Claude Code starts to look less like an assistant and more like an internal developer platform component.
Status Line Configuration
Claude Code can display a custom status line by using a statusLine setting. A common approach is to point it to a local script that prints contextual information such as branch name, environment, or project mode.
Example:
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}
Keep status line commands fast and safe. They may run often, so avoid slow network calls or commands that mutate state.
Security Checklist for Claude Code Projects
Claude Code configuration is not only about productivity. It is also about reducing the risk of accidental exposure or unsafe automation.
Use this checklist before sharing a Claude Code setup with a team.
1. Deny Access to Secret Files
Use permission rules to block reads of sensitive files.
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Read(./config/credentials.json)"
]
}
}
Do not rely on .gitignore alone. .gitignore is for Git; Claude Code permissions are for Claude Code tool access.
2. Keep Local Overrides Local
Commit:
CLAUDE.md;.claude/settings.json;.claude/rules/;.claude/skills/;.claude/agents/if they are useful for the team;- safe hook scripts.
Do not commit:
CLAUDE.local.md;.claude/settings.local.json;.env;- credentials;
- local sandbox URLs if they are personal or sensitive.
3. Be Careful With MCP Servers
MCP servers can expose data and actions. Treat them like developer tools with real permissions.
Before enabling an MCP server for a project:
- inspect what tools it exposes;
- check whether it has write access;
- check whether it can read private data;
- avoid untrusted servers that fetch arbitrary web content;
- prefer least privilege;
- do not commit tokens.
4. Avoid Broad Auto-Approval
A hook that auto-approves every permission prompt is risky. Scope matchers narrowly.
Better:
{
"hooks": {
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"
}
]
}
]
}
}
Risky:
{
"hooks": {
"PermissionRequest": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "echo 'approve everything'"
}
]
}
]
}
}
The first example targets a specific permission flow. The second one removes an important safety boundary.
5. Remember That Local Transcripts Can Contain Sensitive Data
Agent sessions can produce local transcripts, tool outputs, prompt history, debug logs, and file snapshots. If a command prints a secret, that secret may end up in local application data.
Practical mitigations:
- deny reads of known secret paths;
- avoid printing secrets in shell commands;
- reduce local retention where appropriate;
- purge project data when needed;
- keep developer machines encrypted;
- avoid feeding production credentials into prompts or tool output.
What the Image Gets Right
The folder map from the image captures an important idea: Claude Code is not configured through one magic file. It is a layered system.
The strongest points are:
CLAUDE.mdgives project context.CLAUDE.local.mdis for personal overrides..mcp.jsonbelongs at project root for project-level MCP configuration.- Hooks are deterministic and should be used for hard rules.
- Skills are reusable and load on demand.
- Subagents are useful for isolated context.
- Rules help split project instructions by topic or path.
- Settings are the place for permissions and hook registration.
Important Corrections and Nuance
A few details are worth tightening:
| Claim | More precise version |
|---|---|
| “Hooks folder fires every time” | Hook scripts do not run automatically just because they exist. They must be registered in settings.json, plugin hooks, skill frontmatter, or agent frontmatter. |
“CLAUDE.md is project root for Claude Code” | CLAUDE.md is a project instruction file. Claude Code can also read user-level, local, managed, and nested instruction files depending on scope. |
“.gitignore protects secrets” | .gitignore prevents Git commits. Use permissions.deny to block Claude Code from reading sensitive paths. |
| “Commands are the main workflow mechanism” | Existing .claude/commands/ files still work, but new reusable workflows should usually be implemented as skills. |
| “Output styles define project behavior” | Output styles define response format and role. Project behavior belongs in CLAUDE.md, rules, settings, hooks, skills, or agents. |
Recommended Setup for a Real Team
For a production team, I would start with this minimal setup:
your-project/
├── CLAUDE.md
├── CLAUDE.local.md # gitignored
├── .mcp.json # only safe shared MCP servers
└── .claude/
├── hooks/
│ ├── protect-files.sh
│ └── format-after-edit.sh
├── skills/
│ ├── review-diff/
│ │ └── SKILL.md
│ └── prepare-pr/
│ └── SKILL.md
├── agents/
│ └── code-reviewer.md
├── rules/
│ ├── api.md
│ ├── testing.md
│ └── security.md
├── settings.json
└── settings.local.json # gitignored
Then add more only when there is a clear need.
A good adoption order:
- Add a concise
CLAUDE.md. - Add
permissions.denyfor secrets. - Add one or two hooks for formatting and protected files.
- Add a
review-diffskill. - Add path-scoped rules for the most sensitive parts of the codebase.
- Add read-only subagents for review and research.
- Add MCP only after you have a clear trust and access model.
- Convert repeated team workflows into plugins when they become reusable across repositories.
Final Thoughts
The .claude folder is best understood as an agent engineering layer for your repository. It turns Claude Code from a general assistant into a project-aware development tool with conventions, workflows, guardrails, and integrations.
The most useful rule is simple:
Put durable project facts in
CLAUDE.md, hard guarantees in hooks and permissions, reusable workflows in skills, specialized work in subagents, and external tool access behind carefully reviewed MCP servers.
That separation keeps your setup understandable, secure, and easier to evolve as the project grows.
References
- Claude Code Docs: Claude Code overview - code[.]claude[.]com/docs/en/overview
- Claude Code Docs: Explore the
.claudedirectory - code[.]claude[.]com/docs/en/claude-directory - Claude Code Docs: How Claude remembers your project - code[.]claude[.]com/docs/en/memory
- Claude Code Docs: Claude Code settings - code[.]claude[.]com/docs/en/settings
- Claude Code Docs: Automate workflows with hooks - code[.]claude[.]com/docs/en/hooks-guide
- Claude Code Docs: Hooks reference - code[.]claude[.]com/docs/en/hooks
- Claude Code Docs: Extend Claude with skills - code[.]claude[.]com/docs/en/skills
- Claude Code Docs: Create custom subagents - code[.]claude[.]com/docs/en/sub-agents
- Claude Code Docs: Connect Claude Code to tools via MCP - code[.]claude[.]com/docs/en/mcp
- Claude Code Docs: Output styles - code[.]claude[.]com/docs/en/output-styles
- Claude Code Docs: Create plugins - code[.]claude[.]com/docs/en/plugins