Optimizing your Claude Code configuration for development
- Published on
- ·5 min read
Introduction: mastering your AI assistant (or it masters you)
Claude Code's been my dev companion for a year+. But using default settings? Like driving with the dashboard closed. Good settings transform everything: faster responses, save quota, automated tasks, real security.
I'm going to share my complete ~/.claude/settings.json and what each thing does. Hours spent perfecting it.
Environment variables: the core
The env section controls how Claude Code behaves at the lowest level. Here's my setup:
{
"env": {
"DISABLE_NON_ESSENTIAL_MODEL_CALLS": "1",
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "80",
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "64000",
"MAX_THINKING_TOKENS": "63999",
"BASH_DEFAULT_TIMEOUT_MS": "120000",
"BASH_MAX_TIMEOUT_MS": "600000",
"MAX_MCP_OUTPUT_TOKENS": "25000",
"CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR": "1",
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
"DISABLE_TELEMETRY": "1",
"DISABLE_ERROR_REPORTING": "1",
"CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY": "1",
"CLAUDE_CODE_SUBAGENT_MODEL": "haiku"
}
}
Saving your quota (important stuff)
DISABLE_NON_ESSENTIAL_MODEL_CALLS: "1": Claude Code launches "verification" API calls that aren't critical. Disabling keeps quota for real work.
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "80": Default is 60%. I use 80% to keep more history. Useful when you return to a problem discussed an hour ago.
CLAUDE_CODE_MAX_OUTPUT_TOKENS: "64000": Allows very long responses (massive refactorings, articles). Zero quota impact - you pay what you use.
MAX_THINKING_TOKENS: "63999": Extended thinking at max. For hard problems (algorithms, architectures), deep thinking = better solutions.
Managing bash timeouts (crucial!)
BASH_DEFAULT_TIMEOUT_MS: "120000": 2 minutes. Max time before a bash command times out. Useful for slow builds or lengthy tests.
BASH_MAX_TIMEOUT_MS: "600000": 10 minutes if you really want to wait. For massive compilations or deployments.
CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR: "1": CRITICAL. Claude keeps the same pwd between bash commands. Without this, every command restarts from home - nightmare.
Experimental features (actually useful)
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1": Agent teams. If the problem's complex, Claude creates multiple sub-agents working in parallel. Game-changing for multi-faceted projects.
CLAUDE_CODE_SUBAGENT_MODEL: "haiku": Sub-agents use Haiku (faster, cheaper). Haiku is plenty for 90% of work tasks.
Privacy first (because why not)
DISABLE_TELEMETRY: "1", DISABLE_ERROR_REPORTING: "1", CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY: "1": No telemetry, no survey popups. Autonomy over your data.
Security permissions: lock down what matters
Claude Code can read/write anywhere and run shell commands. Powerful - but risky. The permissions section says "no":
{
"permissions": {
"deny": [
"~/.ssh/**",
"~/.aws/**",
"~/.gnupg/**",
"~/.config/gh/**",
"~/.git-credentials",
"~/.netrc",
"~/.kube/config",
"~/.docker/config.json"
],
"blockCommands": ["rm -rf /*", "git push --force", "sudo rm", "dd if=/dev/zero", "mkfs.*"]
}
}
Sensitive files:
~/.ssh/**: SSH keys (PRIVATE!)~/.aws/**: AWS credentials~/.gnupg/**: GPG keys~/.config/gh/**: GitHub token~/.git-credentials: Git credentials~/.kube/config: Kubernetes~/.docker/config.json: Docker registry creds
Blocked commands: Glob patterns like git push --force *. Security is pattern-based - be very specific.
Pro tip: I've created "decoy" files with fake data in sensitive paths. If Claude tries to access them, I see it in the logs immediately. (once caught a hallucination trying to read ~/.ssh)
Hooks: automating before/after
Hooks = shell scripts executed at key moments. I use them to track sessions and metrics:
{
"hooks": {
"UserPromptSubmit": [
{
"name": "claude-prompt-start",
"command": "echo \"[$(date +'%Y-%m-%d %H:%M:%S')] Prompt submitted\" >> ~/.claude/session.log"
},
{
"name": "autoname-session.sh",
"command": "~/.claude/autoname-session.sh"
}
],
"Stop": [
{
"name": "claude-prompt-end",
"command": "echo \"[$(date +'%Y-%m-%d %H:%M:%S')] Session ended\" >> ~/.claude/session.log"
}
]
}
}
UserPromptSubmit: Triggered when you submit a prompt. Useful for:
- Logging timestamps
- Auto-naming sessions based on prompt content (my
autoname-session.shextracts keywords)
Stop: Triggered when Claude Code closes. I log the end to measure total duration.
You can also create hooks that send logs to servers, or run post-session tests.
UI configuration and polish (the small things)
{
"showTurnDuration": true,
"cleanupPeriodDays": 90,
"enableAllProjectMcpServers": false,
"skipDangerousModePermissionPrompt": true,
"spinnerVerbs": {
"mode": "replace",
"verbs": [" ⠋", " ⠙", " ⠹", " ⠸", " ⠼", " ⠴", " ⠦", " ⠧", " ⠇", " ⠏"]
}
}
showTurnDuration: true : Shows response time. Identifies slow calls.
cleanupPeriodDays: 90 : Auto-deletes sessions older than 90 days. Don't saturate your disk.
enableAllProjectMcpServers: false : By default, Claude Code asks before activating project MCP servers. Safety measure - you control what executes.
skipDangerousModePermissionPrompt: true : I'm a power user so I trust myself. Lets me switch to "Dangerous Mode" without confirmation. Use carefully!
Plugins: the superpowers
{
"plugins": [
{
"name": "context7",
"enabled": true
},
{
"name": "safety-net",
"enabled": true
},
{
"name": "ralph-loop",
"enabled": true
}
]
}
Context7: Real-time doc access for 100+ frameworks/libs. Instead of Claude hallucinating Next.js v15's API, it looks it up.
Safety-Net: Basic static analysis on commits/PRs before you push - detects accidentally committed secrets, sensitive logs, etc. Handy.
Ralph-Loop: If Claude detects a build/test error, it automatically loops to fix it. Revolutionary.
The complete file
Here's my full settings.json:
{
"env": {
"DISABLE_NON_ESSENTIAL_MODEL_CALLS": "1",
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "80",
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "64000",
"MAX_THINKING_TOKENS": "63999",
"BASH_DEFAULT_TIMEOUT_MS": "120000",
"BASH_MAX_TIMEOUT_MS": "600000",
"MAX_MCP_OUTPUT_TOKENS": "25000",
"CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR": "1",
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
"DISABLE_TELEMETRY": "1",
"DISABLE_ERROR_REPORTING": "1",
"CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY": "1",
"CLAUDE_CODE_SUBAGENT_MODEL": "haiku"
},
"permissions": {
"deny": [
"~/.ssh/**",
"~/.aws/**",
"~/.gnupg/**",
"~/.config/gh/**",
"~/.git-credentials",
"~/.netrc",
"~/.kube/config",
"~/.docker/config.json"
],
"blockCommands": ["rm -rf /*", "git push --force", "sudo rm", "dd if=/dev/zero", "mkfs.*"]
},
"hooks": {
"UserPromptSubmit": [
{
"name": "claude-prompt-start",
"command": "echo \"[$(date +'%Y-%m-%d %H:%M:%S')] Prompt submitted\" >> ~/.claude/session.log"
}
],
"Stop": [
{
"name": "claude-prompt-end",
"command": "echo \"[$(date +'%Y-%m-%d %H:%M:%S')] Session ended\" >> ~/.claude/session.log"
}
]
},
"showTurnDuration": true,
"cleanupPeriodDays": 90,
"enableAllProjectMcpServers": false,
"skipDangerousModePermissionPrompt": true,
"spinnerVerbs": {
"mode": "replace",
"verbs": [" ⠋", " ⠙", " ⠹", " ⠸", " ⠼", " ⠴", " ⠦", " ⠧", " ⠇", " ⠏"]
},
"plugins": [
{
"name": "context7",
"enabled": true
},
{
"name": "safety-net",
"enabled": true
},
{
"name": "ralph-loop",
"enabled": true
}
]
}
Bottom line
Configuring Claude Code isn't one-and-done. I revisit regularly, add deny patterns when cautious, adjust timeouts. The goal: an environment that pushes toward best practices.
Copy this config, adapt to your context (your sensitive paths, dangerous commands), iterate. Claude Code quickly becomes a real productivity multiplier.