pi-minimal-footer 0.5.0 → 0.5.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 +18 -1
- package/README.md +15 -3
- package/VISION.md +17 -4
- package/extensions/index.ts +31 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.2] - 2026-10-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Publish the same extension as the official scoped mirror `@ryu-cz/pi-minimal-footer`, while retaining `pi-minimal-footer` as the original release path
|
|
15
|
+
- Document both installation names and warn users to install only one
|
|
16
|
+
|
|
17
|
+
## [0.5.1] - 2026-10-07
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Keep the whole Git section in normal text foreground while commits remain to push or pull, returning to dim when synced
|
|
22
|
+
- Bold changed Git divergence arrows/counts for two user submissions; further changes restart the highlight, while tool turns and extension prompts do not consume it
|
|
23
|
+
|
|
10
24
|
## [0.5.0] - 2026-10-07
|
|
11
25
|
|
|
12
26
|
### Added
|
|
@@ -196,7 +210,10 @@ First npm-ready release.
|
|
|
196
210
|
|
|
197
211
|
- Project scaffold — `extensions/index.ts` with basic footer structure, `package.json` with pi extension manifest, `README.md`, `LICENSE` (MIT)
|
|
198
212
|
|
|
199
|
-
[Unreleased]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.
|
|
213
|
+
[Unreleased]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.5.2...HEAD
|
|
214
|
+
[0.5.2]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.5.1...v0.5.2
|
|
215
|
+
[0.5.1]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.5.0...v0.5.1
|
|
216
|
+
[0.5.0]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.4.2...v0.5.0
|
|
200
217
|
[0.4.2]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.4.1...v0.4.2
|
|
201
218
|
[0.4.1]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.4.0...v0.4.1
|
|
202
219
|
[0.4.0]: https://github.com/Ryu-CZ/pi-minimal-footer/compare/v0.3.3...v0.4.0
|
package/README.md
CHANGED
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
<a href="https://pi.dev/packages/pi-minimal-footer"><img src="https://img.shields.io/badge/pi-package-1a1a2e" alt="pi package"></a>
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Pi minimal footer is an opinionated, compact, one-line status bar for [Pi](https://github.com/earendil-works/pi).
|
|
11
11
|
|
|
12
12
|
![Footer preview: ~/git/project main 🧠 Karpathy 🪽 Icarus model · 42/200k · [⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h](media/github-preview.png)
|
|
13
13
|
|
|
14
14
|
**Left**
|
|
15
15
|
|
|
16
16
|
- Working directory: `~/git/project`
|
|
17
|
-
- Git branch
|
|
17
|
+
- Git branch: ` main ↑2 ↓1` (`↑` to push, `↓` to pull)
|
|
18
18
|
|
|
19
19
|
**Right**
|
|
20
20
|
|
|
@@ -27,10 +27,19 @@ An opinionated, compact one-line footer for [Pi](https://github.com/earendil-wor
|
|
|
27
27
|
|
|
28
28
|
Requires Node.js >=22.19.0. Interactive terminal UI only.
|
|
29
29
|
|
|
30
|
+
Choose one npm name (they contain the same extension; do not install both):
|
|
31
|
+
|
|
30
32
|
```bash
|
|
31
33
|
pi install npm:pi-minimal-footer
|
|
34
|
+
# or
|
|
35
|
+
pi install npm:@ryu-cz/pi-minimal-footer
|
|
32
36
|
```
|
|
33
37
|
|
|
38
|
+
`pi-minimal-footer` remains the original, unscoped release path. The scoped
|
|
39
|
+
`@ryu-cz/pi-minimal-footer` package is an official mirror intended to improve
|
|
40
|
+
package indexing; it is not a separate extension. The scoped name is an
|
|
41
|
+
indexing workaround, not a guaranteed fix for pi.dev catalog search.
|
|
42
|
+
|
|
34
43
|
## Commands
|
|
35
44
|
|
|
36
45
|
| Command | Action |
|
|
@@ -60,11 +69,14 @@ Edit `minFooter` in Pi's agent `settings.json` (normally `~/.pi/agent/settings.j
|
|
|
60
69
|
|
|
61
70
|
- `showSkills` shows **extension status text**, not installed skills. The footer does not add the example statuses itself.
|
|
62
71
|
- 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.
|
|
63
|
-
- Git sync counts are omitted for branches without an upstream, detached HEADs, and non-Git directories.
|
|
64
72
|
- `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`.
|
|
65
73
|
|
|
66
74
|
## Reading the footer
|
|
67
75
|
|
|
76
|
+
### Git
|
|
77
|
+
|
|
78
|
+
Counts require a configured upstream. Unsynced branches use the theme's normal foreground; synced branches are dim. Changed counts stay bold until two subsequent user messages; further changes restart the highlight.
|
|
79
|
+
|
|
68
80
|
### Context
|
|
69
81
|
|
|
70
82
|
`42/200k` means tokens used / context window. `?` means Pi has not reported usage yet, including immediately after compaction.
|
package/VISION.md
CHANGED
|
@@ -8,12 +8,11 @@ The [README](README.md) is the user manual. This document records current design
|
|
|
8
8
|
|
|
9
9
|
## Layout contract
|
|
10
10
|
|
|
11
|
-
- Directory and
|
|
11
|
+
- Directory and Git branch form the left group, separated by ``.
|
|
12
12
|
- Each extension status is its own `` tab. Preserve the supplied text; 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
|
-
- Git divergence refreshes on Pi's branch-change signal and normal footer state refreshes; it is best-effort and never allowed to prevent the footer from loading.
|
|
17
16
|
|
|
18
17
|
### Space allocation
|
|
19
18
|
|
|
@@ -37,6 +36,14 @@ Two cells give 6.25% steps; ten give 1.25%. Fill rounds to the nearest eighth-ce
|
|
|
37
36
|
|
|
38
37
|
The bar and reset label have no intervening space. Reset formatting uses local clock time through 24 hours, remaining whole days/hours above 24 hours, and whole days above 10 days. Exactly 24 hours stays clock time; exactly 10 days is `↻10d0h`. Missing reset metadata leaves the bar visible without a label.
|
|
39
38
|
|
|
39
|
+
## Git contract
|
|
40
|
+
|
|
41
|
+
- Pi supplies the branch name. Query `git rev-list --left-right --count HEAD...@{upstream}` for `↑N` local-only and `↓N` upstream-only commits. Use local refs; never fetch automatically.
|
|
42
|
+
- Query outside rendering with a one-second timeout so Git cannot block the TUI. Missing upstreams and command failures omit counts.
|
|
43
|
+
- Refresh on branch-change signals and footer state updates. Ignore older query results to prevent stale counts from restarting highlights.
|
|
44
|
+
- Use the theme's normal text foreground while unsynced, otherwise dim. A count change bolds the arrows/counts until two subsequent user submissions; further changes restart the window. Tool turns and extension prompts do not consume it.
|
|
45
|
+
- Initial loading and working-directory changes establish an unhighlighted baseline. Zero counts hide the arrows entirely.
|
|
46
|
+
|
|
40
47
|
## Subscription usage contract
|
|
41
48
|
|
|
42
49
|
Display only the selected provider's shortest applicable window. Subscription usage and model context usage are separate measurements.
|
|
@@ -96,12 +103,18 @@ For a manual install, copy `extensions/*` into `~/.pi/agent/extensions/`.
|
|
|
96
103
|
- `extensions/index.ts`: settings, state refresh, layout, footer lifecycle, and `/minfooter`.
|
|
97
104
|
- `extensions/lib/usage-limits.ts`: usage refresh, cache, cancellation, and bar/reset rendering.
|
|
98
105
|
- `extensions/lib/usage-providers.ts`: authentication, endpoint selection, and response normalization.
|
|
99
|
-
- `tests/`:
|
|
106
|
+
- `tests/`: lifecycle/layout regressions, Git highlighting with a temporary repository, and usage parsing tests.
|
|
100
107
|
|
|
101
108
|
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.
|
|
102
109
|
|
|
103
110
|
### Checking changes
|
|
104
111
|
|
|
105
|
-
|
|
112
|
+
Run `npm run check` and `npm test` for behavior changes. Cover relevant cases:
|
|
113
|
+
|
|
114
|
+
- Layout: narrow widths, ANSI/wide Unicode, field priority, and separator modes.
|
|
115
|
+
- Git: divergence, synced styling, highlight expiry/restart, and user submissions versus tool turns.
|
|
116
|
+
- Subscription usage: provider switches, timeouts, stale cache, partial updates, and malformed/missing metadata.
|
|
117
|
+
|
|
118
|
+
Preview font-dependent appearance in a real terminal; width checks cannot prove glyph availability.
|
|
106
119
|
|
|
107
120
|
Keep release notes in [CHANGELOG.md](CHANGELOG.md), and keep the README focused on installation and daily use. Preserve [upstream MIT attribution](extensions/lib/LICENSE) when changing adapted provider code.
|
package/extensions/index.ts
CHANGED
|
@@ -116,6 +116,9 @@ interface FooterState {
|
|
|
116
116
|
model: string;
|
|
117
117
|
context: string;
|
|
118
118
|
gitSync: string;
|
|
119
|
+
gitInitialized: boolean;
|
|
120
|
+
gitHighlightInputs: number;
|
|
121
|
+
gitRequest: number;
|
|
119
122
|
}
|
|
120
123
|
|
|
121
124
|
async function getGitSync(cwd: string): Promise<string> {
|
|
@@ -139,12 +142,23 @@ async function getGitSync(cwd: string): Promise<string> {
|
|
|
139
142
|
|
|
140
143
|
async function updateGitSync(state: FooterState): Promise<void> {
|
|
141
144
|
const cwd = state.cwd;
|
|
145
|
+
const request = ++state.gitRequest;
|
|
142
146
|
const gitSync = await getGitSync(cwd);
|
|
143
|
-
|
|
147
|
+
// Refresh events can overlap; an older result must not restart the highlight.
|
|
148
|
+
if (state.cwd !== cwd || request !== state.gitRequest) return;
|
|
149
|
+
if (state.gitInitialized && state.gitSync !== gitSync) state.gitHighlightInputs = 2;
|
|
150
|
+
state.gitSync = gitSync;
|
|
151
|
+
state.gitInitialized = true;
|
|
144
152
|
}
|
|
145
153
|
|
|
146
154
|
function updateState(ctx: ExtensionContext, state: FooterState): void {
|
|
147
|
-
|
|
155
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
156
|
+
if (state.cwd !== cwd) {
|
|
157
|
+
state.gitSync = "";
|
|
158
|
+
state.gitInitialized = false;
|
|
159
|
+
state.gitHighlightInputs = 0;
|
|
160
|
+
}
|
|
161
|
+
state.cwd = cwd;
|
|
148
162
|
state.model = ctx.model?.id ?? "no-model";
|
|
149
163
|
const usage = ctx.getContextUsage();
|
|
150
164
|
if (usage) {
|
|
@@ -233,7 +247,10 @@ function buildLine(
|
|
|
233
247
|
export default function (pi: ExtensionAPI) {
|
|
234
248
|
let config = readConfig();
|
|
235
249
|
let enabled = config.enabled !== false;
|
|
236
|
-
const state: FooterState = {
|
|
250
|
+
const state: FooterState = {
|
|
251
|
+
cwd: process.cwd(), model: "no-model", context: "?", gitSync: "",
|
|
252
|
+
gitInitialized: false, gitHighlightInputs: 0, gitRequest: 0,
|
|
253
|
+
};
|
|
237
254
|
let requestRender: (() => void) | null = null;
|
|
238
255
|
let disposeFooter: (() => void) | null = null;
|
|
239
256
|
const usageLimits = new UsageLimits(() => requestRender?.());
|
|
@@ -284,13 +301,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
284
301
|
? [...footerData.getExtensionStatuses().values()].filter((s) => s.trim())
|
|
285
302
|
: [];
|
|
286
303
|
const branch = config.showGitBranch ? footerData.getGitBranch() : null;
|
|
287
|
-
const
|
|
304
|
+
const syncText = state.gitHighlightInputs > 0 ? theme.bold(state.gitSync) : state.gitSync;
|
|
305
|
+
const branchText = branch ? `${branch}${syncText}` : "";
|
|
288
306
|
const statusSeparator = config.powerlineSeparator ? theme.fg("dim", " ") : " ";
|
|
289
307
|
const line = buildLine(
|
|
290
308
|
width,
|
|
291
309
|
config.showPath ? theme.fg("dim", abbreviateHome(state.cwd, homedir())) : "",
|
|
292
310
|
statuses.length ? statusSeparator + statuses.map((status) => theme.fg("dim", status)).join(statusSeparator) : "",
|
|
293
|
-
|
|
311
|
+
// Keep unsynced branches readable; bold counts separately mark recent changes.
|
|
312
|
+
branchText ? theme.fg(state.gitSync ? "text" : "dim", ` ${branchText}`) : "",
|
|
294
313
|
config.showModel ? theme.bold(state.model) : "",
|
|
295
314
|
config.showContext ? theme.fg("dim", theme.bold(state.context)) : "",
|
|
296
315
|
(available, maxCells = BASE_BAR_CELLS) => usageLimits.line(available, theme, maxCells),
|
|
@@ -322,6 +341,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
322
341
|
install(ctx);
|
|
323
342
|
});
|
|
324
343
|
|
|
344
|
+
// Count user submissions, not turn_end: one prompt can trigger many tool turns.
|
|
345
|
+
// Extension-generated prompts do not consume the user's highlight window.
|
|
346
|
+
pi.on("input", (event, ctx) => {
|
|
347
|
+
if (event.source !== "extension" && state.gitHighlightInputs > 0) state.gitHighlightInputs--;
|
|
348
|
+
refresh(ctx);
|
|
349
|
+
});
|
|
350
|
+
|
|
325
351
|
pi.on("model_select", async (_event, ctx) => {
|
|
326
352
|
selectUsage(ctx);
|
|
327
353
|
refresh(ctx);
|
package/package.json
CHANGED