pi-minimal-footer 0.3.3 → 0.4.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,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.0] - 2026-10-07
11
+
12
+ ### Added
13
+
14
+ - `minFooter.maxUsageBarCells` (default `10`) to cap the subscription usage bar length; use a positive integer such as `4` for a compact bar, excluding brackets and reset time
15
+
16
+ ### Changed
17
+
18
+ - Reduce the compact subscription usage bar baseline from five to two cells before expanding into spare space up to the configured cap
19
+ - Add one space at each footer edge, reserving those columns when fitting narrow terminals
20
+ - Refresh README and package-gallery PNG previews with the current footer, edge padding, and live OpenAI Codex subscription usage
21
+
10
22
  ## [0.3.3] - 2026-10-07
11
23
 
12
24
  ### Changed
package/README.md CHANGED
@@ -9,9 +9,9 @@
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. Interactive terminal UI only.
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
13
 
14
- ![Footer preview: ~/git/project   main  🧠 Karpathy  🪽 Icarus  model · 42/200k · ⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀↻1d8h](media/github-preview.png)
14
+ ![Footer preview: ~/git/project   main  🧠 Karpathy  🪽 Icarus  model · 42/200k · [⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h](media/github-preview.png)
15
15
 
16
16
  ## Install
17
17
 
@@ -44,20 +44,22 @@ Edit `minFooter` in Pi's agent `settings.json` (normally `~/.pi/agent/settings.j
44
44
  "showPath": true,
45
45
  "showModel": true,
46
46
  "showContext": true,
47
- "powerlineSeparator": true
47
+ "powerlineSeparator": true,
48
+ "maxUsageBarCells": 10
48
49
  }
49
50
  }
50
51
  ```
51
52
 
52
53
  - `showSkills` shows **extension status text**, not installed skills. The footer does not add the example statuses itself.
53
54
  - 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
+ - `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`.
54
56
  - Context `42/200k` means tokens used / context window. `?` means Pi has not reported usage yet, including immediately after compaction.
55
57
 
56
58
  ## Reading subscription usage
57
59
 
58
- `⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀↻1d8h` shows **subscription allowance used**, not context usage.
60
+ `[⣿⣿⣿⣤⠀⠀⠀⠀⠀⠀]↻1d8h` shows **subscription allowance used**, not context usage.
59
61
 
60
- - Bar: shown as `[cells]` with 5–10 cells, expanding into spare space; green below 85%, amber from 85%, red from 92%. The brackets keep the bar’s beginning and end visible even when it is empty. Dim means cached after a refresh failure. Very narrow terminals may show fewer cells or only the reset label.
62
+ - Bar: shown as `[cells]` with 2–10 cells by default, expanding into spare space up to `maxUsageBarCells` (or fewer when the cap is below 2); green below 85%, amber from 85%, red from 92%. The brackets keep the bar’s beginning and end visible even when it is empty. Dim means cached after a refresh failure. Very narrow terminals may show fewer cells or only the reset label.
61
63
  - 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.
62
64
  - 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.
63
65
 
@@ -30,6 +30,7 @@ interface Settings {
30
30
  showModel?: boolean;
31
31
  showContext?: boolean;
32
32
  powerlineSeparator?: boolean;
33
+ maxUsageBarCells?: number;
33
34
  };
34
35
  }
35
36
 
@@ -43,6 +44,7 @@ const DEFAULT_SETTINGS: FooterSettings = {
43
44
  showModel: true,
44
45
  showContext: true,
45
46
  powerlineSeparator: true,
47
+ maxUsageBarCells: MAX_BAR_CELLS,
46
48
  };
47
49
 
48
50
  function settingsPath(): string {
@@ -74,7 +76,11 @@ function writeSettings(patch: Partial<Settings>): void {
74
76
 
75
77
  function readConfig(): FooterSettings {
76
78
  const s = readSettings();
77
- return { ...DEFAULT_SETTINGS, ...s.minFooter };
79
+ const config = { ...DEFAULT_SETTINGS, ...s.minFooter };
80
+ if (typeof config.maxUsageBarCells !== "number" || !Number.isSafeInteger(config.maxUsageBarCells) || config.maxUsageBarCells < 1) {
81
+ config.maxUsageBarCells = MAX_BAR_CELLS;
82
+ }
83
+ return config;
78
84
  }
79
85
 
80
86
  function writeEnabled(v: boolean): void {
@@ -141,12 +147,14 @@ const MIN_STATUS_WIDTH = 12;
141
147
  function buildLine(
142
148
  width: number, path: string, statuses: string, branch: string, model: string, context: string,
143
149
  usage: (available: number, maxCells?: number) => string | null,
144
- statusSeparator: string, locationSeparator: string,
150
+ statusSeparator: string, locationSeparator: string, maxUsageBarCells: number,
145
151
  ): string {
146
152
  if (width <= 0) return "";
153
+ if (width <= 2) return " ".repeat(width);
154
+ width -= 2;
147
155
  let core = [model, context].filter(Boolean).join(MODEL_GAP);
148
156
  // Budget the compact bar first; its expanded size must not drive truncation decisions.
149
- const usageBar = usage(width) ?? "";
157
+ const usageBar = usage(width, Math.min(BASE_BAR_CELLS, maxUsageBarCells)) ?? "";
150
158
  const usageGapWidth = usageBar && core ? USAGE_GAP.length : 0;
151
159
  const coreBudget = Math.max(0, width - visibleWidth(usageBar) - usageGapWidth);
152
160
  if (usageBar && coreBudget < MIN_TEXT_WIDTH) {
@@ -182,11 +190,11 @@ function buildLine(
182
190
  // A dropped left group needs no divider; those columns belong to the usage bar instead.
183
191
  const interGroupGapWidth = left && right ? LOCATION_GAP_WIDTH : 0;
184
192
  const spareWidth = Math.max(0, width - visibleWidth(left) - visibleWidth(right) - interGroupGapWidth);
185
- const expandedUsageBar = usage(visibleWidth(usageBar) + spareWidth, MAX_BAR_CELLS) ?? usageBar;
193
+ const expandedUsageBar = usage(visibleWidth(usageBar) + spareWidth, maxUsageBarCells) ?? usageBar;
186
194
  const expandedCore = [core, expandedUsageBar].filter(Boolean).join(USAGE_GAP);
187
195
  right = [fittedStatuses, expandedCore].filter(Boolean).join(statusSeparator);
188
196
  }
189
- return left + " ".repeat(Math.max(0, width - visibleWidth(left) - visibleWidth(right))) + right;
197
+ return " " + left + " ".repeat(Math.max(0, width - visibleWidth(left) - visibleWidth(right))) + right + " ";
190
198
  }
191
199
 
192
200
  // ── Extension ─────────────────────────────────────────────────────────
@@ -251,6 +259,7 @@ export default function (pi: ExtensionAPI) {
251
259
  (available, maxCells = BASE_BAR_CELLS) => usageLimits.line(available, theme, maxCells),
252
260
  statusSeparator,
253
261
  config.powerlineSeparator ? theme.fg("dim", "  ") : " ",
262
+ config.maxUsageBarCells ?? MAX_BAR_CELLS,
254
263
  );
255
264
  return [line];
256
265
  },
@@ -14,7 +14,7 @@ const CELL_STEPS = 8;
14
14
  const PARTIAL_CELL_FILLS = ["", "⡀", "⣀", "⣄", "⣤", "⣦", "⣶", "⣷"];
15
15
 
16
16
  // Start compact so extra precision never steals space from the other footer fields.
17
- export const BASE_BAR_CELLS = 5;
17
+ export const BASE_BAR_CELLS = 2;
18
18
  export const MAX_BAR_CELLS = 10;
19
19
 
20
20
  function formatResetLabel(resetAt: number | null, now: number): string {
Binary file
package/media/preview.png CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-minimal-footer",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
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",