Claude Code status line: context + 5h/7d rate limit bars with reset times, clickable repo/branch/ticket/MR links (jq only; optional glab) A developer created a custom status line for Claude Code that displays context usage, rate limit bars with reset times, and clickable links to the repository, branch, and tickets. The script uses jq and optionally glab, and supports OSC 8 hyperlinks for terminals like iTerm2 and kitty. | /bin/bash | | | Claude Code status line — two lines, subscription-focused rate limits, no cost . | | | | | | ● my-project · ✦ Fable 5 · ⚡high · 🧠 · 🏷 ACME-123 feature/ACME-123-fix · 🔀 42 | | | ██████░░░░ 62% 124k/200k · 5h ████░░░░░░ 41% →17:00 · 7d ██░░░░░░░░ 23% →Wed · ⏱ 34m | | | | | | Features | | | - Context bar: tokens used vs window, green/yellow/red at 70/90% | | | - Rate limits: 5-hour + weekly windows as matching bars, with reset time | | | clock time for 5h, weekday for 7d . Claude.ai Pro/Max only; hidden otherwise. | | | - Clickable OSC 8 project name - repo, branch - tree, Jira/GitLab ticket | | | parsed from the branch name, open MR badge via glab cached, non-blocking | | | - Effort + thinking badges, session duration, subdir indicator | | | | | | Requirements: jq. Optional: glab MR badge , git. macOS + Linux. | | | Terminals with OSC 8 support iTerm2, Ghostty, WezTerm, kitty get clickable | | | links; others just show plain text. | | | | | | Install: | | | 1. Save as ~/.claude/statusline.sh && chmod +x ~/.claude/statusline.sh | | | 2. In ~/.claude/settings.json: | | | "statusLine": { "type": "command", "command": "~/.claude/statusline.sh" } | | | | | | ── config ───────────────────────────────────────────────────────────────── | | | Jira links are per-project: map each Jira project-key PREFIX to its base URL. | | | Only prefixes listed here get a clickable link; an unknown prefix shows the | | | ticket ID as plain text never a wrong link . Add one line per project. | | | GitLab/GitHub issue + repo links need NO config built from the git origin . | | | jira base for { | | | case "$1" in | | | ACME printf 'https://acme.atlassian.net' ;; | | | printf '' ;; | | | esac | | | } | | | GIT CACHE TTL=5 seconds; branch lookup is cached per session to keep renders fast | | | ─────────────────────────────────────────────────────────────────────────── | | | input=$ cat | | | One jq call: floors numerics, defaults nulls, -1 sentinel for absent rate limit. | | | 0x1F unit separator delimiter: non-whitespace, so read keeps empty fields | | | instead of collapsing consecutive ones the tab/whitespace-IFS gotcha . | | | IFS=$'\037' read -r MODEL PROJECT CURDIR PCT WIN TOKENS DURATION MS EFFORT THINK SID RHOST ROWNER RNAME RATE5 RATE7 RESET5 RESET7 < < | | | printf '%s' "$input" | jq -r ' | | | .model.display name // "?" , | | | .workspace.project dir // .workspace.current dir // "." , | | | .workspace.current dir // "." , | | | .context window.used percentage // 0 | floor , | | | .context window.context window size // 200000 , | | | .context window.total input tokens // 0 , | | | .cost.total duration ms // 0 | floor , | | | .effort.level? // "" , | | | .thinking.enabled // false , | | | .session id // "default" , | | | .workspace.repo.host? // "" , | | | .workspace.repo.owner? // "" , | | | .workspace.repo.name? // "" , | | | .rate limits.five hour.used percentage // -1 | floor , | | | .rate limits.seven day.used percentage // -1 | floor , | | | .rate limits.five hour.resets at // -1 | floor , | | | .rate limits.seven day.resets at // -1 | floor | | | | map tostring | join "�" ' | | | | | | Guard PCT so the integer comparisons below never crash on empty/non-numeric. | | | case "$PCT" in ''| 0-9 PCT=0 ;; esac | | | "$PCT" -gt 100 && PCT=100 | | | ── colors literal ESC so we can printf '%s' ───────────────────────────── | | | ESC=$'\033' | | | CYAN="${ESC} 36m"; GREEN="${ESC} 32m"; YELLOW="${ESC} 33m"; RED="${ESC} 31m" | | | MAGENTA="${ESC} 35m"; BLUE="${ESC} 34m"; DIM="${ESC} 2m"; BOLD="${ESC} 1m"; RESET="${ESC} 0m" | | | BEL=$'\a'; OSC="${ESC} 8;;" | | | OSC 8 hyperlink: hlink