Status Line
The status line is a bar at the bottom of Claude Code that shows the output of a script you write.
The script gets session data as JSON on stdin, such as the model and the cost. It prints what to show on stdout.
It does not use API tokens.
At a Glance
| Question | Answer |
|---|---|
| Can you use it? | ✅ Yes. Run / and describe what you want, or write a script yourself. |
| Can you change it? | ✅ Yes. Edit the status key in a settings file. |
| Can you turn it on or off? | Remove status, or run /. disable turns off custom ones. |
| Where does it live? | The status key of user, project, local, or managed settings, and the script it names. |
| Status | Documented Undocumented Differs |
Example
#!/bin/sh
input=$(cat)
model=$(echo "$input" | jq -r '.model.display_name')
used=$(echo "$input" | jq -r '.context_window.used_percentage // 0')
echo "$model | context ${used}%"
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh",
"padding": 1,
"refreshInterval": 30
}
}
The bar shows the model name and how full the context window is. The script also re-runs every 30 seconds.
Settings
Official page: Customize Your Status Line.
| Item | Status | What it does | How it works | Where to set it |
|---|---|---|---|---|
status | Documented | Kind of status line | Must be "command". Required | User, project, local, managed |
status | Documented | Script path or inline shell command | Runs in a shell. A change to it runs the new command at once, without the debounce | Same |
status | Documented | Extra horizontal space in characters | Default 0. Adds to the built-in spacing | Same |
status | Documented | Re-runs the command every N seconds | Minimum 1. The bundle uses Math. ms. For clocks and idle sessions | Same |
status | Documented | Hides the built-in -- text | Use when the script prints vim. itself | Same |
subagent | Documented | Custom row for each subagent in the agent panel | Fields type ("command") and command. See the next section | Same |
/ | Documented | Writes a script in ~/. and the setting | Takes natural language. / removes it | Interactive |
disable | Documented | When true outside managed settings, only a managed status runs | With no managed status the status line is off | Settings |
allow | Documented | Only a managed status shows | A custom one disappears without a warning | Managed |
| Workspace trust | Documented | The command waits for trust | -- logs Status line command skipped: | Project files |
CLAUDE_ | Documented | Status line commands do not load | Managed policy still applies | Env |
When the Script Runs
| Item | Status | What it does | How it works | Where to set it |
|---|---|---|---|---|
| Session start and resume | Documented | First run | Runs once | Each session |
New assistant message, / done, permission mode change, vim mode toggle | Documented | Re-runs the command | Debounced at 300ms. A new trigger cancels a running script | Each session |
Rate-limit resets_ and cache expires_ | Documented | Re-runs at the earliest time | Taken from the data the script last received | Each session |
| Model, fast mode, effort, thinking, and PR status change | Differs | Also re-run the command | The bundle watches main, fast, effort, thinking, pr. The docs list do not name them | Each session |
Output Rules
- Each printed line is a row. ANSI colors and OSC 8 links work.
- The output shows only after exit code
0. A non-zero exit or empty output blanks the line. - Claude Code sets
COLUMNSandLINESbefore it runs the script.tput colsdoes not work. - The variables
CLAUDECODEandCLAUDE_CODE_CHILD_SESSIONare set in the script process. See Environment Variables. claude --debuglogsstderrof each run and the exit code of the first run.- The line hides during the help menu and permission prompts. Outside fullscreen, notifications share the row.
- On Windows, use forward slashes in
command.CLAUDE_CODE_POWERSHELL_RESPECT_EXECUTION_POLICYchanges the PowerShell policy flag.
Source for this list: the official Customize Your Status Line and Environment Variables pages.
Subagent Status Line
subagentStatusLine customizes each subagent row in the agent panel.
Its command runs once per refresh tick and gets all visible rows as one JSON object.
It prints one JSON line for each row it wants to override: {"id": "<task id>", "content": "<row body>"}.
A row without id keeps the default. An empty content hides the row.
The same trust, disableAllHooks, and allowManagedHooksOnly gates apply.
A plugin can ship a default subagentStatusLine in its settings.json.
The input fields are in the Subagent Task Fields table below.
JSON Fields
These fields arrive on stdin. A field marked "may be absent" is missing from the JSON when it has no value.
Always read optional fields with a default, for example jq -r '.vim.mode // empty'.
Session and Model Fields
| Field | Status | What it holds | Notes | Where |
|---|---|---|---|---|
session_ | Documented | Session id | String | Status line |
session_ | Documented | Custom name or AI title | May be absent. The default display name does not fill it | Status line |
prompt_ | Documented | UUID of the prompt in work | May be absent before the first input | Status line |
transcript_ | Documented | Transcript file path | String | Status line |
cwd | Documented | Working directory | Same value as workspace. | Status line |
version | Documented | Claude Code version | 2. here | Status line |
model., model. | Documented | Model id and name | Strings | Status line |
output_ | Documented | Active style name | default when none. See Output Styles | Status line |
fast_ | Documented | Fast mode on | Boolean | Status line |
effort. | Documented | low, medium, high, xhigh, max | May be absent when the model has no effort | Status line |
thinking. | Documented | Extended thinking on | Boolean | Status line |
vim. | Documented | NORMAL, INSERT, VISUAL, VISUAL LINE | May be absent. Present when vim mode is on | Status line |
agent. | Documented | Agent name | Present with -- or agent settings | Status line |
remote. | Undocumented | Id of a remote session | Present when the session is remote. The docs do not list remote | Status line |
Workspace Fields
| Field | Status | What it holds | Notes | Where |
|---|---|---|---|---|
workspace. | Documented | Current directory | Preferred over cwd | Status line |
workspace. | Documented | Launch directory | The bundle fills it from the original cwd | Status line |
workspace. | Documented | Directories from / or -- | Empty array if none | Status line |
workspace. | Documented | Linked worktree name | Absent in the main tree | Status line |
workspace., ., . | Documented | Repository identity from origin | May be absent. GitLab subgroups give a slash path in owner | Status line |
worktree., ., ., ., . | Documented | Worktree session data | Only in a worktree session. branch and original_ may be absent for hook-based worktrees | Status line |
pr., pr. | Documented | Open PR or GitLab merge request | Removed once it merges or closes | Status line |
pr. | Documented | approved, pending, changes_, draft | May be absent alone | Status line |
pr. | Documented | mr for a GitLab merge request | Absent for GitHub | Status line |
Cost, Context, and Limit Fields
| Field | Status | What it holds | Notes | Where |
|---|---|---|---|---|
cost. | Documented | Estimated cost | Client-side list price. Resets at / | Status line |
cost., cost. | Documented | Wall time and API wait time | Milliseconds | Status line |
cost., cost. | Documented | Lines changed | Numbers | Status line |
context_, . | Documented | Tokens in the window | From the last response. 0 before it | Status line |
context_ | Documented | Window size | 200000 or 1000000 | Status line |
context_, . | Documented | Percent used and left | Input tokens only. May be null early | Status line |
context_ | Documented | Per-category tokens | Keys input_, output_, cache_, cache_. null before the first call and after / | Status line |
exceeds_ | Documented | Last response is over 200k tokens | Fixed threshold | Status line |
rate_, . | Documented | used_ and resets_ | Claude.ai Pro and Max only. A window drops after its reset time | Status line |
rate_, . | Documented | Gateway spend limit | Needs 2. | Status line |
rate_, ., . | Documented | Spend in dollars and period daily, weekly, monthly | Needs 2.. Off with CLAUDE_ | Status line |
Prompt Cache Fields
The object prompt_cache appears after the first main-conversation response (needs 2.1.251). Subagent requests are not counted.
| Field | Status | What it holds | Notes | Where |
|---|---|---|---|---|
prompt_ | Documented | Cache is within its TTL | Boolean | Status line |
prompt_ | Documented | Any response reported cache tokens | false means caching is off or not reported | Status line |
prompt_ | Documented | Cache lifetime | "5m" or "1h" | Status line |
prompt_ | Documented | When the cache goes cold | Epoch seconds. null if no cache tokens | Status line |
prompt_, ., . | Documented | Request and miss counts | A miss is over 5% and at least 2,000 tokens re-processed | Status line |
prompt_ | Documented | Cache reads over all input tokens | 0 to 1. null when counts are zero | Status line |
prompt_, . | Documented | Tokens written | Totals for the session and for misses | Status line |
prompt_ | Documented | Time of the last miss | Epoch seconds. null if none | Status line |
prompt_ | Documented | Likely cause | causes array (such as tools_, system_, ttl_, likely_), plus tools_, tools_, system_. Needs 2. | Status line |
prompt_ | Documented | Count per cause | Map | Status line |
prompt_ | Documented | Tokens a cold cache re-caches | null after a compaction until the next request | Status line |
Subagent Task Fields
The subagentStatusLine command gets the base hook fields, columns, and a tasks array.
| Field | Status | What it holds | Notes | Where |
|---|---|---|---|---|
columns | Documented | Usable row width | Number | subagent |
tasks[]. | Documented | Task id | Echo it back as id | subagent |
tasks[]. | Documented | Address name | Optional | subagent |
tasks[]. | Documented | Kind of task | local_ | subagent |
tasks[]. | Documented | Subagent type | Same value as hook agent_. Needs 2. | subagent |
tasks[]. | Documented | State | running, completed, failed, killed | subagent |
tasks[]., tasks[]. | Documented | Short text | label is a progress summary, else description | subagent |
tasks[]. | Documented | Start time | Epoch milliseconds | subagent |
tasks[]., tasks[]. | Documented | Resolved model and its window | Optional | subagent |
tasks[]. | Documented | Configured effort | String or number. Needs 2. | subagent |
tasks[]., tasks[]. | Documented | Running tokens and up to 16 samples | Oldest first | subagent |
tasks[]. | Documented | Subagent working directory | Own worktree if any | subagent |
How It Works
The exact debounce for subagentStatusLine. The source of transcript_path and prompt_id inside the program (a shared helper adds them).
Related Pages
- Output Styles for the style behind
output_style.name. - Environment Variables
- Context and Compaction for what
context_windowcounts. - Request and Cache for what
prompt_cachemeasures.