← Back to daily report

statusline.md

Changed on 2026-01-16 10:19:13 EST

+9 lines added
-1 lines removed
Visual Diff
# Status line configuration¶

> Create a custom status line for Claude Code to display contextual information¶

Make Claude Code your own with a custom status line that displays at the bottom of the Claude Code interface, similar to how terminal prompts (PS1) work in shells like Oh-my-zsh.¶

## Create a custom status line¶

You can either:¶

* Run `/statusline` to ask Claude Code to help you set up a custom status line. By default, it will try to reproduce your terminal's prompt, but you can provide additional instructions about the behavior you want to Claude Code, such as `/statusline show the model name in orange`¶

* Directly add a `statusLine` command to your `.claude/settings.json`:¶

```json theme={null}¶
{¶
"statusLine": {¶
"type": "command",¶
"command": "~/.claude/statusline.sh",¶
"padding": 0 // Optional: set to 0 to let status line go to edge¶
}¶
}¶
```¶

## How it Works¶

* The status line is updated when the conversation messages update¶
* Updates run at most every 300 ms¶
* The first line of stdout from your command becomes the status line text¶
* ANSI color codes are supported for styling your status line¶
* Claude Code passes contextual information about the current session (model, directories, etc.) as JSON to your script via stdin¶

## JSON Input Structure¶

Your status line command receives structured data via stdin in JSON format:¶

```json theme={null}¶
{¶
"hook_event_name": "Status",¶
"session_id": "abc123...",¶
"transcript_path": "/path/to/transcript.json",¶
"cwd": "/current/working/directory",¶
"model": {¶
"id": "claude-opus-4-1",¶
"display_name": "Opus"¶
},¶
"workspace": {¶
"current_dir": "/current/working/directory",¶
"project_dir": "/original/project/directory"¶
},¶
"version": "1.0.80",¶
"output_style": {¶
"name": "default"¶
},¶
"cost": {¶
"total_cost_usd": 0.01234,¶
"total_duration_ms": 45000,¶
"total_api_duration_ms": 2300,¶
"total_lines_added": 156,¶
"total_lines_removed": 23¶
},¶
"context_window": {¶
"total_input_tokens": 15234,¶
"total_output_tokens": 4521,¶
"context_window_size": 200000,¶
"used_percentage": 42.5,¶
"remaining_percentage": 57.5,¶
"current_usage": {¶
"input_tokens": 8500,¶
"output_tokens": 1200,¶
"cache_creation_input_tokens": 5000,¶
"cache_read_input_tokens": 2000¶
}¶
}¶
}¶
```¶

## Example Scripts¶

### Simple Status Line¶

```bash theme={null}¶
#!/bin/bash¶
# Read JSON input from stdin¶
input=$(cat)¶

# Extract values using jq¶
MODEL_DISPLAY=$(echo "$input" | jq -r '.model.display_name')¶
CURRENT_DIR=$(echo "$input" | jq -r '.workspace.current_dir')¶

echo "[$MODEL_DISPLAY] 📁 ${CURRENT_DIR##*/}"¶
```¶

### Git-Aware Status Line¶

```bash theme={null}¶
#!/bin/bash¶
# Read JSON input from stdin¶
input=$(cat)¶

# Extract values using jq¶
MODEL_DISPLAY=$(echo "$input" | jq -r '.model.display_name')¶
CURRENT_DIR=$(echo "$input" | jq -r '.workspace.current_dir')¶

# Show git branch if in a git repo¶
GIT_BRANCH=""¶
if git rev-parse --git-dir > /dev/null 2>&1; then¶
BRANCH=$(git branch --show-current 2>/dev/null)¶
if [ -n "$BRANCH" ]; then¶
GIT_BRANCH=" | 🌿 $BRANCH"¶
fi¶
fi¶

echo "[$MODEL_DISPLAY] 📁 ${CURRENT_DIR##*/}$GIT_BRANCH"¶
```¶

### Python Example¶

```python theme={null}¶
#!/usr/bin/env python3¶
import json¶
import sys¶
import os¶

# Read JSON from stdin¶
data = json.load(sys.stdin)¶

# Extract values¶
model = data['model']['display_name']¶
current_dir = os.path.basename(data['workspace']['current_dir'])¶

# Check for git branch¶
git_branch = ""¶
if os.path.exists('.git'):¶
try:¶
with open('.git/HEAD', 'r') as f:¶
ref = f.read().strip()¶
if ref.startswith('ref: refs/heads/'):¶
git_branch = f" | 🌿 {ref.replace('ref: refs/heads/', '')}"¶
except:¶
pass¶

print(f"[{model}] 📁 {current_dir}{git_branch}")¶
```¶

### Node.js Example¶

```javascript theme={null}¶
#!/usr/bin/env node¶

const fs = require('fs');¶
const path = require('path');¶

// Read JSON from stdin¶
let input = '';¶
process.stdin.on('data', chunk => input += chunk);¶
process.stdin.on('end', () => {¶
const data = JSON.parse(input);¶

// Extract values¶
const model = data.model.display_name;¶
const currentDir = path.basename(data.workspace.current_dir);¶

// Check for git branch¶
let gitBranch = '';¶
try {¶
const headContent = fs.readFileSync('.git/HEAD', 'utf8').trim();¶
if (headContent.startsWith('ref: refs/heads/')) {¶
gitBranch = ` | 🌿 ${headContent.replace('ref: refs/heads/', '')}`;¶
}¶
} catch (e) {¶
// Not a git repo or can't read HEAD¶
}¶

console.log(`[${model}] 📁 ${currentDir}${gitBranch}`);¶
});¶
```¶

### Helper Function Approach¶

For more complex bash scripts, you can create helper functions:¶

```bash theme={null}¶
#!/bin/bash¶
# Read JSON input once¶
input=$(cat)¶

# Helper functions for common extractions¶
get_model_name() { echo "$input" | jq -r '.model.display_name'; }¶
get_current_dir() { echo "$input" | jq -r '.workspace.current_dir'; }¶
get_project_dir() { echo "$input" | jq -r '.workspace.project_dir'; }¶
get_version() { echo "$input" | jq -r '.version'; }¶
get_cost() { echo "$input" | jq -r '.cost.total_cost_usd'; }¶
get_duration() { echo "$input" | jq -r '.cost.total_duration_ms'; }¶
get_lines_added() { echo "$input" | jq -r '.cost.total_lines_added'; }¶
get_lines_removed() { echo "$input" | jq -r '.cost.total_lines_removed'; }¶
get_input_tokens() { echo "$input" | jq -r '.context_window.total_input_tokens'; }¶
get_output_tokens() { echo "$input" | jq -r '.context_window.total_output_tokens'; }¶
get_context_window_size() { echo "$input" | jq -r '.context_window.context_window_size'; }¶

# Use the helpers¶
MODEL=$(get_model_name)¶
DIR=$(get_current_dir)¶
echo "[$MODEL] 📁 ${DIR##*/}"¶
```¶

### Context Window Usage¶

Display the percentage of context window consumed. The `context_window` object contains:¶

* `total_input_tokens` / `total_output_tokens`: Cumulative totals across the entire session¶
* `used_percentage`: Pre-calculated percentage of context window used (0-100)¶
* `remaining_percentage`: Pre-calculated percentage of context window remaining (0-100)¶
* `current_usage`: Current context window usage from the last API call (may be `null` if no messages yet)¶
* `input_tokens`: Input tokens in current context¶
* `output_tokens`: Output tokens generated¶
* `cache_creation_input_tokens`: Tokens written to cache¶
* `cache_read_input_tokens`: Tokens read from cache¶

For acYou can use the pre-calcurlate context percentage, use `current_usage` which reflects the actual d `used_percentage` and `remaining_percentage` fields directly, or calculate from `current_usage` for more control.¶

**Simple approach using pre-calculated percentages:**¶

```bash theme={null}¶
#!/bin/bash¶
input=$(cat)¶

MODEL=$(echo "$input" | jq -r '.model.display_name')¶
PERCENT_USED=$(echo "$input" | jq -r '.
context _window state:.used_percentage // 0')¶

echo "[$MODEL] Context: ${PERCENT_USED}%"¶
```¶

**Advanced approach with manual calculation:**


```bash theme={null}¶
#!/bin/bash¶
input=$(cat)¶

MODEL=$(echo "$input" | jq -r '.model.display_name')¶
CONTEXT_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size')¶
USAGE=$(echo "$input" | jq '.context_window.current_usage')¶

if [ "$USAGE" != "null" ]; then¶
# Calculate current context from current_usage fields¶
CURRENT_TOKENS=$(echo "$USAGE" | jq '.input_tokens + .cache_creation_input_tokens + .cache_read_input_tokens')¶
PERCENT_USED=$((CURRENT_TOKENS * 100 / CONTEXT_SIZE))¶
echo "[$MODEL] Context: ${PERCENT_USED}%"¶
else¶
echo "[$MODEL] Context: 0%"¶
fi¶
```¶

## Tips¶

* Keep your status line concise - it should fit on one line¶
* Use emojis (if your terminal supports them) and colors to make information scannable¶
* Use `jq` for JSON parsing in Bash (see examples above)¶
* Test your script by running it manually with mock JSON input: `echo '{"model":{"display_name":"Test"},"workspace":{"current_dir":"/test"}}' | ./statusline.sh`¶
* Consider caching expensive operations (like git status) if needed¶

## Troubleshooting¶

* If your status line doesn't appear, check that your script is executable (`chmod +x`)¶
* Ensure your script outputs to stdout (not stderr)¶


---¶

> To find navigation and other pages in this documentation, fetch the llms.txt file at: https://code.claude.com/docs/llms.txt

Unified Diff

--- a/statusline.md
+++ b/statusline.md
@@ -63,6 +63,8 @@
     "total_input_tokens": 15234,
     "total_output_tokens": 4521,
     "context_window_size": 200000,
+    "used_percentage": 42.5,
+    "remaining_percentage": 57.5,
     "current_usage": {
       "input_tokens": 8500,
       "output_tokens": 1200,
@@ -207,13 +209,29 @@
 Display the percentage of context window consumed. The `context_window` object contains:
 
 * `total_input_tokens` / `total_output_tokens`: Cumulative totals across the entire session
+* `used_percentage`: Pre-calculated percentage of context window used (0-100)
+* `remaining_percentage`: Pre-calculated percentage of context window remaining (0-100)
 * `current_usage`: Current context window usage from the last API call (may be `null` if no messages yet)
   * `input_tokens`: Input tokens in current context
   * `output_tokens`: Output tokens generated
   * `cache_creation_input_tokens`: Tokens written to cache
   * `cache_read_input_tokens`: Tokens read from cache
 
-For accurate context percentage, use `current_usage` which reflects the actual context window state:
+You can use the pre-calculated `used_percentage` and `remaining_percentage` fields directly, or calculate from `current_usage` for more control.
+
+**Simple approach using pre-calculated percentages:**
+
+```bash  theme={null}
+#!/bin/bash
+input=$(cat)
+
+MODEL=$(echo "$input" | jq -r '.model.display_name')
+PERCENT_USED=$(echo "$input" | jq -r '.context_window.used_percentage // 0')
+
+echo "[$MODEL] Context: ${PERCENT_USED}%"
+```
+
+**Advanced approach with manual calculation:**
 
 ```bash  theme={null}
 #!/bin/bash