headroom.walls.sh · settings
Claude Code settings.json
Complete reference for ~/.claude/settings.json — every field, with examples and the statusLineHook that powers live usage display.
File locations
Claude Code reads settings from two places, merging them (project wins over user):
| File | Scope |
|---|---|
| ~/.claude/settings.json | User-level — applies to every project |
| .claude/settings.json | Project-level — applies only in this repo |
Create either with claude config or edit directly. Both are plain JSON with no schema validation — typos fail silently, so double-check key names.
Top-level fields
model
Set the default model for all sessions.
{
"model": "claude-sonnet-4-6"
}
Overridden by --model on the CLI or /model inside a session. Valid values: any Claude model ID (e.g. claude-opus-4-8, claude-haiku-4-5-20251001).
permissions
Control which tools Claude Code can use without asking for confirmation. Structure:
{
"permissions": {
"allow": [
"Bash(git:*)",
"Bash(npm run *)",
"Read(**)",
"Edit(**)"
],
"deny": [
"Bash(rm -rf *)"
]
}
}
Each entry is ToolName(pattern). The pattern is matched against the tool's input. allow entries skip the confirmation prompt; deny entries block without prompting. Deny takes precedence over allow.
Common patterns:
| Pattern | What it allows |
|---|---|
| Bash(*) | All shell commands without prompting |
| Bash(git:*) | Any git command |
| Bash(npm run *) | npm run scripts only |
| Read(**) | Reading any file |
| Edit(**) | Editing any file |
| WebFetch(*) | Fetching any URL |
env
Environment variables injected into every Claude Code session and all hooks.
{
"env": {
"ANTHROPIC_SMALL_FAST_MODEL": "claude-haiku-4-5-20251001",
"NODE_ENV": "development"
}
}
includeCoAuthoredBy
Whether to append the Co-Authored-By: Claude trailer to commits Claude Code creates. Defaults to true.
{
"includeCoAuthoredBy": false
}
cleanupPeriodDays
How many days before Claude Code prunes old conversation transcripts. Defaults to 30.
{
"cleanupPeriodDays": 7
}
hooks
Hooks are shell commands Claude Code runs at specific lifecycle events. Each hook receives structured JSON on stdin and can write structured JSON to stdout to influence Claude Code's behavior.
{
"hooks": {
"PreToolUse": [...],
"PostToolUse": [...],
"Stop": [...],
"Notification": [...],
"SubagentStop": [...],
"PreCompact": [...]
}
}
Each hook is an array of hook objects:
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "echo 'Claude stopped'"
}
]
}
]
}
}
statusLineHook — the most useful hook
The statusLineHook field (a sibling of hooks, not inside it) runs a command every time Claude Code refreshes its status line. The command's stdout becomes the text shown. It also writes usage data to ~/.claude/headroom-usage.json, which is how Headroom reads your live session and weekly percentages.
{
"statusLineHook": "cat ~/.claude/headroom-usage.json 2>/dev/null | jq -r '"CC \(.sessionUsagePct|floor)%·\(.weeklyUsagePct|floor)%"' 2>/dev/null || echo 'CC --%'"
}
This is the complete setup for Headroom. Once this line is in your ~/.claude/settings.json, Headroom reads the file and shows your real usage. No other configuration needed.
The file ~/.claude/headroom-usage.json is written by Claude Code, not by Headroom. Headroom only reads it. This is why Headroom makes zero network calls — the data is already local.
Full JSON written by the hook:
{
"sessionUsagePct": 34.2,
"weeklyUsagePct": 61.8,
"sessionCost": 0.42,
"modelName": "claude-sonnet-4-6",
"sessionResetSec": 9847,
"weeklyResetSec": 198432
}
→ Full statusLineHook docs and examples · All status line fields explained
Complete example
A typical power-user ~/.claude/settings.json:
{
"model": "claude-sonnet-4-6",
"statusLineHook": "cat ~/.claude/headroom-usage.json 2>/dev/null | jq -r '"CC \(.sessionUsagePct|floor)%·\(.weeklyUsagePct|floor)%"' 2>/dev/null || echo 'CC --%'",
"permissions": {
"allow": [
"Bash(git *)",
"Bash(npm run *)",
"Bash(make *)",
"Read(**)",
"Edit(**)"
]
},
"env": {
"ANTHROPIC_SMALL_FAST_MODEL": "claude-haiku-4-5-20251001"
},
"includeCoAuthoredBy": true,
"cleanupPeriodDays": 30
}
Project-level settings
Project-level settings at .claude/settings.json override user-level settings for the same keys. Useful for per-project model overrides or additional permissions for a specific codebase.
{
"model": "claude-opus-4-8",
"permissions": {
"allow": [
"Bash(docker *)",
"Bash(kubectl *)"
]
}
}
The statusLineHook should usually live in your user-level ~/.claude/settings.json, not project-level — you want usage visible everywhere, not just in one repo.
Applying changes
Changes to settings.json take effect the next time Claude Code starts or when you run /reload inside an active session. There's no watch mode — edits to the file mid-session require a reload.
Once the statusLineHook is set, Headroom shows your Claude Code session (5h) and weekly (7d) usage as a live % in the menu bar — color-coded before a limit stops you mid-task. Free, MIT, ~267 KB.
brew install --cask patwalls/tap/headroom
→ Hook setup docs
→ Rate limits explained
→ Claude Code tips and tricks
→ FAQ