settings.json as the Deterministic Control Surface
CoreConfigure behavior and permissions via settings.json · Difficulty 2/5
Explanation
What settings.json Configures
settings.json -- at ~/.claude/settings.json for the user level and .claude/settings.json at the project level -- configures behavior and permissions:
- Which tools are allowed or denied
- Hook definitions (code that runs at defined points in the agent loop)
- Environment variables
- Model selection
- MCP servers
Why It's Deterministic
settings.json is the deterministic control surface: an allow/deny rule or a hook defined here can block a dangerous command regardless of what the model proposes. This matters because prompt-level instructions (e.g., a line in a system prompt telling Claude not to run destructive commands) are probabilistic -- the model generally follows them but compliance is not guaranteed. settings.json enforces the boundary structurally, outside the model's discretion, which is why it is the right place for permission scoping and hook-based guardrails on high-stakes or destructive actions.
settings.json vs. CLAUDE.md
The two files solve different problems and are not interchangeable:
| CLAUDE.md | settings.json | |
|---|---|---|
| Nature | Context/memory loaded into the model's prompt | Executable configuration enforced outside the model |
| Contains | Conventions, architecture notes, commands, gotchas | Tool allow/deny lists, hooks, env vars, model choice, MCP servers |
| Compliance | Probabilistic (the model reads and generally follows it) | Deterministic (enforced structurally) |
Common exam traps
- Putting permission rules, hooks, or tool allow/deny lists in `CLAUDE.md
-- these belong insettings.json.CLAUDE.mdis read by the model as context; it cannot structurally block an action the way asettings.json` rule or hook can. - Assuming a well-written CLAUDE.md instruction ("never run destructive commands") is an adequate substitute for a settings.json permission rule -- the former is a probabilistic nudge, the latter a deterministic gate.
Key Takeaways
- settings.json (user: ~/.claude/settings.json, project: .claude/settings.json) configures tool permissions, hooks, env vars, model selection, and MCP servers
- settings.json is the deterministic control surface -- an allow/deny rule or hook blocks an action regardless of what the model proposes
- CLAUDE.md is context/memory (probabilistic influence on the model); settings.json is executable configuration (deterministic enforcement)
- Permission and hook rules belong in settings.json, never in CLAUDE.md
Glossary Terms
Shell scripts or commands configured in .claude/settings.json that run at defined lifecycle points: PreToolUse (before tool execution), PostToolUse (after tool execution), Stop (before ending), SubagentStop (when subagent finishes). Used for code quality gates, notifications, logging, and safety checks.
A markdown configuration file read by Claude Code at startup that injects persistent context, project conventions, and tool guidance into every session — without re-prompting. Claude Code supports CLAUDE.md files at the global, project-root, and subdirectory levels (see /glossary/path-specific-rules for the hierarchy). Uses @import for modular organization.
The Claude Code settings file that configures tool permissions, hook scripts, environment variables, and behavioral settings. Project-scoped (.claude/settings.json) checked into version control, or user-scoped (~/.claude/settings.json) for personal preferences. Hooks are defined here.
A process that implements the MCP protocol and exposes tools, resources, and prompts to MCP clients. Built with official SDKs (Python, TypeScript). Deployed locally via stdio or remotely via StreamableHTTP. Claude Code auto-discovers servers configured in .mcp.json.
Related Concepts