Claude Code configuration guide: instruction files, MCP, permissions

Anthropic · CLI · IDE / editor · verified against official docs on 2026-10-12

Claude Code reads CLAUDE.md (project root or .claude/CLAUDE.md), CLAUDE.local.md, ~/.claude/CLAUDE.md and .claude/rules/*.md. Since v2.1.277 it also reads AGENTS.md, but by default only when no CLAUDE.md exists in the working directory or above it. Permissions live in settings.json as allow / ask / deny rules (deny wins). MCP servers go in .mcp.json (project) or ~/.claude.json (user). You can log in with a Claude Pro or Max subscription or use an API key.

Claude Code at a glance

Global instructions✓ Yes
~/.claude/CLAUDE.md, ~/.claude/rules/*.md; org-managed /etc/claude-code/CLAUDE.md (Linux) or /Library/Application Support/ClaudeCode/CLAUDE.md (macOS)
Project instructions✓ Yes
CLAUDE.md or .claude/CLAUDE.md, personal CLAUDE.local.md, .claude/rules/*.md (optional paths: globs); loaded from the working dir and every parent dir
Nested / subfolder✓ Yes
Subdirectory CLAUDE.md loads on demand when Claude reads or edits a file there
AGENTS.md◐ Partial
Yes since v2.1.277, but only if there is no CLAUDE.md / CLAUDE.local.md in the working dir or above (default). Set Project instructions to claude-md-and-agents-md to read both. @AGENTS.md import always works
Skills (SKILL.md)✓ Yes
~/.claude/skills/<name>/SKILL.md, .claude/skills/<name>/SKILL.md. .agents/skills is not listed in the docs
MCP config✓ Yes
.mcp.json at project root (shared, needs approval); user and local scopes in ~/.claude.json; claude mcp add --scope project|user|local
Permissions / allowlist✓ Yes
permissions.allow / ask / deny in ~/.claude/settings.json, .claude/settings.json, .claude/settings.local.json, managed settings. Deny > ask > allow. Modes: default, acceptEdits, plan, auto, dontAsk, bypassPermissions
Sandbox✓ Yes
Opt-in: /sandbox or sandbox.enabled: true. Seatbelt on macOS, bubblewrap + socat on Linux/WSL2
Hooks✓ Yes
hooks in settings.json: PreToolUse, PostToolUse, SessionStart, Stop, UserPromptSubmit and more; exit code 2 blocks a tool call
Claude Pro/Max login✓ Yes
Log in with Claude Pro or Max (also Team/Enterprise)
ChatGPT Plus/Pro login✕ No
Not supported
API key / own plan✓ Yes
ANTHROPIC_API_KEY, Claude Console, Bedrock, Google Cloud, Microsoft Foundry

Exact file paths

PathScopeWhat it does
~/.claude/CLAUDE.mdUserPersonal instructions for every project
CLAUDE.md or .claude/CLAUDE.mdProjectTeam instructions, commit to git
CLAUDE.local.mdProject (personal)Your uncommitted notes; add to .gitignore
.claude/rules/*.mdProjectTopic rules; paths: frontmatter scopes them to globs
AGENTS.mdProjectRead when no CLAUDE.md exists (v2.1.277+)
.claude/settings.jsonProjectShared permissions, hooks, sandbox, env
.claude/settings.local.jsonProject (personal)Your local overrides; 'don't ask again' approvals are saved here
~/.claude/settings.jsonUserPersonal settings for every project
.mcp.jsonProjectTeam MCP servers (mcpServers object)
~/.claude.jsonUser / localUser- and local-scope MCP servers, trust state
.claude/skills/<name>/SKILL.mdProjectAgent Skills (also ~/.claude/skills/)

Using a shared AGENTS.md with Claude Code

Add a CLAUDE.md whose first line is @AGENTS.md (or ln -s AGENTS.md CLAUDE.md). With no CLAUDE.md at all, v2.1.277+ reads AGENTS.md directly. See one AGENTS.md for every agent, or generate one with the AGENTS.md generator.

Copy-paste examples

CLAUDE.md that reuses your AGENTS.md

File: CLAUDE.md

@AGENTS.md

## Claude Code

- Use plan mode for changes under `src/billing/`.
- Run `npm test` before you say a task is done.

Project MCP server

File: .mcp.json

{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/"
    }
  }
}

Hook that hard-blocks destructive shell commands

File: .claude/settings.json (hooks)

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-destructive.sh" }
        ]
      }
    ]
  }
}

The hook script

File: .claude/hooks/block-destructive.sh

#!/usr/bin/env bash
# Reads the tool call as JSON on stdin; exit 2 blocks it and shows the reason to Claude.
cmd=$(jq -r '.tool_input.command // ""')
if echo "$cmd" | grep -Eiq 'rm -[a-z]*r[a-z]*f|git push.*(--force|-f( |$))|drop (table|database)|truncate table|terraform destroy'; then
  echo "Blocked by project policy: $cmd" >&2
  exit 2
fi
exit 0

Safe permissions preset

Safe settings.json: block destructive commands and secrets

File: .claude/settings.json

{
  "permissions": {
    "allow": [
      "Bash(npm run test *)",
      "Bash(npm run lint *)",
      "Bash(git status)",
      "Bash(git diff *)",
      "Bash(git log *)"
    ],
    "ask": [
      "Bash(git push *)",
      "Bash(git commit *)",
      "Bash(npm install *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(rm -fr *)",
      "Bash(sudo *)",
      "Bash(git push --force*)",
      "Bash(git push * --force*)",
      "Bash(git push -f*)",
      "Bash(git push * -f*)",
      "Bash(git reset --hard*)",
      "Bash(git clean *)",
      "Bash(*DROP TABLE*)",
      "Bash(*drop table*)",
      "Bash(*DROP DATABASE*)",
      "Bash(*TRUNCATE TABLE*)",
      "Bash(terraform destroy*)",
      "Bash(kubectl delete *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)"
    ],
    "disableBypassPermissionsMode": "disable"
  },
  "sandbox": {
    "enabled": true
  }
}

Deny rules are checked first, so an allow rule can never re-open a denied command. Deny rules match the command text Claude writes: they do not catch /bin/rm -rf, bash -c 'rm -rf …' or git -C . push --force. Turn on the sandbox and add the PreToolUse hook above for a real boundary.

Gotchas

  • If any CLAUDE.md or CLAUDE.local.md exists in the working directory or a parent, Claude Code reads it instead of AGENTS.md. Adding a personal CLAUDE.local.md silently switches AGENTS.md off unless you set Project instructions to claude-md-and-agents-md.
  • Claude Code does not read AGENTS.override.md, AGENTS.local.md or anything under .agents/ (per the memory docs).
  • Instructions in CLAUDE.md are context, not enforcement. Use permission rules, the sandbox or a PreToolUse hook for anything that must never happen.
  • Keep each CLAUDE.md under about 200 lines; @imports organize content but still load at launch.
  • A symlinked CLAUDE.md -> AGENTS.md works, but Windows clones without core.symlinks get a one-line text file. Prefer the @AGENTS.md import for mixed-OS teams.
  • .mcp.json servers need approval on first run; a cloned repo cannot approve its own servers.

FAQ

Does Claude Code read AGENTS.md?
Yes, since v2.1.277. By default it reads AGENTS.md only when there is no CLAUDE.md or CLAUDE.local.md in the working directory or above it. To read both, set Project instructions to claude-md-and-agents-md in /config, or put @AGENTS.md in your CLAUDE.md.
Where is the Claude Code settings.json?
User settings: ~/.claude/settings.json. Project (shared): .claude/settings.json. Project (personal, gitignored): .claude/settings.local.json. Organizations can deploy managed settings that override all of them.
How do I stop Claude Code from running rm -rf?
Add "Bash(rm -rf *)" to permissions.deny in settings.json. Deny rules beat allow rules. Because rules match the command text, also enable the sandbox (/sandbox) and a PreToolUse hook that exits with code 2 for destructive patterns.
Where is the Claude Code MCP config file?
Project servers go in .mcp.json at the repository root (mcpServers object). User and local servers are stored in ~/.claude.json. Use claude mcp add --scope project|user|local to write them.

Sources

Checked against these official pages on 2026-10-12. Cells marked "Not documented" mean we could not find the behaviour in these docs; it may still exist.