Almost everything Claude Code does in a session is shaped by a JSON file called settings.json. Permissions, hooks, MCP servers, environment variables, plugins, all of it. Understanding this file is the fastest way to shape the harness around your work. This page walks through the whole config model, with sensible defaults and the things not to do.
Claude Code reads settings from up to three places. Each more specific than the last. A setting defined at multiple levels wins at the most specific one.
The merging is cumulative: the global file is your defaults; the per-machine file overrides for your current computer; the per-project file overrides for the current repo. Think of it like CSS specificity for agent configuration.
The config has a bunch of fields. These are the ones that come up in real use, in rough order of importance.
permissions - the most important field.Controls what tools the agent can use without asking. Has three sub-fields:
defaultMode: "manual" (ask every time), "auto" (auto-approve things in the allow list), or "plan" (plan the run first, then execute). Default to "auto" for real work.allow: array of patterns that are always approved. "Read", "Edit", "Bash(git status)", "mcp__notion__*".deny: array of patterns that are always rejected. "Bash(sudo:*)", "Bash(rm -rf:*)".See Permissions for the full design guide - this is the single most important page in the framework.
mcpServers - your installed MCPs.A map of MCP server name → config. Each entry becomes a set of tools the agent can call. Two shapes:
// Local stdio server
"notion": {
"command": "npx",
"args": ["-y", "@notionhq/notion-mcp"],
"env": { "NOTION_API_KEY": "${NOTION_API_KEY}" }
}
// Remote HTTP server
"github-remote": {
"url": "https://api.github.com/mcp",
"headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" }
}
hooks - run your code on agent events.Array of hook definitions. See Hooks for when and why.
env - set environment variables for every session.Tokens, paths, feature flags. Available inside tools and MCP servers. Prefer ${VAR} substitution over literal values so your config can be committed without leaking secrets.
enabledPlugins - turn plugins on/off.A map of plugin ID → boolean. Installed plugins default to enabled; use this to selectively disable.
skipAutoPermissionPrompt - the danger flag.Boolean. If true, Claude Code does NOT pop an approval dialog for calls that aren't in the allow list. Instead, it uses its own judgment. Only use this with a very strict deny list. Otherwise you're handing full autonomy to the model, which is usually a mistake.
autoUpdaterStatus - let it update itself.Controls whether Claude Code auto-updates. Leave on default; updates ship often and you want them.
If you're starting fresh, this is a good starting config. Adjust permissions once you've run a few real sessions.
{
"permissions": {
"defaultMode": "auto",
"allow": [
"Read", "Write", "Edit", "Glob", "Grep",
"Bash(git status)", "Bash(git log:*)", "Bash(git diff:*)",
"Bash(ls:*)", "Bash(cat:*)", "Bash(head:*)", "Bash(tail:*)",
"mcp__notion__*"
],
"deny": [
"Bash(sudo:*)",
"Bash(rm -rf:*)",
"Bash(git push:*)",
"Bash(git reset --hard:*)",
"mcp__*__delete_*"
]
},
"mcpServers": {
"notion": {
"command": "npx",
"args": ["-y", "@notionhq/notion-mcp"],
"env": { "NOTION_API_KEY": "${NOTION_API_KEY}" }
}
}
}
Reads: allowed. Writes and safe shell: allowed. Notion MCP: allowed. Dangerous things: denied. Use as a starting point; widen the allow list as you hit friction.
The project-level .claude/settings.json is meant to be committed into git. Your team picks up the same permissions baseline, the same MCPs, the same hooks. This is how you scale a safety-conscious agent setup across people.
Keep settings.local.json and anything with real secrets OUT of version control. Reference tokens with ${ENV_VAR} substitution so the committed file has no actual credentials in it.
When your team's settings drift ("wait, who added that to the allow list?"), a git diff on .claude/settings.json answers it in ten seconds. This is where version control pays off the most.
~/.claude/settings.json..claude/settings.json in that repo.~/.claude/settings.local.json.Most people settle into a configuration after 2-3 weeks that they rarely touch. The time invested early pays for itself in thousands of friction-free sessions later.
Andrej Karpathy - Let's build GPT from scratch