Claude Code Settings: settings.json, Permissions, and CLAUDE.md
Claude Code works out of the box, but the defaults are deliberately cautious. It asks before running most commands, uses whatever model your plan gives it, and knows nothing about your project's conventions until you tell it. A settings.json file is where you change all of that once, so every session starts configured the way you want. Paired with a CLAUDE.md memory file, it is the difference between re-explaining your project every morning and having Claude Code already know it.
This guide covers the three settings files and how they layer, a realistic configuration you can adapt, the permissions model that decides what runs without asking, and the memory file that carries your project knowledge from session to session. Ready-made configurations live in the Claude Code settings catalog on ToolZip if you would rather install than hand-write.
Where Claude Code Settings Live
Claude Code reads settings from JSON files at different scopes, and knowing which one to edit is half the battle. There are three you will touch regularly:
- User settings —
~/.claude/settings.json. Personal defaults that apply to every project on your machine: your preferred model, your status line, environment variables you always want. - Project settings —
.claude/settings.jsonin the repository root. Shared with your team and checked into version control, so everyone who clones the repo inherits the same permissions, model, and hooks. - Local project settings —
.claude/settings.local.json. Personal overrides for a single project, automatically gitignored so they never reach the shared repo. This is where a machine-specific path or a permission only you need belongs.
When the same key appears in more than one file, the more specific scope wins. Local project settings override shared project settings, which override your user settings; an enterprise managed policy and command-line flags sit above all three. The practical rule: put team-wide rules in .claude/settings.json, personal defaults in ~/.claude/settings.json, and one-off machine tweaks in .claude/settings.local.json.
A Realistic settings.json
Here is a project settings.json that a small team might commit. It pins a model, sets a couple of environment variables, wires up a status line, and defines a permissions policy that lets routine commands run untouched while blocking the ones that should never fire unattended:
{
"model": "claude-sonnet-4-5",
"env": {
"DISABLE_TELEMETRY": "1",
"BASH_DEFAULT_TIMEOUT_MS": "120000"
},
"permissions": {
"defaultMode": "acceptEdits",
"allow": [
"Bash(npm run test:*)",
"Bash(npm run lint:*)",
"Bash(git diff:*)",
"Bash(git status)",
"Read(src/**)"
],
"deny": [
"Bash(rm -rf:*)",
"Bash(curl:*)",
"Read(./.env)",
"Read(./secrets/**)"
],
"ask": [
"Bash(git push:*)"
]
},
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
},
"includeCoAuthoredBy": true
}
Every top-level key here is a real, documented setting. model pins the model for the project so a teammate on a different plan still gets consistent behavior. env injects environment variables into every session Claude Code spawns. statusLine replaces the default footer with the output of a script you control. includeCoAuthoredBy toggles the Co-Authored-By trailer on commits Claude makes. The permissions block is the part you will tune most, so it deserves its own section.
The Permissions Model in Depth
Permissions decide what Claude Code can do without stopping to ask you. The system has three lists and a default mode:
- allow — rules that run automatically with no prompt. Put your safe, repetitive commands here: your test runner, your linter, read-only git inspection.
- deny — rules that are refused outright and cannot be overridden in the session. This is your safety net for destructive or exfiltration-prone commands and for secret files.
- ask — rules that always prompt, even when a broader allow rule would otherwise have matched. Use it for actions that are fine but consequential, like pushing to a remote.
A rule is a tool name with an optional specifier in parentheses. Bash(npm run test:*) matches any command that begins with npm run test — the :* is a prefix wildcard. Read(./.env) matches a single file, and Read(./secrets/**) matches a whole tree using gitignore-style globs. File-aware tools such as Read, Edit, and Write take path patterns; WebFetch takes a domain: specifier; MCP tools use their mcp__server__tool name. A bare tool name with no parentheses matches every use of that tool.
When more than one rule could apply, deny always wins, then ask, then allow. That ordering is what makes a deny list trustworthy: an over-broad allow rule can never accidentally unlock something you explicitly denied.
The defaultMode sets the behavior for anything no rule matches. default prompts for each new kind of action, acceptEdits auto-approves file edits while still gating commands, plan restricts Claude to read-only planning, and bypassPermissions removes prompts entirely — powerful, and reserved for sandboxes you trust. You can also widen Claude's reach beyond the working directory with additionalDirectories. The goal of a good permissions block is to let the boring work flow and stop only for the things that genuinely warrant a human glance. The settings hub collects tested permission profiles you can start from.
CLAUDE.md: Your Project's Memory
Settings control what Claude Code is allowed to do; CLAUDE.md tells it what it needs to know. This Markdown file lives at your repository root and is loaded automatically at the start of every session, so anything in it is context Claude always has without you re-typing it.
Good CLAUDE.md content is the institutional knowledge a new teammate would need on day one:
- Commands — how to build, test, lint, and run the project, especially the non-obvious ones.
- Architecture — the high-level shape of the codebase and where the major pieces live.
- Conventions — naming, formatting, and patterns you want followed, plus libraries to prefer or avoid.
- Guardrails — files or directories not to touch, and steps that must run before committing.
Keep it concise and specific; a focused page beats an exhaustive one the model skims. Run /init in a new project to generate a first draft from the existing code, then edit it down. During a session you can press # to append a note to memory without leaving the conversation, and you can pull in other files with an @path/to/file import so shared standards live in one place. A user-level ~/.claude/CLAUDE.md carries personal preferences across every project, mirroring how user settings work.
How Settings Connect to Hooks
One more thing lives in settings.json: hooks. Where CLAUDE.md is guidance the model chooses to follow, a hook is a shell command the harness runs automatically on a lifecycle event — so it fires every time, not only when the model remembers. Hooks are configured under a hooks key in the very same settings files, which means the same user, project, and local precedence applies to them.
That overlap is deliberate. Your permissions deny list stops a dangerous command from running; a PreToolUse hook can inspect a command and veto it with custom logic; a PostToolUse hook can format every file the moment it is written. Together they turn preferences into guarantees. The Claude Code hooks guide walks through the lifecycle events and exit codes in detail, and the hooks catalog has installable recipes.
Installing Ready-Made Settings and Hooks
You do not have to write any of this by hand. The ToolZip catalog packages curated settings and hooks that install with a single command and merge into your existing files:
# Install a curated settings profile npx claude-code-templates@latest --setting="permissions/safe-defaults" --yes # Install a hook recipe into the same settings.json npx claude-code-templates@latest --hook="formatting/prettier-on-save" --yes
Replace the category/name with any entry from the settings catalog or hooks catalog. Because the installer merges rather than overwrites, you can layer a ready-made permissions profile on top of your own tweaks and keep both. Browse the full Claude Code component library to see settings alongside agents, commands, and MCP servers.
Practical Guidance
- Commit project settings. Checking
.claude/settings.jsonandCLAUDE.mdinto the repo gives everyone the same guardrails and context for free. - Deny first, allow deliberately. A short deny list of genuinely dangerous patterns is worth more than a sprawling allow list. Add allow rules as the same prompts start to repeat.
- Keep secrets out of settings. Never put API keys in a committed
settings.json. Deny reads of.envand secret paths instead, and keep anything sensitive in local settings or your shell. - Review before you install. Ready-made settings and hooks run with your permissions, so read what a profile changes before merging it.
Start small: a model, a handful of allow rules for the commands you approve a dozen times a day, a deny list for the ones you never want unattended, and a tight CLAUDE.md. That alone removes most of the friction from a Claude Code session. Grow the configuration as you notice the same prompt or the same explanation coming up again — every one of those is a line of settings waiting to be written.
Browse Claude Code Settings
Drop-in settings.json configurations for permissions, environment, and more.