pi-zentui 0.20.2 → 0.22.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 +103 -544
- package/extensions/zentui/accent-rail-editor.ts +99 -0
- package/extensions/zentui/accent-rail-layout-patch.ts +457 -0
- package/extensions/zentui/completion-menu.ts +157 -0
- package/extensions/zentui/config.ts +99 -7
- package/extensions/zentui/editor-metadata-format.ts +58 -2
- package/extensions/zentui/footer.ts +12 -22
- package/extensions/zentui/format.ts +56 -12
- package/extensions/zentui/index.ts +206 -97
- package/extensions/zentui/prototype-patch-registry.ts +55 -11
- package/extensions/zentui/repository-root.ts +98 -0
- package/extensions/zentui/settings-command.ts +196 -6
- package/extensions/zentui/settings-previews.ts +164 -46
- package/extensions/zentui/state.ts +11 -0
- package/extensions/zentui/thinking-experimental.ts +1557 -0
- package/extensions/zentui/thinking-steps.ts +156 -0
- package/extensions/zentui/ui.ts +264 -36
- package/extensions/zentui/user-message-styles.ts +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,180 +1,81 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">Zentui</h1>
|
|
2
2
|
|
|
3
|
-
A Starship-inspired statusline and Opencode-style TUI for
|
|
3
|
+
<p align="center">A Starship-inspired statusline and Opencode-style TUI for <a href="https://pi.dev">Pi</a>.</p>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/pi-zentui"><img alt="npm version" src="https://shieldcn.dev/npm/pi-zentui.svg?variant=outline" /></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/pi-zentui"><img alt="npm monthly downloads" src="https://shieldcn.dev/npm/dm/pi-zentui.svg?variant=outline" /></a>
|
|
8
|
+
<a href="https://github.com/lmilojevicc/pi-zentui/actions/workflows/ci.yml"><img alt="CI status" src="https://shieldcn.dev/github/ci/lmilojevicc/pi-zentui.svg?workflow=ci.yml&branch=main&variant=outline" /></a>
|
|
9
|
+
<a href="https://github.com/lmilojevicc/pi-zentui/graphs/contributors"><img alt="GitHub contributors" src="https://shieldcn.dev/github/contributors/lmilojevicc/pi-zentui.svg?variant=outline" /></a>
|
|
10
|
+
<a href="https://github.com/lmilojevicc/pi-zentui/blob/main/LICENSE"><img alt="MIT license" src="https://shieldcn.dev/github/license/lmilojevicc/pi-zentui.svg?variant=outline" /></a>
|
|
11
|
+
</p>
|
|
6
12
|
|
|
7
|
-

|
|
8
14
|
|
|
9
15
|
## What is this?
|
|
10
16
|
|
|
11
|
-
Zentui
|
|
17
|
+
Zentui gives Pi surfaces independent, opt-in treatments:
|
|
12
18
|
|
|
13
|
-
- **Editor** —
|
|
14
|
-
- **User messages** —
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
19
|
+
- **Editor** — Opencode, Opencode copy-friendly, Accent Rail, and Minimalist input treatments
|
|
20
|
+
- **User messages** — framed, framed copy-friendly, compact, and labeled transcript messages
|
|
21
|
+
- **Thinking (Experimental)** — optional Rail, Tree, or Streaming private thinking renderers, without owning the Working line
|
|
22
|
+
- **Working line** — optional ownership of Pi's complete in-progress row and settled turn summary
|
|
23
|
+
- **Footer** — Pi's native Footer, a Starship-style statusline, or a hidden zero-row Footer
|
|
17
24
|
|
|
18
|
-
Editor, User messages, Working line, and selector borders
|
|
25
|
+
Editor, User messages, Thinking (Experimental), Working line, and selector borders have independent `enabled` fields. Footer uses one `style`: `native`, `starship`, or `hidden`. Use `/zentui` to configure each component without coupling it to the others.
|
|
19
26
|
|
|
20
|
-
##
|
|
27
|
+
## Highlights
|
|
21
28
|
|
|
22
|
-
|
|
29
|
+
| Surface | Default | Available treatments |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| Editor | `opencode` | Opencode, copy-friendly, Accent Rail, Minimalist |
|
|
32
|
+
| User messages | `framed` | Framed, copy-friendly, Compact, Labeled |
|
|
33
|
+
| Thinking (Experimental) | disabled (`tree`) | Rail, Tree, Streaming |
|
|
34
|
+
| Working line | disabled | Five spinner presets, live tool/time/thinking/token segments, turn summary |
|
|
35
|
+
| Footer | `starship` | Native, Starship, Hidden |
|
|
36
|
+
| Selector borders | `zentui` | Independent enablement and color source |
|
|
23
37
|
|
|
24
|
-
|
|
25
|
-
- `on branch` — git branch with icon
|
|
26
|
-
- `[!?↑]` — git status indicators (modified, untracked, ahead/behind, stashed, etc.)
|
|
27
|
-
- `via v5.5.0` — runtime detection with version and Starship-style Nerd Font runtime/language modules
|
|
28
|
-
- Optional segments (off by default): selected model/provider, `user@host`, current time, OS icon, session duration, and the **project package version** (e.g. `package.json` → `0.6.0`) — distinct from the runtime segment, which shows the installed toolchain
|
|
29
|
-
- Right side shows context usage, token counts, and cost
|
|
30
|
-
- Built-in footer segments can be shown or hidden individually from `/zentui`
|
|
31
|
-
- Fully custom Starship-style layout via the `components.footer.styles.starship.format` template string — see [Footer Format Template](#footer-format-template)
|
|
32
|
-
- Third-party Pi extension statuses from `ctx.ui.setStatus()` can be shown on the left,
|
|
33
|
-
middle, or right side, or hidden per status key from `/zentui`
|
|
38
|
+
The Starship Footer shows directory, Git, runtime, context, tokens, and cost. Optional segments include model/provider, package version, session duration, `user@host`, time, OS, Git commit, Git metrics, and third-party extension statuses. The layout is segment-driven by default and supports a complete Starship-style format template.
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
Zentui detects a broad set of runtime and language modules, preserves Nerd Font icons with an ASCII mode, and can source colors from the active Pi theme or directly from the terminal palette.
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
- `opencode-copy-friendly` (**Opencode (copy-friendly)** in `/zentui`) preserves the low-rail rendering for clean terminal selection
|
|
39
|
-
- `minimalist` moves session name, cost, model, thinking, context, Git, configurable path, Bash state, and turn duration into a rounded frame
|
|
40
|
-
- The selected model label and provider appear inside both Opencode editor variants; the model ID is used by default, while `components.editor.modelLabel: "name"` uses the display name with ID fallback.
|
|
41
|
-
- Opencode autocomplete rows retain Pi's original unframed trailing layout; Minimalist keeps autocomplete inside its rounded frame
|
|
42
|
-
- Configurable model, provider, thinking-level, accent, and border colors
|
|
42
|
+
## Screenshots
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
### Editors
|
|
45
45
|
|
|
46
46
|
<h4 align="center"><code>opencode</code></h4>
|
|
47
47
|
|
|
48
|
-

|
|
49
49
|
|
|
50
50
|
<h4 align="center"><code>opencode-copy-friendly</code></h4>
|
|
51
51
|
|
|
52
|
-

|
|
53
53
|
|
|
54
|
-
<h4 align="center"><code>
|
|
54
|
+
<h4 align="center"><code>accent-rail</code></h4>
|
|
55
55
|
|
|
56
|
-

|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
<h4 align="center"><code>minimalist</code></h4>
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
- `framed-copy-friendly` (**Framed (copy-friendly)** in `/zentui`) keeps the full-width horizontal borders and blank spacer rows, removes the copied accent rail, and retains a one-cell leading gutter before body text.
|
|
62
|
-
- `compact` uses only an accent rail, with no border or padding rows
|
|
63
|
-
- `labeled` uses a rounded box with the fixed label `User`
|
|
64
|
-
- Disabling User-message styling delegates byte-for-byte to Pi's native renderer; native is not a style ID
|
|
65
|
-
- No custom `plain` message style is provided
|
|
60
|
+

|
|
66
61
|
|
|
67
|
-
User
|
|
62
|
+
### User messages
|
|
68
63
|
|
|
69
64
|
<h4 align="center"><code>framed</code></h4>
|
|
70
65
|
|
|
71
|
-

|
|
72
67
|
|
|
73
68
|
<h4 align="center"><code>framed-copy-friendly</code></h4>
|
|
74
69
|
|
|
75
|
-

|
|
76
71
|
|
|
77
72
|
<h4 align="center"><code>compact</code></h4>
|
|
78
73
|
|
|
79
|
-

|
|
80
75
|
|
|
81
76
|
<h4 align="center"><code>labeled</code></h4>
|
|
82
77
|
|
|
83
|
-

|
|
178
79
|
|
|
179
80
|
## Install
|
|
180
81
|
|
|
@@ -186,456 +87,114 @@ pi install npm:pi-zentui
|
|
|
186
87
|
pi install git:github.com/lmilojevicc/pi-zentui
|
|
187
88
|
```
|
|
188
89
|
|
|
189
|
-
##
|
|
190
|
-
|
|
191
|
-
User config lives at `~/.pi/agent/zentui.json`. The file is optional: missing or invalid known values fall back to Zentui defaults, unknown keys are ignored at runtime, and `/zentui` can patch color-source settings, UI feature toggles, built-in footer segment visibility, and active third-party status placements.
|
|
192
|
-
|
|
193
|
-
The interactive `/zentui` menu is split into exactly eight component-oriented sections, in this order. Use `Tab` and `Shift+Tab` to switch sections:
|
|
194
|
-
|
|
195
|
-
1. **Appearance** — selector-border enablement, style, and colors; icon mode.
|
|
196
|
-
2. **Editor** — editor enablement, style, colors, model label, border behavior, viewport indicators, settings for the selected editor style, and a static synthetic preview.
|
|
197
|
-
3. **User messages** — message enablement, `framed | framed-copy-friendly | compact | labeled` style selection (including **Framed (copy-friendly)**), colors, and a static synthetic Markdown preview.
|
|
198
|
-
4. **Working line** — ownership, settled Turn summary, spinner and text speeds, optional spinner-color motion, text animation, color source, custom-message toggle and editable list, Tool/Elapsed/Thinking/Tokens toggles, and animated preview.
|
|
199
|
-
5. **Footer** — `Native | Starship | Hidden` style selection. Starship additionally shows colors, model label, responsive layout, separator, context style, and path display.
|
|
200
|
-
6. **Segments** — visibility toggles for non-Git Starship segments.
|
|
201
|
-
7. **Git** — Starship Git segment and probe controls.
|
|
202
|
-
8. **Extensions** — Starship extension-status placement and color controls for active keys.
|
|
90
|
+
## Configure
|
|
203
91
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
Starship-specific Footer rows are shown only while Starship is selected. The **Segments**, **Git**, and **Extensions** sections remain available for preconfiguration under every Footer style. Free-form values such as custom formats, Opencode metadata format, raw colors/styles, and inactive extension keys remain JSON-only; Working-line speed accepts validated custom milliseconds in `/zentui`.
|
|
207
|
-
|
|
208
|
-
Useful slash-command shortcuts:
|
|
92
|
+
Run `/zentui` inside Pi to configure Appearance, Editor, User messages, Thinking (Experimental), Working line, Footer, Segments, Git, and Extensions. Use `Tab` and `Shift+Tab` to switch sections. Most changes apply live; Thinking (Experimental) changes are saved and require restarting Pi. Configuration is saved to:
|
|
209
93
|
|
|
210
94
|
```text
|
|
211
|
-
/zentui
|
|
212
|
-
/zentui editor disable
|
|
213
|
-
/zentui statusline enable
|
|
214
|
-
/zentui statusline disable
|
|
215
|
-
/zentui editor toggle
|
|
216
|
-
/zentui messages enable
|
|
217
|
-
/zentui messages disable
|
|
218
|
-
/zentui messages toggle
|
|
219
|
-
/zentui statusline toggle
|
|
220
|
-
/zentui messages
|
|
221
|
-
/zentui user-messages
|
|
222
|
-
/zentui working-line
|
|
223
|
-
/zentui viewport-indicators enable
|
|
224
|
-
/zentui viewport-indicators disable
|
|
225
|
-
/zentui viewport-indicators toggle
|
|
226
|
-
/zentui format "$cwd on branch $git_branch$git_status using $runtime $fill $context"
|
|
227
|
-
/zentui format clear
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
`footer`, `statusline`, `status`, and `status line` are aliases: enable selects Starship, disable selects Native, and toggle selects Native only from Starship (Native or Hidden toggle to Starship).
|
|
231
|
-
|
|
232
|
-
Default config values — copy this and change any value you want:
|
|
233
|
-
|
|
234
|
-
```json
|
|
235
|
-
{
|
|
236
|
-
"projectRefreshIntervalMs": 30000,
|
|
237
|
-
"components": {
|
|
238
|
-
"editor": {
|
|
239
|
-
"enabled": true,
|
|
240
|
-
"style": "opencode",
|
|
241
|
-
"colorSource": "theme",
|
|
242
|
-
"borderColorMode": "static",
|
|
243
|
-
"modelLabel": "id",
|
|
244
|
-
"viewportIndicators": true,
|
|
245
|
-
"styles": {
|
|
246
|
-
"opencode": {
|
|
247
|
-
"metadataFormat": "$model $provider( $thinking)"
|
|
248
|
-
},
|
|
249
|
-
"opencode-copy-friendly": {
|
|
250
|
-
"metadataFormat": "$model $provider( $thinking)"
|
|
251
|
-
},
|
|
252
|
-
"minimalist": {
|
|
253
|
-
"pathDisplay": "compact",
|
|
254
|
-
"contextFormat": "percent",
|
|
255
|
-
"contextGauge": false,
|
|
256
|
-
"showSessionName": true,
|
|
257
|
-
"showTimer": true,
|
|
258
|
-
"showCost": true,
|
|
259
|
-
"showGit": true,
|
|
260
|
-
"contextThresholds": {
|
|
261
|
-
"warning": 70,
|
|
262
|
-
"error": 90
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
"userMessages": {
|
|
268
|
-
"enabled": true,
|
|
269
|
-
"style": "framed",
|
|
270
|
-
"colorSource": "theme",
|
|
271
|
-
"styles": {
|
|
272
|
-
"framed": {},
|
|
273
|
-
"framed-copy-friendly": {},
|
|
274
|
-
"compact": {},
|
|
275
|
-
"labeled": {}
|
|
276
|
-
}
|
|
277
|
-
},
|
|
278
|
-
"workingLine": {
|
|
279
|
-
"enabled": false,
|
|
280
|
-
"turnSummary": true,
|
|
281
|
-
"spinner": "star-bloom",
|
|
282
|
-
"spinnerIntervalMs": 100,
|
|
283
|
-
"animateSpinnerColor": false,
|
|
284
|
-
"textIntervalMs": 60,
|
|
285
|
-
"textAnimation": "classic",
|
|
286
|
-
"colorSource": "theme",
|
|
287
|
-
"messages": {
|
|
288
|
-
"custom": true,
|
|
289
|
-
"values": [
|
|
290
|
-
"Sautéing…", "Cooking…", "Ionizing…", "Zigzagging…",
|
|
291
|
-
"Razzle-dazzling…", "Photosynthesizing…", "Nucleating…", "Brewing…",
|
|
292
|
-
"Combobulating…", "Boogieing…", "Befuddling…", "Alchemizing…",
|
|
293
|
-
"Conjuring…", "Baking…", "Simmering…", "Blanching…"
|
|
294
|
-
]
|
|
295
|
-
},
|
|
296
|
-
"segments": {
|
|
297
|
-
"tool": true,
|
|
298
|
-
"elapsed": true,
|
|
299
|
-
"thought": true,
|
|
300
|
-
"tokens": true
|
|
301
|
-
}
|
|
302
|
-
},
|
|
303
|
-
"selectorBorders": {
|
|
304
|
-
"enabled": true,
|
|
305
|
-
"style": "zentui",
|
|
306
|
-
"colorSource": "theme"
|
|
307
|
-
},
|
|
308
|
-
"footer": {
|
|
309
|
-
"style": "starship",
|
|
310
|
-
"colorSource": "theme",
|
|
311
|
-
"modelLabel": "id",
|
|
312
|
-
"styles": {
|
|
313
|
-
"starship": {
|
|
314
|
-
"format": "",
|
|
315
|
-
"responsive": true,
|
|
316
|
-
"compactFormat": "$cwd$wrap(in $session_name)$wrap(on $git_branch) $git_status$wrap$context$wrap_sep$tokens",
|
|
317
|
-
"compactMaxLines": 2,
|
|
318
|
-
"separator": "pipe",
|
|
319
|
-
"contextStyle": "text",
|
|
320
|
-
"contextThresholds": {
|
|
321
|
-
"warning": 70,
|
|
322
|
-
"error": 90
|
|
323
|
-
},
|
|
324
|
-
"pathDisplay": {
|
|
325
|
-
"mode": "basename",
|
|
326
|
-
"depth": 0
|
|
327
|
-
},
|
|
328
|
-
"segments": {
|
|
329
|
-
"cwd": true,
|
|
330
|
-
"sessionName": true,
|
|
331
|
-
"gitBranch": true,
|
|
332
|
-
"gitStatus": true,
|
|
333
|
-
"gitCounts": false,
|
|
334
|
-
"runtime": true,
|
|
335
|
-
"modelInfo": false,
|
|
336
|
-
"context": true,
|
|
337
|
-
"tokens": true,
|
|
338
|
-
"cost": true,
|
|
339
|
-
"sessionDuration": false,
|
|
340
|
-
"username": false,
|
|
341
|
-
"time": false,
|
|
342
|
-
"os": false,
|
|
343
|
-
"packageVersion": false,
|
|
344
|
-
"gitCommit": false,
|
|
345
|
-
"gitMetrics": false
|
|
346
|
-
},
|
|
347
|
-
"gitBranch": {
|
|
348
|
-
"maxLength": "full"
|
|
349
|
-
},
|
|
350
|
-
"gitCommit": {
|
|
351
|
-
"hashLength": 7,
|
|
352
|
-
"onlyDetached": true,
|
|
353
|
-
"showTag": true
|
|
354
|
-
},
|
|
355
|
-
"gitMetrics": {
|
|
356
|
-
"onlyNonzero": true,
|
|
357
|
-
"ignoreSubmodules": false
|
|
358
|
-
},
|
|
359
|
-
"extensionStatuses": {
|
|
360
|
-
"defaultPlacement": "right",
|
|
361
|
-
"placements": {},
|
|
362
|
-
"colorModes": {}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
},
|
|
368
|
-
"icons": {
|
|
369
|
-
"mode": "auto",
|
|
370
|
-
"cwd": "",
|
|
371
|
-
"git": "",
|
|
372
|
-
"ahead": "↑",
|
|
373
|
-
"behind": "↓",
|
|
374
|
-
"diverged": "⇕",
|
|
375
|
-
"conflicted": "=",
|
|
376
|
-
"untracked": "?",
|
|
377
|
-
"stashed": "$",
|
|
378
|
-
"modified": "!",
|
|
379
|
-
"staged": "+",
|
|
380
|
-
"renamed": "»",
|
|
381
|
-
"deleted": "✘",
|
|
382
|
-
"typechanged": "T",
|
|
383
|
-
"cacheHit": "",
|
|
384
|
-
"editorPrompt": "",
|
|
385
|
-
"rail": "│",
|
|
386
|
-
"username": "",
|
|
387
|
-
"time": "",
|
|
388
|
-
"os": ""
|
|
389
|
-
},
|
|
390
|
-
"colors": {
|
|
391
|
-
"cwd": "bold cyan",
|
|
392
|
-
"sessionName": "bold green",
|
|
393
|
-
"gitBranch": "bold purple",
|
|
394
|
-
"gitStatus": "bold red",
|
|
395
|
-
"contextNormal": "bright-black",
|
|
396
|
-
"contextWarning": "bold yellow",
|
|
397
|
-
"contextError": "bold red",
|
|
398
|
-
"tokens": "bright-black",
|
|
399
|
-
"cost": "bold green",
|
|
400
|
-
"extensionStatus": "bright-black",
|
|
401
|
-
"separator": "bright-black",
|
|
402
|
-
"runtimePrefix": "",
|
|
403
|
-
"sessionDuration": "yellow",
|
|
404
|
-
"packageVersion": "208",
|
|
405
|
-
"gitCommit": "bold green",
|
|
406
|
-
"gitMetricsAdded": "bold green",
|
|
407
|
-
"gitMetricsDeleted": "bold red",
|
|
408
|
-
"username": "bold yellow",
|
|
409
|
-
"time": "bold yellow",
|
|
410
|
-
"os": "bold white",
|
|
411
|
-
"editorAccent": "accent",
|
|
412
|
-
"editorPrompt": "accent",
|
|
413
|
-
"editorBorder": "borderMuted",
|
|
414
|
-
"editorModel": "accent",
|
|
415
|
-
"editorProvider": "text",
|
|
416
|
-
"editorThinking": "muted",
|
|
417
|
-
"editorThinkingMinimal": "thinkingMinimal",
|
|
418
|
-
"editorThinkingLow": "thinkingLow",
|
|
419
|
-
"editorThinkingMedium": "thinkingMedium",
|
|
420
|
-
"editorThinkingHigh": "thinkingHigh",
|
|
421
|
-
"editorThinkingXhigh": "thinkingXhigh"
|
|
422
|
-
}
|
|
423
|
-
}
|
|
95
|
+
~/.pi/agent/zentui.json
|
|
424
96
|
```
|
|
425
97
|
|
|
426
|
-
|
|
427
|
-
- `projectRefreshIntervalMs`: project status polling interval; `0` disables polling. Values `1..4999` clamp up to `5000` (minimum 5s); invalid/non-finite values fall back to `30000`.
|
|
428
|
-
- `components.editor`: owns editor enablement, `opencode | opencode-copy-friendly | minimalist` style selection, color source, border mode, model label, viewport indicators, and all three editor-style configurations.
|
|
429
|
-
- `components.userMessages`: owns message enablement, `framed | framed-copy-friendly | compact | labeled` style selection, and color source. `framed-copy-friendly` remains Zentui-rendered; disabling the component delegates to Pi's native renderer.
|
|
430
|
-
- `components.workingLine`: `enabled` is the sole ownership switch. While enabled, Zentui owns both the Working-row message and indicator and renders the full row. It configures `braille | star-bloom | pinwheel | claude-inspired | pulse`, independent spinner/text speeds, optional Classic/KITT spinner-color participation, `classic | kitt | disabled` text animation, color source, the default-on `messages.custom` toggle and editable 16-value list, plus Tool/Elapsed/Thinking/Tokens segments. Thinking only controls the live row; measurement and final summaries continue while it is hidden. Custom-off and empty-list fallback both render owned `Working…`; Static keeps glyph motion but ignores text speed and spinner-color participation.
|
|
431
|
-
- Optional `colors.workingLineLow`, `colors.workingLineMid`, and `colors.workingLineHigh` override its palette. Without overrides, theme mode uses `dim`, `muted`, and `bold accent`; terminal mode uses `bright-black`, `cyan`, and `bold cyan`.
|
|
432
|
-
- `components.selectorBorders`: owns selector-border enablement, the fixed `zentui` style, and its color source.
|
|
433
|
-
- `components.footer`: owns `native | starship | hidden` style selection, Footer color source, Footer model label, and every Starship option under `styles.starship` (formats, segments, context thresholds, path, Git, and extension statuses). Native restores Pi's built-in Footer; Hidden installs an empty component with zero rows.
|
|
434
|
-
- Editor and Footer `modelLabel` values are independent and have separate controls in the **Editor** and **Footer** sections.
|
|
435
|
-
- Selector borders support only `zentui`; set their owning `enabled` field to `false` for native Pi behavior.
|
|
436
|
-
- Flat released keys such as `editorStyle`, `features`, and `footerFormat` remain accepted as migration input. `components.footer.enabled` and `features.statusLine` migrate to Starship or Native when no valid Footer style is present; Hidden projects `features.statusLine: false`. Canonical `components` paths are the primary JSON interface, and component saves materialize canonical snapshots.
|
|
437
|
-
- Explicit unsupported future component style IDs are preserved unchanged on disk but fail open at runtime: Editor, User-message, and selector-border customization stay disabled, while Footer behavior is Native. Missing, empty, or malformed style values continue normal default and legacy migration behavior.
|
|
438
|
-
- The flat properties returned by `mergeConfig`, `loadConfig`, and save helpers are deprecated compatibility output and will remain available until at least the next major release. This output deprecation is separate from accepted legacy flat JSON input.
|
|
439
|
-
- `polished` and `polished-copy-friendly` remain read-only migration aliases for `opencode` and `opencode-copy-friendly`. Legacy `features.copyFriendly` and the old nested Editor/message `copyFriendly` fields are read-only migration inputs: message copy-friendly `true` selects `framed-copy-friendly` rather than disabling custom rendering. Explicit Editor or User-message style saves remove only the corresponding obsolete nested flag; raw released feature keys, unknown fields, and unknown style data remain preserved as user-owned migration data.
|
|
440
|
-
- The shown `editor*` values match the default `theme` source. Omit those keys to keep Zentui's source-aware defaults when switching between `theme` and `terminal`.
|
|
441
|
-
- `editorAccent` styles Editor and User-message accent rails and the labeled message label.
|
|
442
|
-
- `editorPrompt` styles the `opencode-copy-friendly` Editor prompt glyph. Omit it to use `editorAccent`, then the default accent fallback.
|
|
443
|
-
- `editorBorder` styles the `framed` and `framed-copy-friendly` previous-message top/bottom borders and the active editor in static border color mode; the border glyph stays `─`.
|
|
444
|
-
- `editorGitBranch` and `editorThinkingMax` are optional editor-owned overrides, omitted above so source-specific and adaptive defaults remain active. `editorGitBranch` owns the minimalist Editor branch color independently from Footer `gitBranch`; where Zentui resolves configured thinking colors, `max` falls back through `editorThinkingXhigh` and then `editorThinking`.
|
|
445
|
-
- `editorModel`, `editorProvider`, and `editorThinking*` style the editor metadata. `editorThinking` applies to every non-`off` thinking level unless a level-specific key is set.
|
|
446
|
-
|
|
447
|
-
Tip: with `opencode-copy-friendly`, setting Pi's `editorPaddingX` to `1` in `~/.pi/agent/settings.json` keeps a small left gutter without copying a rail glyph.
|
|
448
|
-
|
|
449
|
-
## Minimalist editor style
|
|
450
|
-
|
|
451
|
-
Set `components.editor.style` to `minimalist` or select it from the `/zentui` **Editor** tab. The rounded frame shows viewport counts, Bash state, the current/completed turn duration, and the explicit Pi session name at top left; cost, model, thinking level, and context usage at top right; viewport count plus Git branch/status at bottom left; and the configured path at bottom right. Unnamed sessions add no placeholder. Autocomplete stays inside the frame when Pi's existing editor output can be split safely. Unknown third-party editor layouts fail open without decoration.
|
|
452
|
-
|
|
453
|
-
The Minimalist editor is inspired by [pi-custom-input](https://github.com/VinhLe1410/pi-custom-input), with an independent implementation in Zentui.
|
|
454
|
-
|
|
455
|
-
While `minimalist` is selected, the `/zentui` **Editor** area shows its focused controls without repeating the style name on every row. Path examples are `src` (`compact`), `zentui/src` (`project`), and `~/Projects/zentui/src` (`full`). Context can render as `11%`, `11%/372k`, or—with the gauge enabled and enough room—`[█░░░░] 11%/372k`. The gauge shortens or disappears before the context text at narrow widths. Session name, timer, cost, and Git can be hidden independently; model, thinking, and context remain structurally stable.
|
|
456
|
-
|
|
457
|
-
Footer visibility is controlled by `components.footer.style`: use `starship`, `native`, or `hidden`. Minimalist editor decoration and the Starship Footer may be shown together, including at narrow widths or after decoration fallback. Minimalist style does not remove Pi's header.
|
|
458
|
-
|
|
459
|
-
## Editor Metadata Format
|
|
460
|
-
|
|
461
|
-
Set `metadataFormat` under either opencode style in `~/.pi/agent/zentui.json` to customize that style's metadata row. The two variants retain independent values:
|
|
98
|
+
A small starter config:
|
|
462
99
|
|
|
463
100
|
```json
|
|
464
101
|
{
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
102
|
+
"components": {
|
|
103
|
+
"editor": {
|
|
104
|
+
"enabled": true,
|
|
105
|
+
"style": "accent-rail"
|
|
106
|
+
},
|
|
107
|
+
"userMessages": {
|
|
108
|
+
"enabled": true,
|
|
109
|
+
"style": "framed"
|
|
110
|
+
},
|
|
111
|
+
"thinkingSteps": {
|
|
112
|
+
"enabled": false,
|
|
113
|
+
"mode": "tree"
|
|
114
|
+
},
|
|
115
|
+
"workingLine": {
|
|
116
|
+
"enabled": false
|
|
117
|
+
},
|
|
118
|
+
"footer": {
|
|
119
|
+
"style": "starship"
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"icons": {
|
|
123
|
+
"mode": "auto"
|
|
124
|
+
}
|
|
477
125
|
}
|
|
478
126
|
```
|
|
479
127
|
|
|
480
|
-
|
|
128
|
+
Detailed reference:
|
|
481
129
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
| `$model` | label selected by `components.editor.modelLabel` (`id`, or name with ID fallback) |
|
|
485
|
-
| `$model_id` | active Pi model ID |
|
|
486
|
-
| `$model_name` | active Pi model display name; empty when no name is set |
|
|
487
|
-
| `$provider` | provider label using Zentui's existing formatting |
|
|
488
|
-
| `$thinking` | current thinking level; empty when thinking is `off` |
|
|
489
|
-
| `$session_name` | current Pi session name; empty when unnamed |
|
|
130
|
+
- [Configuration, component styles, defaults, runtime detection, and compatibility](https://github.com/lmilojevicc/pi-zentui/blob/main/docs/configuration.md)
|
|
131
|
+
- [Footer format template and variables](https://github.com/lmilojevicc/pi-zentui/blob/main/docs/footer-format.md)
|
|
490
132
|
|
|
491
|
-
|
|
133
|
+
The Starship Footer path defaults to `basename`. Opt into `components.footer.styles.starship.pathDisplay.mode: "repository"` to omit the repository directory itself: the repository root renders `.`, while `/repo/extensions/zentui` renders `extensions/zentui`. `depth` keeps the final N components in `full` and `repository` modes; `0` is unlimited. Until a current, safely contained repository root is available, repository mode silently uses the unlimited `full` path with `~` home abbreviation.
|
|
492
134
|
|
|
493
|
-
|
|
135
|
+
Useful shortcuts:
|
|
494
136
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
"components": {
|
|
504
|
-
"footer": {
|
|
505
|
-
"styles": {
|
|
506
|
-
"starship": {
|
|
507
|
-
"format": "$os $username $cwd($sep$session_name)( on $git_branch)( $git_status)( via $runtime)$fill($context)($sep$tokens)($sep$cost)($sep$time)"
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
```
|
|
514
|
-
|
|
515
|
-
Center the branch between directory and cost:
|
|
516
|
-
|
|
517
|
-
```json
|
|
518
|
-
{
|
|
519
|
-
"components": {
|
|
520
|
-
"footer": {
|
|
521
|
-
"styles": {
|
|
522
|
-
"starship": {
|
|
523
|
-
"format": "$cwd $fill $git_branch $fill $cost"
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
137
|
+
```text
|
|
138
|
+
/zentui editor toggle
|
|
139
|
+
/zentui messages toggle
|
|
140
|
+
/zentui working-line
|
|
141
|
+
/zentui statusline toggle
|
|
142
|
+
/zentui viewport-indicators toggle
|
|
143
|
+
/zentui format "$cwd on branch $git_branch$git_status using $runtime $fill $context"
|
|
144
|
+
/zentui format clear
|
|
529
145
|
```
|
|
530
146
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
### Variables
|
|
534
|
-
|
|
535
|
-
| Token | Aliases | Renders |
|
|
536
|
-
| ------------------- | ------------ | ------------------------------------------------------------------- |
|
|
537
|
-
| `$cwd` | `$directory` | current directory |
|
|
538
|
-
| `$session_name` | | current Pi session name |
|
|
539
|
-
| `$git_branch` | `$branch` | git branch with icon |
|
|
540
|
-
| `$git_status` | `$status` | `[!?↑]` status block |
|
|
541
|
-
| `$git_state` | `$state` | `REBASING` / `MERGING` / … (optional `n/m`) |
|
|
542
|
-
| `$git_commit` | `$commit` | short commit hash (+ exact-match tag when present) |
|
|
543
|
-
| `$git_tag` | `$tag` | exact-match tag at HEAD |
|
|
544
|
-
| `$git_metrics` | | aggregate line changes `+added −deleted` |
|
|
545
|
-
| `$git_added` | | added line count (`+N`) |
|
|
546
|
-
| `$git_deleted` | | deleted line count (`−N`) |
|
|
547
|
-
| `$runtime` | | runtime icon + version |
|
|
548
|
-
| `$model` | | selected model label (`components.footer.modelLabel`) |
|
|
549
|
-
| `$provider` | | formatted provider label |
|
|
550
|
-
| `$package` | | project package version, `is <glyph> <version>` (manifest-derived) |
|
|
551
|
-
| `$package_version` | | raw project package version (no icon) |
|
|
552
|
-
| `$session_duration` | `$duration` | session running time |
|
|
553
|
-
| `$username` | | `user@host` |
|
|
554
|
-
| `$os` | | operating-system icon |
|
|
555
|
-
| `$time` | | current time `HH:MM` |
|
|
556
|
-
| `$context` | | context usage (text and/or gauge; finite percentages use one decimal) |
|
|
557
|
-
| `$tokens` | | input/output counts and existing cache-hit percentage |
|
|
558
|
-
| `$cache_read` | | cache-read total (`R1.2k`); empty at zero or when unavailable |
|
|
559
|
-
| `$cache_write` | | cache-write total (`W300`); empty at zero or when unavailable |
|
|
560
|
-
| `$cost` | | session cost |
|
|
561
|
-
| `$subscription` | | `(sub)` in subscription mode; otherwise empty |
|
|
562
|
-
| `$auto_compaction` | | `(auto)` when automatic compaction is enabled; otherwise empty |
|
|
563
|
-
| `$sep` | `$separator` | themed `\|` using `colors.separator` |
|
|
564
|
-
| `$fill` | — | special: splits zones |
|
|
565
|
-
|
|
566
|
-
### `$fill` behavior
|
|
567
|
-
|
|
568
|
-
| `$fill` count | Layout |
|
|
569
|
-
| ------------- | ------------------------------------------------------------------------ |
|
|
570
|
-
| 0 | everything left-aligned |
|
|
571
|
-
| 1 | tokens before → left, tokens after → right |
|
|
572
|
-
| 2 | before first → left, between → **centered middle**, after second → right |
|
|
573
|
-
| 3+ | first two count; extras ignored |
|
|
574
|
-
|
|
575
|
-
- Literal text (`on branch`, `using`, `\|`, spaces) is rendered verbatim — you control all spacing.
|
|
576
|
-
- Each variable renders its core value only (no `on`/`via` prefixes); add those words as literal text.
|
|
577
|
-
- Conditional groups: wrap optional pieces in parentheses, e.g. `$cwd( on $git_branch)($git_status)$fill($context)`. If every `$var` inside a group is empty, the whole group (including its literals) is dropped.
|
|
578
|
-
- `$session_name` is available whenever `components.footer.styles.starship.format` is set, independently of `components.footer.styles.starship.segments.sessionName`; use a conditional group such as `($sep$session_name)` so unnamed sessions leave no separator.
|
|
579
|
-
- The built-in wide footer appends cache totals to the token segment, `(sub)` to cost, and `(auto)` to context when available. Custom formats keep `$tokens`, `$cost`, and `$context` backward-compatible and include telemetry only through the atomic variables above.
|
|
580
|
-
- `DEFAULT_COMPACT_FOOTER_FORMAT` omits model/provider and atomic telemetry. Add their variables explicitly to `components.footer.styles.starship.compactFormat` to opt in at narrow widths. The flat `compactFooterFormat` key is a legacy migration input.
|
|
581
|
-
- Auto-compaction settings refresh on the next normal footer synchronization event. Unsupported Pi capabilities or settings-read errors safely omit optional markers.
|
|
582
|
-
- Unknown `$variables` render empty.
|
|
583
|
-
- Set or clear at runtime: `/zentui format "<template>"` and `/zentui format clear`.
|
|
584
|
-
|
|
585
|
-
## Pi fullscreen mode
|
|
586
|
-
|
|
587
|
-
Pi 0.84 introduces a native fullscreen TUI with a sticky editor and Footer plus an independently scrollable transcript. Enable it in Pi's `~/.pi/agent/settings.json`:
|
|
588
|
-
|
|
589
|
-
```json
|
|
590
|
-
{
|
|
591
|
-
"tuiMode": "fullscreen"
|
|
592
|
-
}
|
|
593
|
-
```
|
|
147
|
+
**Thinking (Experimental)** uses one restart-gated private `AssistantMessageComponent` renderer for Rail, Tree, and Streaming, tested against exact Pi versions 0.80.5, 0.83.0, 0.84.0, and 0.84.4. It is disabled by default and may break after Pi updates. Every enable, disable, or mode change is saved but does not alter the active startup snapshot; restart Pi to apply it. Zentui installs an enabled startup snapshot before transcript restoration. Missing constructors, incompatible child layouts, parser limits, theme/render/width errors, or displaced patch ownership fail open to complete native thinking rather than switching modes.
|
|
594
148
|
|
|
595
|
-
|
|
149
|
+
Rail shows every parsed label in each native contiguous thinking run (`│ Label`, with only the open final phase shown as `│ • Label`). Tree independently shows the latest five labels in each run (`├─ · Label`, settled `└─ · Label`, open `└─ • Label`); it never aggregates across intervening text or tool blocks. Labels are rendered by fresh host-shaped Pi Markdown instances before cropping, so emphasis, code, links, HTML, LaTeX, custom transforms, and native `thinkingText` styling remain host-controlled. Every label occupies one terminal row: ANSI/OSC/grapheme-aware cropping adds `…` only when needed. Native horizontal padding stays external. Connectors are styled directly with the current theme's `accent` callback on every render, so custom themes control them independently. Hidden native thinking remains hidden and keeps Pi's native hidden label.
|
|
596
150
|
|
|
597
|
-
|
|
151
|
+
Streaming retains Pi's host-rendered final five rows under `Thinking 7.1s`, folds completed reasoning under `Thought` or current-session `Thought for 12.3s`, and owns the configured thinking-toggle binding (Ctrl+T by default) only for an active Streaming startup. Restored completions cannot recover a duration because Pi does not persist the thinking-end timestamp. Expand/refold and lifecycle tracking are bounded to 256 retained assistant components; evicted entries are first restored natively. All modes restore/dispose on shutdown. Thinking (Experimental) never writes the Working line and does not change its existing **Thinking time** option, working text, Footer, Editor, statuses, or model behavior.
|
|
598
152
|
|
|
599
|
-
|
|
153
|
+
Pi 0.84 also provides a native fullscreen TUI with a sticky editor and Footer. Zentui does not enable it automatically; select fullscreen from Pi's `/settings`, set `"tuiMode": "fullscreen"` in Pi settings, or launch Pi with `--tui-mode fullscreen`.
|
|
600
154
|
|
|
601
155
|
## Requirements
|
|
602
156
|
|
|
603
157
|
- [Pi](https://pi.dev) coding agent 0.80.5 or newer
|
|
604
|
-
- A [Nerd Font](https://www.nerdfonts.com/) for icons
|
|
158
|
+
- A [Nerd Font](https://www.nerdfonts.com/) for icons, or `icons.mode: "ascii"`
|
|
605
159
|
|
|
606
160
|
## Development
|
|
607
161
|
|
|
608
162
|
```bash
|
|
609
163
|
npm install
|
|
610
|
-
npm run verify
|
|
611
164
|
npm run fmt
|
|
165
|
+
npm run verify
|
|
612
166
|
npm run pack:check
|
|
613
167
|
```
|
|
614
168
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
The project keeps Pi core packages as peer dependencies for runtime and dev dependencies for
|
|
618
|
-
typechecking. To avoid accidentally running the local `node_modules/.bin/pi` shim, the dev scripts use
|
|
619
|
-
the globally installed Pi binary by default:
|
|
169
|
+
Run Pi with only the local extension:
|
|
620
170
|
|
|
621
171
|
```bash
|
|
622
172
|
npm run pi:dev
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Install the checkout as a local Pi package:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
623
178
|
npm run pi:install-local
|
|
624
179
|
```
|
|
625
180
|
|
|
626
|
-
Override the
|
|
181
|
+
Override the globally installed Pi binary when needed:
|
|
627
182
|
|
|
628
183
|
```bash
|
|
629
184
|
PI_BIN=/path/to/pi npm run pi:dev
|
|
630
185
|
```
|
|
631
186
|
|
|
632
|
-
|
|
187
|
+
See [CONTRIBUTING.md](https://github.com/lmilojevicc/pi-zentui/blob/main/CONTRIBUTING.md) for manual UI-test and pull-request expectations.
|
|
188
|
+
|
|
189
|
+
## Inspiration and credits
|
|
633
190
|
|
|
634
|
-
|
|
191
|
+
- [Starship](https://starship.rs/) — inspiration for the informative, segment-based Footer
|
|
192
|
+
- [Opencode](https://github.com/anomalyco/opencode) — inspiration for the Opencode editor treatment
|
|
193
|
+
- [Oh My Pi (`omp`)](https://github.com/can1357/oh-my-pi) by [Can Bölük](https://github.com/can1357) — visual inspiration for the filled, single-left-rail Accent Rail editor
|
|
194
|
+
- [Pi Custom Input](https://github.com/VinhLe1410/pi-custom-input) by [Vinh Le](https://github.com/VinhLe1410) — visual inspiration for Minimalist's framed, border-embedded session, model, context, Git, and path metadata
|
|
635
195
|
|
|
636
|
-
|
|
637
|
-
- [Opencode](https://github.com/opencode-ai/opencode) — terminal-based AI coding assistant
|
|
196
|
+
Zentui's implementations are independent; these credits acknowledge product and visual inspiration rather than source-code reuse.
|
|
638
197
|
|
|
639
198
|
## License
|
|
640
199
|
|
|
641
|
-
MIT
|
|
200
|
+
Zentui is licensed under the MIT License. Wallpaper photo by [Mohammad Alizade](https://unsplash.com/@mohamadaz) on [Unsplash](https://unsplash.com/photos/SB5MIXFjJxs), used under the [Unsplash License](https://unsplash.com/license). The photograph appearing in showcase screenshots is not relicensed under MIT.
|