{"id":51834149,"url":"https://github.com/cell-observatory/claude-statusline","last_synced_at":"2026-07-22T19:00:46.183Z","repository":{"id":370203325,"uuid":"1291456068","full_name":"cell-observatory/claude-statusline","owner":"cell-observatory","description":"Statusline for Claude CLI: context %, 5h/weekly usage with reset countdowns, and a self-calibrating token estimate.\"","archived":false,"fork":false,"pushed_at":"2026-07-18T00:26:35.000Z","size":32,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-18T02:16:29.485Z","etag":null,"topics":["claude","claude-cli","claude-cli-statusline","claude-code","claude-usage","cli","statusline"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cell-observatory.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-06T20:23:20.000Z","updated_at":"2026-07-18T00:26:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cell-observatory/claude-statusline","commit_stats":null,"previous_names":["cell-observatory/claude-statusline"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/cell-observatory/claude-statusline","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cell-observatory%2Fclaude-statusline","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cell-observatory%2Fclaude-statusline/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cell-observatory%2Fclaude-statusline/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cell-observatory%2Fclaude-statusline/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cell-observatory","download_url":"https://codeload.github.com/cell-observatory/claude-statusline/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cell-observatory%2Fclaude-statusline/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35773465,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-22T02:00:06.236Z","response_time":124,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude","claude-cli","claude-cli-statusline","claude-code","claude-usage","cli","statusline"],"created_at":"2026-07-22T19:00:26.573Z","updated_at":"2026-07-22T19:00:46.175Z","avatar_url":"https://github.com/cell-observatory.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# claude-statusline\n![claude-statusline](docs/statusline.svg)\n\nA three-line status line for the [Claude Code](https://code.claude.com) CLI that shows where you\nare, what the session is doing (title + token spend), and your context-window fill and Claude.ai\nplan usage (with reset countdowns) at a glance:\n\n\n\u003csub\u003ePlain-text rendering — bar color tracks usage: green \u0026lt;50%, yellow 50–79%, red ≥80%.\u003c/sub\u003e\n\n```\n14:32 · Jul 17 | main | ~/code/my-project\nAdd request validation to the API | Opus 4.8 · high · think · ↑12k ↓96k ↺8.4M · ◷1h32m\nctx [███─────] 32% · 320k/1M | 5h [█████───] 63% ·2h10m ~4.8M/15M | wk [███████─] 88% ·4d6h ~14M/16M\n```\n\n- **Line 1** — when and where: the clock (**time · date**), the git **branch** (only inside a\n  repo), and the **current path** (`~`-abbreviated).\n- **Line 2** — the session: its **title** (Claude Code's own name for the session; the folder name\n  until one exists) · model, followed by the model's reasoning **effort** (`low`…`max`), a `think`\n  marker when extended thinking is on, the **output style** (when not the default), the session's\n  **token counters** — `↑` input (uncached) · `↓` output · `↺` cached (cache reads), the same split the\n  [Claude Observatory](https://github.com/cell-observatory/claude-observatory) Stats panel shows,\n  via its bundled CLI (the counters are simply omitted when it isn't installed) — and the session\n  **duration** (`◷`) at the end; each shown only when available.\n- **Line 3** — `ctx` context-window used % **and absolute tokens used / window size**; `5h`\n  rolling-5-hour plan usage %; `wk` 7-day plan usage %. Each bar is green \u003c 50%,\n  yellow 50–79%, red ≥ 80%, and shows time until reset.\n  - The `5h`/`wk` bars also carry a `~` **used / total token estimate** (e.g. `~4.8M/15M`). Claude Code\n    exposes only a *percentage* for those windows — never a token count — so this is a rough,\n    self-calibrating figure: the script learns your tokens-per-percent from your own transcripts, then\n    shows the window's used tokens over the projected 100% budget. It starts near this machine's usage\n    and climbs toward your true account total as your other machines move the `%`. See below.\n\n\u003e **Using [Claude Observatory](https://github.com/cell-observatory/claude-observatory)?** This\n\u003e status line ships **bundled** with its CLI — `claude-observatory statusline` installs it with no\n\u003e download. This repo remains the standalone home for statusline-only setups.\n\n## Install\n\n**One-liner** — installs into `~/.claude` and merges a `statusLine` entry into your\n`settings.json`, preserving your other settings:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/cell-observatory/claude-statusline/main/install-statusline.sh | bash\n```\n\nPrefer to look before you leap? Open [`install-statusline.sh`](install-statusline.sh) (or the raw\nURL) first — it's a short, self-contained script that does exactly what's described here.\n\n**Or clone and run:**\n\n```bash\ngit clone https://github.com/cell-observatory/claude-statusline.git\ncd claude-statusline\n./install-statusline.sh\n```\n\n**On remote hosts (over SSH).** The installer is self-contained, so you can stream it to a box\nthat has no clone of this repo and no internet access — it just needs SSH + bash (+ jq):\n\n```bash\n# ad hoc, one host\nssh user@host 'bash -s' \u003c install-statusline.sh\n\n# one or more hosts, via the helper\n./remote-install.sh user@host [user@host2 ...]\n```\n\n`remote-install.sh` runs the ad-hoc command above for each host. Set `CLAUDE_CONFIG_DIR=…` to\ntarget a relocated config dir on the remote, or `SSH=\"ssh -p 2222 -i key\"` (or `-J bastion`) to\ncustomize the connection.\n\nThen open a **fresh** `claude` session. The context bar shows immediately; the `5h`/`wk` usage\nbars fill in after the first reply and only appear on Claude.ai subscription plans\n(Pro/Max/Team) — until then they render a dim `—` placeholder.\n\nThe installer is idempotent — re-run it any time to refresh. It honors `$CLAUDE_CONFIG_DIR`\nif you keep your Claude config somewhere other than `~/.claude` (handy on a remote/SSH box).\n\n**Inside a devcontainer.** The status line runs wherever `claude` runs — i.e. **inside the\ncontainer** — so install it there, not on your laptop. Bake it into your `postCreateCommand` so a\nrebuilt container comes back configured:\n\n```jsonc\n// .devcontainer/devcontainer.json\n{\n  \"postCreateCommand\": \"curl -fsSL https://raw.githubusercontent.com/cell-observatory/claude-statusline/main/install-statusline.sh | bash\",\n  \"remoteEnv\": {\n    // Optional: keep the config (and its statusline-last.json) on a mounted volume so it\n    // survives rebuilds. Set the SAME value everywhere that reads it (see note below).\n    \"CLAUDE_CONFIG_DIR\": \"/workspace/.claude\"\n  }\n}\n```\n\nTwo things the container image must provide: **`jq`** (required) and a **UTF-8 locale** for the bar\nglyphs (the script auto-selects one if the image ships `C.UTF-8`/`en_US.UTF-8`; otherwise add it,\ne.g. `apt-get install -y locales jq`). `python3` is optional (only powers the `~` token estimate).\n\nIf you relocate `CLAUDE_CONFIG_DIR`, point **every** tool that reads it at the same path — Claude\nCode, this status line, and the [Claude Observatory](https://github.com/cell-observatory/claude-observatory)\nsidebar all key off it. The Observatory repo ships a ready-to-copy\n[`docs/devcontainer/`](https://github.com/cell-observatory/claude-observatory/tree/main/docs/devcontainer)\ntemplate that wires up both tools (and the correct `TZ`) in one shot.\n\n## Requirements\n\n- **`jq`** (required — the script parses Claude Code's JSON input with it)\n  - macOS: `brew install jq`\n  - Debian/Ubuntu: `sudo apt-get install -y jq`\n  - RHEL/Fedora: `sudo dnf install -y jq`\n- **`git`** (optional — without it the branch segment is just skipped)\n- **`python3`** (optional — powers the `~` token estimate on the `5h`/`wk` bars; without it the\n  bars still show their percentage. No third-party packages needed.)\n- A **UTF-8 locale** for the bar glyphs (without one everything still works, the bars just may\n  not render). The script auto-selects a UTF-8 locale over SSH when it can.\n\n## The `~` token estimate (5h / wk)\n\nAnthropic only ever tells the client a **percentage** for the 5-hour and weekly windows — never\na token count, and it doesn't publish the token budget behind them. So `~N` is a deliberate\nback-of-envelope estimate, computed locally:\n\n- On a throttled schedule (≤ every 10 min) the script sums the tokens in your own Claude Code\n  transcripts (`~/.claude/projects/…`) that fall inside the current window and divides by the\n  account-wide `%` to learn **tokens-per-percent**; the largest ratio it sees converges on the\n  real budget.\n- It then displays `est = % × tokens-per-percent`, marked `~`. Because the `%` is account-wide,\n  the estimate **starts at roughly this machine's usage and climbs toward your true account\n  total** as sessions on your other machines (or the web) push the `%` up.\n- It's rough — model mix makes tokens-per-percent wobble, and it needs a few hours of use to\n  calibrate. State lives in `~/.claude/statusline-usage.json`; **delete that file to\n  recalibrate** (e.g. after a plan change). The scan is cached, so it adds well under a second.\n\n## Files\n\n- `statusline.sh` — the status line itself. This is the source of truth. Each turn it also writes the\n  exact values it renders to `~/.claude/statusline-last.json` (ctx / 5h / week percentages, token\n  used/size, and reset times), so other tools — e.g. the Claude Observatory VS Code sidebar — can show\n  the same numbers outside a live turn. Safe to delete; it's rewritten on the next turn.\n- `install-statusline.sh` — self-contained installer. It **embeds a verbatim copy** of\n  `statusline.sh` so the one-liner above works with a single file.\n- `remote-install.sh` — install on one or more remote hosts over SSH (streams the installer to\n  each; no clone/internet needed on the remote).\n- `LICENSE` — Apache-2.0.\n\n## Development\n\n`statusline.sh` is the source of truth; `install-statusline.sh` carries a verbatim copy inside a\n`STATUSLINE_EOF` heredoc. **If you edit `statusline.sh`, regenerate the embedded copy** so the\ntwo don't drift:\n\n```bash\n# replace the heredoc body in install-statusline.sh with the current statusline.sh\npython3 - \u003c\u003c'PY'\nnew = open('statusline.sh').read().rstrip('\\n').split('\\n')\nlines = open('install-statusline.sh').read().split('\\n'); out=[]; i=0\nwhile i \u003c len(lines):\n    out.append(lines[i])\n    if lines[i].startswith('cat \u003e ') and lines[i].rstrip().endswith(\"\u003c\u003c'STATUSLINE_EOF'\"):\n        j=i+1\n        while lines[j] != 'STATUSLINE_EOF': j+=1\n        out += new + ['STATUSLINE_EOF']; i=j+1; continue\n    i+=1\nopen('install-statusline.sh','w').write('\\n'.join(out))\nPY\n# sanity: the embedded copy must match\ndiff \u003c(awk \"/STATUSLINE_EOF'\\$/{f=1;next}/^STATUSLINE_EOF\\$/{f=0}f\" install-statusline.sh) statusline.sh\n```\n\n## Uninstall\n\n```bash\nrm -f ~/.claude/statusline.sh ~/.claude/statusline-usage.json\ntmp=$(mktemp); jq 'del(.statusLine)' ~/.claude/settings.json \u003e \"$tmp\" \u0026\u0026 mv \"$tmp\" ~/.claude/settings.json\n```\n\n## License\n\n[Apache-2.0](LICENSE) © Cell Observatory\n\n---\n\n\u003csub\u003eUnofficial and not affiliated with Anthropic. \"Claude\" and \"Claude Code\" are trademarks of Anthropic, PBC.\u003c/sub\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcell-observatory%2Fclaude-statusline","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcell-observatory%2Fclaude-statusline","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcell-observatory%2Fclaude-statusline/lists"}