@narumitw/pi-statusline 0.25.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,18 +1,32 @@
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.
7
+
8
+ A representative uncolored layout:
9
+
10
+ ```text
11
+ ░▒▓ 🤖 sonnet-4 🧠 high 📁 pi-extensions 🌿 main ~2 🪟 ctx 42% 💸 $0.184
12
+ ```
6
13
 
7
14
  ## ✨ Features
8
15
 
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.
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**.
22
+
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.
16
30
 
17
31
  ## 📦 Install
18
32
 
@@ -20,176 +34,258 @@
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.
31
45
 
32
- ## ⚙️ Configuration
46
+ ## 🚀 Quick start
33
47
 
34
- The only configuration source is:
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.
119
+
120
+ ## ⚙️ Settings
121
+
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.
131
+
132
+ A valid legacy `pi-statusline-settings.json` is migrated without rewriting its contents. If both files
133
+ exist, `pi-statusline.json` wins.
41
134
 
42
- There are no project overrides or environment-variable overrides.
135
+ ### Settings reference
43
136
 
44
- ### Default JSON
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
- "usage": "📊",
82
- "caffeinate": "💊",
83
- "firecrawl": "🔥",
84
- "github-pr": "🔎",
85
- "goal": "🎯",
86
- "lsp": "🧰",
87
- "plan-mode": "📝",
88
- "pisync": "🔄",
89
- "subagents": "🧑‍🤝‍🧑",
90
- "unknown-error-retry": "🔁"
163
+ "goal": "◎",
164
+ "foo:*": "🧪"
91
165
  }
92
166
  }
93
167
  ```
94
168
 
95
- All fields are optional in an existing document. Missing fields use defaults.
96
-
97
- ### Appearance
98
-
99
- - `palette`: `tokyo-night`, `ocean`, `sunset`, `forest`, `candy`, `neon`, or `mono`.
100
- - `density`: `compact` or `cozy`.
101
- - `separator`: `none`, `dot`, `bar`, `powerline`, or `round`.
169
+ Use **Advanced → Edit settings JSON** or `/statusline settings` to edit, validate, atomically save, and
170
+ apply the file.
102
171
 
103
- 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.
172
+ ## 🎨 Appearance
104
173
 
105
- ### Segments
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.
106
176
 
107
- `segments` is an ordered list containing:
177
+ When `palettePreset` is `custom`, `palette` maps segment names to foreground/background colors:
108
178
 
109
- ```text
110
- 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
+ }
111
187
  ```
112
188
 
113
- 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 ``.
114
196
 
115
- 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.
116
199
 
117
- Example multiline layout:
200
+ ## 🧩 Advanced layout
118
201
 
119
- ```json
120
- {
121
- "segments": ["model", "line_break", "cwd", "line_break", "branch"]
122
- }
123
- ```
202
+ Open **Advanced → Custom layout** when the curated levels are not enough.
124
203
 
125
- 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 |
126
214
 
127
- ### Segment text
215
+ Every successful change saves and applies immediately; closing the screen does not roll it back.
128
216
 
129
- Each visible segment renders as:
217
+ Available data segments:
130
218
 
131
219
  ```text
132
- prefix + Pi-owned dynamic value + suffix
220
+ brand provider model thinking cwd branch tools context tokens cost time turn
133
221
  ```
134
222
 
135
- 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.
136
227
 
137
228
  ```json
138
229
  {
139
- "segmentText": {
140
- "provider": { "prefix": "Provider: " },
141
- "context": { "prefix": "[", "suffix": "]" },
142
- "cost": { "prefix": "Cost $", "suffix": " USD" }
143
- }
230
+ "segments": ["model", "line_break", "cwd", "branch", "context"]
144
231
  }
145
232
  ```
146
233
 
147
- Prefix and suffix values must be single-line text without terminal control characters; use the `line_break` segment for additional rows.
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.
148
236
 
149
- 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.
237
+ ## 🔌 Extension statuses and icons
150
238
 
151
- ### Extension status icons
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:
152
241
 
153
- `extensionStatusIcons` preserves these rules:
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.
154
248
 
155
- - An exact status key wins, such as `goal` or `foo:server`.
156
- - Installed package aliases such as `@vendor/pi-foo`, `npm:@vendor/pi-foo@1.2.3`, `pi-foo`, or `foo` can configure namespaced statuses.
157
- - An empty string hides the icon but keeps the status text.
158
- - A missing key uses the built-in icon or `🔌` for an unknown key.
159
- - Ambiguous package aliases require an exact status key.
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.
160
252
 
161
- 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.
253
+ For interoperable extensions, prefer one aggregated key or a stable coexistence slot:
162
254
 
163
- ## 💬 Commands
164
-
165
- | Command | Purpose |
166
- | --- | --- |
167
- | `/statusline settings` | Edit raw JSON in TUI, validate, atomically save, and apply immediately |
168
- | `/statusline status` | Show settings path/source, effective appearance, segments, and diagnostics |
169
- | `/statusline help` | Show command and schema guidance |
170
-
171
- 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
+ ```
172
259
 
173
- ## 🌿 Git and activity details
260
+ Put transient activity in the value and always clear the same complete key.
174
261
 
175
- Git status tokens are hidden for clean repositories. When present, they mean `⇡` ahead, `⇣` behind, `+` staged, `~` modified/deleted, `?` untracked, and `!` conflicts.
262
+ ## 🛠️ Troubleshooting
176
263
 
177
- 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`.
178
271
 
179
272
  ## 🗂️ Package layout
180
273
 
181
274
  ```text
182
275
  extensions/pi-statusline/
183
276
  ├── src/
184
- │ ├── ansi.ts
277
+ │ ├── index.ts
278
+ │ ├── statusline.ts
279
+ │ ├── render.ts
280
+ │ ├── powerline.ts
281
+ │ ├── information-profiles.ts
185
282
  │ ├── commands.ts
283
+ │ ├── settings.ts
186
284
  │ ├── extension-status.ts
187
285
  │ ├── git-status.ts
188
- │ ├── render.ts
189
- │ ├── settings.ts
190
- │ ├── statusline.ts
191
- │ ├── tokyo-night.ts
192
- │ └── types.ts
286
+ │ ├── ansi.ts
287
+ │ ├── types.ts
288
+ │ └── presets/
193
289
  ├── test/
194
290
  ├── README.md
195
291
  ├── LICENSE
@@ -197,11 +293,12 @@ extensions/pi-statusline/
197
293
  └── package.json
198
294
  ```
199
295
 
200
- 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.
201
297
 
202
298
  ## 🔎 Keywords
203
299
 
204
- 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.
205
302
 
206
303
  ## 📄 License
207
304
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narumitw/pi-statusline",
3
- "version": "0.25.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": {