Skip to content

Instantly share code, notes, and snippets.

@dmd
Created March 19, 2026 20:30
Show Gist options
  • Select an option

  • Save dmd/32afb5680696821a5064c772d82d0d30 to your computer and use it in GitHub Desktop.

Select an option

Save dmd/32afb5680696821a5064c772d82d0d30 to your computer and use it in GitHub Desktop.
# Claude Code Statusline Setup
Shows `user@host:/cwd use:28% rst:1h45m` in the Claude Code statusline.
The usage % and reset time come from the Anthropic API (5-hour rate limit window).
## Requirements
- `jq` and `curl` installed
- `python3` installed (used for date parsing)
- Claude Code logged in via OAuth
## Setup
### 1. Create the script
Save the script below to `~/.claude/statusline-command.sh`:
```bash
#!/bin/bash
input=$(cat)
cwd=$(echo "$input" | jq -r '.workspace.current_dir')
# Usage limit: fetch from Anthropic API, cache for 5 minutes
CACHE=/tmp/claude-usage-cache.json
usage_str="?%"
get_token() {
# macOS: credentials stored in keychain
if command -v security &>/dev/null; then
security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null \
| jq -r '.claudeAiOauth.accessToken // empty'
return
fi
# Linux: credentials stored in a JSON file
local creds=~/.claude/.credentials.json
if [ -f "$creds" ]; then
jq -r '.claudeAiOauth.accessToken // empty' "$creds"
fi
}
file_age_seconds() {
if stat -f %m "$1" &>/dev/null; then
# macOS (BSD stat)
echo $(( $(date +%s) - $(stat -f %m "$1") ))
else
# Linux (GNU stat)
echo $(( $(date +%s) - $(stat -c %Y "$1") ))
fi
}
update_cache() {
if [ -f "$CACHE" ]; then
[ "$(file_age_seconds "$CACHE")" -gt 300 ] || return
fi
TOKEN=$(get_token)
[ -n "$TOKEN" ] || return
TMPFILE=$(mktemp)
curl -s -m 5 \
-H "Authorization: Bearer $TOKEN" \
-H "anthropic-beta: oauth-2025-04-20" \
https://api.anthropic.com/api/oauth/usage > "$TMPFILE" 2>/dev/null \
&& [ -s "$TMPFILE" ] && mv "$TMPFILE" "$CACHE" || rm -f "$TMPFILE"
}
build_usage_str() {
[ -f "$CACHE" ] || return
pct=$(jq -r '.five_hour.utilization // empty' "$CACHE" 2>/dev/null)
[ -n "$pct" ] || return
pct=$(printf '%.0f' "$pct")
usage_str="${pct}%"
resets_at=$(jq -r '.five_hour.resets_at // empty' "$CACHE" 2>/dev/null)
[ -n "$resets_at" ] || return
reset_epoch=$(python3 -c "from datetime import datetime; print(int(datetime.fromisoformat('$resets_at'.replace('Z','+00:00')).timestamp()))" 2>/dev/null)
[ -n "$reset_epoch" ] || return
now=$(date +%s)
diff=$(( reset_epoch - now ))
[ "$diff" -gt 0 ] || return
h=$(( diff / 3600 ))
m=$(( (diff % 3600) / 60 ))
usage_str="${pct}% rst:${h}h${m}m"
}
update_cache
build_usage_str
printf '\033[01;32m%s@%s\033[00m:\033[01;36m%s\033[00m \033[97muse:%s\033[00m' \
"$(whoami)" "$(hostname -s)" "$cwd" "$usage_str"
```
Then make it executable:
```bash
chmod +x ~/.claude/statusline-command.sh
```
### 2. Configure Claude Code
Add the `statusLine` key to `~/.claude/settings.json`:
```json
{
"statusLine": {
"type": "command",
"command": "bash ~/.claude/statusline-command.sh"
}
}
```
If the file already exists, merge the `statusLine` key into it.
### 3. Test
```bash
echo '{"workspace":{"current_dir":"'"$PWD"'"}}' | bash ~/.claude/statusline-command.sh
```
You should see something like:
```
dmd@host:/home/dmd use:5% rst:1h32m
```
(with colors, if your terminal supports them)
## How it works
Claude Code pipes a JSON object to the statusline command on stdin. The script extracts the current working directory from that JSON.
For usage data, it calls `https://api.anthropic.com/api/oauth/usage` using your OAuth access token and caches the result in `/tmp/claude-usage-cache.json` for 5 minutes. The percentage and reset countdown come from the `five_hour` fields in the API response.
On macOS, the OAuth token is read from the macOS keychain. On Linux, it's read from `~/.claude/.credentials.json`.
## Colors
| Element | Color |
|---|---|
| `user@host` | Bold green |
| Current directory | Bold cyan |
| `use:` and reset time | Bright white |
@dmd
Copy link
Copy Markdown
Author

dmd commented Mar 19, 2026

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment