@hasna/statusline 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -29
- package/dist/accounts.d.ts +24 -0
- package/dist/cli.js +421 -51
- package/dist/context-window.d.ts +22 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +427 -52
- package/dist/mcp/index.js +19802 -6343
- package/dist/providers/codex.d.ts +19 -0
- package/dist/providers/opencode.d.ts +16 -0
- package/dist/providers/types.d.ts +1 -1
- package/package.json +10 -8
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ on and off — machine name, project + branch, model, context remaining, session
|
|
|
5
5
|
and more — rendered as one or more rows in your agent's status bar.
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
apple03 · statusline (main) · 12h · 1.2k · fable 5 [1m] · 90% left · $0.04
|
|
8
|
+
apple03 · statusline (main) · 12h · 1.2k · fable 5 [1m] · 90% left · 95% cached · $0.04
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
Built with [Bun](https://bun.sh) + TypeScript. The CLI renderer is dependency-light; the optional MCP server uses the Model Context Protocol SDK. Apache-2.0.
|
|
@@ -22,7 +22,7 @@ That's it — Claude Code picks it up on the next status refresh (no restart nee
|
|
|
22
22
|
## Segments
|
|
23
23
|
|
|
24
24
|
`statusline list` shows a compact, enabled-first summary of your segments (use
|
|
25
|
-
`statusline list --all` for every row). The table below is the full catalog — all
|
|
25
|
+
`statusline list --all` for every row). The table below is the full catalog — all 30
|
|
26
26
|
segment ids from `src/segments/index.ts`.
|
|
27
27
|
|
|
28
28
|
`renderLine` walks your configured segment order, renders each one, and **drops**
|
|
@@ -36,7 +36,8 @@ anything that returns `null` or throws. A failed segment never breaks the host U
|
|
|
36
36
|
| `git-branch` | off | Current Git branch | `git branch --show-current` in `cwd` | outside git or detached | `main` |
|
|
37
37
|
| `commit-age` | on | Time since last commit (compact) | `git log -1` epoch vs now | no commits / not a repo | `12h` |
|
|
38
38
|
| `loc` | on | Lines of code tracked by Git (compact) | `git ls-files` + `wc -l` in repo root | outside git or zero lines | `1.2k` |
|
|
39
|
-
| `current-dir` | off | Current working directory (basename) | `StatusContext.cwd` | never (always renders basename) | `
|
|
39
|
+
| `current-dir` | off | Current working directory (basename) | `StatusContext.cwd` | never (always renders basename) | `statusline` |
|
|
40
|
+
| `cwd` | off | Current working directory (full path) | `StatusContext.cwd`, home directory abbreviated to `~`, head elided past 40 chars | no cwd in the payload | `~/work/statusline` |
|
|
40
41
|
| `model` | off | Current model name (no context tag) | `StatusContext.model.id` via friendly formatter | no model id | `fable 5` |
|
|
41
42
|
| `model-context` | on | Model name with context-size tag | same formatter, keeps `[tag]` suffix | no model id | `fable 5 [1m]` |
|
|
42
43
|
| `model-with-reasoning` | off | Model name with its reasoning effort | lowercased `model.display_name` (or friendly id) + `effort.level`; falls back to `thinking.enabled` when on | no model | `fable (xhigh)` |
|
|
@@ -45,12 +46,15 @@ anything that returns `null` or throws. A failed segment never breaks the host U
|
|
|
45
46
|
| `auth-email` | off | Account email this session is logged in as | the agent's own login record for this config dir, else the registry | no login recorded | `dev@example.com` |
|
|
46
47
|
| `five-hour-limit` | off | Percentage of the 5-hour rate limit used | `rate_limits.five_hour.used_percentage` | host reports no limit data | `5h:42%` |
|
|
47
48
|
| `seven-day-limit` | off | Percentage of the 7-day rate limit used | `rate_limits.seven_day.used_percentage` | host reports no limit data | `7d:12%` |
|
|
49
|
+
| `usage-session` | off | Session (5-hour) usage **remaining** for this pane's own account | this process's `CLAUDE_CONFIG_DIR` account uuid → the accounts usage cache at `~/.hasna/accounts/cache/usage/<uuid>.json` (kept warm by `@hasna/accounts`; **no cloud call**) | not on the Anthropic API (custom endpoint); on Anthropic, shows `5h —` when usage is unknown, missing, stale, or rate-limited | `5h 87%` |
|
|
50
|
+
| `usage-weekly` | off | Weekly usage **remaining** for this pane's own account (the binding limit) | same local usage cache as `usage-session` | not on the Anthropic API (custom endpoint); on Anthropic, shows `7d —` when usage is unavailable | `7d 92%` |
|
|
48
51
|
| `thread-title` | off | Thread title set with `/rename` | `session_name` | thread not renamed | `ship it` |
|
|
49
|
-
| `context-used` | off | Percentage of context window used | session transcript JSONL (`contextUsage`) | transcript missing/unreadable | `10%` |
|
|
52
|
+
| `context-used` | off | Percentage of context window used | session transcript JSONL (`contextUsage`) | transcript missing/unreadable | `ctx 10%` |
|
|
50
53
|
| `context-remaining` | on | Percentage of context window remaining | transcript via `contextUsage` | transcript missing/unreadable | `90% left` |
|
|
51
54
|
| `used-tokens` | off | Total tokens in the context window | transcript usage block (input + output) | transcript missing/unreadable | `102k tok` |
|
|
55
|
+
| `cache-rate` | on | Percentage of input tokens served from cache | transcript usage block (`cache_read_input_tokens` / total input-side); Codex rollout / OpenCode DB for those providers | transcript missing/unreadable or zero input-side tokens | `87% cached` |
|
|
52
56
|
| `cost` | on | Session cost in USD | `StatusContext.cost.totalCostUsd` | cost is zero or missing | `$1,234.50` |
|
|
53
|
-
| `duration` | off | Session wall-clock duration | `StatusContext.cost.totalDurationMs` | duration is zero or missing | `
|
|
57
|
+
| `duration` | off | Session wall-clock duration | `StatusContext.cost.totalDurationMs` | duration is zero or missing | `1h 30m` |
|
|
54
58
|
| `lines-changed` | off | Lines added/removed this session | `cost.totalLinesAdded/Removed` | both zero | `+142/-18` |
|
|
55
59
|
| `output-style` | off | Active output style | `StatusContext.outputStyle` | style is `default` or missing | `concise` |
|
|
56
60
|
| `agent-version` | off | Host agent version | `StatusContext.version` | version missing | `v2.1.39` |
|
|
@@ -59,14 +63,23 @@ anything that returns `null` or throws. A failed segment never breaks the host U
|
|
|
59
63
|
|
|
60
64
|
### Context segments and transcripts
|
|
61
65
|
|
|
62
|
-
Segments that report context usage (`context-used`, `context-remaining`, `used-tokens
|
|
63
|
-
read the session transcript path from the provider payload.
|
|
64
|
-
JSONL for the last assistant entry with a `usage` block and
|
|
65
|
-
`input_tokens + cache_creation_input_tokens + cache_read_input_tokens`. Window
|
|
66
|
-
**1,000,000** when the model id contains `[1m]`, otherwise **200,000**.
|
|
66
|
+
Segments that report context usage (`context-used`, `context-remaining`, `used-tokens`,
|
|
67
|
+
`cache-rate`) read the session transcript path from the provider payload.
|
|
68
|
+
`contextUsage` scans the JSONL for the last assistant entry with a `usage` block and
|
|
69
|
+
sums `input_tokens + cache_creation_input_tokens + cache_read_input_tokens`. Window
|
|
70
|
+
size is **1,000,000** when the model id contains `[1m]`, otherwise **200,000**.
|
|
71
|
+
|
|
72
|
+
`cache-rate` is `cache_read_input_tokens / (input_tokens + cache_creation_input_tokens
|
|
73
|
+
+ cache_read_input_tokens)` from the same last usage block, rendered as a rounded
|
|
74
|
+
percentage (`87% cached`). It renders `0% cached` during the pre-warm phase of a
|
|
75
|
+
session (a nonzero divisor with no cache hits yet) — the same render-zero-not-drop
|
|
76
|
+
convention as `five-hour-limit` — and is omitted only when the transcript is
|
|
77
|
+
missing/unreadable or the divisor is zero. For Codex and OpenCode it reads those
|
|
78
|
+
providers' own usage channels instead (see Providers below).
|
|
67
79
|
|
|
68
80
|
With the test fixture transcript (100k input-side tokens on a 1m window), expect
|
|
69
|
-
`context-used` → `10%`, `context-remaining` → `90% left`, `used-tokens` → `102k tok
|
|
81
|
+
`context-used` → `ctx 10%`, `context-remaining` → `90% left`, `used-tokens` → `102k tok`,
|
|
82
|
+
`cache-rate` → `95% cached`.
|
|
70
83
|
|
|
71
84
|
### Which account am I? (`auth-profile`)
|
|
72
85
|
|
|
@@ -105,7 +118,15 @@ registry knows about always wins.
|
|
|
105
118
|
### Colours
|
|
106
119
|
|
|
107
120
|
Segments may declare a colour, applied by `renderLine` when colours are on
|
|
108
|
-
(the default).
|
|
121
|
+
(the default). Only standard 16-colour ANSI codes are used, so the palette
|
|
122
|
+
works in any modern terminal on both light and dark backgrounds, and
|
|
123
|
+
separators are never coloured.
|
|
124
|
+
|
|
125
|
+
- the context gauges go green below 50%, yellow from 50% to 79%, and red at
|
|
126
|
+
80% and above (the same shape the rate-limit segments use);
|
|
127
|
+
- the rate-limit segments escalate from yellow to red at 80%;
|
|
128
|
+
- `cwd` uses a calm blue accent and elides the head of long paths;
|
|
129
|
+
- model, cost and duration render dim, so they never compete with a warning.
|
|
109
130
|
|
|
110
131
|
```bash
|
|
111
132
|
statusline colors off # or set "colors": false in the config
|
|
@@ -119,7 +140,7 @@ statusline colors off # or set "colors": false in the config
|
|
|
119
140
|
enabled segments first, capped rows, and hints for the detail paths:
|
|
120
141
|
|
|
121
142
|
```
|
|
122
|
-
Segments:
|
|
143
|
+
Segments: 8 enabled / 30 total (showing 12 of 30)
|
|
123
144
|
state default id
|
|
124
145
|
on yes machine
|
|
125
146
|
on yes project
|
|
@@ -127,6 +148,7 @@ on yes commit-age
|
|
|
127
148
|
on yes loc
|
|
128
149
|
on yes model-context
|
|
129
150
|
on yes context-remaining
|
|
151
|
+
on yes cache-rate
|
|
130
152
|
on yes cost
|
|
131
153
|
off no project-name
|
|
132
154
|
off no git-branch
|
|
@@ -179,7 +201,7 @@ Config lives at `~/.config/statusline/config.json` (override with `$STATUSLINE_C
|
|
|
179
201
|
{
|
|
180
202
|
"separator": " · ",
|
|
181
203
|
"colors": true,
|
|
182
|
-
"segments": ["machine", "project", "commit-age", "loc", "model-context", "context-remaining", "cost"]
|
|
204
|
+
"segments": ["machine", "project", "commit-age", "loc", "model-context", "context-remaining", "cache-rate", "cost"]
|
|
183
205
|
}
|
|
184
206
|
```
|
|
185
207
|
|
|
@@ -231,7 +253,9 @@ saveConfig(next);
|
|
|
231
253
|
Useful exports include `parseClaudeInput`, `renderLine`, `renderStatusline`, `segments`,
|
|
232
254
|
`getSegment`, `listSegments`, `defaultConfig`, `loadConfig`, `saveConfig`, `configPath`,
|
|
233
255
|
`previewStatusline`, `enableSegments`, `disableSegments`, `orderSegments`,
|
|
234
|
-
`setSeparator`, `setColors`, `installClaude`,
|
|
256
|
+
`setSeparator`, `setColors`, `installClaude`, the cache-rate channel
|
|
257
|
+
(`cacheRate`, `codexCacheRate`, `latestCodexSessionPath`, `opencodeCacheRate`), and the
|
|
258
|
+
account, context, format, and Git helpers.
|
|
235
259
|
|
|
236
260
|
## MCP
|
|
237
261
|
|
|
@@ -304,30 +328,63 @@ on every status refresh — **no restart needed**.
|
|
|
304
328
|
|
|
305
329
|
Every field is optional — partial or empty payloads still produce a usable context.
|
|
306
330
|
|
|
307
|
-
###
|
|
331
|
+
### Codex CLI (implemented, env-selected)
|
|
332
|
+
|
|
333
|
+
Codex ships its own built-in segment picker and has no external `statusLine` command
|
|
334
|
+
hook, so there is no `statusline install codex` — the renderer is invoked standalone
|
|
335
|
+
with the provider selected by the environment:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
STATUSLINE_PROVIDER=codex statusline render
|
|
339
|
+
```
|
|
308
340
|
|
|
309
|
-
`
|
|
310
|
-
|
|
341
|
+
`cache-rate` then reads the newest Codex session rollout
|
|
342
|
+
(`~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl`, newest file mtime): the LAST
|
|
343
|
+
`event_msg` line whose `payload.type` is `token_count`, whose
|
|
344
|
+
`payload.info.total_token_usage` holds **cumulative session totals**
|
|
345
|
+
(`input_tokens`, `cached_input_tokens`, `cache_write_input_tokens`, …). The rate is
|
|
346
|
+
`cached_input_tokens / (input_tokens + cached_input_tokens + cache_write_input_tokens)`,
|
|
347
|
+
clamped to `[0, 1]`. Exposed on the SDK as `latestCodexSessionPath()` /
|
|
348
|
+
`codexCacheRate(path?)`. Caveat: the semantics of Codex's `input_tokens` relative to
|
|
349
|
+
`cached_input_tokens` (uncached-only vs total) are inferred from measured samples —
|
|
350
|
+
the clamp and the fixture tests lock the adapter to the documented shape.
|
|
351
|
+
|
|
352
|
+
### OpenCode (implemented, env-selected)
|
|
353
|
+
|
|
354
|
+
OpenCode has no statusline/footer hook in its config as of v1.3.x, so the same
|
|
355
|
+
env-selector applies:
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
STATUSLINE_PROVIDER=opencode statusline render
|
|
359
|
+
```
|
|
311
360
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
segment
|
|
361
|
+
`cache-rate` reads `~/.local/share/opencode/opencode.db` (SQLite) with a read-only
|
|
362
|
+
`Bun.sqlite` query — zero new dependencies, and a WAL lock mid-write degrades to
|
|
363
|
+
omitting the segment, never a crash. It takes the newest session row's
|
|
364
|
+
`tokens_cache_read / (tokens_input + tokens_cache_read + tokens_cache_write)` from the
|
|
365
|
+
`session` table, falling back to `session_v2` when `session` has no populated row (both
|
|
366
|
+
schemas carry the columns). SDK surface: `opencodeCacheRate({ dbPath?, sessionId? })`.
|
|
315
367
|
|
|
316
|
-
### Cursor (not implemented)
|
|
368
|
+
### Cursor (not implemented — no verifiable source)
|
|
317
369
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
370
|
+
No `statusline install cursor` and no adapter. Unlike Codex and OpenCode, Cursor has
|
|
371
|
+
**no local per-turn token-usage record to read**: `~/.cursor/chats/*/store.db` holds
|
|
372
|
+
only `blobs`/`meta` tables, and `~/.cursor/ai-tracking/ai-code-tracking.db` carries no
|
|
373
|
+
per-turn usage. Token usage is only visible in Cursor's own UI/API, so per the honesty
|
|
374
|
+
rule no adapter is fabricated. If Cursor later persists usage locally, an adapter slots
|
|
375
|
+
in behind the same `cacheRate(ctx)` dispatch.
|
|
321
376
|
|
|
322
377
|
### Other agents
|
|
323
378
|
|
|
324
379
|
| Agent | Status |
|
|
325
380
|
|-------|--------|
|
|
326
|
-
|
|
|
327
|
-
|
|
|
381
|
+
| Codex CLI | ✅ `STATUSLINE_PROVIDER=codex` — `cache-rate` from the newest session rollout |
|
|
382
|
+
| OpenCode | ✅ `STATUSLINE_PROVIDER=opencode` — `cache-rate` from the sessions DB |
|
|
383
|
+
| Cursor | ❌ no local per-turn token usage exists — no adapter (see above) |
|
|
384
|
+
| Codewith | ⏳ no statusline/footer hook; a future `parseCodewithInput` would map its payload into `StatusContext` and reuse the registry (tracked in STA-00003) |
|
|
328
385
|
|
|
329
|
-
Adding a provider means one small
|
|
330
|
-
(`src/providers/types.ts`). PRs welcome.
|
|
386
|
+
Adding a provider means one small adapter: agent payload/source → `StatusContext`
|
|
387
|
+
(`src/providers/types.ts`) or a `cacheRate(ctx)` data channel. PRs welcome.
|
|
331
388
|
|
|
332
389
|
## Development
|
|
333
390
|
|
package/dist/accounts.d.ts
CHANGED
|
@@ -49,4 +49,28 @@ export declare function sessionAccount(env?: Env, tool?: string): Promise<Sessio
|
|
|
49
49
|
* blob, which is large enough to only touch when a segment asks for it.
|
|
50
50
|
*/
|
|
51
51
|
export declare function sessionAccountEmail(env?: Env, tool?: string): Promise<string | null>;
|
|
52
|
+
/**
|
|
53
|
+
* The account uuid the host agent recorded as logged in for this config dir.
|
|
54
|
+
* Read from the same live state blob `sessionAccountEmail` prefers, so it names
|
|
55
|
+
* whoever is actually signed in now — the account whose usage the warmer
|
|
56
|
+
* cached — rather than a registry entry that can lag a re-login or a switch.
|
|
57
|
+
* Returns null when no record is present or the value is not a safe cache key.
|
|
58
|
+
*/
|
|
59
|
+
export declare function sessionAccountUuid(env?: Env): string | null;
|
|
60
|
+
/** Usage headroom for this session's account, as percent still available. */
|
|
61
|
+
export interface SessionUsage {
|
|
62
|
+
/** The ~5-hour session window's remaining percent, or null when unknown. */
|
|
63
|
+
sessionHeadroom: number | null;
|
|
64
|
+
/** The weekly window's remaining percent — the binding limit — or null. */
|
|
65
|
+
weeklyHeadroom: number | null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Session and weekly usage headroom for the account this pane is running as,
|
|
69
|
+
* read straight from the accounts usage cache — never the cloud API, which the
|
|
70
|
+
* launched, registry-stripped session cannot reach and could not afford on
|
|
71
|
+
* every render anyway. Returns nulls (so a segment shows a neutral marker)
|
|
72
|
+
* whenever the account is unknown, the cache is missing, stale, corrupt, or
|
|
73
|
+
* keyed to a different account. Never throws.
|
|
74
|
+
*/
|
|
75
|
+
export declare function sessionUsage(env?: Env, now?: Date): SessionUsage;
|
|
52
76
|
export {};
|