pi-zentui 0.23.0 → 0.25.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 +31 -26
- package/docs/configuration.md +168 -33
- package/docs/footer-format.md +169 -0
- package/extensions/zentui/accent-rail-editor.ts +15 -4
- package/extensions/zentui/codex-quota-display.ts +34 -0
- package/extensions/zentui/codex-quota.ts +296 -0
- package/extensions/zentui/component-colors.ts +158 -0
- package/extensions/zentui/component-settings.ts +99 -0
- package/extensions/zentui/config.ts +289 -103
- package/extensions/zentui/editor-metadata-format.ts +55 -20
- package/extensions/zentui/editor-mouse.ts +94 -0
- package/extensions/zentui/footer.ts +195 -58
- package/extensions/zentui/format.ts +11 -1
- package/extensions/zentui/icons.ts +53 -13
- package/extensions/zentui/index.ts +73 -3
- package/extensions/zentui/minimalist-editor.ts +95 -25
- package/extensions/zentui/runtime.ts +59 -29
- package/extensions/zentui/selector-border.ts +9 -3
- package/extensions/zentui/settings-command.ts +968 -664
- package/extensions/zentui/settings-keys.ts +59 -0
- package/extensions/zentui/settings-list-selection.ts +30 -0
- package/extensions/zentui/settings-previews.ts +11 -4
- package/extensions/zentui/style.ts +6 -0
- package/extensions/zentui/thinking-experimental.ts +62 -10
- package/extensions/zentui/ui.ts +200 -65
- package/extensions/zentui/user-message-styles.ts +65 -34
- package/extensions/zentui/user-message.ts +172 -34
- package/extensions/zentui/working-line.ts +92 -20
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
## What is this?
|
|
16
16
|
|
|
17
|
-
Zentui gives Pi surfaces
|
|
17
|
+
Zentui gives Pi surfaces independently selectable treatments:
|
|
18
18
|
|
|
19
19
|
- **Editor** — Opencode, Opencode copy-friendly, Accent Rail, and Minimalist input treatments
|
|
20
20
|
- **User messages** — framed, framed copy-friendly, compact, and labeled transcript messages
|
|
@@ -91,7 +91,7 @@ pi install git:github.com/lmilojevicc/pi-zentui
|
|
|
91
91
|
|
|
92
92
|
## Configure
|
|
93
93
|
|
|
94
|
-
Run `/zentui` inside Pi to configure Appearance, Editor, User messages, Thinking (Experimental), Working line, Footer, Segments
|
|
94
|
+
Run `/zentui` inside Pi to configure Appearance, Editor, User messages, Thinking (Experimental), Working line, and Footer. With Starship selected, Footer contains **Segments →**, **Git →**, and **Extension statuses →** child pages. Use `Tab` and `Shift+Tab` to switch sections; compact help follows your configured selection keys. Every section has a direct route (for example, `/zentui footer`). `/zentui segments`, `/zentui git`, and `/zentui extensions` open the Footer child pages when Starship is active; under Native or Hidden they open Footer with a requires-Starship explanation, without changing style or saved preferences. The configured cancel key returns from a child to Footer; at the top level it closes settings. Extension statuses are published keyed Footer statuses, not extension management or Working line integrations. Inactive options retain their saved preferences. Most changes apply live. Active Streaming can switch live to Rail or Tree, and Rail and Tree can switch live between each other. Entering Streaming from a structural mode, first enable, and re-enable after a live disable require restarting Pi. Configuration is saved to:
|
|
95
95
|
|
|
96
96
|
```text
|
|
97
97
|
~/.pi/agent/zentui.json
|
|
@@ -112,36 +112,37 @@ Presets apply once, saving only these component selections. Colors, color source
|
|
|
112
112
|
|
|
113
113
|
The displayed preset is derived from your current selections: individual changes may show **Custom**, and returning to a matching combination restores its name. No `preset` config key is saved or reapplied at startup. Defaults are unchanged and match Opencode. Selecting a preset keeps settings open for further adjustments. Editor installation waits until the panel closes; if editor ownership prevents application, the saved choice may require reloading Pi.
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
### Minimal overrides
|
|
116
|
+
|
|
117
|
+
Installation enables Opencode Editor, Framed User messages, Zentui selector borders, and Starship Footer. Working line and Thinking (Experimental) remain disabled. Missing fields retain those defaults; there is no automatic migration. Auto icons use Nerd glyphs for iTerm2, WezTerm, Ghostty, Kitty, and Alacritty environment signals, and otherwise fall back to ASCII. Set `ZENTUI_NERD_FONTS=1` or `0` to override Auto. These environment heuristics cannot detect whether a Nerd Font is installed or configured; explicit `nerd` and `ascii` modes always win. ASCII changes icons, not the entire UI.
|
|
118
|
+
|
|
119
|
+
Change only what you need. For example, this changes only the Editor's accent:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"components": {
|
|
124
|
+
"editor": { "colors": { "accent": "bold blue" } }
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Each owner's **Color overrides** action edits raw styles independently. **Reset / inherit** deletes the local key; an empty string intentionally removes styling. Shared `colors` remain live historical fallbacks before **and after** migration. Color sources remain independent too.
|
|
130
|
+
|
|
131
|
+
To adopt **only User messages**, explicitly leave the other default-enabled surfaces alone:
|
|
116
132
|
|
|
117
133
|
```json
|
|
118
134
|
{
|
|
119
135
|
"components": {
|
|
120
|
-
"editor": {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
"userMessages": {
|
|
125
|
-
"enabled": true,
|
|
126
|
-
"style": "framed"
|
|
127
|
-
},
|
|
128
|
-
"thinkingSteps": {
|
|
129
|
-
"enabled": false,
|
|
130
|
-
"mode": "tree"
|
|
131
|
-
},
|
|
132
|
-
"workingLine": {
|
|
133
|
-
"enabled": false
|
|
134
|
-
},
|
|
135
|
-
"footer": {
|
|
136
|
-
"style": "starship"
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
"icons": {
|
|
140
|
-
"mode": "auto"
|
|
136
|
+
"editor": { "enabled": false },
|
|
137
|
+
"userMessages": { "enabled": true, "style": "framed" },
|
|
138
|
+
"selectorBorders": { "enabled": false },
|
|
139
|
+
"footer": { "style": "native" }
|
|
141
140
|
}
|
|
142
141
|
}
|
|
143
142
|
```
|
|
144
143
|
|
|
144
|
+
Disabled/Native leaves Pi or a predecessor in control. Hidden instead intentionally owns zero Footer rows. Ordinary saves snapshot only the edited owner. `/zentui migrate` is a separate confirmed all-owner selection/source/style-option snapshot; it preserves aliases, unknown fields, and shared color inheritance, and never copies generated palettes. See the configuration reference for exact owner color keys and reset behavior.
|
|
145
|
+
|
|
145
146
|
Detailed reference:
|
|
146
147
|
|
|
147
148
|
- [Configuration, component styles, defaults, runtime detection, and compatibility](https://github.com/lmilojevicc/pi-zentui/blob/main/docs/configuration.md)
|
|
@@ -161,7 +162,7 @@ Useful shortcuts:
|
|
|
161
162
|
/zentui format clear
|
|
162
163
|
```
|
|
163
164
|
|
|
164
|
-
**Thinking (Experimental)** uses one private `AssistantMessageComponent` renderer for Rail, Tree, and Streaming, tested against exact Pi versions 0.80.5, 0.82.1, 0.83.0, 0.84.0,
|
|
165
|
+
**Thinking (Experimental)** uses one private `AssistantMessageComponent` renderer for Rail, Tree, and Streaming, tested against exact Pi versions 0.80.5, 0.82.1, 0.83.0, 0.84.0, 0.84.4, and 0.85.1. It is disabled by default and may break after Pi updates. Zentui installs an enabled startup mode before transcript restoration. A healthy installed controller lets active Streaming switch live to Rail or Tree, and lets Rail and Tree switch live between each other, without reinstalling its patch. Entering Streaming from Rail or Tree saves the choice but keeps the active structural mode until restart. Disabling live restores native thinking and releases Streaming resources. First enable and re-enable after a live disable are also restart-gated. Mode changes while disabled only preconfigure the next enable. Startup failures, missing constructors, incompatible private child layouts, parser limits, theme/render/width errors, and displaced patch ownership fail open to complete native thinking. If cleanup throws while leaving Streaming, disabling still restores native thinking and a structural selection still becomes active; the successful change warns that Streaming is unavailable for the rest of the session.
|
|
165
166
|
|
|
166
167
|
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. Rail and Tree follow Pi's thinking visibility. Complete strict SGR styling is stripped before parsing; every other terminal control and unsafe or unstructured content keeps the complete run native. 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.
|
|
167
168
|
|
|
@@ -169,10 +170,14 @@ Streaming retains Pi's host-rendered final five rows under `Thinking 7.1s`, fold
|
|
|
169
170
|
|
|
170
171
|
Pi 0.84 also provides a native fullscreen TUI with a sticky editor and Footer. Pi 0.84.4 is covered by a fullscreen live-transition PTY smoke in addition to the standard matrix. Zentui does not enable fullscreen automatically; select it from Pi's `/settings`, set `"tuiMode": "fullscreen"` in Pi settings, or launch Pi with `--tui-mode fullscreen`.
|
|
171
172
|
|
|
173
|
+
**Codex quota (opt-in):** Show remaining 5-hour/weekly quota for `openai-codex` through independent Editor and Starship Footer settings, both off by default. See [configuration and private-endpoint limitations](./docs/configuration.md#codex-account-quota), including `$codex_quota` for custom templates.
|
|
174
|
+
|
|
175
|
+
Minimalist can also show the latest assistant prompt's cache hit rate in its top-right metadata. Enable **Editor → Minimalist → Cache hit rate** or set `components.editor.styles.minimalist.showCacheHit` to `true`; it is off by default and does not depend on Footer.
|
|
176
|
+
|
|
172
177
|
## Requirements
|
|
173
178
|
|
|
174
179
|
- [Pi](https://pi.dev) coding agent 0.80.5 or newer
|
|
175
|
-
- A [Nerd Font](https://www.nerdfonts.com/) for icons
|
|
180
|
+
- A [Nerd Font](https://www.nerdfonts.com/) for Nerd icons; Auto falls back to ASCII when no supported terminal signal is present
|
|
176
181
|
|
|
177
182
|
## Development
|
|
178
183
|
|
package/docs/configuration.md
CHANGED
|
@@ -4,27 +4,75 @@
|
|
|
4
4
|
|
|
5
5
|
Zentui reads optional user configuration from `~/.pi/agent/zentui.json`. Missing or invalid known values fall back to defaults. Unknown fields are ignored at runtime but preserved on disk by component save operations where they are user-owned migration or future-style data.
|
|
6
6
|
|
|
7
|
+
## Start with minimal overrides
|
|
8
|
+
|
|
9
|
+
Do not copy the complete defaults into your file. Omitted fields keep defaults and source-aware inheritance. New installs enable Opencode Editor, Framed User messages, Zentui selector borders, and Starship Footer; Working line and Thinking (Experimental) are disabled.
|
|
10
|
+
|
|
11
|
+
Change just one surface:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"components": {
|
|
16
|
+
"footer": { "colors": { "cwd": "bold green" } }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
To adopt only User messages while leaving the other default-enabled surfaces native or predecessor-controlled:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"components": {
|
|
26
|
+
"editor": { "enabled": false },
|
|
27
|
+
"userMessages": { "enabled": true, "style": "framed" },
|
|
28
|
+
"selectorBorders": { "enabled": false },
|
|
29
|
+
"footer": { "style": "native" }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Native releases Zentui's ownership; Hidden deliberately installs a zero-row Footer. Disabling a component preserves its dormant preferences. See [color overrides and inheritance](#component-color-overrides-and-inheritance) and [explicit migration](#compatibility-and-migration) before snapshotting legacy settings.
|
|
35
|
+
|
|
7
36
|
## `/zentui` settings
|
|
8
37
|
|
|
9
|
-
The interactive `/zentui` menu is split into
|
|
38
|
+
The interactive `/zentui` menu is split into six component-oriented sections. Use `Tab` and `Shift+Tab` to switch sections. Selection/Change/Back/Close hints follow injected host keybindings (with older-host defaults when unavailable). Narrow help retains Change, Sections, and Back (on child pages) or Close guidance:
|
|
10
39
|
|
|
11
|
-
1. **Appearance** — component Preset; selector-border enablement, style, and colors; icon mode.
|
|
12
|
-
2. **Editor** — enablement, style, colors, model label, border behavior, viewport indicators, settings for the selected editor style, and a static synthetic preview.
|
|
40
|
+
1. **Appearance** — component Preset; selector-border enablement, informational fixed style, and colors; icon mode.
|
|
41
|
+
2. **Editor** — enablement, style, colors, Codex quota, model label, border behavior, viewport indicators, settings for the selected editor style, and a static synthetic preview.
|
|
13
42
|
3. **User messages** — enablement, style, colors, and a static synthetic Markdown preview.
|
|
14
43
|
4. **Thinking (Experimental)** — private Rail, Tree, or Streaming rendering; active Streaming can switch live to Rail or Tree, Rail and Tree can switch live between each other, and the private renderer may break after Pi updates.
|
|
15
44
|
5. **Working line** — ownership, settled Turn summary, spinner and text speeds, optional spinner-color motion, text animation, color source, custom messages, Tool/Elapsed/Thinking time/Tokens segments, and animated preview.
|
|
16
|
-
6. **Footer** — Native, Starship, or Hidden. Starship additionally exposes colors, model label, responsive layout, separator, context style, and path display.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
45
|
+
6. **Footer** — Native, Starship, or Hidden. Starship additionally exposes colors, Codex quota, model label, responsive layout, separator, context style, and path display.
|
|
46
|
+
- **Segments →** — visibility toggles for non-Git Starship segments.
|
|
47
|
+
- **Git →** — Starship Footer Git segment and probe controls, not Editor Git controls.
|
|
48
|
+
- **Extension statuses →** — Starship placement and color controls for active published keyed Footer statuses; not extension management or Working line integrations.
|
|
49
|
+
|
|
50
|
+
The three Footer child entries appear only with Starship selected. Child headings show their scope (for example, **Footer > Git**). The configured cancel key returns to Footer focused on the originating child entry; at the top level it still closes settings. `Tab` / `Shift+Tab` remain available on child pages to move to the next / previous top-level section relative to Footer. Visiting or backing out of a page does not save settings or change component ownership.
|
|
51
|
+
|
|
52
|
+
Editor, User messages, Thinking (Experimental), and Working line retain independent configuration. Editor, User-message, and Thinking previews remain visible while their component is disabled. Only the Working-line preview owns an animation timer. Starship-specific rows are shown only while Starship is selected. Footer Color overrides remain available for preconfiguration under every Footer style and say **Saved for Starship** when inactive. Native and Hidden hide the three child entries without changing their saved preferences. Other dormant choices explain their scope without rewriting values. Auto icons assume a Nerd Font without detecting one; ASCII replaces icons only, not all borders or UI glyphs.
|
|
20
53
|
|
|
21
|
-
|
|
54
|
+
Free-form values such as custom formats, Opencode metadata formats, and inactive extension keys remain JSON-only. Component raw colors are editable through each component’s **Color overrides** action, with explicit **Reset / inherit**. Working-line speed accepts validated custom milliseconds in `/zentui`.
|
|
55
|
+
|
|
56
|
+
Every section and Footer child page has a direct route and completion:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
/zentui appearance
|
|
60
|
+
/zentui editor
|
|
61
|
+
/zentui user-messages
|
|
62
|
+
/zentui thinking
|
|
63
|
+
/zentui working-line
|
|
64
|
+
/zentui footer
|
|
65
|
+
/zentui segments
|
|
66
|
+
/zentui git
|
|
67
|
+
/zentui extensions
|
|
68
|
+
```
|
|
22
69
|
|
|
23
|
-
|
|
70
|
+
`/zentui segments`, `/zentui git`, and `/zentui extensions` open the corresponding **Footer > …** child page when Starship is active. Under Native or Hidden, they instead open Footer with a requires-Starship explanation; they do not show active child controls, enable Starship, or write configuration.
|
|
24
71
|
|
|
25
|
-
Useful slash-command shortcuts:
|
|
72
|
+
`messages` and `thinking-steps` remain section aliases; Footer also accepts the aliases below. Useful slash-command shortcuts:
|
|
26
73
|
|
|
27
74
|
```text
|
|
75
|
+
/zentui migrate
|
|
28
76
|
/zentui editor enable
|
|
29
77
|
/zentui editor disable
|
|
30
78
|
/zentui editor toggle
|
|
@@ -85,7 +133,10 @@ URL when an extension supplies only a label.
|
|
|
85
133
|
|
|
86
134
|
## Complete default configuration
|
|
87
135
|
|
|
88
|
-
|
|
136
|
+
Reference only—not a starter file. Prefer the minimal overrides above. Optional editor source-aware overrides such as `editorRail`, `editorGitBranch`, and `editorThinkingMax` are intentionally omitted.
|
|
137
|
+
|
|
138
|
+
<details>
|
|
139
|
+
<summary>Expand the complete defaults</summary>
|
|
89
140
|
|
|
90
141
|
```json
|
|
91
142
|
{
|
|
@@ -93,6 +144,7 @@ Copy this example and change only the values you need. Optional editor source-aw
|
|
|
93
144
|
"components": {
|
|
94
145
|
"editor": {
|
|
95
146
|
"enabled": true,
|
|
147
|
+
"codexQuota": false,
|
|
96
148
|
"style": "opencode",
|
|
97
149
|
"colorSource": "theme",
|
|
98
150
|
"borderColorMode": "static",
|
|
@@ -100,11 +152,11 @@ Copy this example and change only the values you need. Optional editor source-aw
|
|
|
100
152
|
"viewportIndicators": true,
|
|
101
153
|
"styles": {
|
|
102
154
|
"opencode": {
|
|
103
|
-
"metadataFormat": "$model $provider( $thinking)",
|
|
155
|
+
"metadataFormat": "$model $provider( $thinking)( $codex_quota)",
|
|
104
156
|
"completionMenu": "palette"
|
|
105
157
|
},
|
|
106
158
|
"opencode-copy-friendly": {
|
|
107
|
-
"metadataFormat": "$model $provider( $thinking)",
|
|
159
|
+
"metadataFormat": "$model $provider( $thinking)( $codex_quota)",
|
|
108
160
|
"completionMenu": "palette"
|
|
109
161
|
},
|
|
110
162
|
"accent-rail": {
|
|
@@ -119,6 +171,7 @@ Copy this example and change only the values you need. Optional editor source-aw
|
|
|
119
171
|
"showSessionName": true,
|
|
120
172
|
"showTimer": true,
|
|
121
173
|
"showCost": true,
|
|
174
|
+
"showCacheHit": false,
|
|
122
175
|
"showGit": true,
|
|
123
176
|
"contextThresholds": {
|
|
124
177
|
"warning": 70,
|
|
@@ -186,13 +239,14 @@ Copy this example and change only the values you need. Optional editor source-aw
|
|
|
186
239
|
},
|
|
187
240
|
"footer": {
|
|
188
241
|
"style": "starship",
|
|
242
|
+
"codexQuota": false,
|
|
189
243
|
"colorSource": "theme",
|
|
190
244
|
"modelLabel": "id",
|
|
191
245
|
"styles": {
|
|
192
246
|
"starship": {
|
|
193
247
|
"format": "",
|
|
194
248
|
"responsive": true,
|
|
195
|
-
"compactFormat": "$cwd$wrap(in $session_name)$wrap(on $git_branch) $git_status$wrap$context$wrap_sep$tokens",
|
|
249
|
+
"compactFormat": "$cwd$wrap(in $session_name)$wrap(on $git_branch) $git_status$wrap$context$wrap_sep$tokens$wrap_sep($codex_quota)",
|
|
196
250
|
"compactMaxLines": 2,
|
|
197
251
|
"separator": "pipe",
|
|
198
252
|
"contextStyle": "text",
|
|
@@ -303,15 +357,17 @@ Copy this example and change only the values you need. Optional editor source-aw
|
|
|
303
357
|
}
|
|
304
358
|
```
|
|
305
359
|
|
|
360
|
+
</details>
|
|
361
|
+
|
|
306
362
|
## Core configuration
|
|
307
363
|
|
|
308
364
|
- Style values accept Starship/terminal strings such as `bold purple`, `fg:202`, `#89b`, `#89b4fa`, and `bg:blue fg:bright-green`, or Pi theme tokens such as `accent`, `borderMuted`, and `thinkingHigh`. Short `#rgb` values expand to `#rrggbb`.
|
|
309
|
-
- `projectRefreshIntervalMs` controls project-status polling. `0` disables polling. Values `1..4999` clamp to the five-second minimum; invalid or non-finite values use `30000`.
|
|
365
|
+
- `projectRefreshIntervalMs` controls project-status polling, not opt-in quota refresh. `0` disables project polling. Values `1..4999` clamp to the five-second minimum; invalid or non-finite values use `30000`.
|
|
310
366
|
- `components.editor` owns Editor enablement, `opencode | opencode-copy-friendly | accent-rail | minimalist` style selection, color source, border mode, model label, viewport indicators, and all four style configurations.
|
|
311
367
|
- Editor `modelLabel` uses `id` by default; `name` uses the display name with ID fallback. Footer has an independent `modelLabel` control.
|
|
312
368
|
- `components.userMessages` owns User-message enablement, `framed | framed-copy-friendly | compact | labeled` style selection, and color source. Disabling it delegates byte-for-byte to Pi's native renderer.
|
|
313
369
|
- `components.thinkingSteps` independently owns opt-in **Thinking (Experimental)** display. It defaults to `{ "enabled": false, "mode": "tree" }`; canonical modes are `rail | tree | streaming`. The former persisted `streaming-experimental` value is accepted only as a migration alias and is normalized to `streaming` on save.
|
|
314
|
-
- All three modes decorate Pi's private host renderer and are tested on exact Pi versions 0.80.5, 0.82.1, 0.83.0, 0.84.0,
|
|
370
|
+
- All three modes decorate Pi's private host renderer and are tested on exact Pi versions 0.80.5, 0.82.1, 0.83.0, 0.84.0, 0.84.4, and 0.85.1. Active Streaming can switch live to Rail or Tree, and Rail and Tree can switch live between each other. Entering Streaming from a structural mode, first enable, and re-enable after live disable require restart; live disable restores native thinking. Disabled mode changes only preconfigure.
|
|
315
371
|
- `components.workingLine.enabled` is the sole Working-line ownership switch. Thinking (Experimental) never enables, configures, or owns the Working line and leaves the existing **Thinking time** option unchanged.
|
|
316
372
|
- `components.selectorBorders` owns selector-border enablement, fixed `zentui` style, and color source. Disable it for native Pi behavior.
|
|
317
373
|
- `components.footer` owns `native | starship | hidden` style selection, color source, model label, and Starship options. Hidden installs an empty component with zero rows.
|
|
@@ -319,6 +375,41 @@ Copy this example and change only the values you need. Optional editor source-aw
|
|
|
319
375
|
- Active third-party statuses from `ctx.ui.setStatus()` can be placed left, middle, or right, hidden per key, and assigned independent color modes.
|
|
320
376
|
- The shown `editor*` colors match the default `theme` source. Omit them to preserve source-aware defaults when switching between `theme` and `terminal`.
|
|
321
377
|
|
|
378
|
+
### Codex account quota
|
|
379
|
+
|
|
380
|
+
`components.editor.codexQuota` and `components.footer.codexQuota` are independent booleans, both `false` by default. Enable either from its **Codex quota** settings row, or merge these leaves into your existing file:
|
|
381
|
+
|
|
382
|
+
```json
|
|
383
|
+
{
|
|
384
|
+
"components": {
|
|
385
|
+
"editor": { "codexQuota": true },
|
|
386
|
+
"footer": { "codexQuota": false }
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
This example enables only Editor quota, without changing any component's style or enablement. Minimalist with Hidden Footer is supported. Footer quota requires Starship. Neither toggle enables another surface or changes a color source, and presets preserve both choices.
|
|
392
|
+
|
|
393
|
+
- Only the exact active provider `openai-codex` with native Codex API and ChatGPT-origin model/provider routing is eligible, not `openai`, proxies (including same-ID overrides), or similarly named models. Resolved-auth routing overrides must also use the ChatGPT origin. Use Pi's existing ChatGPT/Codex login; API billing balances are not supported.
|
|
394
|
+
- Values are **remaining**, rounded percentages: `5h 80% | week 60%`. Only exact 18,000-second and 604,800-second windows are recognized, independently of response ordering. Other durations stay unknown rather than acquiring incorrect labels.
|
|
395
|
+
- `--` means unavailable, including a missing window, unsupported auth API/account, or no successful request. `0%` means exhausted. A newer partial response replaces the previous snapshot completely.
|
|
396
|
+
- Transient HTTP/network/schema failures and refresh deadlines (including slow authentication lookups) retain successful values with a textual `stale` warning. Values older than two minutes also become stale. Missing, failed, or rejected authentication clears the cache, as do account changes, provider changes, loss of all consumers, and teardown. Credentials and quota are never persisted by Zentui.
|
|
397
|
+
- One shared poller refreshes roughly every minute, including idle time, only in a TUI session with an owned, enabled eligible consumer. Both toggles off means no quota auth lookup or request. Editor templates without `$codex_quota` do not create demand; Footer considers both wide and responsive compact paths. HTTP 429 can delay the next request via `Retry-After`. Each refresh has a ten-second deadline; late uncancelable auth results are ignored.
|
|
398
|
+
- Opencode variants include quota conditionally in their shipped metadata defaults. Minimalist adds it beside context when space allows. Accent Rail adds one editor-owned row beneath input and viewport indicators, before autocomplete. At narrow widths quota is omitted as a unit rather than clipping away labels or `stale`. Input text and Working line are unaffected.
|
|
399
|
+
- Quota reuses the selected component's `contextNormal`, `contextWarning`, and `contextError` color roles. Remaining quota at or below 50% uses warning, at or below 20% uses error; stale values use at least warning. Editor never borrows Footer overrides. Settings previews use synthetic values only.
|
|
400
|
+
|
|
401
|
+
**Custom templates remain authoritative.** Saved nonempty formats, including copies of old defaults, are never rewritten or augmented outside the template. Add `( $codex_quota)` to either Opencode variant's `metadataFormat`, `($sep$codex_quota)` to a Footer wide `format`, or `$wrap_sep($codex_quota)` to `compactFormat`. Tokens remain empty when the corresponding quota toggle is off or the provider is ineligible. Unlike ordinary Footer `segments` flags, quota consent cannot be bypassed by a template.
|
|
402
|
+
|
|
403
|
+
**Compatibility and privacy:** Zentui uses Pi's public active-model metadata, `modelRegistry.getProvider("openai-codex")`, and `getProviderAuth("openai-codex")`, available on tested Pi 0.84.0 and 0.85.1. Hosts without safe model/provider routing metadata do not collect or display quota; unavailable auth shows placeholders. There is no fallback to private storage or older credential APIs; the overall Pi minimum is unchanged. Auth is sent only to `https://chatgpt.com/backend-api/wham/usage`, with redirects rejected. JWT decoding is limited to the account-routing claim and is not identity verification. An opaque credential change invalidates cached data conservatively.
|
|
404
|
+
|
|
405
|
+
The endpoint is undocumented and may change or reject some plans. Its path and seconds-based window field are corroborated by [OpenAI's Codex client](https://github.com/openai/codex/blob/rust-v0.98.0/codex-rs/backend-client/src/client.rs); this is not a public API guarantee. Automated verification uses synthetic responses, not a live account. No reset times, countdowns, alerts, or quota history are provided.
|
|
406
|
+
|
|
407
|
+
### Footer layout authority
|
|
408
|
+
|
|
409
|
+
Under `components.footer.styles.starship`, `segments` toggles choose the **built-in wide layout** when `format` is empty. An explicit wide `format` chooses its own variables instead. With `responsive` enabled, Zentui tries the wide layout, then reflows it, then uses the independent `compactFormat` template if it still cannot fit. `compactMaxLines` limits compact rows, not their segment selection.
|
|
410
|
+
|
|
411
|
+
Templates can show a disabled built-in segment or omit an enabled one: disabling Current directory and enabling Session cost can hide cwd and show cost at wide widths, while the default compact template still shows `$cwd` and omits `$cost`. Edit `format` or `compactFormat` to change those templates; `/zentui format clear` resets only the wide layout. Git counts remain a formatting choice for git-status values in both built-in and template layouts. `/zentui` segment descriptions disclose these boundaries; toggles never rewrite templates.
|
|
412
|
+
|
|
322
413
|
### Footer path display
|
|
323
414
|
|
|
324
415
|
`components.footer.styles.starship.pathDisplay.mode` accepts `basename`, `full`, or the opt-in `repository`; the unchanged default is `basename`. Repository mode removes the repository directory name: at `/repo` it renders `.`, and at `/repo/extensions/zentui` it renders `extensions/zentui`. Zentui finds the nearest ancestor with a `.git` directory or worktree `.git` file without starting an extra Git process.
|
|
@@ -327,22 +418,53 @@ For `full` and `repository`, `depth` is the number of final components to retain
|
|
|
327
418
|
|
|
328
419
|
Repository roots are associated with the cwd that produced them. While the current root is missing, stale, outside the cwd, still being refreshed, or unavailable after a lookup failure or Git-to-non-Git transition, Zentui silently renders the unlimited `full` path, including `~` home abbreviation. Built-in and custom `$cwd` layouts use the same result at wide and compact widths. These options belong only to the Starship Footer; Minimalist Editor path semantics are unchanged.
|
|
329
420
|
|
|
330
|
-
###
|
|
421
|
+
### Component color overrides and inheritance
|
|
422
|
+
|
|
423
|
+
Use sparse `components.<owner>.colors` objects to change only one surface:
|
|
424
|
+
|
|
425
|
+
```json
|
|
426
|
+
{
|
|
427
|
+
"colors": { "editorAccent": "blue", "cwdText": "bold cyan" },
|
|
428
|
+
"components": {
|
|
429
|
+
"editor": { "colors": { "accent": "fg:202", "gitBranch": "bold blue" } },
|
|
430
|
+
"userMessages": { "colors": { "accent": "", "border": "bright-black" } },
|
|
431
|
+
"selectorBorders": { "colors": { "border": "borderMuted" } },
|
|
432
|
+
"footer": { "colors": { "cwd": "bold green" } },
|
|
433
|
+
"workingLine": { "colors": { "high": "bold cyan" } }
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
Resolution is **component override → historical shared `colors` fallback → existing selected-source default**, both before and after explicit migration. Absent overrides preserve historical output. Shared colors remain optional live fallbacks indefinitely: changing a shared fallback can affect every owner that still inherits it. An override never changes another owner or its color source. There is no generated palette or resolved ANSI snapshot in these objects.
|
|
439
|
+
|
|
440
|
+
Empty strings and whitespace-only strings mean deliberately **unstyled**, not missing. **Reset / inherit** deletes the local key; hand-deleting a key does the same. Unsupported values are ignored at runtime, while invalid and unknown future JSON keys remain preserved on disk. The settings editor validates supported style strings, distinguishes Escape from an empty submission, and offers role selection within one **Color overrides** action per component (selector borders use Appearance). Thinking (Experimental) has no raw color object or control.
|
|
441
|
+
|
|
442
|
+
| Owner | Local keys | Historical shared fallback |
|
|
443
|
+
| --- | --- | --- |
|
|
444
|
+
| `footer` | `cwd`, `sessionName`, `gitBranch`, `gitStatus`, `contextNormal`, `contextWarning`, `contextError`, `cost`, `sessionDuration`, `tokens`, `separator`, `runtimePrefix`, `extensionStatus`, `packageVersion`, `gitCommit`, `gitMetricsAdded`, `gitMetricsDeleted`, `username`, `time`, `os` | Same-named shared key |
|
|
445
|
+
| `editor` | `cwd`, `sessionName`, `gitStatus`, `contextNormal`, `contextWarning`, `contextError`, `cost`, `sessionDuration` | Same-named shared key; used by Minimalist metadata and quota |
|
|
446
|
+
| `editor` | `gitBranch` | `editorGitBranch`, then explicitly configured shared `gitBranch` / `git`; never the generated Footer branch default |
|
|
447
|
+
| `editor` | `accent`, `border`, `prompt`, `rail`, `shellRail`, `model`, `provider`, `thinking`, `thinkingMinimal`, `thinkingLow`, `thinkingMedium`, `thinkingHigh`, `thinkingXhigh`, `thinkingMax` | `editorAccent`, `editorBorder`, `editorPrompt`, `editorRail`, `editorShellRail`, `editorModel`, `editorProvider`, `editorThinking`, and matching `editorThinking*` level keys |
|
|
448
|
+
| `userMessages` | `accent`, `border` | `editorAccent`, `editorBorder` |
|
|
449
|
+
| `selectorBorders` | `border` | No shared raw key: defaults to theme `borderMuted` / terminal `bright-black`; never inherits `editorBorder` |
|
|
450
|
+
| `workingLine` | `low`, `mid`, `high` | `workingLineLow`, `workingLineMid`, `workingLineHigh` |
|
|
331
451
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
-
|
|
335
|
-
|
|
336
|
-
-
|
|
337
|
-
-
|
|
338
|
-
-
|
|
339
|
-
-
|
|
452
|
+
Shared aliases `cwdText → cwd` and `git → gitBranch` remain accepted. Footer model/provider are plain text and the detected runtime label uses its runtime module's style, not invented Footer color keys.
|
|
453
|
+
|
|
454
|
+
Role-specific defaults and chains remain intact:
|
|
455
|
+
|
|
456
|
+
- Copy-friendly Opencode prompt uses explicit prompt → configured accent → the existing theme `accent` / terminal `blue` fallback. Model's constant fallback does **not** inherit a configured accent. Minimalist retains its distinct model/thinking defaults.
|
|
457
|
+
- In shell-command mode (`!` or `!!`), Opencode's left rail and model label share `shellRail` → configured `accent` → theme `bashMode` / terminal `bright-cyan`. Normal model coloring is unchanged.
|
|
458
|
+
- Accent Rail uses only `rail` / `editorRail`, then warm theme `syntaxNumber` / terminal `215`; it does not inherit `accent`.
|
|
459
|
+
- Minimalist branch defaults to theme `bold syntaxKeyword` / terminal `bold blue` when no local or explicit shared branch style exists.
|
|
460
|
+
- Thinking levels use their level key then generic `thinking`; Max uses `thinkingMax → thinkingXhigh → thinking`. Static metadata and adaptive borders retain their existing distinct fallback behavior; theme-adaptive borders still defer to Pi's thinking-border callback.
|
|
461
|
+
- Working-line defaults remain theme `dim`, `muted`, `bold accent`, or terminal `bright-black`, `cyan`, `bold cyan`. Both animated rows and summaries consume local overrides. New persisted Turn summaries snapshot the effective high style; when no safe SGR prefix exists (including an unstyled high override), they retain the safe bold-cyan substitute. Existing persisted summaries keep their recorded style; legacy version-1 summaries use current high styling.
|
|
340
462
|
|
|
341
463
|
## Editor styles
|
|
342
464
|
|
|
343
465
|
### Accent Rail
|
|
344
466
|
|
|
345
|
-
Set `components.editor.style` to `accent-rail` or select **Accent Rail** in `/zentui`. Each input row uses its style-owned `rail` glyph (`▎`, or `asciiRail` in ASCII mode), one blank cell before text, and Pi's neutral filled surface.
|
|
467
|
+
Set `components.editor.style` to `accent-rail` or select **Accent Rail** in `/zentui`. Each input row uses its style-owned `rail` glyph (`▎`, or `asciiRail` in ASCII mode), one blank cell before text, and Pi's neutral filled surface. By default it has no prompt glyph, metadata, enclosing border, or blank chrome row. Opt-in eligible Codex quota is the sole metadata exception, adding a separate row beneath input when it fits. Viewport counts appear only while content is clipped.
|
|
346
468
|
|
|
347
469
|
Known autocomplete rows retain Pi's native text, descriptions, and scrolling on the same full-width surface. The selected native `→` becomes the configured rail without replacing Pi's selected-text color. Ambiguous third-party editor layouts fail open using already-rendered native rows.
|
|
348
470
|
|
|
@@ -354,9 +476,9 @@ Set `ZENTUI_DEBUG=1` when launching Pi to log the workaround diagnostic without
|
|
|
354
476
|
|
|
355
477
|
### Minimalist
|
|
356
478
|
|
|
357
|
-
Set `components.editor.style` to `minimalist` or select it in `/zentui`. The rounded frame places viewport counts, Bash state, current/completed turn duration, and explicit session name at top left; cost, model, thinking, and
|
|
479
|
+
Set `components.editor.style` to `minimalist` or select it in `/zentui`. The rounded frame places viewport counts, Bash state, current/completed turn duration, and explicit session name at top left; cost, model, thinking, context, and optional latest-prompt cache hit rate at top right; viewport count plus Git at bottom left; and configured path at bottom right. Unnamed sessions add no placeholder.
|
|
358
480
|
|
|
359
|
-
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.
|
|
481
|
+
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`. Enable `showCacheHit` to append values such as `Cache 98.2%`; it defaults to `false`, omits missing data, yields before context at narrow widths, and remains independent of Footer. The gauge shortens or disappears before the context text at narrow widths. Session name, timer, cost, cache hit rate, and Git can be hidden independently; model, thinking, and context remain structurally stable.
|
|
360
482
|
|
|
361
483
|
Autocomplete stays inside the frame when Pi output can be split safely. Unknown third-party layouts fail open. Footer visibility remains independently controlled by `components.footer.style`; Minimalist does not remove Pi's header.
|
|
362
484
|
|
|
@@ -410,12 +532,13 @@ The configured right zone and Pi's operational right status are right-aligned to
|
|
|
410
532
|
| `$context` | compact current context usage and window, for example `26.8%/272k` |
|
|
411
533
|
| `$tokens` | cumulative session input/output tokens only, for example `↑76k ↓1.6k` |
|
|
412
534
|
| `$cache_hit` | latest assistant prompt cache-hit rate to one decimal; `0.0%` when unavailable |
|
|
535
|
+
| `$codex_quota` | remaining 5-hour/weekly account quota; requires Editor quota consent and active `openai-codex` |
|
|
413
536
|
|
|
414
537
|
`$context` uses Pi's current context snapshot and the live assistant context override, refreshing on the existing 250 ms streaming render cadence. `$tokens` and `$cache_hit` use authoritative persisted session snapshots, so they update at normal session synchronization boundaries rather than estimating in-progress totals. These variables are independent of Footer visibility, style, color source, and configuration.
|
|
415
538
|
|
|
416
|
-
Model variables use `editorModel
|
|
539
|
+
Model variables use Editor `colors.model` (legacy `editorModel`), provider uses `colors.provider` (legacy `editorProvider`), and thinking uses the matching Editor level style. Literal text, session name, and usage metadata use the neutral editor-border theme style. ANSI/VT sequences, controls, and line-breaking whitespace are sanitized without collapsing ordinary spaces.
|
|
417
540
|
|
|
418
|
-
Missing, non-string, or empty values use `$model $provider( $thinking)
|
|
541
|
+
Missing, non-string, or empty values use `$model $provider( $thinking)( $codex_quota)`, with identical spacing while quota is off. A non-empty format that resolves to no metadata preserves the normal blank spacer and metadata rows. This option is JSON-only; `/zentui format` controls the Footer.
|
|
419
542
|
|
|
420
543
|
## User-message styles
|
|
421
544
|
|
|
@@ -445,7 +568,7 @@ Only an actually open thinking phase uses `•`; a text/tool transition or resto
|
|
|
445
568
|
|
|
446
569
|
Streaming keeps the reviewed host-rendered behavior: while open it shows the latest five rendered terminal rows beneath `Thinking 7.1s`; completion folds under `Thought` or current-session `Thought for Ns`. Restored entries have no duration because Pi does not persist a reliable thinking-end timestamp. Only a session started in active Streaming owns its validated configured `app.thinking.toggle` binding and one-second timer. Ctrl+T expands/refolds native reasoning. Startup resource failures and private-shape/render failures use complete native thinking. A cleanup callback that throws while leaving Streaming is contained: Rail or Tree remains active, while Streaming becomes unavailable for that session. Component and timing tracking are bounded to 256; evicted entries are restored natively first.
|
|
447
570
|
|
|
448
|
-
The exact all-mode private matrix covers Pi 0.80.5, 0.82.1, 0.83.0, 0.84.0,
|
|
571
|
+
The exact all-mode private matrix covers Pi 0.80.5, 0.82.1, 0.83.0, 0.84.0, 0.84.4, and 0.85.1 under dark, light, and current themes, narrow/wide widths and resize; Pi 0.84.4 also has a fullscreen live-transition PTY smoke. Thinking (Experimental) never owns or writes the Working line, including its unchanged **Thinking time** option, and does not own Footer, Editor, widgets, statuses, or model behavior.
|
|
449
572
|
|
|
450
573
|
## Working line
|
|
451
574
|
|
|
@@ -515,9 +638,15 @@ Zentui accepts at most 16 unique keys, keys up to 64 code units, and values up t
|
|
|
515
638
|
| `↓` | Behind |
|
|
516
639
|
| `⇕` | Diverged |
|
|
517
640
|
|
|
641
|
+
## Icon Auto detection
|
|
642
|
+
|
|
643
|
+
`icons.mode: "auto"` preserves Auto in memory and on disk while deriving an effective mode for the current process. Exact `ZENTUI_NERD_FONTS=1` or `0` overrides Auto. Otherwise Auto selects Nerd glyphs when `TERM_PROGRAM` is `iTerm.app`, `WezTerm`, or `ghostty` (case-insensitive), or when `KITTY_WINDOW_ID` or `ALACRITTY_SOCKET` is nonempty. Unknown terminals, VS Code, and Windows Terminal default to ASCII-safe glyphs. Explicit `nerd` and `ascii` modes ignore the override and environment signals.
|
|
644
|
+
|
|
645
|
+
This is conservative terminal-environment detection, not font probing: terminal identity cannot prove that a Nerd Font is installed or configured. Use explicit mode or `ZENTUI_NERD_FONTS` when Auto chooses incorrectly. Custom icon overrides still win over either effective mode.
|
|
646
|
+
|
|
518
647
|
## Runtime detection
|
|
519
648
|
|
|
520
|
-
Runtime/language modules use Starship Nerd Font symbols and defaults such as `bold green` for Node.js. Theme mode maps those styles through Pi; Footer terminal mode uses the terminal colorscheme's ANSI colors.
|
|
649
|
+
Runtime/language modules use Starship Nerd Font symbols and defaults such as `bold green` for Node.js. Theme mode maps those styles through Pi; Footer terminal mode uses the terminal colorscheme's ANSI colors. In Auto mode, runtime, OS, package, rail, and gauge symbols all use the same derived effective icon mode.
|
|
521
650
|
|
|
522
651
|
| Runtime/language | Detection examples |
|
|
523
652
|
| --- | --- |
|
|
@@ -593,7 +722,13 @@ Save this in Pi's `~/.pi/agent/settings.json`, select fullscreen in Pi's `/setti
|
|
|
593
722
|
|
|
594
723
|
## Compatibility and migration
|
|
595
724
|
|
|
596
|
-
Canonical `components` paths are the primary JSON interface.
|
|
725
|
+
Canonical `components` paths are the primary JSON interface. Ordinary component saves snapshot and normalize **only the edited owner**: that owner's current legacy-derived selections, sources, and style options become explicit, while unrelated raw JSON values and future styles remain untouched and legacy-derived. Unknown fields do not affect runtime behavior. Color overrides stay sparse and unrelated raw color values are never normalized on save.
|
|
726
|
+
|
|
727
|
+
Run **`/zentui migrate`** or **Appearance → Migrate component selections** for a separate, explicitly confirmed all-owner snapshot. The confirmation explains that component selections, color sources, and style options are frozen against future shared/root legacy selection edits, while shared raw color inheritance remains active. Migration reads the latest disk file after confirmation, preserves unknown fields, aliases and templates, writes atomically (including through a valid symlink), and is idempotent. It never copies generated color defaults or resolved ANSI into owner overrides. Cancellation, unavailable UI, stale session dialogs, corrupt/unreadable config, and failed atomic writes do not change the config. There is **no automatic startup or first-edit migration** and no version marker.
|
|
728
|
+
|
|
729
|
+
Snapshot saves remove the edited owners' obsolete nested copy-friendly/Footer-enabled flags after capturing their effective choices. Deliberately reintroducing an owner-local legacy alias is still an edit to that owner: for example, `components.userMessages.styles.framed.copyFriendly` retains its documented alias behavior with `style: "framed"`. This is distinct from shared/root legacy recoupling, which canonical snapshots prevent.
|
|
730
|
+
|
|
731
|
+
Legacy coupled saver APIs remain explicit multi-owner compatibility transactions; ordinary settings controls never use them. Presets remain sparse, selection-only combinations rather than migrations.
|
|
597
732
|
|
|
598
733
|
- Flat released inputs such as `editorStyle`, `features`, `footerFormat`, and `compactFooterFormat` remain accepted for migration.
|
|
599
734
|
- `components.footer.enabled` and `features.statusLine` migrate to Starship or Native when no valid Footer style exists; Hidden projects `features.statusLine: false`.
|