Claude Code Settings: Ideal vs. Reality
@adocomplete posted “5 Claude Code Settings” on X. Went in hoping to escape the constant Ask prompts — and came out with a clearer picture of where the ideal meets reality.
Previously wrote about Claude Code permission settings being completely opaque, about three weeks ago. Did anything change? Time to check.
The 5 Settings
Here’s what Ado shared:
1. defaultMode: “acceptEdits”
{
"permissions": {
"defaultMode": "acceptEdits"
}
}
Auto-approve file edits. Bash commands still prompt.
The idea: you’re reviewing the diff anyway, so clicking “approve” on each edit is just noise.
2. attribution
{
"attribution": {
"commit": "",
"pr": ""
}
}
Controls the Co-authored-by: Claude line in git commits and pull requests. Empty string gives you a clean history.
Replaces the old includeCoAuthoredBy setting.
3. cleanupPeriodDays
{
"cleanupPeriodDays": 0
}
How many days to keep session history. Default is 30.
0: wipe every session- Larger values: keep history longer
4. alwaysThinkingEnabled
{
"alwaysThinkingEnabled": true,
"env": {
"MAX_THINKING_TOKENS": "8000"
}
}
Enables Extended Thinking on every response. Trades latency for quality.
The MAX_THINKING_TOKENS env var controls how many tokens to spend on thinking.
5. additionalDirectories
{
"permissions": {
"additionalDirectories": ["../shared-lib", "~/docs"]
}
}
By default, Claude Code is sandboxed to the project directory. Use this to grant access to shared libraries or sibling directories in a monorepo.
Where the Settings Live
| OS | User settings | Project settings |
|---|---|---|
| Windows | %USERPROFILE%\.claude\settings.json | .claude/settings.json |
| macOS/Linux | ~/.claude/settings.json | .claude/settings.json |
Project settings can be committed to git. Personal overrides go in .claude/settings.local.json (gitignore recommended).
The Gap Between Expectation and Reality
Here’s where things get interesting.
Wildcards aren’t truly wild
Writing Bash(npm *) doesn’t prevent Bash(npm run build:*) from being added separately.
The official docs say it plainly:
Bash rules use prefix matching, not regex
Bash patterns are prefix matches and can be bypassed
Prefix matching, not regex. And explicitly “can be bypassed.”
bypassPermissions still asks for some things
defaultMode has three levels:
| Mode | Behavior |
|---|---|
askAlways | Prompt every time (default) |
acceptEdits | Auto-approve files, prompt for Bash |
bypassPermissions | Auto-approve everything |
Thought bypassPermissions meant fully hands-off. In practice, some minimum confirmations still appeared — WebFetch needed individual approval too.
Side note: built a WebFetch alternative skill to skip approval prompts, but it’s not a complete solution since Claude Code can’t access sites it can’t access regardless of the skill.
One creative workaround: use an MCP to have Gemini fetch URLs and pass back only the results. AI collaboration — Gemini is less likely to block Google’s own ecosystem.
The allow list has limits
{
"permissions": {
"allow": [
"Bash(pnpm:*)",
"Bash(git:*)"
]
}
}
This should mean “pnpm and git, no questions.” Mostly.
In practice, each new subcommand gets appended to settings.local.json. The issue described in the previous article is still there.
What Actually Works
Perfect control isn’t realistic. Tune to your workflow.
”One task, one chat” style
{
"cleanupPeriodDays": 0,
"permissions": {
"defaultMode": "acceptEdits"
}
}
No need for session history. Once the task is done, the context is done. Useful knowledge goes into CLAUDE.md.
”Just let it run” style
{
"permissions": {
"defaultMode": "acceptEdits",
"allow": [
"Bash(pnpm:*)",
"Bash(npm:*)",
"Bash(git:*)",
"Bash(docker:*)"
]
}
}
Pre-allow the common commands. Not perfect, but reduces the Ask frequency.
Quality-focused style
{
"alwaysThinkingEnabled": true,
"env": {
"MAX_THINKING_TOKENS": "10000"
}
}
Useful for complex refactors or architecture decisions. But there’s a latency and cost tradeoff (when using the API).
For simple tasks, using /think on demand is often more efficient than always-on thinking.
What I Adopted and What I Didn’t
| Setting | Adopted | Reason |
|---|---|---|
defaultMode: "acceptEdits" | Yes | Want to hand off the work |
cleanupPeriodDays: 0 | Yes | One task, one chat |
attribution: "" | No | Keeping AI attribution for transparency |
alwaysThinkingEnabled | No | /think when needed is enough |
additionalDirectories | No | Not needed for current project structure |
There’s no single configuration that makes Claude Code perfect.
- Wildcards are prefix matches and can be bypassed
bypassPermissionsstill prompts for some things- The
allowlist isn’t airtight, but it does reduce Ask frequency
Don’t chase perfection. Cherry-pick what fits your workflow and accept that things won’t always behave exactly as configured — that’s just how it is.
References
- @adocomplete — original post
- Claude Code settings — official docs
Related articles
- Claude Code Permission Settings: I Have No Idea What’s Going On — the prequel to this post
- Claude Code Session Management, How Do You Handle It? — session management and skill workflows
- Token Management Guide for When Your CLAUDE.md Gets Out of Hand — MCP usage and the 4-layer strategy
- Claude Code Tips Complete Guide — 10 picks from 44 techniques