@hank-warren/pi-statusline 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
@@ -1,5 +1,22 @@
1
1
  # @hank-warren/pi-statusline
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add an optional **Thinking level** segment between the model and the provider.
8
+
9
+ `/statusline` gains a **Thinking level** toggle, off by default. When on, the
10
+ active model's thinking level renders after the model id
11
+ (`gpt-5.6-luna | medium | openai-codex | …`) in a new `thinking` palette role
12
+ present in every theme.
13
+ `off` on a reasoning model is spelled `thinking off`, as Pi's own footer does; a
14
+ model that cannot reason drops the segment entirely, leaving no stray separator.
15
+
16
+ The footer repaints the moment the level changes — the cycle keybinding
17
+ (Shift+Tab by default), `/model`, or an extension calling `pi.setThinkingLevel()`
18
+ — without waiting for a turn.
19
+
3
20
  ## 0.8.0
4
21
 
5
22
  ### Minor Changes
package/README.md CHANGED
@@ -10,7 +10,7 @@ gpt-5.6-sol | pi-extensions:main* ⇣1 | 40k/1.0m |  97·54  80
10
10
 
11
11
  ## What it shows
12
12
 
13
- - **Line 1** — active model ID, optionally the provider of that model, current directory basename and Git branch, current context usage/window, subscription usage headroom (see below), and any [custom items](#custom-items) you configure. A yellow `*` marks a dirty checkout and `⇣N` shows how many commits it is behind its locally known upstream ref. Unknown context usage is rendered as `?/<window>` until Pi can provide an estimate. Exceptional prompt-cache hits trigger the celebration described below.
13
+ - **Line 1** — active model ID, optionally its thinking level and provider, current directory basename and Git branch, current context usage/window, subscription usage headroom (see below), and any [custom items](#custom-items) you configure. A yellow `*` marks a dirty checkout and `⇣N` shows how many commits it is behind its locally known upstream ref. Unknown context usage is rendered as `?/<window>` until Pi can provide an estimate. Exceptional prompt-cache hits trigger the celebration described below.
14
14
  - **Worktree lines** — when the session works in or sends tool calls into linked worktrees, one line shows the same branch/dirty/behind state for each worktree plus its associated PR number.
15
15
  - **Final line** — the full Pi session ID.
16
16
 
@@ -23,7 +23,7 @@ Colors come from a selectable [theme](#themes), with context warning thresholds.
23
23
  - **Theme** — the color palette, cycled with Enter or Space. See [Themes](#themes).
24
24
  - **Cache celebration** — `off` or one of five badge animations, cycled with Enter or Space and previewed live in the statusline below. See [Animation styles](#animation-styles).
25
25
  - **Custom item list** — below the alias row: enables or disables each configured item, shows what it is currently doing, and **Add custom item…** hands the job to the agent. A **Custom items** `on`/`off` row for the whole segment appears once at least one item is configured. See [Custom items](#custom-items).
26
- - **Model**, **Provider**, **Directory & git**, **Context**, **Subscription usage**, **Worktree line**, **Session ID line** — `on`/`off`, cycled with Enter or Space. **Provider** is the only one that starts `off`; it shows the provider id exactly as Pi reports it, so a [pi-multi-login](../pi-multi-login) alias renders as `anthropic-team` and names the login actually spending — something a model id like `claude-opus-5` never carries. With no model, or a model reporting no provider, the segment is simply absent. Disabled segments are dropped from line 1 without leaving a stray ` | ` separator; hiding the worktree line also stops its `git`/`gh` polling, and hiding usage stops the usage poller. With every element off the footer collapses to a single blank row.
26
+ - **Model**, **Thinking level**, **Provider**, **Directory & git**, **Context**, **Subscription usage**, **Worktree line**, **Session ID line** — `on`/`off`, cycled with Enter or Space. **Thinking level** starts `off`; it renders the active level (`high`, `medium`, …, or `thinking off` — spelled out, as Pi's own footer does) between the model and the provider, repaints the moment the level changes (the cycle keybinding, Shift+Tab by default, `/model`, or an extension calling `pi.setThinkingLevel()`), and is absent for a model that cannot reason. **Provider** also starts `off`; it shows the provider id exactly as Pi reports it, so a [pi-multi-login](../pi-multi-login) alias renders as `anthropic-team` and names the login actually spending — something a model id like `claude-opus-5` never carries. With no model, or a model reporting no provider, the segment is simply absent. Disabled segments are dropped from line 1 without leaving a stray ` | ` separator; hiding the worktree line also stops its `git`/`gh` polling, and hiding usage stops the usage poller. With every element off the footer collapses to a single blank row.
27
27
  - **Worktree root** — the directory whose immediate children are tracked as session worktrees (default `~/repos/worktrees`). `~` and `$HOME` are expanded; a relative path is rejected and the previous value kept.
28
28
  - **Repo aliases** — short display names for repositories on the worktree line. Enter edits the selected `repo → alias` pair, `d` deletes it, and `Add alias…` creates one from a `repo=alias` line.
29
29
 
package/index.ts CHANGED
@@ -44,6 +44,8 @@ import {
44
44
 
45
45
  export interface StatuslineData {
46
46
  model: string;
47
+ /** Thinking level of the active model; absent when the model cannot reason. */
48
+ thinkingLevel?: string;
47
49
  /** Provider id of the active model; absent when there is no model. */
48
50
  provider?: string;
49
51
  cwd: string;
@@ -189,6 +191,12 @@ export function renderStatusline(
189
191
  const customSegments = settings.showCustomItems ? (data.customValues ?? []).filter((value) => value.length > 0) : [];
190
192
  const segments = [
191
193
  settings.showModel ? styled(palette.model, data.model) : undefined,
194
+ // A non-reasoning model has no level to show, so the segment goes with it.
195
+ // "off" on a reasoning model is a real state and reads as pi's own footer
196
+ // spells it, because a bare "off" between two ids means nothing.
197
+ settings.showThinking && data.thinkingLevel
198
+ ? styled(palette.thinking, data.thinkingLevel === "off" ? "thinking off" : data.thinkingLevel)
199
+ : undefined,
192
200
  // No provider is a missing segment, not a placeholder: the model id already
193
201
  // says "no-model" in that state, and a second one would only add noise.
194
202
  settings.showProvider && data.provider ? styled(palette.provider, data.provider) : undefined,
@@ -517,6 +525,9 @@ export default function statuslineExtension(pi: ExtensionAPI): void {
517
525
  const usage = ctx.getContextUsage();
518
526
  const cwd = basename(ctx.cwd) || ctx.cwd;
519
527
  const model = ctx.model?.id.split("/").pop() || "no-model";
528
+ // ctx.thinkingLevel is a live getter on the session; the pi accessor is
529
+ // the same value for hosts whose context does not expose it.
530
+ const thinkingLevel = ctx.model?.reasoning ? (ctx.thinkingLevel ?? pi.getThinkingLevel()) : undefined;
520
531
  // Commands size themselves with COLUMNS, so the tracker needs the
521
532
  // width the footer is actually being drawn at.
522
533
  customItems.setContext({ columns: width });
@@ -525,6 +536,7 @@ export default function statuslineExtension(pi: ExtensionAPI): void {
525
536
  renderStatusline(
526
537
  {
527
538
  model,
539
+ thinkingLevel,
528
540
  provider: ctx.model?.provider,
529
541
  cwd,
530
542
  cwdGit,
@@ -575,6 +587,9 @@ export default function statuslineExtension(pi: ExtensionAPI): void {
575
587
  }
576
588
  requestRender?.();
577
589
  });
590
+ // The cycle keybinding (Shift+Tab by default) changes the level without a
591
+ // turn or a model change, so nothing else would repaint the segment.
592
+ pi.on("thinking_level_select", () => requestRender?.());
578
593
  pi.on("session_tree", (_event, ctx) => resetTracker(ctx));
579
594
  pi.on("session_shutdown", () => {
580
595
  cacheCelebration.dispose();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hank-warren/pi-statusline",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Compact Pi footer statusline with Git/worktree context, token usage, and neon celebrations for exceptional prompt-cache hits.",
5
5
  "type": "module",
6
6
  "keywords": [
package/settings-menu.ts CHANGED
@@ -35,6 +35,7 @@ interface BooleanRow {
35
35
  /** Toggle rows, in statusline render order. */
36
36
  export const BOOLEAN_ROWS: readonly BooleanRow[] = [
37
37
  { id: "showModel", label: "Model", description: "Show the active model id." },
38
+ { id: "showThinking", label: "Thinking level", description: "Show the thinking level of the active model." },
38
39
  { id: "showProvider", label: "Provider", description: "Show the provider of the active model." },
39
40
  { id: "showDirectory", label: "Directory & git", description: "Show the working directory and its git branch." },
40
41
  { id: "showContext", label: "Context", description: "Show context tokens used against the window." },
package/settings.ts CHANGED
@@ -19,6 +19,7 @@ import { DEFAULT_THEME, isThemeName, type StatuslineThemeName } from "./themes.t
19
19
  /** Toggle keys, in the order the `/statusline` menu lists them. */
20
20
  export const BOOLEAN_SETTING_KEYS = [
21
21
  "showModel",
22
+ "showThinking",
22
23
  "showProvider",
23
24
  "showDirectory",
24
25
  "showContext",
@@ -51,6 +52,9 @@ function defaultWorktreeRoot(home: string = homedir()): string {
51
52
  export function defaultSettings(home: string = homedir()): StatuslineSettings {
52
53
  return {
53
54
  showModel: true,
55
+ // Opt-in: an extra segment on every existing footer would be a surprise,
56
+ // and most sessions keep one thinking level for their whole life.
57
+ showThinking: false,
54
58
  // Opt-in: the provider is redundant for anyone with a single login per family.
55
59
  showProvider: false,
56
60
  showDirectory: true,
package/themes.ts CHANGED
@@ -5,6 +5,8 @@
5
5
  export interface StatuslinePalette {
6
6
  /** Active model id. */
7
7
  model: string;
8
+ /** Thinking level of the active model. */
9
+ thinking: string;
8
10
  /** Provider id of the active model. */
9
11
  provider: string;
10
12
  /** Repository and directory names. */
@@ -37,6 +39,7 @@ const rgb = (hex: string): string => {
37
39
  /** The palette this package shipped before themes existed. */
38
40
  const DEFAULT: StatuslinePalette = {
39
41
  model: rgb("#0099ff"),
42
+ thinking: rgb("#5fb0ff"),
40
43
  provider: rgb("#7aa2c8"),
41
44
  path: rgb("#dcdcdc"),
42
45
  branch: rgb("#56b6c2"),
@@ -53,6 +56,7 @@ const DEFAULT: StatuslinePalette = {
53
56
  /** Dracula, with the pink branch colour from Hank's Herdr sidebar config. */
54
57
  const DRACULA: StatuslinePalette = {
55
58
  model: rgb("#bd93f9"),
59
+ thinking: rgb("#a98ae0"),
56
60
  provider: rgb("#9580c9"),
57
61
  path: rgb("#f8f8f2"),
58
62
  branch: rgb("#ff79c6"),
@@ -68,6 +72,7 @@ const DRACULA: StatuslinePalette = {
68
72
 
69
73
  const GITHUB_DARK: StatuslinePalette = {
70
74
  model: rgb("#58a6ff"),
75
+ thinking: rgb("#6399db"),
71
76
  provider: rgb("#6e8bb5"),
72
77
  path: rgb("#c9d1d9"),
73
78
  branch: rgb("#39c5cf"),
@@ -83,6 +88,7 @@ const GITHUB_DARK: StatuslinePalette = {
83
88
 
84
89
  const CATPPUCCIN_MOCHA: StatuslinePalette = {
85
90
  model: rgb("#cba6f7"),
91
+ thinking: rgb("#b89adf"),
86
92
  provider: rgb("#a58fc4"),
87
93
  path: rgb("#cdd6f4"),
88
94
  branch: rgb("#89dceb"),
@@ -99,6 +105,7 @@ const CATPPUCCIN_MOCHA: StatuslinePalette = {
99
105
  /** No colour at all: white text, dimmed punctuation, a grey badge flash. */
100
106
  const WHITE: StatuslinePalette = {
101
107
  model: rgb("#ffffff"),
108
+ thinking: rgb("#ffffff"),
102
109
  provider: rgb("#ffffff"),
103
110
  path: rgb("#ffffff"),
104
111
  branch: rgb("#ffffff"),