{"id":51908116,"url":"https://github.com/tangjianfang/claudecode-statusline","last_synced_at":"2026-07-27T01:30:39.946Z","repository":{"id":372675816,"uuid":"1309074414","full_name":"tangjianfang/claudecode-statusline","owner":"tangjianfang","description":"Custom status line for Claude Code: model, output TPS, token/cost totals, git branch, context usage — plus an opt-in auto-continue loop and a pricing updater. Zero-dependency single-file Node.js.","archived":false,"fork":false,"pushed_at":"2026-07-22T18:26:21.000Z","size":92,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-22T20:14:49.582Z","etag":null,"topics":["agentic-loop","anthropic","auto-continue","claude","claude-code","claude-hooks","cli","cost-tracking","pricing","status-line","statusline","stop-hook","terminal","token-counter","tps"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/tangjianfang.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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-22T17:18:05.000Z","updated_at":"2026-07-22T18:29:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tangjianfang/claudecode-statusline","commit_stats":null,"previous_names":["tangjianfang/claudecode-statusline"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/tangjianfang/claudecode-statusline","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangjianfang%2Fclaudecode-statusline","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangjianfang%2Fclaudecode-statusline/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangjianfang%2Fclaudecode-statusline/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangjianfang%2Fclaudecode-statusline/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tangjianfang","download_url":"https://codeload.github.com/tangjianfang/claudecode-statusline/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangjianfang%2Fclaudecode-statusline/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35933751,"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-26T02:00:06.503Z","response_time":89,"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":["agentic-loop","anthropic","auto-continue","claude","claude-code","claude-hooks","cli","cost-tracking","pricing","status-line","statusline","stop-hook","terminal","token-counter","tps"],"created_at":"2026-07-27T01:30:39.194Z","updated_at":"2026-07-27T01:30:39.933Z","avatar_url":"https://github.com/tangjianfang.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cc-statusline\n\nCustom status line for [Claude Code](https://claude.ai/code), plus an optional auto-continue loop. Single-file Node.js scripts, zero dependencies (built-ins only).\n\n- **`statusline.js`** — model, output TPS, tokens, cost, git branch, context %, rate-limit usage. Also renders one row per subagent.\n- **`loopctl.js`** — turns Claude Code's `Stop` hook into a per-project, opt-in \"keep going\" loop. **Off everywhere by default**; you enable it per-project with `loopctl on`.\n\n## Install\n\n```bash\nnpm install -g @tangjianfang/claudecode-statusline\n```\n\nThe `postinstall` hook automatically:\n\n- copies `statusline.js` + `loopctl.js` to `~/.claude/`\n- registers them in `~/.claude/settings.json` (`statusLine`, `subagentStatusLine`, `hooks.Stop`)\n- seeds `~/.claude/pricing.json` if missing\n\nRestart Claude Code. Done.\n\nThe same package is also published under the shorter name `@tangjianfang/cc-statusline`.\n\n## What it looks like\n\nTwo lines in the status bar:\n\n```\n[Sonnet 5] 📁 my-project 🌿 main PR#123👀 ctx:42%\nTPS:38.2 out:1.2k cache:15k Σ↓120k ↑8.4k +120/-15 ~cost:$0.31 dur:2m 14s 5h:24% 7d:81% ⚡fast 🧠think eff:high\n```\n\nThe branch name is a clickable link to that branch's page on the remote (GitHub / GitLab / Bitbucket) when the `origin` resolves; on other hosts it stays plain text. Subagent rows render like:\n\n```\nExplore  running  166.7tok/s  tok:50k(25%)  5m00s  ~$0.01  eff:high\nfix-bug completed 400.0tok/s  tok:120k(60%) 5m00s  ~$0.04  eff:medium\n```\n\n### Screenshot\n\nReal example while running in Claude Code — the status line (model, project, branch, loop badge, context %, TPS, tokens, cost, duration, rate limits, reasoning effort) plus one row per active subagent, all live:\n\n![cc-statusline running in Claude Code with multiple subagents](docs/cc-statusline-preview.png)\n\nEach subagent row shows its name, status, recent throughput (`tok/s`), context usage with percent of window, how long it's been running, an approximate cost (when `ANTHROPIC_MODEL` is set so the script can look up pricing — see [Cost estimation](#cost-estimation)), and reasoning effort. The cost figure is approximate since subagent payloads don't break down input vs output tokens; the `~$` prefix flags it.\n\n## Auto-continue loop (loopctl)\n\nOff everywhere by default. To use it in a project:\n\n```bash\ncd /path/to/project\n\nloopctl on --max 8 --push     # enable: up to 8 rounds, auto-commit + push each round\nloopctl off                   # disable\nloopctl status                # show current state\nloopctl presets               # list built-in prompts (find-bugs, improve, tests, ...)\n```\n\nBuilt-in presets for `--preset \u003cname\u003e`: `next-step` (default), `find-bugs`, `improve`, `tests`, `docs`, `refactor`. For a fully custom prompt, use `--prompt \"your text here\"`.\n\n---\n\n## Reference\n\n### Manual / GitHub install\n\nIf you'd rather skip npm (or want fine-grained control over what gets overwritten):\n\n```bash\ngit clone https://github.com/tangjianfang/claudecode-statusline.git\ncd claudecode-statusline\nnode statusline.js --install\nnode loopctl.js --install\n```\n\nEach `--install` runs the same y/n prompts as before — handy if you want to keep an existing file or setting.\n\nAfter installing, verify the wiring with:\n\n```bash\ncc-statusline status    # shows ~/.claude files, settings.json contents, pricing.json entry count\nloopctl status           # shows loop state for the current project\n```\n\n### Cost estimation\n\nThe `~cost:` figure is computed by the script itself from the transcript's token counts (split into fresh input / output / cache-read / cache-creation, accumulated session-wide), times a per-model pricing table that lives in `pricing.json`:\n\n```\ncost = freshInput/1M × p.in\n     + output/1M      × p.out\n     + cacheRead/1M   × p.cacheRead\n     + cacheCreate/1M × p.cacheWrite\n```\n\n**Why self-compute:** Claude Code's `data.cost.total_cost_usd` is priced at Anthropic's rates, which is wrong when you route to a third-party model via `ANTHROPIC_BASE_URL` (e.g. MiniMax).\n\n**The pricing file:** `pricing.json` is the single source of truth — one file, shipped with the repo and seeded into `~/.claude/pricing.json` on install (only if it doesn't already exist; never overwrites your copy). It covers the canonical chat models of every mainstream provider: Anthropic, OpenAI, Google/Gemini, MiniMax, DeepSeek, Meta/Llama, Mistral, xAI/Grok, Cohere, Alibaba/Qwen.\n\nKey format:\n\n```json\n{\n  \"MiniMax-M3\": { \"in\": 0.3, \"out\": 1.2, \"cacheRead\": 0.06, \"cacheWrite\": 0 }\n}\n```\n\n`statusline.js` resolves a model by exact name first, then longest case-insensitive substring. When no entry matches, it falls back to `data.cost.total_cost_usd` shown as `~cost?:` to flag that it's the untrusted client estimate. Both figures are estimates — hence the `~` prefix; don't \"fix\" this by dropping the prefix.\n\n#### Refreshing rates manually\n\n```bash\nnode pricing-updater.js                                # fetch mainstream providers, merge into ~/.claude/pricing.json\nnode pricing-updater.js --model KEY                    # also include a specific litellm key (repeatable)\nnode pricing-updater.js --list [pattern]               # print matching keys + rates, write nothing\nnode pricing-updater.js --overwrite                    # replace target entirely instead of merging\nnode pricing-updater.js --out pricing.json --overwrite # maintainer: refresh repo's shipped copy\n```\n\nThere is **no scheduled task and no auto-update** — updating pricing is an explicit, user-initiated action, since silently rewriting rate data in the background (with the network and trust risks that entails) is not something this tool does for you.\n\n### loopctl flags (full)\n\n| Flag | Description |\n|---|---|\n| `--max N` | Auto-continue for at most N rounds (default 8). **Claude Code force-releases a Stop hook after 8 consecutive blocks without progress**, so `--max` above 8 may be cut short. Raise the ceiling with `CLAUDE_CODE_STOP_HOOK_BLOCK_CAP`. |\n| `--push` / `--no-push` | Run `git add -A \u0026\u0026 git commit \u0026\u0026 git push` each round (default off). **Pushes directly to the current branch, including `main`** — no dedicated-branch safety net. |\n| `--preset \u003cname\u003e` | Pick the per-round prompt from a built-in template. Unknown names error out. |\n| `--prompt \"...\"` | Fully customize the per-round prompt; takes precedence over `--preset` (last-parsed wins). |\n\n#### Built-in `--preset` values\n\n| Name | Prompt |\n|---|---|\n| `next-step` (default) | What is the next task? Plan and execute it. |\n| `find-bugs` | Proactively check the current code for potential bugs or logic issues. Fix any you find and explain the fix. |\n| `improve` | Proactively look for things in the project that can be improved (code quality, readability, performance, docs, test coverage, etc.). Pick one valuable improvement and make it. |\n| `tests` | Check whether the project's tests are complete and passing. Add missing test cases or fix failing tests. |\n| `docs` | Check whether the docs (README, comments, etc.) are consistent with the current code. Update anything outdated or missing. |\n| `refactor` | Find a piece of code that can be safely simplified or refactored, and do so without changing behavior. |\n\n### npm scripts\n\n| Script | What it does |\n|---|---|\n| `npm run check` | Syntax-check all three scripts (`node --check`). |\n| `npm run install` | Run both `--install` flows manually. |\n| `npm run install-statusline` | Install only the status line. |\n| `npm run install-loopctl` | Install only loopctl. |\n| `npm run update-pricing` | Fetch current rates and merge into `~/.claude/pricing.json`. |\n| `npm run pricing:list -- minimax` | Print litellm keys/rates matching a pattern. |\n| `npm run presets` | List loopctl's built-in `--preset` prompts. |\n| `npm run demo` / `npm run demo:subagent` | Smoke test against an empty / sample payload. |\n\n\u003e `loopctl on` / `off` / `status` are deliberately not npm scripts (npm `run` uses the package dir as cwd, so a `npm run loopctl:on` would toggle the loop for *this repo*, not your project). Run `loopctl on` directly inside the target project.\n\n### Dependencies\n\nNone — only Node.js built-ins (`fs`, `path`, `os`, `readline`, `child_process`, `url`, `https`). Node.js ≥ 16.\n\n### How the status line gets its data\n\nClaude Code pipes a JSON payload on stdin. The main-session payload has session/cost/rate-limit info but no per-message token/timing data, so the script re-parses the JSONL transcript at `data.transcript_path` line-by-line, pairing each `assistant` message's `usage.output_tokens` with the timestamp of the preceding `user` message to derive TPS and accumulate session-wide input/output totals (excluding cache-read tokens from the input sum, since those repeat every turn). For subagent rows, the per-task rate comes from `tokenSamples` (parsed defensively; falls back to `tokenCount / elapsed` when the shape is unrecognized).\n\n### Known limitations\n\n- **TPS is not real-time** — the line only re-runs when a new assistant message completes, `/compact` finishes, permission mode changes, etc. For more frequent refresh, add `\"refreshInterval\": 2` to the `statusLine` config in `~/.claude/settings.json`.\n- **TPS reads low** — the denominator is \"previous user/tool_result timestamp → assistant message completion\", which includes network round-trips and time-to-first-token rather than pure decode time.\n- **`~cost:` is an estimate** — see [Cost estimation](#cost-estimation).\n- **Subagent `tokenSamples` is undocumented** — falls back to a coarse `tokenCount / elapsed-time` estimate and is labeled `tok/s` rather than `TPS`.\n- **Branch links support GitHub / GitLab / Bitbucket only** — self-hosted Git renders the branch as plain text rather than a guessed-wrong link.\n- **loopctl is an open-ended autonomous loop** — the round cap only prevents infinite runs; it doesn't check whether the work is actually done. Don't leave it unattended for long stretches.\n- **loopctl's `--max` is bounded by Claude Code's own Stop-hook protection** (8 by default).\n- **loopctl's `--push` pushes directly to the current branch** (including `main`) — no dedicated-branch guard. Push failures don't abort the loop but are folded into the `reason` text.\n\n### Notes\n\nThe end of `statusline.js` contains an optional, environment-specific integration: if `AUTOCLAUDE_BROADCAST` is set to a `broadcast.js` module path, the current session info is broadcast to an \"AutoClaude\" sensor. Wrapped in try/catch; silently skips when the variable is unset or the path is missing, so it never affects status line output.\n\n### Releasing a new version (maintainer)\n\nPushes to `main` trigger `.github/workflows/publish.yml`, which auto-publishes to npm — but only when the version in `package.json` differs from what's already on npm. Docs-only pushes are silent. The release flow:\n\n```bash\nnpm version patch   # bumps version in package.json + creates local v1.0.3 tag\n# update CHANGELOG.md\ngit add . \u0026\u0026 git commit -m \"...\" \u0026\u0026 git push\n```\n\nCI then: publishes to `@tangjianfang/claudecode-statusline`, publishes to `@tangjianfang/cc-statusline`, pushes the `v1.0.3` tag, and creates the GitHub Release.\n\n**Required GitHub secret:** `NPM_TOKEN` — a granular access token with bypass-2fa + publish scope on both packages. Add it at `https://github.com/tangjianfang/claudecode-statusline/settings/secrets/actions`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftangjianfang%2Fclaudecode-statusline","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftangjianfang%2Fclaudecode-statusline","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftangjianfang%2Fclaudecode-statusline/lists"}