@leo-alvarenga/pi-zen-frame 0.12.0 → 0.12.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.
@@ -32,6 +32,17 @@ export interface HeaderEnv {
32
32
  const RANDOM_TIP =
33
33
  HEADER_TIPS[Math.floor(Math.random() * HEADER_TIPS.length)]?.text ?? "";
34
34
 
35
+ function wrapLines(
36
+ lines: string[],
37
+ maxLen: number,
38
+ style?: (line: string) => string,
39
+ ): string[] {
40
+ const wrapped = lines.map((l) => wrapTextWithAnsi(l, maxLen)).flat();
41
+ if (style) return wrapped.map((l) => (l.length ? style(l) : l));
42
+
43
+ return wrapped;
44
+ }
45
+
35
46
  export function createHeader(
36
47
  _tui: TUI,
37
48
  theme: Theme,
@@ -57,29 +68,6 @@ export function createHeader(
57
68
  color: settings.header?.logoColor ?? DEFAULT_SETTINGS.header?.logoColor,
58
69
  };
59
70
 
60
- const leftLines = [
61
- ...logo.lines.map((l) => theme.fg(logo.color, l)),
62
-
63
- "",
64
- "",
65
-
66
- theme.bold(
67
- theme.fg(
68
- "muted",
69
- settings.header?.heading ?? DEFAULT_SETTINGS.header?.heading,
70
- ),
71
- ),
72
-
73
- "",
74
-
75
- theme.italic(
76
- theme.fg(
77
- "muted",
78
- settings.header?.subheading ?? DEFAULT_SETTINGS.header?.subheading,
79
- ),
80
- ),
81
- ];
82
-
83
71
  const border = (s: string, fg?: ThemeColor) => theme.fg(fg ?? accentColor, s);
84
72
 
85
73
  /** Space-pad `text` so it sits horizontally centered within `inner` cols. */
@@ -106,7 +94,7 @@ export function createHeader(
106
94
  }
107
95
 
108
96
  /** Right column halves: top = model(+provider), bottom = cwd + git. */
109
- function infoRows(env: HeaderEnv): string[] {
97
+ function infoRows(env: HeaderEnv, width: number): string[] {
110
98
  const icons = DEFAULT_ICONS;
111
99
  const parts: string[] = [];
112
100
 
@@ -123,46 +111,74 @@ export function createHeader(
123
111
 
124
112
  return [
125
113
  theme.bold(border("Model Info")),
126
- env.modelName ? theme.fg("muted", `${icons.model} ${env.modelName}`) : "",
114
+
115
+ ...wrapLines(
116
+ [
117
+ env.modelName
118
+ ? theme.fg("muted", `${icons.model} ${env.modelName}`)
119
+ : "",
120
+ ],
121
+ width,
122
+ (str) => theme.fg("muted", str),
123
+ ),
124
+
127
125
  "",
126
+
128
127
  theme.bold(border("Current Directory")),
129
128
  parts.length ? parts.join(" · ") : "",
129
+
130
130
  "",
131
+
131
132
  theme.bold(border("Tip")),
132
- theme.fg("muted", RANDOM_TIP),
133
+ ...wrapLines([RANDOM_TIP], width, (str) => theme.fg("muted", str)),
133
134
  ];
134
135
  }
135
136
 
136
137
  return {
137
138
  render(width: number): string[] {
138
- // Too narrow for a box → fall back to a plain centered logo.
139
- if (width < MIN_BOX_WIDTH) {
140
- return leftLines;
141
- }
142
-
143
139
  const env = getEnv(pi);
144
- const rightRows = infoRows(env);
145
140
 
146
141
  const inner = Math.max(0, width - 2);
147
142
  const leftW = Math.floor(inner * LEFT_COL_RATIO);
148
- const rightW = inner - leftW - 1; // divider column
143
+
144
+ const rightW = inner - leftW - 1;
145
+
146
+ const rightLines = infoRows(env, rightW - 2);
147
+ const leftLines = [
148
+ ...logo.lines.map((l) => theme.fg(logo.color, l)),
149
+
150
+ "",
151
+ "",
152
+
153
+ ...wrapLines(
154
+ [settings.header?.heading ?? DEFAULT_SETTINGS.header?.heading ?? ""],
155
+ leftW - 2,
156
+ ).map((line) => theme.bold(theme.fg("muted", line))),
157
+
158
+ "",
159
+
160
+ ...wrapLines(
161
+ [
162
+ settings.header?.subheading ??
163
+ DEFAULT_SETTINGS.header?.subheading ??
164
+ "",
165
+ ],
166
+ leftW - 2,
167
+ ).map((line) => theme.italic(theme.fg("muted", line))),
168
+ ];
169
+
170
+ // Too narrow for a box → fall back to a plain centered logo.
171
+ if (width < MIN_BOX_WIDTH) {
172
+ return leftLines;
173
+ }
149
174
 
150
175
  // No truncation: overflow wraps onto following lines until it all fits.
151
- const leftWrapped = leftLines
152
- .map((l) => wrapTextWithAnsi(l, leftW))
153
- .flat();
154
- const rightWrapped = rightRows
155
- .map((r) => wrapTextWithAnsi(r, Math.max(1, rightW - 2))) // 2-col indent
156
- .flat();
157
-
158
- const height = Math.max(leftWrapped.length, rightWrapped.length);
159
- const logoTop = Math.max(
160
- 0,
161
- Math.floor((height - leftWrapped.length) / 2),
162
- );
176
+ const height = Math.max(leftLines.length, rightLines.length);
177
+ const logoTop = Math.max(0, Math.floor((height - leftLines.length) / 2));
178
+
163
179
  const rightTop = Math.max(
164
180
  0,
165
- Math.floor((height - rightWrapped.length) / 2),
181
+ Math.floor((height - rightLines.length) / 2),
166
182
  );
167
183
 
168
184
  const lines: string[] = [""];
@@ -172,12 +188,10 @@ export function createHeader(
172
188
 
173
189
  for (let i = 0; i < height; i++) {
174
190
  const l = i - logoTop;
175
- const leftLine =
176
- l >= 0 && l < leftWrapped.length ? leftWrapped[l]! : "";
191
+ const leftLine = l >= 0 && l < leftLines.length ? leftLines[l]! : "";
177
192
 
178
193
  const r = i - rightTop;
179
- const rightLine =
180
- r >= 0 && r < rightWrapped.length ? rightWrapped[r]! : "";
194
+ const rightLine = r >= 0 && r < rightLines.length ? rightLines[r]! : "";
181
195
 
182
196
  lines.push(splitRow(leftW, rightW, leftLine, rightLine));
183
197
  }
@@ -0,0 +1,12 @@
1
+ /** External contract IDs: the zen-mode keybinding and the optional
2
+ * pi-agent-manager integration (no hard dependency).
3
+ */
4
+ /** pi-agent-manager integration (optional — no hard dependency). */
5
+ export const PI_AGENT_MANAGER_AGENT_EVENT = "pi-agent-manager:agent-changed";
6
+ export const PI_AGENT_MANAGER_AGENT_DATA_KEY = "pi-agent-manager-agent";
7
+
8
+ /** Keybinding id users bind in keybindings.json to toggle zen mode. */
9
+ export const ZEN_MODE_SHORTCUT_ID = "piZenFrame.zenMode";
10
+ /** Default key when the user hasn't bound one (override or disable via
11
+ * keybindings.json; `[]` disables the shortcut, `/zen_mode` still works). */
12
+ export const ZEN_MODE_DEFAULT_KEY = "ctrl+shift+z";
@@ -0,0 +1,47 @@
1
+ import type { Settings } from "../types";
2
+ import { WORKING_MESSAGES } from "./messages";
3
+ export const DEFAULT_SETTINGS: Settings = {
4
+ zenMode: false,
5
+ accentColor: "accent",
6
+
7
+ header: {
8
+ enable: false,
9
+ logoColor: "text",
10
+ accentColor: "accent",
11
+
12
+ heading: "Welcome back!",
13
+ subheading:
14
+ "Ready for your next session? Terminal warm, context clean, tools ready to execute",
15
+
16
+ logo: ["█████████ ", "███ ███ ", "██████ ", "███ ███"],
17
+ },
18
+
19
+ workingMessage: {
20
+ enable: true,
21
+ intervalMs: 3000,
22
+ messages: WORKING_MESSAGES,
23
+ },
24
+
25
+ frame: {
26
+ icons: {},
27
+ paddingX: 1,
28
+ enable: true,
29
+ minWidth: 20,
30
+ marginTop: 0,
31
+ showCwd: true,
32
+ paddingTop: 1,
33
+ marginBottom: 0,
34
+ showModel: true,
35
+ paddingBottom: 1,
36
+ showSpinner: false,
37
+ showContext: true,
38
+ showThinking: true,
39
+ showAgentMode: true,
40
+ borderColor: "text",
41
+
42
+ colors: {},
43
+ // ponytail: colors were dormant (nothing read them); now wired — keep
44
+ // defaults unset so segments keep their natural colors and zen-mode is
45
+ // the mute switch.
46
+ },
47
+ };
@@ -0,0 +1,2 @@
1
+ /** Config file name (in the pi agent dir) holding user settings. */
2
+ export const CONFIG_FILE_NAME = "pi-zen-frame.json";
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Constants, grouped by concern and re-exported from a single barrel.
3
+ * Import everything with `import { ... } from "../config/constants"` —
4
+ * resolution keeps working now that this is a directory.
5
+ */
6
+ export * from "./file";
7
+ export * from "./contracts";
8
+ export * from "./visuals";
9
+ export * from "./messages";
10
+ export * from "./defaults";
@@ -0,0 +1,176 @@
1
+ import type { BannerTip } from "../types";
2
+ export const WORKING_MESSAGES: string[] = [
3
+ "Exploring",
4
+ "Tinkering",
5
+ "Searching",
6
+ "Polishing",
7
+ "Herding",
8
+ "Consulting",
9
+ "Chasing",
10
+ "Rearranging",
11
+ "Sharpening",
12
+ "Reticulating",
13
+ "Warming",
14
+ "Feeding",
15
+ "Whispering",
16
+ "Counting",
17
+ "Dusting",
18
+ "Tightening",
19
+ "Watering",
20
+ "Aligning",
21
+ "Reading",
22
+ "Charging",
23
+ "Summoning",
24
+ "Calibrating",
25
+ "Sorting",
26
+ "Debating",
27
+ "Brewing",
28
+ "Stargazing",
29
+ "Walking",
30
+ "Folding",
31
+ "Rounding",
32
+ "Cooking",
33
+ "Crunching",
34
+ "Cogitating",
35
+ "Analyzing",
36
+ "Architecting",
37
+ "Assembling",
38
+ "Building",
39
+ "Calculating",
40
+ "Compiling",
41
+ "Composing",
42
+ "Crafting",
43
+ "Decoding",
44
+ "Designing",
45
+ "Drafting",
46
+ "Editing",
47
+ "Evaluating",
48
+ "Experimenting",
49
+ "Explaining",
50
+ "Extracting",
51
+ "Generating",
52
+ "Integrating",
53
+ "Iterating",
54
+ "Juggling",
55
+ "Mapping",
56
+ "Measuring",
57
+ "Merging",
58
+ "Modeling",
59
+ "Navigating",
60
+ "Optimizing",
61
+ "Organizing",
62
+ "Parsing",
63
+ "Planning",
64
+ "Pondering",
65
+ "Processing",
66
+ "Refactoring",
67
+ "Refining",
68
+ "Rendering",
69
+ "Resolving",
70
+ "Reviewing",
71
+ "Scanning",
72
+ "Sifting",
73
+ "Simulating",
74
+ "Streamlining",
75
+ "Structuring",
76
+ "Synthesizing",
77
+ "Testing",
78
+ "Tracing",
79
+ "Translating",
80
+ "Triaging",
81
+ "Unraveling",
82
+ "Validating",
83
+ "Verifying",
84
+ "Wrangling",
85
+ ];
86
+
87
+ export const HEADER_TIPS: BannerTip[] = [
88
+ {
89
+ type: "Tip",
90
+ text: "Press Ctrl + G inside Pi's input box to open your default system $EDITOR (e.g., Neovim) for writing long, complex prompts",
91
+ },
92
+ {
93
+ type: "Did You Know?",
94
+ text: "Model reasoning quality degrades as the context window fills up. Use /compact or start fresh sessions once context exceeds 50–60%",
95
+ },
96
+ {
97
+ type: "Workflow",
98
+ text: "Isolate planning from execution: use a read-only profile for architectural planning and switch to full permissions only when building",
99
+ },
100
+ {
101
+ type: "Did You Know?",
102
+ text: "Modern models like Claude 3.5 and 3.7 process boundaries in XML tags (<context>, <rules>, <code_diff>) significantly better than raw Markdown dividers",
103
+ },
104
+ {
105
+ type: "Tip",
106
+ text: "Always truncate or filter large log outputs before handing them to an agent — a 10,000-line stack trace will immediately saturate your token cache",
107
+ },
108
+ {
109
+ type: "Tip",
110
+ text: "Export global environment variables (like $EDITOR and $VISUAL) in ~/.bashenv (or your shell's env file) so background subshells and GUI-spawned processes inherit them cleanly",
111
+ },
112
+ {
113
+ type: "Did You Know?",
114
+ text: "Smooth 80ms Braille sequences (⠋, ⠙, ⠹, ⠸) or quadrant block meters give immediate visual feedback without consuming much screen real estate",
115
+ },
116
+ {
117
+ type: "Prompting",
118
+ text: "Tell models what TO DO instead of what NOT to do—negative constraints like 'don't use markdown' are frequently ignored compared to positive instructions",
119
+ },
120
+ {
121
+ type: "Workflow",
122
+ text: "Use fuzzy file references by typing `@` in Pi's input box to quickly anchor specific codebase files directly into the prompt context",
123
+ },
124
+ {
125
+ type: "Tip",
126
+ text: "Place heavy longform context or data files near the top of your prompt and put your actual instructions or questions at the very end for better accuracy",
127
+ },
128
+ {
129
+ type: "Did You Know?",
130
+ text: "Pi saves session history as a tree. You can use `/tree` or `/fork` to branch off a previous point in a conversation to test an alternative approach",
131
+ },
132
+ {
133
+ type: "Prompting",
134
+ text: "Define specific output formats (e.g., JSON schemas or concise bullet points) upfront to prevent models from generating unnecessary verbose prose",
135
+ },
136
+ {
137
+ type: "Tip",
138
+ text: "Paste screenshots straight into the prompt with Ctrl+V (Alt+V on Windows) — models can see error dialogs, UIs, and graphs you can't describe in words",
139
+ },
140
+ {
141
+ type: "Tip",
142
+ text: "Type `@` to anchor files into the prompt — pi inlines the real contents, so the model reads your code, not your summary of it",
143
+ },
144
+ {
145
+ type: "Tip",
146
+ text: "Swap models mid-session with `/model` or Ctrl+L instead of restarting — you keep the conversation context, just change the brain",
147
+ },
148
+ {
149
+ type: "Did You Know?",
150
+ text: "Shift+Tab cycles through your recent models without opening the picker — fastest way to A/B two models on the same prompt",
151
+ },
152
+ {
153
+ type: "Workflow",
154
+ text: "Run `/compact` before starting a big new task: the conversation is summarized and you continue with a clean, cheap context",
155
+ },
156
+ {
157
+ type: "Workflow",
158
+ text: "Assign one agent mode per task phase — read-only for planning/research, full privileges only for execution — so a misfired tool call can't touch your repo",
159
+ },
160
+ {
161
+ type: "Prompting",
162
+ text: "Restate the single most important requirement in the *last* line of a long prompt — instructions given early fade as context grows",
163
+ },
164
+ {
165
+ type: "Prompting",
166
+ text: "Show, don't tell: paste the exact error text plus the file:line that produced it. Vague 'it's broken' prompts get shotgun fixes",
167
+ },
168
+ {
169
+ type: "Tip",
170
+ text: "Keep messages atomic — one question or one change per message. Mega-prompts amortize badly over a long session",
171
+ },
172
+ {
173
+ type: "Workflow",
174
+ text: "For multi-file changes, ask for a plan first (files touched + order) and approve it before any edits — cheap insurance against wrong-direction refactors",
175
+ },
176
+ ];
@@ -0,0 +1,84 @@
1
+ import type { ThemeColor } from "@earendil-works/pi-coding-agent";
2
+ import type { FrameIcons, SpinnerPhase } from "../types";
3
+ /** Spinner animation frames per phase (pi-editor-shell style). */
4
+ export const SPINNER_FRAMES: Record<SpinnerPhase, string[]> = {
5
+ idle: ["⠃", "⠞", "⡵", "⠿", "⢹", "⠄"],
6
+ outputting: ["⠋", "⠙", "⠸", "⠴", "⠦", "⠇", "⠏"],
7
+ thinking: ["󰌶", "󰌶", "󰌶", "󰌶", "󰌵", "󰌵", "󰌵", "󰌵"],
8
+ toolcall: ["●", "●", "●", "●", "○", "○", "○", "○"],
9
+ exec: ["⠂", "⠅", "⠍", "⠟", "⠿", "⠽", "⠿", "⠟", "⠍", "⠅", "⠂"],
10
+
11
+ // Sample ["░", "▒", "▓", "█", "▓", "▒"],
12
+ };
13
+
14
+ /** Nerd Font defaults (override any subset via `frame.icons`). */
15
+ export const DEFAULT_ICONS: FrameIcons = {
16
+ model: "󰣖",
17
+ folder: " ",
18
+ context: "",
19
+ gitDirty: "",
20
+ thinking: "󰌶",
21
+ gitBranch: "",
22
+ };
23
+
24
+ /** Thinking level → theme token, mirroring pi's own border-color mapping. */
25
+ export const THINKING_TOKEN: Record<string, string> = {
26
+ off: "thinkingOff",
27
+ minimal: "thinkingMinimal",
28
+ low: "thinkingLow",
29
+ medium: "thinkingMedium",
30
+ high: "thinkingHigh",
31
+ xhigh: "thinkingXhigh",
32
+ max: "thinkingMax",
33
+ };
34
+
35
+
36
+ export const THEME_COLORS: Record<ThemeColor, true> = {
37
+ accent: true,
38
+ border: true,
39
+ borderAccent: true,
40
+ borderMuted: true,
41
+ success: true,
42
+ error: true,
43
+ warning: true,
44
+ muted: true,
45
+ dim: true,
46
+ text: true,
47
+ searchMatchText: true,
48
+ thinkingText: true,
49
+ userMessageText: true,
50
+ customMessageText: true,
51
+ customMessageLabel: true,
52
+ toolTitle: true,
53
+ toolOutput: true,
54
+ mdHeading: true,
55
+ mdLink: true,
56
+ mdLinkUrl: true,
57
+ mdCode: true,
58
+ mdCodeBlock: true,
59
+ mdCodeBlockBorder: true,
60
+ mdQuote: true,
61
+ mdQuoteBorder: true,
62
+ mdHr: true,
63
+ mdListBullet: true,
64
+ toolDiffAdded: true,
65
+ toolDiffRemoved: true,
66
+ toolDiffContext: true,
67
+ syntaxComment: true,
68
+ syntaxKeyword: true,
69
+ syntaxFunction: true,
70
+ syntaxVariable: true,
71
+ syntaxString: true,
72
+ syntaxNumber: true,
73
+ syntaxType: true,
74
+ syntaxOperator: true,
75
+ syntaxPunctuation: true,
76
+ thinkingOff: true,
77
+ thinkingMinimal: true,
78
+ thinkingLow: true,
79
+ thinkingMedium: true,
80
+ thinkingHigh: true,
81
+ thinkingXhigh: true,
82
+ thinkingMax: true,
83
+ bashMode: true,
84
+ };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@leo-alvarenga/pi-zen-frame",
3
3
  "description": "A pi-coding-agent extension that gives the TUI editor a simple yet polished look and feel",
4
4
  "author": "Leonardo A. Alvarenga",
5
- "version": "0.12.0",
5
+ "version": "0.12.2",
6
6
  "license": "MIT",
7
7
  "repository": "github.com/leo-alvarenga/pi-mono",
8
8
  "publishConfig": {
@@ -1,279 +0,0 @@
1
- import { ThemeColor } from "@earendil-works/pi-coding-agent";
2
- import type { BannerTip, FrameIcons, Settings, SpinnerPhase } from "./types";
3
-
4
- export const CONFIG_FILE_NAME = "pi-zen-frame.json";
5
-
6
- /** pi-agent-manager integration (optional — no hard dependency). */
7
- export const PI_AGENT_MANAGER_AGENT_EVENT = "pi-agent-manager:agent-changed";
8
- export const PI_AGENT_MANAGER_AGENT_DATA_KEY = "pi-agent-manager-agent";
9
-
10
- /** Keybinding id users bind in keybindings.json to toggle zen mode. */
11
- export const ZEN_MODE_SHORTCUT_ID = "piZenFrame.zenMode";
12
- /** Default key when the user hasn't bound one (override or disable via
13
- * keybindings.json; `[]` disables the shortcut, `/zen_mode` still works). */
14
- export const ZEN_MODE_DEFAULT_KEY = "ctrl+shift+z";
15
-
16
- /** Spinner animation frames per phase (pi-editor-shell style). */
17
- export const SPINNER_FRAMES: Record<SpinnerPhase, string[]> = {
18
- idle: ["⠃", "⠞", "⡵", "⠿", "⢹", "⠄"],
19
- outputting: ["⠋", "⠙", "⠸", "⠴", "⠦", "⠇", "⠏"],
20
- thinking: ["󰌶", "󰌶", "󰌶", "󰌶", "󰌵", "󰌵", "󰌵", "󰌵"],
21
- toolcall: ["●", "●", "●", "●", "○", "○", "○", "○"],
22
- exec: ["⠂", "⠅", "⠍", "⠟", "⠿", "⠽", "⠿", "⠟", "⠍", "⠅", "⠂"],
23
-
24
- // Sample ["░", "▒", "▓", "█", "▓", "▒"],
25
- };
26
-
27
- /** Nerd Font defaults (override any subset via `frame.icons`). */
28
- export const DEFAULT_ICONS: FrameIcons = {
29
- model: "󰣖",
30
- folder: " ",
31
- context: "",
32
- gitDirty: "",
33
- thinking: "󰌶",
34
- gitBranch: "",
35
- };
36
-
37
- /** Thinking level → theme token, mirroring pi's own border-color mapping. */
38
- export const THINKING_TOKEN: Record<string, string> = {
39
- off: "thinkingOff",
40
- minimal: "thinkingMinimal",
41
- low: "thinkingLow",
42
- medium: "thinkingMedium",
43
- high: "thinkingHigh",
44
- xhigh: "thinkingXhigh",
45
- max: "thinkingMax",
46
- };
47
-
48
- /** Rotating messages for the working loader (single-word verbs; some silly, some plausible). */
49
- export const WORKING_MESSAGES: string[] = [
50
- "Exploring",
51
- "Tinkering",
52
- "Searching",
53
- "Polishing",
54
- "Herding",
55
- "Consulting",
56
- "Chasing",
57
- "Rearranging",
58
- "Sharpening",
59
- "Reticulating",
60
- "Warming",
61
- "Feeding",
62
- "Whispering",
63
- "Counting",
64
- "Dusting",
65
- "Tightening",
66
- "Watering",
67
- "Aligning",
68
- "Reading",
69
- "Charging",
70
- "Summoning",
71
- "Calibrating",
72
- "Sorting",
73
- "Debating",
74
- "Brewing",
75
- "Stargazing",
76
- "Walking",
77
- "Folding",
78
- "Rounding",
79
- "Cooking",
80
- "Crunching",
81
- "Cogitating",
82
- "Analyzing",
83
- "Architecting",
84
- "Assembling",
85
- "Building",
86
- "Calculating",
87
- "Compiling",
88
- "Composing",
89
- "Crafting",
90
- "Decoding",
91
- "Designing",
92
- "Drafting",
93
- "Editing",
94
- "Evaluating",
95
- "Experimenting",
96
- "Explaining",
97
- "Extracting",
98
- "Generating",
99
- "Integrating",
100
- "Iterating",
101
- "Juggling",
102
- "Mapping",
103
- "Measuring",
104
- "Merging",
105
- "Modeling",
106
- "Navigating",
107
- "Optimizing",
108
- "Organizing",
109
- "Parsing",
110
- "Planning",
111
- "Pondering",
112
- "Processing",
113
- "Refactoring",
114
- "Refining",
115
- "Rendering",
116
- "Resolving",
117
- "Reviewing",
118
- "Scanning",
119
- "Sifting",
120
- "Simulating",
121
- "Streamlining",
122
- "Structuring",
123
- "Synthesizing",
124
- "Testing",
125
- "Tracing",
126
- "Translating",
127
- "Triaging",
128
- "Unraveling",
129
- "Validating",
130
- "Verifying",
131
- "Wrangling",
132
- ];
133
-
134
- export const HEADER_TIPS: BannerTip[] = [
135
- {
136
- type: "Tip",
137
- text: "Press Ctrl + G inside Pi's input box to open your default system $EDITOR (e.g., Neovim) for writing long, complex prompts",
138
- },
139
- {
140
- type: "Did You Know?",
141
- text: "Model reasoning quality degrades as the context window fills up. Use /compact or start fresh sessions once context exceeds 50–60%",
142
- },
143
- {
144
- type: "Workflow",
145
- text: "Isolate planning from execution: use a read-only profile for architectural planning and switch to full permissions only when building",
146
- },
147
- {
148
- type: "Did You Know?",
149
- text: "Modern models like Claude 3.5 and 3.7 process boundaries in XML tags (<context>, <rules>, <code_diff>) significantly better than raw Markdown dividers",
150
- },
151
- {
152
- type: "Tip",
153
- text: "Always truncate or filter large log outputs before handing them to an agent—a 10,000-line stack trace will immediately saturate your token cache",
154
- },
155
- {
156
- type: "Tip",
157
- text: "Export global environment variables (like $EDITOR and $VISUAL) in ~/.bashenv (or your shell's env file) so background subshells and GUI-spawned processes inherit them cleanly",
158
- },
159
- {
160
- type: "Did You Know?",
161
- text: "Smooth 80ms Braille sequences (⠋, ⠙, ⠹, ⠸) or quadrant block meters give immediate visual feedback without consuming much screen real estate",
162
- },
163
- {
164
- type: "Prompting",
165
- text: "Tell models what TO DO instead of what NOT to do—negative constraints like 'don't use markdown' are frequently ignored compared to positive instructions",
166
- },
167
- {
168
- type: "Workflow",
169
- text: "Use fuzzy file references by typing `@` in Pi's input box to quickly anchor specific codebase files directly into the prompt context",
170
- },
171
- {
172
- type: "Tip",
173
- text: "Place heavy longform context or data files near the top of your prompt and put your actual instructions or questions at the very end for better accuracy",
174
- },
175
- {
176
- type: "Did You Know?",
177
- text: "Pi saves session history as a tree. You can use `/tree` or `/fork` to branch off a previous point in a conversation to test an alternative approach",
178
- },
179
- {
180
- type: "Prompting",
181
- text: "Define specific output formats (e.g., JSON schemas or concise bullet points) upfront to prevent models from generating unnecessary verbose prose",
182
- },
183
- ];
184
-
185
- export const DEFAULT_SETTINGS: Settings = {
186
- zenMode: false,
187
- accentColor: "accent",
188
-
189
- header: {
190
- enable: false,
191
- logoColor: "text",
192
- accentColor: "accent",
193
-
194
- heading: "Welcome back!",
195
- subheading:
196
- "Ready for your next session? Terminal warm, context clean, tools ready to execute",
197
-
198
- logo: ["█████████ ", "███ ███ ", "██████ ", "███ ███"],
199
- },
200
-
201
- workingMessage: {
202
- enable: true,
203
- intervalMs: 3000,
204
- messages: WORKING_MESSAGES,
205
- },
206
-
207
- frame: {
208
- icons: {},
209
- paddingX: 1,
210
- enable: true,
211
- minWidth: 20,
212
- marginTop: 0,
213
- showCwd: true,
214
- paddingTop: 1,
215
- marginBottom: 0,
216
- showModel: true,
217
- paddingBottom: 1,
218
- showSpinner: false,
219
- showContext: true,
220
- showThinking: true,
221
- showAgentMode: true,
222
- borderColor: "text",
223
-
224
- colors: {},
225
- // ponytail: colors were dormant (nothing read them); now wired — keep
226
- // defaults unset so segments keep their natural colors and zen-mode is
227
- // the mute switch.
228
- },
229
- };
230
-
231
- export const THEME_COLORS: Record<ThemeColor, true> = {
232
- accent: true,
233
- border: true,
234
- borderAccent: true,
235
- borderMuted: true,
236
- success: true,
237
- error: true,
238
- warning: true,
239
- muted: true,
240
- dim: true,
241
- text: true,
242
- searchMatchText: true,
243
- thinkingText: true,
244
- userMessageText: true,
245
- customMessageText: true,
246
- customMessageLabel: true,
247
- toolTitle: true,
248
- toolOutput: true,
249
- mdHeading: true,
250
- mdLink: true,
251
- mdLinkUrl: true,
252
- mdCode: true,
253
- mdCodeBlock: true,
254
- mdCodeBlockBorder: true,
255
- mdQuote: true,
256
- mdQuoteBorder: true,
257
- mdHr: true,
258
- mdListBullet: true,
259
- toolDiffAdded: true,
260
- toolDiffRemoved: true,
261
- toolDiffContext: true,
262
- syntaxComment: true,
263
- syntaxKeyword: true,
264
- syntaxFunction: true,
265
- syntaxVariable: true,
266
- syntaxString: true,
267
- syntaxNumber: true,
268
- syntaxType: true,
269
- syntaxOperator: true,
270
- syntaxPunctuation: true,
271
- thinkingOff: true,
272
- thinkingMinimal: true,
273
- thinkingLow: true,
274
- thinkingMedium: true,
275
- thinkingHigh: true,
276
- thinkingXhigh: true,
277
- thinkingMax: true,
278
- bashMode: true,
279
- };