pi-minimal-footer 0.4.0 → 0.4.2
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 +23 -1
- package/README.md +30 -9
- package/VISION.md +3 -3
- package/extensions/index.ts +2 -1
- package/extensions/lib/usage-limits.ts +6 -2
- package/extensions/lib/usage-providers.ts +3 -0
- package/media/pi-preview.png +0 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.2] - 2026-10-07
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Point pi.dev package preview metadata to a dedicated 16:9 PNG (1280×720), preserving the footer image without stretching or cropping
|
|
15
|
+
|
|
16
|
+
## [0.4.1] - 2026-10-07
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Restructure README with separate left/right feature lists, clearer context and subscription usage guidance, explicit adapter verification limits, and source installation under development
|
|
21
|
+
- Refresh the vision contract for the two-cell baseline, bracketed bars, and nine-second timeout
|
|
22
|
+
- Explain cache retention, refresh jitter, exact-model quota selection, and readability thresholds with rationale comments; update the source footer example to show brackets
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- Restore reset-label-only usage on terminals too narrow for a bracketed cell, with regression coverage for reset-only, hidden-usage, and one-cell width boundaries
|
|
27
|
+
- Align usage detection and regression expectations with bracketed bars, the two-cell baseline, bracket-aware width allocation, and ten-cell rounding for small percentages
|
|
28
|
+
|
|
10
29
|
## [0.4.0] - 2026-10-07
|
|
11
30
|
|
|
12
31
|
### Added
|
|
@@ -167,7 +186,10 @@ First npm-ready release.
|
|
|
167
186
|
|
|
168
187
|
- Project scaffold — `extensions/index.ts` with basic footer structure, `package.json` with pi extension manifest, `README.md`, `LICENSE` (MIT)
|
|
169
188
|
|
|
170
|
-
[Unreleased]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.
|
|
189
|
+
[Unreleased]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.4.2...HEAD
|
|
190
|
+
[0.4.2]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.4.1...v0.4.2
|
|
191
|
+
[0.4.1]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.4.0...v0.4.1
|
|
192
|
+
[0.4.0]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.3...v0.4.0
|
|
171
193
|
[0.3.3]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.2...v0.3.3
|
|
172
194
|
[0.3.2]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.1...v0.3.2
|
|
173
195
|
[0.3.1]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.0...v0.3.1
|
package/README.md
CHANGED
|
@@ -9,18 +9,26 @@
|
|
|
9
9
|
|
|
10
10
|
An opinionated, compact one-line footer for [Pi](https://github.com/earendil-works/pi).
|
|
11
11
|
|
|
12
|
-
Path and branch on the left; extension statuses, model, context, and subscription usage bar on the right. Shrinks to fit narrow terminals, with one space of padding at each edge. Interactive terminal UI only.
|
|
13
|
-
|
|
14
12
|
![Footer preview: ~/git/project main 🧠 Karpathy 🪽 Icarus model · 42/200k · [⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h](media/github-preview.png)
|
|
15
13
|
|
|
14
|
+
**Left**
|
|
15
|
+
|
|
16
|
+
- Working directory: `~/git/project`
|
|
17
|
+
- Git branch: ` main`
|
|
18
|
+
|
|
19
|
+
**Right**
|
|
20
|
+
|
|
21
|
+
- Extension statuses: ` 🧠 Karpathy 🪽 Icarus`
|
|
22
|
+
- Model: `model`
|
|
23
|
+
- Context usage: `42/200k`
|
|
24
|
+
- Subscription usage bar with reset time: `[⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h`
|
|
25
|
+
|
|
16
26
|
## Install
|
|
17
27
|
|
|
18
|
-
Requires Node.js >=22.19.0.
|
|
28
|
+
Requires Node.js >=22.19.0. Interactive terminal UI only.
|
|
19
29
|
|
|
20
30
|
```bash
|
|
21
31
|
pi install npm:pi-minimal-footer
|
|
22
|
-
# Or install from source:
|
|
23
|
-
pi install git:github.com/Ryu-CZ/pi-minimal-footer
|
|
24
32
|
```
|
|
25
33
|
|
|
26
34
|
## Commands
|
|
@@ -53,20 +61,33 @@ Edit `minFooter` in Pi's agent `settings.json` (normally `~/.pi/agent/settings.j
|
|
|
53
61
|
- `showSkills` shows **extension status text**, not installed skills. The footer does not add the example statuses itself.
|
|
54
62
|
- Set `powerlineSeparator` to `false` for plain spaces instead of `` / `` if your font lacks those glyphs. The git icon `` also needs a compatible font; hide it with `showGitBranch: false` if needed.
|
|
55
63
|
- `maxUsageBarCells` caps the Braille bar length (excluding brackets and reset time). Use a positive integer, e.g. `4` for a compact bar; invalid values fall back to `10`.
|
|
56
|
-
- Context `42/200k` means tokens used / context window. `?` means Pi has not reported usage yet, including immediately after compaction.
|
|
57
64
|
|
|
58
|
-
## Reading
|
|
65
|
+
## Reading the footer
|
|
66
|
+
|
|
67
|
+
### Context
|
|
68
|
+
|
|
69
|
+
`42/200k` means tokens used / context window. `?` means Pi has not reported usage yet, including immediately after compaction.
|
|
70
|
+
|
|
71
|
+
### Subscription usage
|
|
59
72
|
|
|
60
73
|
`[⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h` shows **subscription allowance used**, not context usage.
|
|
61
74
|
|
|
62
|
-
- Bar
|
|
75
|
+
- **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.
|
|
76
|
+
- **Colors:** green below 85%, amber from 85%, red from 92%.
|
|
77
|
+
- **Cached data:** dim after a refresh failure.
|
|
63
78
|
- 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.
|
|
64
79
|
- 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.
|
|
65
80
|
|
|
66
|
-
|
|
81
|
+
Implemented adapters: **OpenAI Codex, Claude OAuth, GitHub Copilot, Gemini CLI, MiniMax, Kimi Coding, and OpenCode Go**. Uses Pi's existing credentials; ordinary Claude API keys do not expose subscription usage. Authenticated endpoints remain unverified live; see [verification limits](VISION.md).
|
|
67
82
|
|
|
68
83
|
## Development & design
|
|
69
84
|
|
|
85
|
+
Install from source:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pi install git:github.com/Ryu-CZ/pi-minimal-footer
|
|
89
|
+
```
|
|
90
|
+
|
|
70
91
|
See [VISION.md](VISION.md) for design constraints, local development, provider details, and verification limits. Release history: [CHANGELOG.md](CHANGELOG.md).
|
|
71
92
|
|
|
72
93
|
## Credits
|
package/VISION.md
CHANGED
|
@@ -18,9 +18,9 @@ The [README](README.md) is the user manual. This document records current design
|
|
|
18
18
|
|
|
19
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.
|
|
20
20
|
|
|
21
|
-
Lay out other fields with a
|
|
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.
|
|
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
|
|
|
25
25
|
| Cell | Fill |
|
|
26
26
|
|---|---|
|
|
@@ -57,7 +57,7 @@ Reuse Pi's selected-provider credentials. Copilot uses the GitHub login token fr
|
|
|
57
57
|
- Consume passive Codex response headers/stream events and Claude quota headers when available.
|
|
58
58
|
- Otherwise fetch on startup/provider switch, then roughly every four minutes without a fresh response update. Sample independent uniform ±⅛ jitter (3.5–4.5 minutes) for each attempt or fresh displayed-window update to spread fallback requests across sessions. Keep that deadline across unrelated window updates; a reported reset time still triggers an earlier refresh.
|
|
59
59
|
- Merge partial windows. A weekly-only signal must not replace a cached shorter window or postpone its refresh.
|
|
60
|
-
- Bound authentication, fetch, and response-body parsing by a shared
|
|
60
|
+
- Bound authentication, fetch, and response-body parsing by a shared nine-second timeout. Release stalled work so polling can recover.
|
|
61
61
|
- Provider switches clear usage immediately, cancel pending work, and invalidate late results. Gemini model switches also refresh model-specific usage.
|
|
62
62
|
- Missing credentials and explicit empty/unlimited responses clear usage. Temporary authentication, network, or parsing failures retain only the current provider's cached usage, dimmed; without cache, hide it.
|
|
63
63
|
- Invalid optional reset metadata must not discard otherwise valid usage. Zero usage is an empty bar, not an absent usage bar.
|
package/extensions/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Minimal footer — replaces pi's default footer with a clean status line:
|
|
3
3
|
*
|
|
4
|
-
* ~/path/to/dir main status1 status2 sonnet · 12/128k ·
|
|
4
|
+
* ~/path/to/dir main status1 status2 sonnet · 12/128k · [⣿⣶⠀⠀⠀]↻16:40
|
|
5
5
|
*
|
|
6
6
|
* Settings are persisted in the agent directory (usually ~/.pi/agent)
|
|
7
7
|
* settings.json under "minFooter".
|
|
@@ -141,6 +141,7 @@ function updateState(ctx: ExtensionContext, state: FooterState): void {
|
|
|
141
141
|
const MODEL_GAP = " · ";
|
|
142
142
|
const USAGE_GAP = " · ";
|
|
143
143
|
const LOCATION_GAP_WIDTH = 3;
|
|
144
|
+
// Below these budgets, ellipses dominate text and status tabs stop being useful at a glance.
|
|
144
145
|
const MIN_TEXT_WIDTH = 4;
|
|
145
146
|
const MIN_STATUS_WIDTH = 12;
|
|
146
147
|
|
|
@@ -186,6 +186,7 @@ export class UsageLimits {
|
|
|
186
186
|
this.render();
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
// Independent deadlines spread fallback requests across sessions sharing a subscription.
|
|
189
190
|
private randomizeRefresh(): void {
|
|
190
191
|
this.refreshDelay = REFRESH_MS + (Math.random() * 2 - 1) * REFRESH_JITTER_MS;
|
|
191
192
|
}
|
|
@@ -246,8 +247,11 @@ export class UsageLimits {
|
|
|
246
247
|
if (!this.ctx || !window) return null;
|
|
247
248
|
const now = Date.now();
|
|
248
249
|
const resetLabel = formatResetLabel(window.resetAt, now);
|
|
249
|
-
//
|
|
250
|
-
if (width <
|
|
250
|
+
// Keep the reset useful when the terminal cannot fit even one bracketed cell.
|
|
251
|
+
if (width < resetLabel.length + 3) {
|
|
252
|
+
return resetLabel && width >= resetLabel.length ? theme.fg("dim", resetLabel) : null;
|
|
253
|
+
}
|
|
254
|
+
// Brackets keep the edges of a zero-usage bar visible.
|
|
251
255
|
const cells = Math.min(maxCells, Math.max(1, width - resetLabel.length - 2));
|
|
252
256
|
const steps = Math.round(window.used / 100 * cells * CELL_STEPS);
|
|
253
257
|
const filled = "⣿".repeat(Math.floor(steps / CELL_STEPS)) + PARTIAL_CELL_FILLS[steps % CELL_STEPS];
|
|
@@ -136,6 +136,8 @@ export function parseUsageWindows(provider: string, model: string, payload: unkn
|
|
|
136
136
|
if (window) windows[key] = window;
|
|
137
137
|
else malformed = true;
|
|
138
138
|
};
|
|
139
|
+
// Valid siblings remain useful; explicit absence clears cache, while malformed
|
|
140
|
+
// snapshots throw so a temporary provider failure retains dimmed cached usage.
|
|
139
141
|
const finish = () => {
|
|
140
142
|
if (Object.keys(windows).length) return windows;
|
|
141
143
|
if (recognized && !malformed) return null;
|
|
@@ -247,6 +249,7 @@ export function parseUsageWindows(provider: string, model: string, payload: unkn
|
|
|
247
249
|
if (!ok) malformed = true;
|
|
248
250
|
return ok;
|
|
249
251
|
});
|
|
252
|
+
// A malformed exact match must not substitute another model family's quota.
|
|
250
253
|
const hasExact = buckets.some((b) => b.modelId === model);
|
|
251
254
|
const family = model.toLowerCase().includes("flash") ? "flash" : model.toLowerCase().includes("pro") ? "pro" : null;
|
|
252
255
|
const selected = valid.filter((b) => hasExact ? b.modelId === model : family && String(b.modelId).toLowerCase().includes(family));
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-minimal-footer",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "An opinionated minimal footer extension for Pi — clean status line with path, extension statuses, model, and context usage.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -49,6 +49,6 @@
|
|
|
49
49
|
"extensions": [
|
|
50
50
|
"./extensions"
|
|
51
51
|
],
|
|
52
|
-
"image": "https://raw.githubusercontent.com/Ryu-CZ/pi-minimal-footer/main/media/preview.png"
|
|
52
|
+
"image": "https://raw.githubusercontent.com/Ryu-CZ/pi-minimal-footer/main/media/pi-preview.png"
|
|
53
53
|
}
|
|
54
54
|
}
|