Claude Codehigh

settings.json & Permission Modes

settings.json (project-level) and ~/.claude/settings.json (global) configure Claude Code behavior: hooks, permissions, environment variables, model preferences. settings.local.json is the gitignored personal override.

Memory anchor

settings.json is the office key card system — project settings are the building badge (everyone has it), settings.local is your personal access (cleaning crew can't get in your office).

Expected depth

Permission modes: 'default' (prompts for non-allowlisted tools), 'acceptEdits' (auto-approve file edits), 'plan' (read-only, no edits), 'bypassPermissions' (no prompts — dangerous). The 'permissions' field has 'allow' and 'deny' arrays for specific tool patterns: 'Bash(npm install:*)' allows npm install commands, 'Bash(rm -rf:*)' denies recursive deletes. Permissions match before the model is even asked — they're enforced by the harness.

Deep — senior internals

Settings merge in order: ~/.claude/settings.json → <project>/.claude/settings.json → <project>/.claude/settings.local.json (most specific wins for scalars; arrays merge or replace based on key). 'env' injects environment variables into all hook and tool executions. Use settings.local.json for personal allowlists (dev DB credentials), settings.json for shared team rules (deny push --force). enableAllProjectMcpServers / disabledMcpjsonServers control MCP server activation per project. enableHooks / disableAllHooks are the kill switches.

🎤Interview-ready answer

settings.json is where I configure Claude Code per-project: which tools are auto-approved, which are denied, what hooks run, environment variables. The permission system is harness-enforced — 'Bash(npm test:*)' on the allow list means the model never gets prompted. The split between settings.json (committed, team-shared) and settings.local.json (gitignored, personal) lets us share team rules while keeping individual workflow tweaks private. I always have a 'deny' list for destructive commands: rm -rf, git push --force, kubectl delete.

Common trap

Putting secrets in settings.json. It gets committed. Use settings.local.json for anything sensitive, or better, use environment variables loaded from .env files outside the repo.

Related concepts