
Optimizing your Claude Code configuration for development
Why bother tuning this
Running Claude Code on default settings leaves quota savings, automated tasks and a free security layer on the table. Here's a complete ~/.claude/settings.json, section by section.
Environment variables
{
"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 quota. DISABLE_NON_ESSENTIAL_MODEL_CALLS cuts non-critical "verification" API calls. CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: 80 raises the default 60% threshold 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, whole articles) with zero quota impact — you pay what you use. MAX_THINKING_TOKENS: 63999 maxes out extended thinking: on hard problems (algorithms, architecture), deeper thinking means better solutions.
Bash timeouts. BASH_DEFAULT_TIMEOUT_MS at 2 minutes for slow builds, BASH_MAX_TIMEOUT_MS at 10 minutes for massive compilations or deployments. And critically CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR: 1, which keeps the same pwd between commands — without it, every command restarts from home.
Experimental features. CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: 1 lets Claude spin up multiple sub-agents in parallel on complex problems, and CLAUDE_CODE_SUBAGENT_MODEL: haiku runs them on a faster, cheaper model that's plenty for most delegated work.
Privacy. DISABLE_TELEMETRY, DISABLE_ERROR_REPORTING and CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY remove telemetry and survey popups.
Security permissions
Claude Code can read, write and run shell commands anywhere. The permissions section bounds that:
{
"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.*"]
}
}
The protected paths cover SSH keys, AWS credentials, GPG keys, the GitHub token, Git credentials, ~/.netrc, the Kubernetes config and Docker registry credentials. Blocked commands are glob patterns, so be very specific.
A useful trick: put "decoy" files with fake data in sensitive paths. Any access attempt shows up in the logs immediately.
Hooks: automating before/after
Hooks run shell scripts at key moments in a session's lifecycle:
{
"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"
}
]
}
}
UserPromptSubmitfires on every submitted prompt: timestamp logging, plus auto-naming the session by extracting keywords from the prompt.Stopfires when Claude Code closes, logging the end so you can measure total duration.
You can also build hooks that ship logs to a server or run post-session tests.
UI configuration
{
"showTurnDuration": true,
"cleanupPeriodDays": 90,
"enableAllProjectMcpServers": false,
"skipDangerousModePermissionPrompt": true,
"spinnerVerbs": {
"mode": "replace",
"verbs": [" ⠋", " ⠙", " ⠹", " ⠸", " ⠼", " ⠴", " ⠦", " ⠧", " ⠇", " ⠏"]
}
}
showTurnDuration shows response time and identifies slow calls. cleanupPeriodDays: 90 auto-deletes old sessions before they saturate the disk. enableAllProjectMcpServers: false keeps the confirmation prompt before activating a project's MCP servers — a safety measure over what executes. skipDangerousModePermissionPrompt: true lets you switch into Dangerous Mode without confirmation, best reserved for users who know what they're doing.
Plugins
{
"plugins": [
{ "name": "context7", "enabled": true },
{ "name": "safety-net", "enabled": true },
{ "name": "ralph-loop", "enabled": true }
]
}
Context7 provides real-time docs for 100+ frameworks, avoiding hallucinated APIs. Safety-Net runs basic static analysis on commits and PRs before you push, catching accidentally committed secrets and sensitive logs. Ralph-Loop automatically loops on build or test errors until they're fixed, with no intervention.
Bottom line
This config isn't one-and-done: deny patterns grow as concerns arise, timeouts get adjusted per project. The goal is an environment that pushes toward best practices by default. Copy it, adapt it to your sensitive paths and dangerous commands, iterate.
Related articles