← Back to cipheryogi portfolio

Claude Code File Structure & Configuration

A practical map of where Claude Code keeps instructions, settings, MCP server configuration, reusable capabilities, project state and credentials — and how personal and team-level files differ.

Personal + project scopes Instructions ≠ settings MCP configuration Credentials stored separately Git-sharing boundaries Managed policy

Companion guide: Claude Code Capabilities (tools, agents, skills, hooks, permission modes, models and automation).

1. The Mental Model

Claude Code uses different files for what it should know, how it should behave, and which external tools it can access.

InstructionsCLAUDE.md files provide persistent context: project architecture, coding standards, conventions and working preferences.
Settingssettings.json controls behaviour: permissions, hooks, model defaults, environment and other configuration.
MCP configuration.mcp.json defines project-shared MCP servers. Local-scope servers (the default, this project only) and user-scope servers (all your projects) are stored in ~/.claude.json.
Application state~/.claude.json also holds Claude Code state such as project trust and other local state. It is not simply a preferences file.

2. End-to-End File Structure

Personal configuration lives under your home directory. Team-shared configuration lives in the project repository and can be committed to Git.

flowchart TD
  U["YOUR MACHINE"] --> HOME["Home directory · ~/.claude/"]
  U --> STATE["~/.claude.json"]
  U --> PROJ["PROJECT REPOSITORY"]
  U --> MANAGED["MANAGED POLICY · OS system directory"]
  MANAGED --> M1["CLAUDE.md · managed-settings.json
managed-mcp.json · deployed by IT"] HOME --> H1["CLAUDE.md
Personal instructions"] HOME --> H2["settings.json
Personal settings"] HOME --> H3["skills/ · agents/ · rules/ · output-styles/
Personal reusable assets"] HOME --> H4["projects/
Session transcripts and auto memory"] HOME --> H5["plugins/ · keybindings.json
Installed plugins, shortcuts"] STATE --> S1["Local- and user-scope MCP servers"] STATE --> S2["Project trust and local application state"] PROJ --> P1["CLAUDE.md or .claude/CLAUDE.md
Project / team instructions"] PROJ --> P7["CLAUDE.local.md
Personal project instructions"] PROJ --> P2[".mcp.json
Team-shared MCP servers"] PROJ --> P3[".claude/"] P3 --> P4["settings.json
Shared project settings"] P3 --> P5["settings.local.json
Personal project overrides"] P3 --> P6["skills/ · agents/ · rules/ · workflows/
Project capabilities and guidance"] P1 --> GIT["Can be committed and shared"] P2 --> GIT P4 --> GIT P6 --> GIT P5 --> LOCAL["Normally kept local / excluded from Git"] P7 --> LOCAL classDef user fill:#e8f1ff,stroke:#3975c6,color:#132238; classDef team fill:#e8f7f1,stroke:#157a5a,color:#103e31; classDef state fill:#fff5dd,stroke:#9a6500,color:#5a3d00; classDef private fill:#f1eaff,stroke:#7b52b9,color:#2f1f4b; classDef managed fill:#fff0f0,stroke:#a93636,color:#5a1d1d; class HOME,H1,H2,H3,H4,H5 user; class P1,P2,P3,P4,P6,GIT team; class STATE,S1,S2 state; class P5,P7,LOCAL private; class MANAGED,M1 managed;
Managed policy (organization) Personal environment Project / team assets Application state Local-only override
Important: Personal versus team scope is determined by file location and sharing/commit practices — not by the filename alone. A CLAUDE.md can be personal or team-level.

3. The Important Files and Directories

What each item is for, where it lives, and whether it is normally shared.

File / directoryPurposeTypical scope
~/.claude.jsonWritten by Claude Code itself: account details, local-scope MCP servers (the default for claude mcp add, stored under each project's path), user-scope MCP servers, per-project trust decisions and the global config keys that /config writes. Not the main file for general preferences, and not meant for hand editing.Personal
~/.claude/settings.jsonUser-wide settings such as permissions, hooks, model defaults and environment configuration.Personal
~/.claude/CLAUDE.mdInstructions that should apply across your projects, such as your preferred explanation style or general coding practices.Personal
CLAUDE.md or .claude/CLAUDE.mdProject context, architecture, build/test commands, coding conventions and team instructions. Usually placed at the repository root. See section 5 for how multiple files combine.Team when committed
.claude/settings.jsonShared project settings, including project permissions and hooks.Team when committed
.claude/settings.local.jsonPersonal project-specific settings and overrides; normally excluded from version control.Personal
.mcp.jsonProject-scoped MCP server definitions that can be shared with the team. Secrets should be supplied securely, not committed as literals.Team when committed
CLAUDE.local.mdPersonal project instructions, loaded alongside CLAUDE.md and appended after it. Claude Code does not git-ignore it for you, so add it to .gitignore.Personal
~/.claude/skills/ and .claude/skills/Reusable skills and workflows. User-level skills are personal; project-level skills can be shared.Personal / team
~/.claude/agents/ and .claude/agents/Custom subagent definitions for specialist tasks. Scope follows the directory in which they are stored.Personal / team
.claude/rules/ and ~/.claude/rules/Modular instructions, optionally scoped to file paths with paths frontmatter. User rules apply to every project and load before project rules.Team / personal
~/.claude/projects/Per-project session transcripts (plaintext, deleted after cleanupPeriodDays, default 30 days) and auto memory (kept, not swept).Personal
.claude/commands/ and ~/.claude/commands/Legacy custom commands. Still work, but commands have been merged into skills, and a skill with the same name wins.Personal / team
.claude/workflows/ and ~/.claude/workflows/Saved dynamic workflow scripts, run as /<name>. The project copy wins on a name clash.Personal / team
output-styles/ (under ~/.claude/ or .claude/)Custom output styles as Markdown files.Personal / team
.claude/agent-memory/ · .claude/agent-memory-local/ · ~/.claude/agent-memory/Persistent memory for custom subagents that set the memory field (project, local and user scope).Team / personal
~/.claude/plugins/Installed plugins, cloned marketplaces and plugin data. Which plugins are on is recorded in enabledPlugins in a settings file.Personal
~/.claude/keybindings.jsonCustom keyboard shortcuts. Global only. Open it with /keybindings.Personal
Managed policy directorymanaged-settings.json, managed-settings.d/, managed-mcp.json and a managed CLAUDE.md, deployed by your organization. See section 10.Organization

4. The Three Concepts to Keep Separate

This is the distinction that prevents most confusion when configuring Claude Code.

1

CLAUDE.md — What Claude should know

Persistent instructions and context supplied to Claude during work.

  • Architecture and design constraints
  • Coding standards and conventions
  • Build, test and deployment commands
  • Project-specific terminology and guidance

Think: the project's working handbook.

2

settings.json — How Claude should operate

Configuration that governs Claude Code's behaviour and available capabilities.

  • Tool permissions: allow / ask / deny
  • Hooks and environment variables
  • Model and other runtime defaults
  • Other supported Claude Code settings

Think: the operating policy and configuration.

3

.mcp.json / ~/.claude.json — Which MCP servers are configured

MCP server definitions connect Claude Code to external tools and data sources.

  • .mcp.json: project-scoped, shareable server definitions
  • ~/.claude.json: local-scope (default, this project only) and user-scope (all projects) MCP servers, plus local state
  • Credentials should be handled securely

Think: the connection directory for external capabilities.

5. How Instructions Load

CLAUDE.md files are layered by scope and concatenated, never overridden. Knowing the order explains most "why did Claude do that" moments.

ScopeLocationWho it applies to
Managed policymacOS /Library/Application Support/ClaudeCode/CLAUDE.md
Linux / WSL /etc/claude-code/CLAUDE.md
Windows C:\Program Files\ClaudeCode\CLAUDE.md
Everyone the organization deploys it to. It can't be excluded with claudeMdExcludes.
User~/.claude/CLAUDE.mdYou, in every project
Project./CLAUDE.md or ./.claude/CLAUDE.mdThe team, through source control
Local./CLAUDE.local.mdYou, in this project. Add it to .gitignore yourself.
Rules.claude/rules/**/*.md and ~/.claude/rules/**/*.mdTeam or you. Rules without paths load like .claude/CLAUDE.md.
1

At launch

CLAUDE.md and CLAUDE.local.md load from the working directory and every directory above it.

  • Concatenated from the filesystem root down to the working directory, so the closest file is read last
  • Within a directory, CLAUDE.local.md is appended after CLAUDE.md
  • User rules load before project rules. Neither overrides the other.
2

On demand

Files below the working directory don't load at launch.

  • A subdirectory's CLAUDE.md loads once Claude reads, writes or edits a file in that subdirectory
  • A path-scoped rule loads when Claude touches a file matching its paths globs
3

Imports

@path/to/file pulls another file into a CLAUDE.md.

  • Relative paths resolve from the importing file, and imports can nest up to four hops deep
  • A project import that resolves outside the working directory needs a one-time approval
  • Imports organize content but don't reduce context cost
BehaviourDetail
SizeAim for under 200 lines per file. A launch-time file over 4 MiB is skipped entirely. Block-level HTML comments (<!-- -->) are stripped before loading, so they cost no tokens.
AGENTS.mdRead only when no CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md exists in the working directory or above (v2.1.277+). To use both, put @AGENTS.md inside a CLAUDE.md, or set Project instructions in /config to claude-md-and-agents-md.
MonoreposclaudeMdExcludes skips specific CLAUDE.md or rules files by glob against absolute paths. The docs suggest putting it in .claude/settings.local.json.
Mid-session editsCLAUDE.md is read at session start. After /compact, the project-root CLAUDE.md and unscoped rules are re-read from disk, so an edit takes effect after /compact or in a new session.
Extra directoriesDirectories added with --add-dir don't contribute their CLAUDE.md unless CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 is set.

Example project CLAUDE.md (keep it short and specific):

# Architecture
- All API routes use the middleware chain: auth → validate → handler
- Database access only through the repository pattern

# Commands
- Build: npm run build · Test: npm test · Lint: npm run lint

# Conventions
- Never use the `any` type in TypeScript
- Every new feature includes unit and integration tests

Path-scoped rule (.claude/rules/api.md, loads only when Claude works on matching files):

---
paths:
  - "src/api/**/*.ts"
---

# API Development Rules
- All API endpoints must include input validation
- Use the standard error response format
CLAUDE.md is context, not enforcement. Claude reads it as guidance. Permission rules are enforced by Claude Code itself, so a CLAUDE.md line can't grant or remove access. For something that must happen every time, use a permissions.deny rule or a hook (section 9).

6. Auto Memory

Notes Claude writes for itself so later sessions in the same project don't start from zero.

AspectCLAUDE.mdAuto memory
Who writes itYou (or /init)Claude, as it works. You can also ask it to remember something.
LocationRepository or ~/.claude/~/.claude/projects/<project>/memory/, with a MEMORY.md index plus topic files
Shared?Can be committedMachine-local only
LoadingWhole file at launchFirst 200 lines or first 25KB of MEMORY.md, whichever comes first. Topic files are read on demand.
  • <project> is derived from the git repository, not a hash, so all worktrees and subdirectories of one repo share one memory directory.
  • Turn it off with the /memory toggle, "autoMemoryEnabled": false in a project's settings, or CLAUDE_CODE_DISABLE_AUTO_MEMORY=1. Move it with autoMemoryDirectory (an absolute or ~/ path).
  • Subagents don't see the main conversation's auto memory (forks are the exception). A custom subagent with a memory field gets its own agent-memory/<name>/ directory.
  • Auto memory files are not deleted by the cleanupPeriodDays sweep that removes old transcripts.

7. Settings Precedence and Workspace Trust

When the same key is set in several files, the highest level wins. Committed project settings also wait for each teammate to trust the folder.

1. Managed settings

Deployed by the organization. Nothing below can override a managed key.

2. Command line

--settings <file-or-json> for one session only.

3. Project local

.claude/settings.local.json

4. Shared project

.claude/settings.json

5. User

~/.claude/settings.json

Lists merge

Arrays such as permissions.allow combine across files instead of replacing each other. For permissions, a deny at any level beats an allow at another.

RuleWhat it means in practice
Environment variables aren't a levelEach variable and settings key pair has its own rule. ANTHROPIC_MODEL in your shell beats the model key in any file.
Some keys are ignored in a repo filepermissions.defaultMode set to auto or bypassPermissions has no effect from project or local settings. Keys whose scope is User or Managed never apply from a committed file. Global config keys apply only from ~/.claude.json.
Workspace trust gates the committed filepermissions.allow, additionalDirectories, extraKnownMarketplaces and most env values in .claude/settings.json apply only after the trust dialog is accepted. deny and ask rules apply immediately.
claude -p skips the trust dialogProject allow rules aren't used, but settings-file hooks, the env block, apiKeyHelper and .mcp.json servers do run. For untrusted repos use --bare, --setting-sources user or --settings '{"disableAllHooks": true}'.
Verify what loaded/status shows the Setting sources line. claude doctor lists rejected entries. Settings files are strict JSON, so add "$schema": "https://json.schemastore.org/claude-code-settings.json" for editor validation.

8. MCP Server Scopes

Three scopes decide where an MCP server definition is stored and who gets it.

ScopeStored inAvailable inAdd with
Local (default)~/.claude.json, under the project's pathThis project, only for youclaude mcp add <name> ...
Project.mcp.json at the project rootEveryone who clones the repoclaude mcp add --scope project ...
User~/.claude.jsonAll your projectsclaude mcp add --scope user ...
  • Precedence: if one server name is defined in several places, Claude Code connects once, using the whole entry from the highest source: Local, then Project, then User, then plugin servers, then claude.ai connectors. Fields are not merged.
  • MCP "local" scope is not settings.local.json. They are unrelated files.
  • Approval: interactive sessions ask before using servers from a project's .mcp.json. Reset your choices with claude mcp reset-project-choices. claude -p and Agent SDK runs load them without asking.
  • Secrets: .mcp.json supports ${VAR} and ${VAR:-default} expansion. See section 11.
  • Organization control: managed-mcp.json takes exclusive control of which servers exist. allowedMcpServers and deniedMcpServers can be set in any settings scope and merge across scopes. A denylist match always blocks a server. Only allowManagedMcpServersOnly: true in managed settings limits the allowlist to managed sources.
claude mcp add --transport http shared-server --scope project https://example.com/mcp
claude mcp list                    # shows servers and warns about unset ${VAR}s
claude mcp reset-project-choices   # re-prompt for .mcp.json approvals

9. Where Hooks Are Configured

Hooks are scripts Claude Code runs itself at lifecycle events, so they don't depend on the model choosing to follow an instruction.

LocationActive when
~/.claude/settings.jsonAll your projects
.claude/settings.jsonEveryone in the project (commit it)
.claude/settings.local.jsonYou, in this project
Managed policy settingsOrganization-wide. Only a managed disableAllHooks can turn these off.
Plugin hooks/hooks.jsonWhile the plugin is enabled
Skill frontmatterThe rest of the session, once the skill is invoked
Subagent frontmatterOnly while that subagent runs

Hook entries merge across levels. /hooks opens a read-only browser showing each hook's source. "disableAllHooks": true turns them off. Events, handler types and exit codes are covered in the companion Claude Code Capabilities guide.

Format every file Claude edits (.claude/settings.json):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }
        ]
      }
    ]
  }
}

10. Enterprise Managed Configuration

Organizations deploy policy that sits above every personal and project file.

OSManaged directory
macOS/Library/Application Support/ClaudeCode/
Linux and WSL/etc/claude-code/
WindowsC:\Program Files\ClaudeCode\ (the legacy C:\ProgramData\ClaudeCode\ path is not read)
managed-settings.json

Policy settings such as permission rules, allowed models, sandbox and telemetry. Drop-in fragments go in managed-settings.d/*.json, merged in alphabetical order after the main file.

managed-mcp.json

Same format as .mcp.json. Takes exclusive control: users can't add other servers. An empty mcpServers disables MCP.

Managed CLAUDE.md

Organization-wide guidance, or the claudeMd key inside managed settings. Use it for behaviour and managed permissions.deny for enforcement.

  • Delivery sources, highest first: server-managed settings (claude.ai admin console or a Claude apps gateway), MDM / OS policy (macOS com.anthropic.claudecode plist, Windows HKLM\SOFTWARE\Policies\ClaudeCode), the managed-settings.json file, then the user-writable HKCU registry fallback. By default only the highest source that has a policy is used.
  • Managed skills and output styles live in .claude/skills/ and .claude/output-styles/ inside the managed directory.
  • Developers run /status to see which managed source applies to them.

11. Where Credentials Fit

Do not treat ~/.claude.json as a credentials vault.

Authentication credentials

Claude Code authentication is handled through the platform's secure credential storage. On macOS, this generally means Keychain.

MCP secrets

Use supported environment-variable or secret-injection mechanisms. Avoid hard-coding API keys or tokens in a shared .mcp.json.

Configuration files

Files can contain server commands, arguments, environment-variable references and non-secret settings. A reference to a secret is not the secret itself.

Security rule: Never commit API keys, access tokens, passwords or private certificates to CLAUDE.md, settings.json or .mcp.json.

How to supply secrets safely, file by file

The principle is the same everywhere: the file holds a reference (a variable name, a helper script path or an OAuth registration), and the secret itself lives in the OS keychain, a secret manager or your shell environment.

WhereSafe patternHow
CLAUDE.mdNo secrets, ever. Name the variable instead.Write “the API token is read from $SN_MCP_TOKEN”. CLAUDE.md is loaded into Claude's context, so anything in it is sent to the model.
.mcp.json (local servers)Environment-variable expansionUse ${VAR} or ${VAR:-default} in a server's command, args, env, url or headers. Each teammate sets the variable on their own machine.
.mcp.json (remote servers with OAuth)Built-in OAuth 2.0 flowAdd the server without a token, then authenticate from /mcp or with claude mcp login <name>. Tokens are stored securely and refreshed automatically. A client secret passed with --client-secret is stored in the macOS Keychain or a credentials file, not in the config.
.mcp.json (short-lived tokens, SSO, Kerberos)headersHelperPoint headersHelper at a script that prints a JSON object of headers. It runs on every connection, has a 10-second timeout and is re-run automatically on a 401/403.
settings.json (Claude API key)apiKeyHelperPoint apiKeyHelper at a script that returns the key, for example from a vault. Use it for rotating credentials.
settings.json env blockNon-secret values onlyThe env block is plain JSON. Don't put tokens in a committed .claude/settings.json. .claude/settings.local.json stays out of Git but is still plaintext on disk.
Secret files in the repo (.env)Deny rulesAdd Read(./.env) and Read(./.env.*) to permissions.deny so Claude can't read them.
Claude Code loginLeave it to Claude CodemacOS: encrypted Keychain (falls back to ~/.claude/.credentials.json, mode 0600, if the Keychain rejects the write). Linux: ~/.claude/.credentials.json, mode 0600. Windows: %USERPROFILE%\.claude\.credentials.json.
CI pipelinesCI secret store and an environment variableRun claude setup-token once to generate a one-year OAuth token, store it as a CI secret and expose it as CLAUDE_CODE_OAUTH_TOKEN. For API billing, use ANTHROPIC_API_KEY the same way.

Step 1. Store the secret in the macOS Keychain (the trailing -w prompts for the value so it never appears in shell history).

security add-generic-password -a "$USER" -s sn-mcp-token -w

Step 2. Export it from the Keychain in ~/.zshrc, so only the variable name is ever written to any file.

export SN_MCP_TOKEN="$(security find-generic-password -s sn-mcp-token -w)"

Step 3. Reference the variable in the committed .mcp.json.

{
  "mcpServers": {
    "internal-api": {
      "type": "http",
      "url": "${INTERNAL_API_URL:-https://api.example.com}/mcp",
      "headers": { "Authorization": "Bearer ${SN_MCP_TOKEN}" }
    }
  }
}

Step 4. Check it: claude mcp list warns about any variable that isn't set. Open a new terminal first, so ~/.zshrc is reloaded.

Dynamic headers for tokens that expire (the script must print JSON such as {"Authorization": "Bearer …"}):

"internal-api": {
  "type": "http",
  "url": "https://mcp.internal.example.com",
  "headersHelper": "/opt/bin/get-mcp-auth-headers.sh"
}

Claude API key from a vault, plus deny rules for local secret files (~/.claude/settings.json):

{
  "apiKeyHelper": "/Users/you/bin/get-anthropic-key.sh",
  "permissions": {
    "deny": ["Read(./.env)", "Read(./.env.*)"]
  }
}
Pitfalls to know:
  • If a referenced variable isn't set and has no default, the config still loads but the literal ${VAR} text is sent. claude mcp list reports a warning for that server.
  • A variable set to an empty string counts as set, so ${VAR:-default} expands to empty, not to the default.
  • In a remote server's url and headers, known credential variables always read as empty, even when set, and a :-default on them is ignored. This covers Claude Code's own credentials (ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN), cloud provider credentials (AWS_BEARER_TOKEN_BEDROCK) and others such as HTTPS_PROXY and NPM_TOKEN. It stops a repository or plugin from sending them to a server it names. A name outside this set, such as API_KEY, expands normally, so copy a covered value into a variable with your own name.
  • If a static Authorization header is rejected, Claude Code reports the connection as failed and doesn't fall back to OAuth. Remove the header to use OAuth.
  • claude mcp add --env KEY=value sets environment variables for the server. As a precaution, don't pass a literal secret this way for a project-scoped server that will be committed. Use a ${VAR} reference in .mcp.json instead.

12. What Should Be Shared with the Team?

A practical Git-sharing model for a consistent team environment.

ArtifactCommit to Git?Reason
CLAUDE.mdUsually yesEnsures the team uses consistent project context and engineering conventions.
.claude/settings.jsonUsually yesShares agreed project-level permissions and hooks. Review changes before adoption.
.mcp.jsonUsually yes, without secretsGives teammates a consistent MCP server configuration.
.claude/skills/, .claude/agents/, .claude/rules/, .claude/workflows/When project-specificShares reusable workflows, specialist agents and project rules.
.claude/settings.local.jsonNoContains individual developer preferences or local overrides. Claude Code adds it to your global git excludes the first time it writes it. If you created it by hand, add it to .gitignore yourself.
CLAUDE.local.mdNoPersonal project instructions. Not ignored automatically, so add it to .gitignore.
.claude/agent-memory/OptionalProject-scope subagent memory, shareable through version control. Keep .claude/agent-memory-local/ out of Git.
.claude/worktrees/NoWorktrees created by claude --worktree. Add the folder to .gitignore.
~/.claude/ and ~/.claude.jsonNoPersonal environment, history, local state and user-specific configuration.
Recommended baseline: maintain a concise root CLAUDE.md, keep shared project settings deliberate, and put reusable team workflows in project-level skills or agents. Keep personal preferences and local state outside the repository.

13. Quick Decision Guide

When you want to change something, use this guide to find the right place.

Instructions

“Claude should always follow our ServiceNow development standards.”

Put the standards in the project CLAUDE.md if they apply to the team, or in ~/.claude/CLAUDE.md if they are your personal preferences.

Settings

“Claude must ask before running a potentially destructive command.”

Configure the relevant tool permissions in the appropriate settings.json scope.

MCP

“Everyone on the project should have the same MCP server definitions.”

Use project-level .mcp.json, and ensure secrets are injected securely rather than committed.

Personal configuration

“I want my own MCP server or personal working preferences.”

Put personal preferences in ~/.claude/CLAUDE.md and ~/.claude/settings.json. For a personal MCP server, run claude mcp add --scope user (all projects) or claude mcp add with the default local scope (this project only). Both are stored in ~/.claude.json in your home directory, not inside the ~/.claude/ folder.

Credentials

“Where should my Claude login token or API key go?”

Use Claude Code's secure authentication flow or an appropriate secret manager/environment-variable mechanism — not a shared instruction or settings file.