@hasna/statusline 0.0.1 → 0.0.2
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 +199 -22
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1025 -0
- package/dist/config.d.ts +9 -0
- package/dist/context-window.d.ts +14 -0
- package/dist/format.d.ts +4 -0
- package/dist/git.d.ts +6 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +646 -0
- package/dist/install.d.ts +5 -0
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/index.js +20313 -0
- package/dist/providers/claude.d.ts +7 -0
- package/dist/providers/types.d.ts +25 -0
- package/dist/render.d.ts +4 -0
- package/dist/segments/index.d.ts +3 -0
- package/package.json +34 -4
- package/src/config.ts +0 -53
- package/src/context-window.ts +0 -51
- package/src/format.ts +0 -36
- package/src/git.ts +0 -55
- package/src/index.ts +0 -143
- package/src/install.ts +0 -20
- package/src/providers/claude.ts +0 -35
- package/src/providers/types.ts +0 -23
- package/src/render.ts +0 -19
- package/src/segments/index.ts +0 -187
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ and more — rendered as a single line for your agent's status bar.
|
|
|
8
8
|
apple03 · statusline (main) · 12h · 1.2k · fable 5 [1m] · 90% left · $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.
|
|
12
12
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
@@ -21,32 +21,92 @@ That's it — Claude Code picks it up on the next status refresh (no restart nee
|
|
|
21
21
|
|
|
22
22
|
## Segments
|
|
23
23
|
|
|
24
|
-
`statusline list` shows
|
|
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 18
|
|
26
|
+
segment ids from `src/segments/index.ts`.
|
|
27
|
+
|
|
28
|
+
`renderLine` walks your configured segment order, renders each one, and **drops**
|
|
29
|
+
anything that returns `null` or throws. A failed segment never breaks the host UI.
|
|
30
|
+
|
|
31
|
+
| Segment | Default | Description | Data source | Omit when | Example |
|
|
32
|
+
|---------|---------|-------------|-------------|-----------|---------|
|
|
33
|
+
| `machine` | on | Machine hostname (short) | `os.hostname()` — first label before `.` | never (always renders) | `apple03` |
|
|
34
|
+
| `project` | on | Project name with current Git branch | `gitProjectName(cwd)` + `gitBranch(cwd)`; falls back to cwd basename | no project name resolvable | `statusline (main)` |
|
|
35
|
+
| `project-name` | off | Project name only | `gitProjectName(cwd)` or cwd basename | outside a git repo with no name | `statusline` |
|
|
36
|
+
| `git-branch` | off | Current Git branch | `git branch --show-current` in `cwd` | outside git or detached | `main` |
|
|
37
|
+
| `commit-age` | on | Time since last commit (compact) | `git log -1` epoch vs now | no commits / not a repo | `12h` |
|
|
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) | `open-statusline` |
|
|
40
|
+
| `model` | off | Current model name (no context tag) | `StatusContext.model.id` via friendly formatter | no model id | `fable 5` |
|
|
41
|
+
| `model-context` | on | Model name with context-size tag | same formatter, keeps `[tag]` suffix | no model id | `fable 5 [1m]` |
|
|
42
|
+
| `context-used` | off | Percentage of context window used | session transcript JSONL (`contextUsage`) | transcript missing/unreadable | `10%` |
|
|
43
|
+
| `context-remaining` | on | Percentage of context window remaining | transcript via `contextUsage` | transcript missing/unreadable | `90% left` |
|
|
44
|
+
| `used-tokens` | off | Total tokens in the context window | transcript usage block (input + output) | transcript missing/unreadable | `102k tok` |
|
|
45
|
+
| `cost` | on | Session cost in USD | `StatusContext.cost.totalCostUsd` | cost is zero or missing | `$1,234.50` |
|
|
46
|
+
| `duration` | off | Session wall-clock duration | `StatusContext.cost.totalDurationMs` | duration missing | `1h30m` |
|
|
47
|
+
| `lines-changed` | off | Lines added/removed this session | `cost.totalLinesAdded/Removed` | both zero | `+142/-18` |
|
|
48
|
+
| `output-style` | off | Active output style | `StatusContext.outputStyle` | style is `default` or missing | `concise` |
|
|
49
|
+
| `agent-version` | off | Host agent version | `StatusContext.version` | version missing | `v2.1.39` |
|
|
50
|
+
| `session-id` | off | Session identifier (short) | first UUID segment of `sessionId` | no session id | `abc12345` |
|
|
51
|
+
|
|
52
|
+
### Context segments and transcripts
|
|
53
|
+
|
|
54
|
+
Segments that report context usage (`context-used`, `context-remaining`, `used-tokens`)
|
|
55
|
+
read the session transcript path from the provider payload. `contextUsage` scans the
|
|
56
|
+
JSONL for the last assistant entry with a `usage` block and sums
|
|
57
|
+
`input_tokens + cache_creation_input_tokens + cache_read_input_tokens`. Window size is
|
|
58
|
+
**1,000,000** when the model id contains `[1m]`, otherwise **200,000**.
|
|
59
|
+
|
|
60
|
+
With the test fixture transcript (100k input-side tokens on a 1m window), expect
|
|
61
|
+
`context-used` → `10%`, `context-remaining` → `90% left`, `used-tokens` → `102k tok`.
|
|
62
|
+
|
|
63
|
+
### Quick reference from `statusline list`
|
|
64
|
+
|
|
65
|
+
`statusline list` is compact by default so it stays friendly in agent terminals —
|
|
66
|
+
enabled segments first, capped rows, and hints for the detail paths:
|
|
25
67
|
|
|
26
68
|
```
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
[ ] output-style Active output style (omitted when default)
|
|
43
|
-
[ ] agent-version Host agent version (e.g. Claude Code version)
|
|
44
|
-
[ ] session-id Session identifier (short)
|
|
69
|
+
Segments: 7 enabled / 18 total (showing 12 of 18)
|
|
70
|
+
state default id
|
|
71
|
+
on yes machine
|
|
72
|
+
on yes project
|
|
73
|
+
on yes commit-age
|
|
74
|
+
on yes loc
|
|
75
|
+
on yes model-context
|
|
76
|
+
on yes context-remaining
|
|
77
|
+
on yes cost
|
|
78
|
+
off no project-name
|
|
79
|
+
off no git-branch
|
|
80
|
+
off no current-dir
|
|
81
|
+
off no model
|
|
82
|
+
off no context-used
|
|
83
|
+
Hint: use `--all` for all matching rows, `statusline show <id>` for details, `--verbose` for descriptions, `--json` for machines.
|
|
45
84
|
```
|
|
46
85
|
|
|
86
|
+
Use gradual disclosure when you need more:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
statusline list --verbose # include descriptions, still capped
|
|
90
|
+
statusline list --all --verbose # include every row with descriptions
|
|
91
|
+
statusline list --all # show every segment row
|
|
92
|
+
statusline list --limit 5 # cap rows explicitly
|
|
93
|
+
statusline list --enabled # only enabled segments
|
|
94
|
+
statusline list --disabled # only disabled segments
|
|
95
|
+
statusline list --search token # filter by id or description
|
|
96
|
+
statusline list --json # structured output for tooling
|
|
97
|
+
statusline show model-context # full details for one segment
|
|
98
|
+
statusline inspect used-tokens --json # JSON detail path
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`statusline list --json` returns `{ total, matching, showing, limited, segments, next }`.
|
|
102
|
+
Each segment has `{ id, description, enabled, defaultEnabled }`; `next` is `null`
|
|
103
|
+
unless the result is limited. Column padding is display-only — it does not affect
|
|
104
|
+
statusbar width.
|
|
105
|
+
|
|
47
106
|
## Usage
|
|
48
107
|
|
|
49
108
|
```bash
|
|
109
|
+
statusline list # compact segment summary
|
|
50
110
|
statusline enable used-tokens duration # turn segments on (appended at the end)
|
|
51
111
|
statusline disable loc # turn segments off
|
|
52
112
|
statusline order machine project model-context cost # exact order = enabled set
|
|
@@ -64,6 +124,23 @@ Config lives at `~/.config/statusline/config.json` (override with `$STATUSLINE_C
|
|
|
64
124
|
}
|
|
65
125
|
```
|
|
66
126
|
|
|
127
|
+
## Theming and layout
|
|
128
|
+
|
|
129
|
+
There is no fixed width knob — the rendered line grows with enabled segments. Control
|
|
130
|
+
length practically:
|
|
131
|
+
|
|
132
|
+
1. **Fewer segments** — `statusline disable` segments you do not need, or `statusline order` to pick a compact set.
|
|
133
|
+
2. **Shorter separator** — `statusline separator "·"` or `" | "` (default is `" · "`).
|
|
134
|
+
3. **Split project info** — use `project-name` + `git-branch` instead of combined `project` if you want to omit the branch when unknown.
|
|
135
|
+
4. **Rely on omit-when-null** — segments like `cost`, `context-remaining`, and `lines-changed` disappear when data is unavailable instead of showing placeholders.
|
|
136
|
+
|
|
137
|
+
**Segment order matters.** `statusline order a b c` sets both the display order and the
|
|
138
|
+
exact enabled set — segments not listed are disabled. `statusline enable` appends new
|
|
139
|
+
ids to the end; `statusline disable` removes them.
|
|
140
|
+
|
|
141
|
+
**Config path:** `~/.config/statusline/config.json`, overridable with `$STATUSLINE_CONFIG`.
|
|
142
|
+
`statusline reset` restores `defaultConfig()` (separator + default segment list above).
|
|
143
|
+
|
|
67
144
|
## How it works
|
|
68
145
|
|
|
69
146
|
Claude Code pipes a JSON payload (cwd, model, session cost, transcript path, …) to the
|
|
@@ -72,11 +149,103 @@ renders each enabled segment, drops anything unavailable, and prints one line. S
|
|
|
72
149
|
that need more than the payload offers (e.g. `context-remaining`) read the session
|
|
73
150
|
transcript to compute it. A segment failure is never fatal — it's simply omitted.
|
|
74
151
|
|
|
152
|
+
## SDK
|
|
153
|
+
|
|
154
|
+
The package root is a side-effect-free SDK surface:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import {
|
|
158
|
+
renderStatusline,
|
|
159
|
+
listSegments,
|
|
160
|
+
enableSegments,
|
|
161
|
+
saveConfig,
|
|
162
|
+
loadConfig,
|
|
163
|
+
} from "@hasna/statusline";
|
|
164
|
+
|
|
165
|
+
const config = loadConfig();
|
|
166
|
+
const line = await renderStatusline({ cwd: process.cwd() }, config);
|
|
167
|
+
const next = enableSegments(["duration"], config).config;
|
|
168
|
+
saveConfig(next);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Useful exports include `parseClaudeInput`, `renderLine`, `segments`, `getSegment`,
|
|
172
|
+
`defaultConfig`, `loadConfig`, `saveConfig`, `configPath`, `previewStatusline`,
|
|
173
|
+
`orderSegments`, `disableSegments`, `setSeparator`, and `installClaude`.
|
|
174
|
+
|
|
175
|
+
## MCP
|
|
176
|
+
|
|
177
|
+
`statusline-mcp` starts a stdio MCP server:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
statusline-mcp
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
It exposes safe tools for `render_statusline`, `preview_statusline`,
|
|
184
|
+
`list_segments`, `get_config`, `update_config`, `enable_segments`,
|
|
185
|
+
`disable_segments`, `order_segments`, and `reset_config`. Config mutation tools
|
|
186
|
+
require `confirm_write: true`; every mutation tool supports `dry_run: true`.
|
|
187
|
+
|
|
188
|
+
The MCP server intentionally does not mutate Claude settings. Use
|
|
189
|
+
`statusline install claude` or the `installClaude()` SDK helper when you
|
|
190
|
+
explicitly want to wire the CLI into Claude Code.
|
|
191
|
+
|
|
75
192
|
## Providers
|
|
76
193
|
|
|
194
|
+
### Claude Code (implemented)
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
bun install -g @hasna/statusline
|
|
198
|
+
statusline install claude
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`installClaude()` writes to `~/.claude/settings.json`:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"statusLine": { "type": "command", "command": "statusline render" }
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Existing settings are preserved; the previous file is backed up as
|
|
210
|
+
`settings.json.bak-statusline`. Claude Code pipes JSON on stdin to `statusline render`
|
|
211
|
+
on every status refresh — **no restart needed**.
|
|
212
|
+
|
|
213
|
+
**stdin fields** parsed by `parseClaudeInput` (`src/providers/claude.ts`):
|
|
214
|
+
|
|
215
|
+
| Payload field | Maps to `StatusContext` |
|
|
216
|
+
|---------------|-------------------------|
|
|
217
|
+
| `cwd` / `workspace.current_dir` | `cwd` |
|
|
218
|
+
| `workspace.project_dir` | `projectDir` |
|
|
219
|
+
| `model.id`, `model.display_name` | `model.id`, `model.displayName` |
|
|
220
|
+
| `cost.total_cost_usd` | `cost.totalCostUsd` |
|
|
221
|
+
| `cost.total_duration_ms` | `cost.totalDurationMs` |
|
|
222
|
+
| `cost.total_lines_added/removed` | `cost.totalLinesAdded/Removed` |
|
|
223
|
+
| `transcript_path` | `transcriptPath` |
|
|
224
|
+
| `session_id` | `sessionId` |
|
|
225
|
+
| `version` | `version` |
|
|
226
|
+
| `output_style.name` | `outputStyle` |
|
|
227
|
+
|
|
228
|
+
Every field is optional — partial or empty payloads still produce a usable context.
|
|
229
|
+
|
|
230
|
+
### Codewith (not implemented)
|
|
231
|
+
|
|
232
|
+
`statusline install` only accepts `claude` today. Running
|
|
233
|
+
`statusline install codewith` errors with *unsupported target* (`src/cli.ts`).
|
|
234
|
+
|
|
235
|
+
The renderer is provider-agnostic: a future `parseCodewithInput` would map Codewith's
|
|
236
|
+
status payload into `StatusContext` (`src/providers/types.ts`) and reuse the same
|
|
237
|
+
segment registry. No install wiring exists yet (tracked in STA-00003).
|
|
238
|
+
|
|
239
|
+
### Cursor (not implemented)
|
|
240
|
+
|
|
241
|
+
Same gap as Codewith — no `statusline install cursor` subcommand and no Cursor-specific
|
|
242
|
+
parser. A future adapter would implement `parseCursorInput` → `StatusContext` and hook
|
|
243
|
+
into Cursor's status bar the same way Claude does (tracked in STA-00004).
|
|
244
|
+
|
|
245
|
+
### Other agents
|
|
246
|
+
|
|
77
247
|
| Agent | Status |
|
|
78
248
|
|-------|--------|
|
|
79
|
-
| Claude Code | ✅ `statusline install claude` |
|
|
80
249
|
| OpenCode | ⏳ no statusline/footer hook in its config as of v1.3.x — the renderer is provider-agnostic (`src/providers/`), so an adapter slots in the moment one exists |
|
|
81
250
|
| Codex CLI | Codex ships its own built-in segment picker; no external command hook |
|
|
82
251
|
|
|
@@ -87,8 +256,16 @@ Adding a provider means one small parser: agent payload → `StatusContext`
|
|
|
87
256
|
|
|
88
257
|
```bash
|
|
89
258
|
bun install
|
|
259
|
+
bun run typecheck
|
|
90
260
|
bun test
|
|
91
|
-
|
|
261
|
+
bun run build
|
|
262
|
+
echo '{"cwd":"'$PWD'","model":{"id":"claude-fable-5[1m]"}}' | bun src/cli.ts render
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Spot-check fixture output:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
cat test/fixtures/claude-input.json | bun src/cli.ts render
|
|
92
269
|
```
|
|
93
270
|
|
|
94
271
|
## License
|
package/dist/cli.d.ts
ADDED