An open API service indexing awesome lists of open source software.

https://github.com/tangjianfang/claudecode-statusline

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.
https://github.com/tangjianfang/claudecode-statusline

agentic-loop anthropic auto-continue claude claude-code claude-hooks cli cost-tracking pricing status-line statusline stop-hook terminal token-counter tps

Last synced: 3 days ago
JSON representation

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.

Awesome Lists containing this project

README

          

# cc-statusline

Custom 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).

- **`statusline.js`** — model, output TPS, tokens, cost, git branch, context %, rate-limit usage. Also renders one row per subagent.
- **`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`.

## Install

```bash
npm install -g @tangjianfang/claudecode-statusline
```

The `postinstall` hook automatically:

- copies `statusline.js` + `loopctl.js` to `~/.claude/`
- registers them in `~/.claude/settings.json` (`statusLine`, `subagentStatusLine`, `hooks.Stop`)
- seeds `~/.claude/pricing.json` if missing

Restart Claude Code. Done.

The same package is also published under the shorter name `@tangjianfang/cc-statusline`.

## What it looks like

Two lines in the status bar:

```
[Sonnet 5] 📁 my-project 🌿 main PR#123👀 ctx:42%
TPS: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
```

The 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:

```
Explore running 166.7tok/s tok:50k(25%) 5m00s ~$0.01 eff:high
fix-bug completed 400.0tok/s tok:120k(60%) 5m00s ~$0.04 eff:medium
```

### Screenshot

Real 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:

![cc-statusline running in Claude Code with multiple subagents](docs/cc-statusline-preview.png)

Each 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.

## Auto-continue loop (loopctl)

Off everywhere by default. To use it in a project:

```bash
cd /path/to/project

loopctl on --max 8 --push # enable: up to 8 rounds, auto-commit + push each round
loopctl off # disable
loopctl status # show current state
loopctl presets # list built-in prompts (find-bugs, improve, tests, ...)
```

Built-in presets for `--preset `: `next-step` (default), `find-bugs`, `improve`, `tests`, `docs`, `refactor`. For a fully custom prompt, use `--prompt "your text here"`.

---

## Reference

### Manual / GitHub install

If you'd rather skip npm (or want fine-grained control over what gets overwritten):

```bash
git clone https://github.com/tangjianfang/claudecode-statusline.git
cd claudecode-statusline
node statusline.js --install
node loopctl.js --install
```

Each `--install` runs the same y/n prompts as before — handy if you want to keep an existing file or setting.

After installing, verify the wiring with:

```bash
cc-statusline status # shows ~/.claude files, settings.json contents, pricing.json entry count
loopctl status # shows loop state for the current project
```

### Cost estimation

The `~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`:

```
cost = freshInput/1M × p.in
+ output/1M × p.out
+ cacheRead/1M × p.cacheRead
+ cacheCreate/1M × p.cacheWrite
```

**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).

**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.

Key format:

```json
{
"MiniMax-M3": { "in": 0.3, "out": 1.2, "cacheRead": 0.06, "cacheWrite": 0 }
}
```

`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.

#### Refreshing rates manually

```bash
node pricing-updater.js # fetch mainstream providers, merge into ~/.claude/pricing.json
node pricing-updater.js --model KEY # also include a specific litellm key (repeatable)
node pricing-updater.js --list [pattern] # print matching keys + rates, write nothing
node pricing-updater.js --overwrite # replace target entirely instead of merging
node pricing-updater.js --out pricing.json --overwrite # maintainer: refresh repo's shipped copy
```

There 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.

### loopctl flags (full)

| Flag | Description |
|---|---|
| `--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`. |
| `--push` / `--no-push` | Run `git add -A && git commit && git push` each round (default off). **Pushes directly to the current branch, including `main`** — no dedicated-branch safety net. |
| `--preset ` | Pick the per-round prompt from a built-in template. Unknown names error out. |
| `--prompt "..."` | Fully customize the per-round prompt; takes precedence over `--preset` (last-parsed wins). |

#### Built-in `--preset` values

| Name | Prompt |
|---|---|
| `next-step` (default) | What is the next task? Plan and execute it. |
| `find-bugs` | Proactively check the current code for potential bugs or logic issues. Fix any you find and explain the fix. |
| `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. |
| `tests` | Check whether the project's tests are complete and passing. Add missing test cases or fix failing tests. |
| `docs` | Check whether the docs (README, comments, etc.) are consistent with the current code. Update anything outdated or missing. |
| `refactor` | Find a piece of code that can be safely simplified or refactored, and do so without changing behavior. |

### npm scripts

| Script | What it does |
|---|---|
| `npm run check` | Syntax-check all three scripts (`node --check`). |
| `npm run install` | Run both `--install` flows manually. |
| `npm run install-statusline` | Install only the status line. |
| `npm run install-loopctl` | Install only loopctl. |
| `npm run update-pricing` | Fetch current rates and merge into `~/.claude/pricing.json`. |
| `npm run pricing:list -- minimax` | Print litellm keys/rates matching a pattern. |
| `npm run presets` | List loopctl's built-in `--preset` prompts. |
| `npm run demo` / `npm run demo:subagent` | Smoke test against an empty / sample payload. |

> `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.

### Dependencies

None — only Node.js built-ins (`fs`, `path`, `os`, `readline`, `child_process`, `url`, `https`). Node.js ≥ 16.

### How the status line gets its data

Claude 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).

### Known limitations

- **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`.
- **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.
- **`~cost:` is an estimate** — see [Cost estimation](#cost-estimation).
- **Subagent `tokenSamples` is undocumented** — falls back to a coarse `tokenCount / elapsed-time` estimate and is labeled `tok/s` rather than `TPS`.
- **Branch links support GitHub / GitLab / Bitbucket only** — self-hosted Git renders the branch as plain text rather than a guessed-wrong link.
- **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.
- **loopctl's `--max` is bounded by Claude Code's own Stop-hook protection** (8 by default).
- **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.

### Notes

The 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.

### Releasing a new version (maintainer)

Pushes 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:

```bash
npm version patch # bumps version in package.json + creates local v1.0.3 tag
# update CHANGELOG.md
git add . && git commit -m "..." && git push
```

CI then: publishes to `@tangjianfang/claudecode-statusline`, publishes to `@tangjianfang/cc-statusline`, pushes the `v1.0.3` tag, and creates the GitHub Release.

**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`.