{"id":49328493,"url":"https://github.com/arcasilesgroup/claudeline","last_synced_at":"2026-05-15T13:03:59.610Z","repository":{"id":354028647,"uuid":"1221846708","full_name":"arcasilesgroup/claudeline","owner":"arcasilesgroup","description":"Cross-platform statusline for Claude Code — model, context, rate limits, effort, thinking","archived":false,"fork":false,"pushed_at":"2026-04-26T19:52:39.000Z","size":232,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-26T21:02:10.298Z","etag":null,"topics":["anthropic","bun","claude","claude-code","cli","developer-tools","statusline","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@arcasilesgroup/claudeline","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arcasilesgroup.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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-04-26T18:54:46.000Z","updated_at":"2026-04-26T19:52:43.000Z","dependencies_parsed_at":"2026-04-26T21:02:14.614Z","dependency_job_id":null,"html_url":"https://github.com/arcasilesgroup/claudeline","commit_stats":null,"previous_names":["arcasilesgroup/claudeline"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/arcasilesgroup/claudeline","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcasilesgroup%2Fclaudeline","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcasilesgroup%2Fclaudeline/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcasilesgroup%2Fclaudeline/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcasilesgroup%2Fclaudeline/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arcasilesgroup","download_url":"https://codeload.github.com/arcasilesgroup/claudeline/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcasilesgroup%2Fclaudeline/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33067476,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["anthropic","bun","claude","claude-code","cli","developer-tools","statusline","typescript"],"created_at":"2026-04-26T21:00:24.981Z","updated_at":"2026-05-15T13:03:59.604Z","avatar_url":"https://github.com/arcasilesgroup.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# claudeline\n\n[![npm version](https://img.shields.io/npm/v/@arcasilesgroup/claudeline.svg?logo=npm)](https://www.npmjs.com/package/@arcasilesgroup/claudeline)\n[![CI](https://github.com/arcasilesgroup/claudeline/actions/workflows/ci.yml/badge.svg)](https://github.com/arcasilesgroup/claudeline/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/arcasilesgroup/claudeline/actions/workflows/codeql.yml/badge.svg)](https://github.com/arcasilesgroup/claudeline/actions/workflows/codeql.yml)\n[![Security](https://github.com/arcasilesgroup/claudeline/actions/workflows/security.yml/badge.svg)](https://github.com/arcasilesgroup/claudeline/actions/workflows/security.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n\nA cross-platform statusline for [Claude Code](https://claude.com/claude-code).\nTypeScript, single binary, zero config.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/arcasilesgroup/claudeline/main/docs/screenshot-active-dark.png\" alt=\"claudeline running inside Claude Code during an active session: model name with 1M context, ✍️ context %, working directory and dirty git branch, effort glyph, thinking indicator, 5-hour and weekly rate-limit bars, and the accept-edits permission hint\" width=\"900\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/arcasilesgroup/claudeline/main/docs/demo-statusline.gif\" alt=\"claudeline animated demo: model, context %, dir+git, cost, effort, thinking, rate-limit bars filling up\" width=\"900\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/arcasilesgroup/claudeline/main/docs/demo-cli.gif\" alt=\"claudeline doctor — sectioned tree-style diagnostic output\" width=\"900\" /\u003e\n\u003c/p\u003e\n\n## Features\n\n- **Model + context %** — colored by usage threshold (green → orange → yellow → red)\n- **Cost per session** — `💸 $X.XX` from Claude Code's authoritative server-side total, with a token×pricing fallback for older runtimes\n- **Working directory + git** — branch, dirty flag, worktree marker (`⎇:branch`), optional `⚡` for `--dangerously-skip-permissions`\n- **Session duration** — elapsed since session start\n- **Effort indicator** — distinct glyphs for `max`, `xhigh`, `high`, `medium`, `low`\n- **Thinking indicator** — 🧠 when extended thinking is enabled\n- **Fast mode badge** — 🐇 when running with `--fast`\n- **1M context warning** — 📚 when the session exceeds 200K tokens\n- **Rate limits** — 5-hour, weekly, and optional extra credits, sourced from Claude Code stdin first, OAuth API as fallback\n- **Rate-limit projection** — `~38m` next to the bar tells you when you'll hit 100% at the current burn rate\n- **Latency badge** — `🐢 Xms` when the OAuth API is slow (yellow ≥1 s, red ≥3 s)\n- **Locale-aware** — 12h / 24h auto-detected, timezone from system\n- **Glyph modes** — `CLAUDELINE_GLYPHS=emoji` (default), `nerd` (NerdFont), `plain` (ASCII for SSH/no-emoji terminals)\n- **Cross-platform** — macOS, Linux, Windows. Node ≥ 18, Bun, or one of our self-contained binaries\n\n## Why this vs the bash original\n\nThere's an excellent bash statusline by [@kamranahmedse](https://github.com/kamranahmedse/claude-statusline) that inspired claudeline. If you're choosing between them, here's where claudeline diverges:\n\n| | claudeline | bash original |\n| --- | --- | --- |\n| **macOS, Linux** | ✅ | ✅ |\n| **Windows** | ✅ (npm shim + native binary) | ❌ requires bash + jq + curl |\n| **Cost source** | server-side `cost.total_cost_usd` from Claude Code (truth) | derived from token math (drifts from reality) |\n| **Rate-limit projection** | `~38m` at current burn rate | not present |\n| **Latency badge** | yes, with yellow/red thresholds | not present |\n| **Worktree-aware git** | `⎇:branch` | branch-only |\n| **Fast mode + 1M context warnings** | yes | not present |\n| **Tests** | comprehensive suite (TDD) | 0 |\n| **Schema validation** | Zod, tolerant of `null` and unknown fields | none |\n| **Distribution** | npm + Homebrew + Bun-compiled binaries (5 platforms) | source only |\n| **Cold start (single render)** | ~85–140 ms p50 | ~30–60 ms (no Node runtime) |\n| **Runtime deps** | `zod` only | `jq`, `curl`, `bash`, `git` |\n\nIf you want the leanest, no-runtime-deps option and you're macOS/Linux-only, the bash original is great. If you want a single tool that works the same on every platform with tested rendering, accurate cost, projections, and richer signals — that's what claudeline ships.\n\n## Install\n\n### One-line installer (macOS, Linux — no Node required)\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/arcasilesgroup/claudeline/main/scripts/install.sh | bash\n```\n\nDetects your platform, downloads the right Bun-compiled binary from the latest GitHub release, verifies the SHA256, drops it in `~/.local/bin/`, and runs `claudeline install` to wire it into Claude Code. Re-run any time to upgrade. The script is short and unobfuscated — read it before piping if you're cautious: [`scripts/install.sh`](./scripts/install.sh).\n\n### npm (any platform with Node ≥ 18)\n\n```bash\nnpm install -g @arcasilesgroup/claudeline\n# or pnpm add -g @arcasilesgroup/claudeline\n# or bun install -g @arcasilesgroup/claudeline\n```\n\n### Homebrew (macOS, Linux)\n\n```bash\nbrew tap arcasilesgroup/claudeline\nbrew install claudeline\n```\n\n### Self-contained binary (manual)\n\nDownload the right asset from the [releases page](https://github.com/arcasilesgroup/claudeline/releases/latest), make it executable, drop it on your PATH:\n\n```bash\n# example for macOS arm64\ncurl -fsSL -o claudeline \\\n  https://github.com/arcasilesgroup/claudeline/releases/latest/download/claudeline-darwin-arm64\nchmod +x claudeline \u0026\u0026 mv claudeline /usr/local/bin/\n```\n\nWire it into Claude Code:\n\n```bash\nclaudeline install\n```\n\nThis adds the following to `~/.claude/settings.json`:\n\n```json\n{\n  \"statusLine\": {\n    \"type\": \"command\",\n    \"command\": \"claudeline render\"\n  }\n}\n```\n\nRestart Claude Code. Done.\n\nTo revert:\n\n```bash\nclaudeline uninstall\n```\n\n## What it shows\n\nThe first line is composed of these segments, separated by `│`:\n\n| Segment    | Source                                              |\n| ---------- | --------------------------------------------------- |\n| Model      | `model.display_name` from stdin                     |\n| Context %  | `context_window` (tokens / size or used_percentage) |\n| Directory  | `cwd` basename + git branch + dirty flag + worktree |\n| Cost       | `current_usage` tokens × Anthropic price for `model.id` |\n| Session    | elapsed since `session.start_time`                  |\n| Effort     | `effort.level` from stdin, fallback `effortLevel`   |\n| Thinking   | `thinking.enabled`, fallback `alwaysThinkingEnabled`|\n| Latency    | `⚡ Xms` when the OAuth API takes \u003e1 s              |\n\nWhen Claude Code provides rate limits in the stdin JSON, those are used\ndirectly. Otherwise claudeline calls the OAuth usage API once per minute and\ncaches the response under the OS temp directory with `0600` permissions.\n\n### Effort glyphs\n\n| Level     | Glyph | Color   |\n| --------- | ----- | ------- |\n| `max`     | ◉     | magenta |\n| `xhigh`   | ◉     | magenta |\n| `high`    | ●     | magenta |\n| `medium`  | ◑     | dim     |\n| `low`     | ◔     | dim     |\n\n### Glyph modes\n\nSet the `CLAUDELINE_GLYPHS` environment variable in your shell or in\n`~/.claude/settings.json` env block:\n\n| Mode    | When to use                                                |\n| ------- | ---------------------------------------------------------- |\n| `emoji` | (default) emojis + Unicode geometric shapes                |\n| `nerd`  | Patched [NerdFont](https://www.nerdfonts.com) terminal     |\n| `plain` | SSH / `screen` / terminals without Unicode or emoji        |\n\n### Rate-limit projection\n\nWhen the 5-hour bar moves between two consecutive renders, claudeline\nestimates how long until you hit 100% at the current pace and renders\n`~38m` (or `~2h5m`) next to the percentage. The previous sample is\nkept under `\u003ctmpdir\u003e/claudeline-\u003cuid\u003e/state.json` (`0o600`).\n\n### 12h vs 24h\n\nDetected automatically:\n\n1. macOS preference `AppleICUForce24HourTime` (if explicitly set)\n2. macOS `AppleLocale`\n3. `LC_TIME` / `LC_ALL` / `LANG` environment variables\n4. Default: 24h, except regions `US` / `CA` (12h)\n\nTimezone comes from `Intl.DateTimeFormat().resolvedOptions().timeZone`.\n\n### OAuth token sources (fallback only)\n\nWhen Claude Code does not supply rate limits in stdin, claudeline looks up\nthe OAuth token to call the usage API:\n\n1. `CLAUDE_CODE_OAUTH_TOKEN` environment variable\n2. macOS Keychain (`security find-generic-password -s \"Claude Code-credentials\"`)\n3. Linux `secret-tool` (libsecret)\n4. `~/.claude/.credentials.json`\n\nThe token is **never** written to disk, logged, or sent to any host other\nthan `api.anthropic.com`.\n\n## CLI usage\n\n```text\nclaudeline render                Read JSON from stdin and emit the statusline\nclaudeline render --json         Same input, structured JSON output (for editors/scripts)\nclaudeline install               Wire claudeline as the statusLine in ~/.claude/settings.json\nclaudeline uninstall             Remove claudeline from ~/.claude/settings.json\nclaudeline doctor                Run diagnostics and print a pass/warn/fail report\nclaudeline doctor --json         Same checks, structured JSON output (for scripts/editors)\nclaudeline summary               Show local session history (cost, models, top windows)\nclaudeline summary --enable      Start tracking sessions in ~/.claudeline/sessions.jsonl\nclaudeline summary --disable     Stop tracking and delete the local session log\nclaudeline refresh               Force a fresh OAuth-API fetch (bypasses the cache)\nclaudeline --help                Show this help\nclaudeline --version             Show version\n```\n\n### `claudeline summary` (opt-in local cost tracking)\n\nRun `claudeline summary --enable` once to start logging one record per render to\n`~/.claudeline/sessions.jsonl`. The reader dedups by session id (last value\nwins), so the cost shown for each session is the final server-reported total.\nAll data stays on this machine — no network egress, no telemetry.\n\n```text\n  claudeline summary\n  log: /Users/me/.claudeline/sessions.jsonl\n\n  Today       $7.65 across 2 sessions\n              · Claude Opus 4.6              $5.50 (1 session)\n              · Claude Sonnet 4.6            $2.15 (1 session)\n\n  This week   $42.10 across 14 sessions\n              · Claude Sonnet 4.6           $28.40 (10 sessions)\n              · Claude Opus 4.6             $13.70 (4 sessions)\n\n  This month  …\n  All time    …\n```\n\nStop tracking and delete the log: `claudeline summary --disable`. JSON output for\ndashboards: `claudeline summary --json`.\n\n### `claudeline render --json` and `claudeline doctor --json`\n\nBoth subcommands accept `--json` for editor / dashboard integrations. The render\noutput is the structured data behind the ANSI line (model, cost, context,\nsession, rate limits, latency); the doctor output is the same checks the human\nreport covers, in a stable schema you can parse without ANSI.\n\n### Freshness, cache, and `claudeline refresh`\n\nclaudeline only renders when Claude Code calls it. Between renders the\nstatusline is frozen — that's a property of Claude Code's hook contract,\nnot something we can change. What we *can* do is be fresh when called.\n\nThe OAuth-API rate-limit data is cached locally with a default TTL of\n30 seconds (override with `CLAUDELINE_CACHE_TTL_SEC=15` etc., clamped\nto 1–300). Each render does one of three things based on cache age:\n\n- **0–5 s old:** serve cached, no network\n- **5 s–TTL old:** serve cached and spawn a background refresh so the\n  *next* render sees fresh data (stale-while-revalidate)\n- **\u003eTTL or missing:** fetch synchronously\n\nIf you want the freshest numbers right now, run `claudeline refresh` —\nit does a synchronous OAuth fetch and updates the cache immediately.\n`claudeline doctor` shows the current cache age and configured TTL so\nyou can debug \"claudeline says X, claude.ai says Y\" mismatches.\n\n**Important caveat — stdin priority and the \"fresh mode\" escape hatch:**\nrecent Claude Code versions pass `rate_limits` directly in stdin on every\nrender. By default claudeline uses that source (it's whatever the active\nsession itself sees) and **bypasses the cache entirely** for the 5-hour /\nweekly bars. That means `claudeline refresh` updates the cache but you\nwon't see the change in your statusline — Claude Code is already\noverriding it with stdin data on the next render.\n\nIf you want `claudeline refresh` to actually drive what's shown:\n\n```bash\nclaudeline config set prefer-api true\n```\n\nThis persists in `~/.claudeline/config.json` so you don't have to bet\non env-var propagation through your shell rc and Claude Code's\nsubprocess. The env var (`CLAUDELINE_PREFER_API=1`) still works as a\nruntime override, with this precedence:\n\n```\nenv \u003e ~/.claudeline/config.json \u003e default (false)\n```\n\nThe trade-off is one extra OAuth-API call when the cache expires (every\n30 s by default; tune via `claudeline config set cache-ttl-sec 15`). You\nalso lose the \"always as fresh as my session knows\" property of stdin\npriority. Run `claudeline doctor` or `claudeline config get` to see\nwhich source is in effect, plus the verbatim env values claudeline\nactually sees — useful when \"I exported X but it doesn't seem to be\ntaking\" turns out to be a propagation surprise.\n\n### `claudeline doctor`\n\nEight read-only diagnostic checks against your environment, grouped into\nsections and rendered in `claude doctor` style. Always exits 0 —\ninformational only, never modifies anything.\n\n```text\n────────────────────────────────────────────────────────────────────────\n\n  Diagnostics\n  ├ Version: claudeline 0.3.2\n  ├ Engine: Node 25.9.0\n  ├ Platform: darwin-arm64\n  └ Cache directory: /var/folders/.../claudeline-501\n\n  Configuration\n  ├ statusLine wired in ~/.claude/settings.json\n  ├ effortLevel in settings.json: \"high\"\n  ├ Cache directory exists with 0o700 permissions\n  └ Stdin schema parses a synthetic test payload\n\n  Health\n  ├ Cache entry shape parses cleanly\n  └ State file shape parses cleanly\n\n  ⚠ CLAUDE_CODE_EFFORT_LEVEL=max in environment\n    ├ This overrides settings.json effortLevel and blocks /model.\n    └ Unset it or comment out the export in your shell rc to use /model freely.\n\n  Summary: 0 errors, 1 warning, 6 ok\n```\n\nWarnings and errors are surfaced in their own block beneath the report\n(eye lands at the end, per [clig.dev][]). The output respects\n[`NO_COLOR`][nocolor], `TERM=dumb`, and non-TTY pipes — ANSI is dropped\nautomatically when the consumer isn't a colour-capable terminal, so\npiping to `grep`/`awk` produces clean text.\n\n[clig.dev]: https://clig.dev/\n[nocolor]: https://no-color.org/\n\n## Local development\n\nYou need [Bun](https://bun.com) ≥ 1.3.\n\n```bash\ngit clone https://github.com/arcasilesgroup/claudeline\ncd claudeline\nbun install\nbun test          # 100 tests\nbunx tsc --noEmit # strict TS, exact optional, no implicit any\nbun run build     # produces dist/cli.js for npm\n```\n\nRun against a fixture:\n\n```bash\necho '{\"model\":{\"display_name\":\"Opus 4.7\"},\"effort\":{\"level\":\"max\"},\"cwd\":\".\"}' \\\n  | bun src/cli.ts render\n```\n\nBuild a self-contained binary for your platform:\n\n```bash\nbun build src/cli.ts --compile --outfile=dist/claudeline\n./dist/claudeline --version\n```\n\n## Project principles\n\nThis codebase is small on purpose:\n\n- **TDD** — every module has tests written alongside (or before) the code.\n  See [`tests/`](./tests).\n- **SDD** — [`src/schemas.ts`](./src/schemas.ts) (Zod) is the source of truth\n  for the input JSON contract, the OAuth usage API response, and\n  `~/.claude/settings.json`.\n- **DRY / KISS / YAGNI** — no plugin systems, no abstractions for\n  unimplemented features, no half-finished code.\n- **SOLID** — segments are pure functions; side-effecting code (git,\n  network, filesystem) is injected into the orchestrator\n  (`renderStatusline`) so it can be tested without mocks.\n\n## Security\n\nclaudeline is non-privileged and minimal-surface. Highlights:\n\n- Single runtime dependency: [`zod`](https://zod.dev) for input validation\n- All external commands invoked with `child_process.spawnSync` using fixed\n  argv arrays (no shell interpolation)\n- HTTP calls bounded by a 5 s `AbortController` timeout\n- Cache files written with `0600` inside a `0700` directory, contain only\n  rate-limit metadata\n- CI runs CodeQL, gitleaks, OSV-Scanner, and `bun audit` on every PR\n  and weekly\n\nFound a security issue? Please use\n[private vulnerability reporting](https://github.com/arcasilesgroup/claudeline/security/advisories/new)\nor follow the process in [SECURITY.md](./SECURITY.md). Do **not** open a\npublic issue.\n\n## Contributing\n\nPRs welcome. Read [CONTRIBUTING.md](./CONTRIBUTING.md) and follow the\n[Code of Conduct](./CODE_OF_CONDUCT.md).\n\n## License\n\n[MIT](./LICENSE) © Arcasiles Group\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcasilesgroup%2Fclaudeline","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farcasilesgroup%2Fclaudeline","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcasilesgroup%2Fclaudeline/lists"}