@narumitw/pi-statusline 0.23.0 → 0.28.0

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 CHANGED
@@ -1,194 +1,291 @@
1
- # ✨ pi-statusline — Configurable Tokyo Night Footer for Pi
1
+ # ✨ pi-statusline — A Beautiful, Practical Footer for Pi
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@narumitw/pi-statusline)](https://www.npmjs.com/package/@narumitw/pi-statusline) [![Pi extension](https://img.shields.io/badge/Pi-extension-blue)](https://pi.dev) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
4
4
 
5
- `@narumitw/pi-statusline` is a native [Pi coding agent](https://pi.dev) extension that replaces Pi's footer with a configurable Tokyo Night powerline statusline.
5
+ `@narumitw/pi-statusline` gives [Pi](https://pi.dev) an opinionated powerline footer that looks good
6
+ without setup and keeps useful context visible as the terminal narrows.
6
7
 
7
- ## Features
8
+ A representative uncolored layout:
8
9
 
9
- - Shows provider, model, thinking, directory, Git/PR state, tools, context, tokens, cost, time, and extension statuses.
10
- - Uses one Starship-inspired `░▒▓` / `` Tokyo Night layout.
11
- - Configures segment order, visibility, multiline breaks, surrounding text, palette, density, separators, and extension icons through JSON.
12
- - Creates a complete editable default configuration on first session start.
13
- - Applies validated `/statusline settings` edits immediately after an atomic save.
14
- - Caches Git state outside footer rendering and guards stale session results.
15
- - Wraps extension statuses safely at narrow terminal widths.
10
+ ```text
11
+ ░▒▓ 🤖 sonnet-4 🧠 high 📁 pi-extensions 🌿 main ~2 🪟 ctx 42% 💸 $0.184
12
+ ```
13
+
14
+ ## ✨ Features
15
+
16
+ - **Zero-config default:** model, thinking, workspace, Git/PR state, context use, and cost.
17
+ - **Responsive:** removes lower-priority segments before important information gets clipped.
18
+ - **Quiet when idle:** activity appears only while Pi is streaming or running tools.
19
+ - **Easy choices:** three information levels and seven previewable color presets.
20
+ - **Still flexible:** custom layouts, multiline rows, colors, labels, separators, and status icons stay
21
+ available under **Advanced**.
16
22
 
17
- ## Install
23
+ > **Need more customization?** See
24
+ > [`pi-starship`](https://github.com/narumiruna/pi-extensions/tree/main/extensions/pi-starship)
25
+ > ([npm](https://www.npmjs.com/package/@narumitw/pi-starship)). It uses a
26
+ > [Starship-inspired](https://starship.rs/) TOML format and style syntax for deeper control over
27
+ > layout, modules, and colors. Choose `pi-statusline` for practical defaults and quick setup.
28
+ >
29
+ > Do not enable both extensions at the same time because both own Pi's footer.
30
+
31
+ ## 📦 Install
18
32
 
19
33
  ```bash
20
34
  pi install npm:@narumitw/pi-statusline
21
35
  ```
22
36
 
23
- Try it once or from a checkout:
37
+ Try it without installing, or load it from this repository:
24
38
 
25
39
  ```bash
26
40
  pi -e npm:@narumitw/pi-statusline
27
41
  pi -e ./extensions/pi-statusline
28
42
  ```
29
43
 
30
- Do not enable this together with `@narumitw/pi-starship`: both extensions own Pi's footer. Use `pi-starship` instead when you need full Starship-style format/style grammar.
44
+ For the best result, use a terminal font that includes Powerline glyphs and emoji.
45
+
46
+ ## 🚀 Quick start
47
+
48
+ 1. Install the extension and start Pi.
49
+ 2. Run `/statusline`.
50
+ 3. Choose an appearance or information level; changes apply immediately.
51
+
52
+ ```text
53
+ Appearance (tokyo-night)
54
+ Information (balanced)
55
+ Advanced
56
+ Status
57
+ Help
58
+ ```
59
+
60
+ | Menu item | What it does |
61
+ | --- | --- |
62
+ | **Appearance** | Preview palettes with Up/Down; Enter applies and Escape cancels |
63
+ | **Information** | Preview and apply a curated set of segments |
64
+ | **Advanced** | Open Custom layout or Edit settings JSON |
65
+ | **Status** | Show the effective source, path, appearance, layout, and diagnostics |
66
+ | **Help** | Show command and schema guidance |
67
+
68
+ ### Information levels
69
+
70
+ Selecting a level replaces only the `segments` array. Unknown and unrelated JSON fields are
71
+ preserved.
72
+
73
+ | Level | Included segments |
74
+ | --- | --- |
75
+ | **Minimal** | `model cwd branch context` |
76
+ | **Balanced** (default) | `model thinking cwd branch tools context cost` |
77
+ | **Detailed** | `provider model thinking cwd branch tools context tokens cost time` |
78
+ | **Custom** | Any other segment order, including explicit line breaks |
79
+
80
+ The `tools` segment takes no space while idle.
81
+
82
+ ## 💬 Commands
83
+
84
+ | Command | Purpose |
85
+ | --- | --- |
86
+ | `/statusline` | Open Appearance, Information, Advanced, Status, and Help |
87
+ | `/statusline settings` | Open the JSON editor in TUI mode |
88
+ | `/statusline status` | Show the effective settings and diagnostics |
89
+ | `/statusline help` | Show command and schema guidance |
90
+
91
+ The direct `settings`, `status`, and `help` routes remain for compatibility. RPC receives observable
92
+ notifications instead of TUI-only controls. Unknown subcommands and trailing arguments are rejected.
93
+
94
+ ## 📐 Runtime behavior
95
+
96
+ ### Responsive fitting
97
+
98
+ Each row keeps its configured segment order. If it is too wide, pi-statusline removes the
99
+ lowest-priority segment, recomputes the powerline transitions, and repeats until the row fits.
100
+ Retention priority is highest to lowest:
101
+
102
+ ```text
103
+ context model branch tools cwd thinking cost provider tokens time turn brand
104
+ ```
105
+
106
+ Explicit `line_break` entries remain row boundaries. A single segment that is still too wide is
107
+ ANSI-safely truncated.
108
+
109
+ ### Activity, Git, and PR state
110
+
111
+ - During active work, `tools` shows `💭 thinking` or `⚙ <tool>` with parallel counts.
112
+ - Activity disappears after the agent settles and resets across session replacement or shutdown.
113
+ - Clean repositories show no Git counters.
114
+ - Dirty counters are `⇡` ahead, `⇣` behind, `+` staged, `~` modified/deleted, `?` untracked, and `!`
115
+ conflicts.
116
+ - A linked GitHub PR appears with the branch when possible, avoiding a duplicate extension status.
117
+ - Context color changes to warning at 70% and error at 90%.
118
+ - Git state is cached outside footer rendering and stale session results are ignored.
31
119
 
32
- ## Configuration
120
+ ## ⚙️ Settings
33
121
 
34
- The only configuration source is:
122
+ The extension uses one user-level file:
35
123
 
36
124
  ```text
37
125
  <getAgentDir()>/pi-statusline.json
38
126
  ```
39
127
 
40
- On first session start, the extension atomically creates the complete default document. It never overwrites an existing malformed or unreadable file. A valid legacy `pi-statusline-settings.json` is migrated by preserving its original bytes; the canonical filename wins when both exist.
128
+ There are no project or environment overrides. On first session start, pi-statusline atomically
129
+ creates a complete editable default. It never overwrites malformed or unreadable settings. Settings
130
+ reload on startup, `/reload`, and session replacement.
41
131
 
42
- There are no project overrides or environment-variable overrides.
132
+ A valid legacy `pi-statusline-settings.json` is migrated without rewriting its contents. If both files
133
+ exist, `pi-statusline.json` wins.
43
134
 
44
- ### Default JSON
135
+ ### Settings reference
136
+
137
+ | Field | Accepted values | Purpose |
138
+ | --- | --- | --- |
139
+ | `palettePreset` | `tokyo-night`, `ocean`, `sunset`, `forest`, `candy`, `neon`, `mono`, `custom` | Select the active color preset |
140
+ | `palette` | Per-segment `fg`/`bg` `#RRGGBB` colors | Define colors used by `custom` |
141
+ | `density` | `compact`, `cozy` | Control horizontal padding |
142
+ | `separator` | `none`, `dot`, `bar`, `powerline`, `round` | Separate adjacent segments in one color block |
143
+ | `segments` | Ordered unique segment names and `line_break` | Control visibility, order, and rows |
144
+ | `segmentText` | Per-segment `prefix` and `suffix` | Wrap Pi-owned dynamic values |
145
+ | `extensionStatusIcons` | Raw status key or `namespace:*` to icon string | Customize extension status icons |
146
+
147
+ All fields are optional in an existing document. Missing fields use defaults. Unknown fields produce a
148
+ warning but are preserved by menu saves. Invalid recognized values block saving, leaving the previous
149
+ file and live footer unchanged.
150
+
151
+ A compact customization example:
45
152
 
46
153
  ```json
47
154
  {
48
- "palette": "tokyo-night",
155
+ "palettePreset": "ocean",
49
156
  "density": "compact",
50
- "separator": "none",
51
- "segments": [
52
- "brand",
53
- "provider",
54
- "model",
55
- "thinking",
56
- "cwd",
57
- "branch",
58
- "tools",
59
- "context",
60
- "tokens",
61
- "cost",
62
- "time"
63
- ],
157
+ "separator": "dot",
158
+ "segments": ["model", "thinking", "cwd", "branch", "context", "cost"],
64
159
  "segmentText": {
65
- "brand": { "prefix": "", "suffix": "" },
66
- "provider": { "prefix": "🔌 ", "suffix": "" },
67
- "model": { "prefix": "🤖 ", "suffix": "" },
68
- "thinking": { "prefix": "🧠 ", "suffix": "" },
69
- "cwd": { "prefix": "📁 ", "suffix": "" },
70
- "branch": { "prefix": "🌿 ", "suffix": "" },
71
- "tools": { "prefix": "", "suffix": "" },
72
- "context": { "prefix": "🪟 ctx ", "suffix": "" },
73
- "tokens": { "prefix": "🔢 ", "suffix": "" },
74
- "cost": { "prefix": "💸 $", "suffix": "" },
75
- "time": { "prefix": "🕒 ", "suffix": "" },
76
- "turn": { "prefix": "🔁 #", "suffix": "" }
160
+ "context": { "prefix": "ctx ", "suffix": "" }
77
161
  },
78
162
  "extensionStatusIcons": {
79
- "chrome-devtools": "🌐",
80
- "codex-usage": "📊",
81
- "caffeinate": "💊",
82
- "firecrawl": "🔥",
83
- "github-pr": "🔎",
84
- "goal": "🎯",
85
- "lsp": "🧰",
86
- "plan-mode": "📝",
87
- "pisync": "🔄",
88
- "subagents": "🧑‍🤝‍🧑",
89
- "unknown-error-retry": "🔁"
163
+ "goal": "◎",
164
+ "foo:*": "🧪"
90
165
  }
91
166
  }
92
167
  ```
93
168
 
94
- All fields are optional in an existing document. Missing fields use defaults.
95
-
96
- ### Appearance
169
+ Use **Advanced → Edit settings JSON** or `/statusline settings` to edit, validate, atomically save, and
170
+ apply the file.
97
171
 
98
- - `palette`: `tokyo-night`, `ocean`, `sunset`, `forest`, `candy`, `neon`, or `mono`.
99
- - `density`: `compact` or `cozy`.
100
- - `separator`: `none`, `dot`, `bar`, `powerline`, or `round`.
172
+ ## 🎨 Appearance
101
173
 
102
- The separator applies only between adjacent segments in the same color block. Color-block transitions always use ``. Extension statuses remain on separate wrapped lines with their own palette-colored separator.
174
+ Named palettes provide contrast-checked color ramps. Appearance previews update while the picker
175
+ moves, but save only when Enter is pressed; Escape restores the saved palette.
103
176
 
104
- ### Segments
177
+ When `palettePreset` is `custom`, `palette` maps segment names to foreground/background colors:
105
178
 
106
- `segments` is an ordered list containing:
107
-
108
- ```text
109
- brand provider model thinking cwd branch tools context tokens cost time turn line_break
179
+ ```json
180
+ {
181
+ "palettePreset": "custom",
182
+ "palette": {
183
+ "model": { "fg": "#090c0c", "bg": "#a3aed2" },
184
+ "context": { "fg": "#c0caf5", "bg": "#1d2230" }
185
+ }
186
+ }
110
187
  ```
111
188
 
112
- The array controls visibility and actual rendering order. Data segments must remain unique. The special `line_break` segment starts another footer row and may repeat when another segment separates each occurrence; consecutive `line_break` entries are invalid. Each row receives its own powerline start and end. `line_break` has no `segmentText` entry.
189
+ - Selecting `custom` without a palette copies the active named preset as a starting point.
190
+ - A manually authored `"palettePreset": "custom"` without `palette` uses Tokyo Night colors.
191
+ - Named presets ignore but preserve an existing custom palette.
192
+ - A `palette` object without `palettePreset` selects `custom`.
193
+ - Legacy string palettes such as `"palette": "ocean"` remain accepted.
194
+ - Missing custom colors remain unstyled instead of inheriting Tokyo Night.
195
+ - Adjacent segments with identical colors share one block; transitions use ``.
113
196
 
114
- An empty array hides the main powerline while still allowing extension statuses to render. `turn` is available but omitted by default.
197
+ `segmentText` values must be single-line text without terminal control characters. Use `line_break`
198
+ for another row rather than inserting a newline into a prefix or suffix.
115
199
 
116
- Example multiline layout:
200
+ ## 🧩 Advanced layout
117
201
 
118
- ```json
119
- {
120
- "segments": ["model", "line_break", "cwd", "line_break", "branch"]
121
- }
122
- ```
202
+ Open **Advanced → Custom layout** when the curated levels are not enough.
123
203
 
124
- This is valid because the `line_break` entries are separated. `["model", "line_break", "line_break", "cwd"]` is invalid.
204
+ | Key | Action |
205
+ | --- | --- |
206
+ | Up/Down | Navigate |
207
+ | Page Up/Page Down | Move by one viewport |
208
+ | Enter/Space | Show or hide the selected segment |
209
+ | `M` | Enter or leave Move mode |
210
+ | Up/Down in Move mode | Reorder the selected visible segment |
211
+ | `Alt+Up` / `Alt+Down` | Reorder without entering Move mode |
212
+ | `B` | Add or remove a line break after the selected segment |
213
+ | Escape | Leave Move mode first, then close the screen |
125
214
 
126
- ### Segment text
215
+ Every successful change saves and applies immediately; closing the screen does not roll it back.
127
216
 
128
- Each visible segment renders as:
217
+ Available data segments:
129
218
 
130
219
  ```text
131
- prefix + Pi-owned dynamic value + suffix
220
+ brand provider model thinking cwd branch tools context tokens cost time turn
132
221
  ```
133
222
 
134
- Override either string independently:
223
+ Data segments must be unique. `line_break` may repeat when data segments separate occurrences, but
224
+ consecutive breaks are invalid. It has no `segmentText` entry. The menu cleans up leading, trailing,
225
+ and newly consecutive breaks after visibility changes. Manually authored leading/trailing breaks
226
+ represent empty rows.
135
227
 
136
228
  ```json
137
229
  {
138
- "segmentText": {
139
- "provider": { "prefix": "Provider: " },
140
- "context": { "prefix": "[", "suffix": "]" },
141
- "cost": { "prefix": "Cost $", "suffix": " USD" }
142
- }
230
+ "segments": ["model", "line_break", "cwd", "branch", "context"]
143
231
  }
144
232
  ```
145
233
 
146
- Prefix and suffix values must be single-line text without terminal control characters; use the `line_break` segment for additional rows.
147
-
148
- This structured model intentionally does not provide variables or a format language. Dynamic Git, PR, activity, usage, token, and cost formatting remains owned by the extension.
234
+ An empty `segments` array hides the main powerline while extension statuses can still render. The
235
+ extension intentionally has no variable or format language; use `pi-starship` when you need one.
149
236
 
150
- ### Extension status icons
237
+ ## 🔌 Extension statuses and icons
151
238
 
152
- `extensionStatusIcons` preserves these rules:
239
+ Other extension statuses appear below the main powerline, wrap to terminal width, and are limited to
240
+ five items. Icons resolve in this order:
153
241
 
154
- - An exact status key wins, such as `goal` or `foo:server`.
155
- - Installed package aliases such as `@vendor/pi-foo`, `npm:@vendor/pi-foo@1.2.3`, `pi-foo`, or `foo` can configure namespaced statuses.
156
- - An empty string hides the icon but keeps the status text.
157
- - A missing key uses the built-in icon or `🔌` for an unknown key.
158
- - Ambiguous package aliases require an exact status key.
242
+ 1. Exact configured raw key, such as `goal` or `foo:server`.
243
+ 2. Longest configured colon wildcard, such as `foo:*` or `foo:server:*`.
244
+ 3. Unambiguous installed-package alias, such as `@vendor/pi-foo`, `pi-foo`, or `foo`.
245
+ 4. Leading emoji supplied by the status text.
246
+ 5. Built-in icon.
247
+ 6. Generic `🔌` fallback.
159
248
 
160
- Statuses from other extensions appear below the main powerline. The linked GitHub PR status is hidden from that line when the branch segment already renders it.
249
+ Set an icon to `""` to hide only the icon. Wildcards match colon namespaces, not slash-delimited keys;
250
+ configure slash keys exactly. Compatibility fallbacks retain `codex-usage`, `pisync`, and
251
+ `unknown-error-retry`; an explicit canonical key wins.
161
252
 
162
- ## Commands
163
-
164
- | Command | Purpose |
165
- | --- | --- |
166
- | `/statusline settings` | Edit raw JSON in TUI, validate, atomically save, and apply immediately |
167
- | `/statusline status` | Show settings path/source, effective appearance, segments, and diagnostics |
168
- | `/statusline help` | Show command and schema guidance |
253
+ For interoperable extensions, prefer one aggregated key or a stable coexistence slot:
169
254
 
170
- Invalid or cancelled edits leave both the previous file and effective runtime configuration unchanged. The editor is TUI-only; status and help are safe in TUI, print, JSON, and RPC modes.
255
+ ```text
256
+ <extension-id>
257
+ <extension-id>:<stable-slot>
258
+ ```
171
259
 
172
- ## Git and activity details
260
+ Put transient activity in the value and always clear the same complete key.
173
261
 
174
- Git status tokens are hidden for clean repositories. When present, they mean `⇡` ahead, `⇣` behind, `+` staged, `~` modified/deleted, `?` untracked, and `!` conflicts.
262
+ ## 🛠️ Troubleshooting
175
263
 
176
- The tools segment distinguishes active tools, streaming/thinking, the last completed tool, and idle state. Parallel calls are summarized without running subprocesses during footer rendering.
264
+ - **Powerline symbols look wrong:** use a font with Powerline glyphs; emoji support is also recommended.
265
+ - **The footer reports settings warnings:** run `/statusline status`, then `/statusline settings` to fix
266
+ invalid recognized fields.
267
+ - **The footer appears to be replaced:** disable `pi-starship` or another extension that also calls
268
+ Pi's `setFooter()`.
269
+ - **A custom segment disappears on a narrow terminal:** check the responsive priority above or add an
270
+ explicit `line_break`.
177
271
 
178
- ## Package layout
272
+ ## 🗂️ Package layout
179
273
 
180
274
  ```text
181
275
  extensions/pi-statusline/
182
276
  ├── src/
183
- │ ├── ansi.ts
277
+ │ ├── index.ts
278
+ │ ├── statusline.ts
279
+ │ ├── render.ts
280
+ │ ├── powerline.ts
281
+ │ ├── information-profiles.ts
184
282
  │ ├── commands.ts
283
+ │ ├── settings.ts
185
284
  │ ├── extension-status.ts
186
285
  │ ├── git-status.ts
187
- │ ├── render.ts
188
- │ ├── settings.ts
189
- │ ├── statusline.ts
190
- │ ├── tokyo-night.ts
191
- │ └── types.ts
286
+ │ ├── ansi.ts
287
+ │ ├── types.ts
288
+ │ └── presets/
192
289
  ├── test/
193
290
  ├── README.md
194
291
  ├── LICENSE
@@ -196,12 +293,13 @@ extensions/pi-statusline/
196
293
  └── package.json
197
294
  ```
198
295
 
199
- Only `src/statusline.ts` is a Pi entrypoint. Other modules are package-internal.
296
+ `src/index.ts` is the thin Pi entrypoint; all other modules are package-internal.
200
297
 
201
- ## Keywords
298
+ ## 🔎 Keywords
202
299
 
203
- Pi extension, Pi coding agent, configurable statusline, Tokyo Night, terminal footer, token usage, context window, model status, TypeScript Pi package.
300
+ Pi extension, Pi coding agent, statusline, Tokyo Night, powerline, responsive terminal footer,
301
+ context usage, model status.
204
302
 
205
- ## License
303
+ ## 📄 License
206
304
 
207
305
  MIT. See [`LICENSE`](./LICENSE).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narumitw/pi-statusline",
3
- "version": "0.23.0",
3
+ "version": "0.28.0",
4
4
  "description": "Pi extension that replaces the footer with an information-rich statusline.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "pi": {
21
21
  "extensions": [
22
- "./src/statusline.ts"
22
+ "./src/index.ts"
23
23
  ]
24
24
  },
25
25
  "scripts": {