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.
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).
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.
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.
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.
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.