pi-minimal-footer 0.8.0 → 0.9.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/CHANGELOG.md CHANGED
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.9.0] - 2026-10-30
11
+
12
+ ### Added
13
+
14
+ - Optional provider prefix (`minFooter.showProvider`) and colored thinking level (`minFooter.showThinking`), both off by default. Thanks to [@mkaros2025].
15
+ - Hide subscription usage and stop its background queries with `minFooter.showUsage: false`. Thanks to [@mkaros2025].
16
+ - Other extensions can show or hide subscription usage for the session without changing saved preferences (`pi-minimal-footer:set-usage-enabled`).
17
+
18
+ ### Changed
19
+
20
+ - Context label turns yellow at 85% and red at 92% of the configured compaction threshold.
21
+
22
+ ## [0.8.1] - 2026-10-28
23
+
24
+ ### Fixed
25
+
26
+ - Apply changed context-display settings immediately when enabling the footer or starting a session
27
+ - Prevent outdated Git counts and highlights after switching directories, replacing the footer, or disabling it
28
+ - Correct documentation and previews to match current context formatting, usage-bar behavior, and settings
29
+
10
30
  ## [0.8.0] - 2026-10-28
11
31
 
12
32
  ### Added
@@ -273,7 +293,11 @@ First npm-ready release.
273
293
 
274
294
  - Project scaffold — `extensions/index.ts` with basic footer structure, `package.json` with pi extension manifest, `README.md`, `LICENSE` (MIT)
275
295
 
276
- [Unreleased]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.8.0...HEAD
296
+ [@mkaros2025]: https://github.com/mkaros2025
297
+
298
+ [Unreleased]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.9.0...HEAD
299
+ [0.9.0]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.8.1...v0.9.0
300
+ [0.8.1]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.8.0...v0.8.1
277
301
  [0.8.0]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.7.1...v0.8.0
278
302
  [0.7.1]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.7.0...v0.7.1
279
303
  [0.7.0]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.6.0...v0.7.0
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  An opinionated, compact, one-line status bar for [Pi](https://github.com/earendil-works/pi).
11
11
 
12
- ![Footer preview: ~/git/project   main 🧠 Karpathy 🪽 Icarus model · 42k/200k · [⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h](media/preview.png)
12
+ ![Footer preview: ~/git/project   main ↑2 · 🧠 Karpathy · 🪽 Icarus · gpt-6-sol · 42k/200k · subscription usage with reset time](media/preview.png)
13
13
 
14
14
  **Left**
15
15
 
@@ -31,8 +31,6 @@ Choose one npm name (they contain the same extension; do not install both):
31
31
 
32
32
  ```bash
33
33
  pi install npm:pi-minimal-footer
34
- # or
35
- pi install npm:@ryu-cz/pi-minimal-footer
36
34
  ```
37
35
 
38
36
  The scoped package is an official mirror, not a separate extension.
@@ -58,6 +56,9 @@ Edit `minFooter` in Pi's agent `settings.json` (normally `~/.pi/agent/settings.j
58
56
  "showPath": true,
59
57
  "showModel": true,
60
58
  "showContext": true,
59
+ "showProvider": false,
60
+ "showThinking": false,
61
+ "showUsage": true,
61
62
  "contextAsPercentage": false,
62
63
  "powerlineSeparator": true,
63
64
  "gitRefreshSeconds": 91,
@@ -68,7 +69,10 @@ Edit `minFooter` in Pi's agent `settings.json` (normally `~/.pi/agent/settings.j
68
69
  }
69
70
  ```
70
71
 
72
+ - `showProvider` prefixes the model with its provider id, e.g. `opencode-go/deepseek-v4.1-flash`; default `false`.
73
+ - `showThinking` appends the thinking level for reasoning models, e.g. `deepseek-v4.1-flash high` or `thinking off`, in Pi's matching `thinking*` theme color; default `false`.
71
74
  - `showSkills` shows **extension status text**, not installed skills. The footer does not add the example statuses itself.
75
+ - `showUsage` enables this footer's own provider usage queries and the subscription usage bar; set it to `false` when another extension already publishes quota; default `true`.
72
76
  - Set `powerlineSeparator` to `false` for plain spaces instead of `` / `` if your font lacks those glyphs. The git icon `` and sync arrows also need compatible glyphs; hide Git data with `showGitBranch: false` if needed.
73
77
  - `gitRefreshSeconds`: local refresh interval; `1`–`2147483` seconds; default `91`.
74
78
  - `gitFetch`: background fetch on startup, then roughly 5 minutes after each attempt completes; failures are silent; default `false`.
@@ -83,7 +87,9 @@ Counts require a configured upstream. Unsynced branches use normal text color; s
83
87
 
84
88
  ### Context
85
89
 
86
- `42k/200k` means tokens used / context window. Set `"contextAsPercentage": true` under `minFooter` to show `21.0%/200k` instead. Unknown usage shows `?`.
90
+ `42k/200k` means tokens used / context window. Set `"contextAsPercentage": true` under `minFooter` to show `21.0%/200k` instead. Unknown token usage shows `?/200k` when the window is known, or `?` when context information is unavailable.
91
+
92
+ The whole context label keeps its normal dim color below 85% of Pi’s compaction trigger (`contextWindow - reserveTokens`), turns yellowish (`warning`) at 85%, and red (`error`) at 92%. It uses Pi’s effective compaction settings, including exact `provider/modelId` overrides, with a default reserve of 16,384 tokens. Colors apply in both display modes, even when auto-compaction is disabled. Unknown usage or a non-positive trigger keeps the normal color.
87
93
 
88
94
  ### Subscription usage
89
95
 
@@ -91,7 +97,7 @@ Counts require a configured upstream. Unsynced branches use normal text color; s
91
97
 
92
98
  - **Bar:** expands into spare space, using 2–10 cells by default, capped by `maxUsageBarCells`. Smaller caps and very narrow terminals may show fewer cells or only the reset label.
93
99
  - **Colors:** green below 85%, amber from 85%, red from 92%.
94
- - **Cached data:** dim after a refresh failure.
100
+ - **Cached data:** dim after a refresh failure or when its reset time has passed.
95
101
  - Reset: local `↻HH:mm` through 24 hours; whole days/hours above 24 hours (`↻1d8h`); whole days above 10 days (`↻12d`). Remaining durations round down. No reset reported means bar only.
96
102
  - Shows the shortest available usage window for the selected provider. Missing credentials, unsupported/local models, or absent limits hide the usage bar. Custom proxy endpoints are not polled.
97
103
  - Virtual/routed models show model and context usage, but no subscription bar.
@@ -119,19 +125,13 @@ Only one footer extension can be active. For plugin integration, see [VISION.md]
119
125
 
120
126
  ## Programmatic control
121
127
 
122
- Other Pi extensions can enable or disable the footer for the current session without changing saved settings:
128
+ Other Pi extensions can control this footer without changing saved preferences:
123
129
 
124
- ```typescript
125
- pi.events.emit("pi-minimal-footer:set-enabled", { enabled: false }); // disable
126
- pi.events.emit("pi-minimal-footer:set-enabled", { enabled: true }); // enable
127
- ```
130
+ - **Footer** (`pi-minimal-footer:set-enabled`): enable or disable for the current session.
131
+ - **Subscription usage** (`pi-minimal-footer:set-usage-enabled`): show or hide the bar and its background queries independently—useful when your terminal already shows quota.
132
+ - New sessions and `/reload` restore saved preferences.
128
133
 
129
- - Events work only while this extension's session is active.
130
- - The latest command or event wins.
131
- - `/minfooter on/off` saves your preference into config; events don't.
132
- - Enabling may replace another footer.
133
- - Disabling restores Pi's default footer if this footer is active; it leaves another extension's active footer untouched.
134
- - New sessions and `/reload` use your saved preference.
134
+ Event API and integration rules: [developer guide](VISION.md#session-only-footer-control).
135
135
 
136
136
  ## Development & design
137
137
 
package/VISION.md CHANGED
@@ -9,16 +9,16 @@ The [README](README.md) is the user manual. This document records current design
9
9
  ## Layout contract
10
10
 
11
11
  - Directory and Git branch form the left group, separated by ``.
12
- - Each extension status is its own `` tab. Preserve the supplied text; do not invent status labels, parentheses, or pipes.
12
+ - Each extension status is its own `` tab. Preserve the supplied text except for replacing line breaks and tabs with spaces; do not invent status labels, parentheses, or pipes.
13
13
  - Model, context, and subscription usage form the rightmost group, separated by ` · `. Model identifies the running engine; context describes its usage; the usage bar stays anchored at the right edge.
14
14
  - Powerline separators are dim. `powerlineSeparator: false` replaces them with a single space. Font availability cannot be detected reliably.
15
15
  - Measure terminal columns with `visibleWidth`, not string length. Preserve ANSI styling and wide-character accounting when truncating.
16
16
 
17
17
  ### Space allocation
18
18
 
19
- Reserve the usage bar and model/context before allocating location and statuses. Statuses and location may shorten or disappear; on sufficiently narrow terminals, model/context can also shorten or disappear.
19
+ Reserve the usage bar and model/context before allocating location and statuses. Statuses and location may shorten or disappear; on sufficiently narrow terminals, model/context can also shorten or disappear. The model field is one protected unit: an optional `provider/` prefix, the bold model id, and an optional thinking level colored by Pi's `thinking*` theme tokens are truncated together, so the field never splits into separate segments.
20
20
 
21
- Lay out other fields with a two-cell usage bar first. Grow the bar only into leftover columns, up to ten cells—never truncate another field solely to enlarge it. At extreme widths, shrink to one cell, show only the reset label, or hide usage if neither can fit. Brackets keep an empty bar's edges visible and count toward its width, but not its cell cap.
21
+ Lay out other fields with a two-cell usage bar first, or fewer if `maxUsageBarCells` is smaller. Grow the bar only into leftover columns, up to `maxUsageBarCells` (default ten)—never truncate another field solely to enlarge it. At extreme widths, shrink to one cell, show only the reset label, or hide usage if neither can fit. Brackets keep an empty bar's edges visible and count toward its width, but not its cell cap. With `showUsage: false` no bar is reserved at all, and the usage owner is stopped before any credential lookup, request, or timer is created.
22
22
 
23
23
  Two cells give 6.25% steps; ten give 1.25%. Fill rounds to the nearest eighth-cell step. Only the final partially filled cell uses an intermediate shade:
24
24
 
@@ -41,6 +41,7 @@ The bar and reset label have no intervening space. Reset formatting uses local c
41
41
  - Default to tokens used / context window, with an explicit `k` suffix on both values. Never deduplicate units across the slash.
42
42
  - Always use kilos, including for million-token windows (`1000k`, not `1M`). Below 10k, use two significant digits where one-token resolution permits, capped at three decimal places in kilos: `0.001k`, `0.012k`, `0.11k`, `0.78k`, `0.99k`, `1.0k`, `9.0k`. At and above 10k, round to whole kilos: `10k`, `124k`, `1000k`. Zero is `0k`; rounding can promote `9.999k` to `10k`.
43
43
  - `minFooter.contextAsPercentage` defaults to `false`. Opting in replaces only the numerator with percentage used to one decimal place, e.g. `24.7%/500k`. Keep context distinct from the subscription usage bar.
44
+ - Reload settings at installation boundaries (enable and session start) before deriving footer state, so the first render uses the effective configuration. Ordinary refreshes use the cached configuration and must not reload settings.
44
45
  - Unknown token usage is `?/500k` in either mode; absent context usage is `?`. Never present unknown usage as zero.
45
46
 
46
47
  ## Git contract
@@ -66,7 +67,7 @@ Display only the selected provider's shortest applicable window. Subscription us
66
67
  | Kimi Coding (`kimi-coding`) | Shortest available window; accepts used or remaining counts and week/month durations |
67
68
  | OpenCode Go (`opencode-go`) | Shortest rolling/weekly/monthly window |
68
69
 
69
- Reuse Pi's selected-provider credentials. Copilot uses the GitHub login token from Pi's configured agent directory or `COPILOT_GITHUB_TOKEN`. Pi 1.0.3 does not include Gemini CLI in its built-in model catalog. Do not poll custom proxy endpoints or make model requests to obtain usage.
70
+ Reuse Pi's selected-provider credentials. Copilot uses the saved OAuth GitHub login token when applicable; otherwise it uses the credentials resolved by Pi, which can include `COPILOT_GITHUB_TOKEN`. Ambient environment tokens do not override Pi's resolved credentials. Pi 1.0.3 does not include Gemini CLI in its built-in model catalog. Do not poll custom proxy endpoints or make model requests to obtain usage.
70
71
 
71
72
  ### Refresh and failure behavior
72
73
 
@@ -87,7 +88,7 @@ The comparison with [mtrojnar/pi-usage](https://github.com/mtrojnar/pi-usage) in
87
88
 
88
89
  ## Local development
89
90
 
90
- Requires Node.js >=22.19.0. Local dependencies pin Pi 1.0.3; compatibility CI tests Pi 1.0.3 and 1.1.0 on Node.js 22.19.0. Provider requests are mocked. These are tested versions, not a guarantee for every intervening or future release.
91
+ Requires Node.js >=22.19.0. Local dependencies pin Pi 1.0.3; compatibility CI is configured to test Pi 1.0.3, 1.1.0, and 1.3.0 on Node.js 22.19.0. Provider requests are mocked. These are tested versions, not a guarantee for every intervening or future release.
91
92
 
92
93
  ```bash
93
94
  npm ci
@@ -133,20 +134,47 @@ Emit after this extension's `session_start` handler has run; events before start
133
134
 
134
135
  The latest explicit action wins: `/minfooter on/off` changes the current footer and saves the preference, while this event changes only the current session. Normal refreshes never undo the choice. A new session or extension reload starts from the saved preference.
135
136
 
136
- Disabling restores Pi's default footer only if we still own the active footer; otherwise it leaves the active footer untouched. Enabling explicitly installs our footer and may replace another extension's footer; repeated enables while we own it do nothing. Neither action restores a previous extension's footer. A coordinating extension must choose the active footer—there is no priority stack or automatic reactivation.
137
+ Disabling restores Pi's default footer only if we still own the active footer; otherwise it leaves the active footer untouched. Enabling explicitly installs our footer and may replace another extension's footer. Repeated enable events while we own it do nothing; `/minfooter on` reloads settings and reinstalls the footer. Neither action restores a previous extension's footer. A coordinating extension must choose the active footer—there is no priority stack or automatic reactivation.
138
+
139
+ #### Session-only usage control
140
+
141
+ Control subscription usage independently of footer visibility:
142
+
143
+ ```typescript
144
+ pi.events.emit("pi-minimal-footer:set-usage-enabled", { enabled: false }); // suppress usage
145
+ pi.events.emit("pi-minimal-footer:set-usage-enabled", { enabled: true }); // enable usage
146
+ pi.events.emit("pi-minimal-footer:set-usage-enabled", { enabled: null }); // restore saved showUsage
147
+ ```
148
+
149
+ - A boolean overrides `minFooter.showUsage`; `null` clears the override. No settings writes or notifications.
150
+ - Emit after this extension's `session_start` handler. Events outside an active session, missing `enabled`, and values other than boolean or `null` are ignored. Repeated override values do nothing.
151
+ - Disabling clears cached usage, cancels pending requests, and stops timers. Late results and passive provider updates cannot revive usage.
152
+ - Enabling selects usage only while the footer is enabled, owns a live renderer, and runs in TUI mode. It never installs or replaces a footer.
153
+ - Changes request a redraw without reinstalling the renderer or refreshing Git.
154
+ - The override survives footer toggles and reinstallation, but resets on session start/shutdown and extension reload. Clearing it uses the cached setting; settings reload at the normal installation boundaries.
155
+ - No automatic host detection. A coordinating extension can suppress duplicate quota reporting, for example when a terminal plugin already displays usage.
137
156
 
138
157
  ### Code map
139
158
 
140
- - `extensions/index.ts`: settings, plain state updates, active-footer refresh gate, layout, footer lifecycle, and `/minfooter`.
159
+ - `extensions/index.ts`: Pi events/commands, footer ownership, model/context formatting, theme application, and module wiring.
160
+ - `extensions/lib/footer-settings.ts`: defaults, validation, and settings persistence; preserves unrelated preferences.
161
+ - `extensions/lib/footer-layout.ts`: width allocation and truncation of supplied segments, independent of Pi lifecycle and theme selection.
162
+ - `extensions/lib/git-status.ts`: Git divergence state, stale-result protection, highlight pulses, local polling, and optional fetch/cancellation. The active renderer starts/stops this lifecycle; superseded renderer disposal cannot stop its replacement.
141
163
  - `extensions/lib/usage-limits.ts`: usage refresh, cache, cancellation, and bar/reset rendering.
142
- - `extensions/lib/usage-providers.ts`: authentication, endpoint selection, and response normalization.
143
- - `tests/`: lifecycle/layout regressions, Git highlighting with a temporary repository, and usage parsing tests.
164
+ - `extensions/lib/usage-providers.ts`: authentication, endpoint selection, and named private provider parsers. `parseUsageWindows` gates supported endpoints, dispatches parsing with an explicit snapshot, and centrally distinguishes valid windows, absence, and malformed responses.
165
+ - `tests/min-footer.test.mjs`: settings, session lifecycle, and context-format integration coverage.
166
+ - `tests/layout.test.mjs`: layout, ANSI/Unicode, and usage bar/reset formatting.
167
+ - `tests/git.test.mjs`: fetch jitter, live ownership, stale queries across refresh/restart/directory changes, and Git highlighting with a temporary repository.
168
+ - `tests/usage-lifecycle.test.mjs`: usage authentication, polling, cancellation, passive updates, and provider integration.
169
+ - `tests/helpers/footer-fixture.mjs`: shared real-loader/context helpers and per-process isolated agent/home setup, default settings resets, and teardown.
170
+ - `tests/usage-parsing.test.mjs`: provider parsing.
171
+ - `tests/persistence-order.test.mjs`: real `AgentSession` message persistence and post-persistence footer usage.
144
172
 
145
173
  Settings live under `minFooter` in Pi's configured agent directory. Read them at session start or explicit toggle; ordinary refreshes use cached settings. Preserve unrelated settings on writes. Only install the footer in interactive terminal mode.
146
174
 
147
175
  ### Checking changes
148
176
 
149
- Run `npm run check` and `npm test` for behavior changes. Cover relevant cases:
177
+ Run `npm run check` and `npm test` for behavior changes. Each test file can also run independently, e.g. `node --test tests/git.test.mjs`. Keep the default per-file process isolation: the shared footer fixture sets isolated agent/home environment paths before importing Pi and resets settings and `Math.random` for each test. Provider requests are mocked; numeric context formatting remains real-loader integration coverage. Cover relevant cases:
150
178
 
151
179
  - Layout: narrow widths, ANSI/wide Unicode, field priority, and separator modes.
152
180
  - Git: divergence, synced styling, highlight expiry/restart, and user submissions versus tool turns.