Configure

Three layers, one file of yours, and the keys you can set in it.

Three layers

Configuration is three layers, deep-merged low to high:

LayerPathWho writes it
defaultscompiled into the binarynobody — they ship with it
user~/.config/claude-status/config.jsonyou
repo<repo-root>/.config/claude-status.jsonyou, per repository, by hand

Objects merge key by key. Arrays and scalars replace wholesale, so setting lines in your config gets you exactly the layout you asked for rather than yours appended to the default.

A layer that is missing, malformed or not a JSON object is ignored and the bar still draws. Nothing here is fragile, and nothing here is required — with no file anywhere at all, every default below is in effect.

The repo layer is a special case: it may set one key, and it is covered on its own page — see Per-repo.

Your file

Put only what you changed in it. Anything you leave alone follows the binary forward when you upgrade.

Generate a config builds this file from the published schema, with every key’s description beside it — or write it by hand from the reference below.

{
  "$schema": "https://raw.githubusercontent.com/virajp/claude-status/main/schemas/claude-status.schema.json",
  "lines": [
    ["model", "context", "rl5h", "rl7d", "spend", "cost"],
    ["project", "worktree", "branch"]
  ],
  "segments": {
    "cost": { "bg": "green", "bold": true }
  }
}

The $schema pointer is worth keeping: an editor that understands JSON Schema will then complete the key names and reject the ones that do not exist. The schema itself is generated from the binary’s own types, so it cannot drift from what the binary accepts.

Drawing the bar never writes to your configuration. Whatever it needs to draw, it reads. A render does write two things, neither of them yours: the spend cache under ~/.cache/claude-status/, from a detached background refresh; and — only when you have set CLAUDE_STATUS_USAGE_DIR — a small usage mirror for that session, written in-process on every render so the caps hook has something to read. The one command that writes a config file is --configure, which you run yourself.

The keys

KeyIs
linesordered rows of segment entries — the layout. See Segments
segmentsdefault styling per segment id
palettenamed colours as [r, g, b] triples
defaultFgforeground for any segment that does not set its own fg
powerlinethe divider glyphs: cap, sep, sepThin, thinFg
gaugethe context meter: width, filled, empty
symbolsthe glyph drawn before each kind of value
typeSymbolsglyph per subagent type, with _default as the fallback
capsthe four thresholds the PostToolUse hook measures against
spendrefreshMinutes and show for the monthly-budget segment
subagentstyling and the description budget for the subagent panel
worktreePatternthe regex that decides a checkout is a worktree
projectNamebelongs in the repo layer — a user-layer value names every repo

Colours

A colour is one of three things, anywhere one is expected:

  • a palette name"aqua", "orange", or any key you added to palette
  • a hex string"#d79921" or "#fa0"
  • an RGB triple[215, 153, 33]

null clears a colour the defaults set, so that segment falls through to defaultFg.

Styling resolves inline override → segments.<id> → the built-in fallback. An entry in lines can therefore be a plain id, or an object that names one and overrides its colours just for that position:

{
  "lines": [
    ["model", { "name": "cost", "bg": "red", "bold": true }]
  ]
}

Caps

The --caps-hook runs after each tool call and compares your usage to these. Cross one and it injects a directive telling Claude to finish the current step, write a handoff, and stop — once per escalation, so it will not nag.

The hook does nothing until you set CLAUDE_STATUS_USAGE_DIR. It reads your usage from a mirror written there by the render, and there is no default location — with the variable unset the hook exits silently and successfully every time, so a broken setup looks exactly like a quiet one. --configure wires the hook but cannot set the variable for you, because it belongs to the environment Claude Code runs in rather than to a file this binary owns. Set it wherever that environment is defined:

export CLAUDE_STATUS_USAGE_DIR="$HOME/.cache/claude-status/usage"

claude-status --debug will not tell you the variable is missing either — the caps thresholds it prints are the ones the hook would use. If you want to know the hook is live, set the variable, run a session, and check that files appear in that directory.

{
  "caps": {
    "context": 65,
    "fiveHour": 90,
    "sevenDay": 80,
    "spend": 90
  }
}

Those are the shipped values, as percentages. Set any one of them and the others keep their defaults.

spend only ever fires on a seat that has a monthly budget, and it is checked before the other three: a rate-limit window empties itself on a timer, whereas an exhausted budget needs somebody to act. The figure comes from the same cache the spend segment reads, so the hook never fetches.

A cap that is absent, negative, non-numeric or above 1000 falls back to its shipped default. 0 is a real cap, meaning “breach on any usage at all”.

The spend segment

spend shows an account’s monthly budget, and it is built for team and enterprise seats whose limit is a spend cap rather than the rolling windows. On a Pro or Max seat it stays hidden under the default show: "auto" — that is working as intended, and it is much the most common reason you do not see it.

{
  "spend": {
    "show": "auto",
    "refreshMinutes": 15
  }
}

show: "always" renders it whenever budget data exists — useful for watching an extra-usage credit cap on a Pro or Max seat. refreshMinutes is the minimum gap between fetches; 0 disables the background refresh entirely and the segment then renders whatever the cache already holds.

Four gates can hide it, in order: it is not in your lines; there is no usable cached figure yet; the account has no budget block; or the seat is one that auto hides. --debug tells you which one applied.

A render never fetches. The figure comes from a cache at ~/.cache/claude-status/spend.json, refreshed in the background by a child process the render never waits on.

Environment variables

Two are optional. The third is not, if you want the caps hook to do anything:

VariableDoes
CLAUDE_STATUS_SPEND_CACHEoverride the spend cache path
CLAUDE_STATUS_SPEND_URLoverride the usage endpoint — for testing
CLAUDE_STATUS_USAGE_DIRwhere the usage mirror is written — the caps hook is inert without it