phewsh 0.11.11 → 0.11.13

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/commands/watch.js CHANGED
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // Watches .intent/ for changes and auto-pushes to Supabase + regenerates CLAUDE.md.
4
4
  // This is the backbone of cross-tool continuity:
5
- // edit in terminal → web dashboard updates → Claude Code knows.
5
+ // edit in terminal → phewsh.com/intent updates → Claude Code knows.
6
6
  //
7
7
  // Usage:
8
8
  // phewsh watch Start watching (push + CLAUDE.md)
@@ -85,8 +85,8 @@ function generateClaudeSection() {
85
85
  const decisionGate = gate || projectJson?.decisionGate;
86
86
 
87
87
  sections.push(`# PHEWSH Adaptive Context — ${projectName}`);
88
+ sections.push(`> **Generated file. Do not edit.** Modify .intent/ instead — this section regenerates automatically.`);
88
89
  sections.push(`> Auto-synced by \`phewsh watch\` | ${new Date().toISOString().split('T')[0]}`);
89
- sections.push(`> This section is regenerated on every .intent/ change. Do not edit manually.`);
90
90
  sections.push('');
91
91
 
92
92
  // Project identity
@@ -318,25 +318,25 @@ function watchIntent() {
318
318
 
319
319
  function showHelp() {
320
320
  console.log(`
321
- phewsh watch — Live .intent/ sync daemon
321
+ phewsh watch — Keep AI tools in sync with .intent/
322
322
 
323
323
  Usage:
324
324
  phewsh watch Start watching
325
325
  phewsh watch --no-claude Skip CLAUDE.md regeneration
326
- phewsh watch --no-push Skip cloud push (local CLAUDE.md only)
326
+ phewsh watch --no-push Skip cloud push (local only)
327
327
  phewsh watch --verbose Show detailed sync info
328
328
 
329
329
  What it does:
330
330
  Watches .intent/ for changes and automatically:
331
- 1. Pushes updated artifacts to Supabase (web dashboard updates live)
332
- 2. Regenerates the PHEWSH section in CLAUDE.md (Claude Code stays current)
331
+ 1. Regenerates CLAUDE.md so Claude Code stays current with .intent/
332
+ 2. Pushes to phewsh.com/intent (optional needs account)
333
333
 
334
- This creates the cross-tool continuity loop:
335
- edit gate in terminal -> web dashboard reorganizes -> Claude already knows
334
+ The loop:
335
+ edit .intent/ CLAUDE.md updates cloud mirror updates every tool knows
336
336
 
337
337
  Requirements:
338
338
  - .intent/ directory must exist (run \`phewsh intent --init\`)
339
- - \`phewsh login\` for cloud push (optional CLAUDE.md works without it)
339
+ - Everything works without an account. Account adds cloud sync.
340
340
  `);
341
341
  }
342
342
 
@@ -352,8 +352,8 @@ async function main() {
352
352
  const loggedIn = !!config?.supabaseUserId;
353
353
 
354
354
  console.log('');
355
- console.log(` ${b(w('PHEWSH Watch'))} ${g('v' + require('../package.json').version)}`);
356
- console.log(` ${g('Live .intent/ sync cross-tool continuity')}`);
355
+ console.log(` ${b(w('.intent/ Watch'))} ${g('v' + require('../package.json').version)}`);
356
+ console.log(` ${g('Keeps your AI tools in sync with .intent/')}`);
357
357
  console.log('');
358
358
 
359
359
  // Show what's enabled
@@ -361,7 +361,7 @@ async function main() {
361
361
  if (!flags.noClaude) features.push(`${green('●')} CLAUDE.md auto-sync`);
362
362
  else features.push(`${g('○')} CLAUDE.md ${g('(disabled)')}`);
363
363
 
364
- if (!flags.noPush && loggedIn) features.push(`${green('●')} Cloud push (web dashboard)`);
364
+ if (!flags.noPush && loggedIn) features.push(`${green('●')} Cloud push phewsh.com/intent`);
365
365
  else if (!flags.noPush && !loggedIn) features.push(`${yellow('●')} Cloud push ${g('(not logged in — run phewsh login)')}`);
366
366
  else features.push(`${g('○')} Cloud push ${g('(disabled)')}`);
367
367
 
package/lib/ui.js CHANGED
@@ -1,6 +1,22 @@
1
- // phewsh ui — zero-dependency terminal animations and visual helpers
2
- // Pure ANSI escape sequences. No chalk, no ora, no bloat.
1
+ // phewsh ui — the exhale
2
+ // Relief. Quiet execution. Cool sweet future.
3
+ // Zero dependencies. Pure ANSI. The terminal breathes.
3
4
 
5
+ // ── PHEWSH palette ───────────────────────────────────────
6
+ // 24-bit color for terminals that support it (most modern ones do).
7
+ // Fallback-safe: if 24-bit fails, the text still renders.
8
+ const rgb = (r, g, b) => (s) => `\x1b[38;2;${r};${g};${b}m${s}\x1b[0m`;
9
+ const rgbBg = (r, g, b) => (s) => `\x1b[48;2;${r};${g};${b}m${s}\x1b[0m`;
10
+
11
+ // Brand colors — relief, quiet, future
12
+ const teal = rgb(100, 215, 195); // cool calm — primary
13
+ const peach = rgb(255, 195, 145); // warm exhale — accent
14
+ const sage = rgb(130, 150, 140); // quiet — secondary text
15
+ const slate = rgb(80, 90, 88); // whisper — dim text
16
+ const cream = rgb(240, 235, 225); // clarity — bright text
17
+ const ember = rgb(220, 140, 90); // glow — warnings/energy
18
+
19
+ // Standard ANSI fallbacks (used where 24-bit might not render)
4
20
  const b = (s) => `\x1b[1m${s}\x1b[0m`;
5
21
  const d = (s) => `\x1b[2m${s}\x1b[0m`;
6
22
  const w = (s) => `\x1b[97m${s}\x1b[0m`;
@@ -18,30 +34,43 @@ const show = '\x1b[?25h';
18
34
  const up = (n = 1) => `\x1b[${n}A`;
19
35
  const clearLine = '\x1b[2K\r';
20
36
 
21
- // ── Spinner ──────────────────────────────────────────────
22
- // Returns { stop } call stop() when work is done.
23
- const SPINNER_FRAMES = [' ·', ' · ·', ' · · ·', ' · · · ·', '· · · · ·', ' · · · ·', ' · · ·', ' · ·'];
24
- const BRAILLE_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
25
- const BREATH_FRAMES = ['░', '▒', '▓', '█', '▓', '▒', '░', ' '];
26
- const PULSE_FRAMES = ['·', '•', '●', '•'];
27
-
28
- function spinner(text = 'thinking', style = 'braille') {
29
- const frames = style === 'dots' ? SPINNER_FRAMES
30
- : style === 'breath' ? BREATH_FRAMES
31
- : style === 'pulse' ? PULSE_FRAMES
32
- : BRAILLE_FRAMES;
37
+ // ── Sleep helper ─────────────────────────────────────────
38
+ const sleep = (ms) => new Promise(r => setTimeout(r, ms));
39
+
40
+ // ── Spinner: the exhale pulse ────────────────────────────
41
+ // Breathes in and out. Calm. Not frantic.
42
+ const EXHALE_FRAMES = [
43
+ ' · ',
44
+ ' · · ',
45
+ ' · · ',
46
+ ' · · ',
47
+ '· ·',
48
+ ' · · ',
49
+ ' · · ',
50
+ ' · · ',
51
+ ];
52
+
53
+ const BREATH_DOTS = [' ·', ' · ·', '· · ·', ' · ·', ' ·', ' '];
54
+
55
+ const GENTLE_FRAMES = ['·', '•', '●', '•', '·', ' '];
56
+
57
+ function spinner(text = 'thinking', style = 'exhale') {
58
+ const frames = style === 'gentle' ? GENTLE_FRAMES
59
+ : style === 'dots' ? BREATH_DOTS
60
+ : EXHALE_FRAMES;
33
61
  let i = 0;
34
62
  let stopped = false;
63
+ let currentText = text;
35
64
  process.stdout.write(hide);
36
65
  const interval = setInterval(() => {
37
66
  if (stopped) return;
38
67
  const frame = frames[i % frames.length];
39
- process.stdout.write(`${clearLine} ${cyan(frame)} ${g(text)}`);
68
+ process.stdout.write(`${clearLine} ${teal(frame)} ${sage(currentText)}`);
40
69
  i++;
41
- }, style === 'breath' ? 120 : 80);
70
+ }, style === 'gentle' ? 150 : 100);
42
71
 
43
72
  return {
44
- update(newText) { text = newText; },
73
+ update(newText) { currentText = newText; },
45
74
  stop(finalText) {
46
75
  stopped = true;
47
76
  clearInterval(interval);
@@ -51,86 +80,136 @@ function spinner(text = 'thinking', style = 'braille') {
51
80
  };
52
81
  }
53
82
 
54
- // ── Animated brand reveal ────────────────────────────────
55
- // Draws the PHEWSH logo line by line with a cascading effect.
56
- function brandReveal(fast = false) {
57
- return new Promise((resolve) => {
58
- const lines = [
59
- '',
60
- ` ${d('😮\u200d💨')} ${d('🤫')}`,
61
- '',
62
- ` ${b(w('█▀█ █░█ █▀▀ █░█ █▀ █░█'))}`,
63
- ` ${b(w('█▀▀ █▀█ ██▄ ▀▄▀ ▄█ █▀█'))}`,
64
- '',
65
- ];
83
+ // ── The Exhale: signature brand animation ────────────────
84
+ // This is the first thing you see. It should feel like a breath.
85
+ // Inhale (pause) exhale (particles expand) → settle (logo forms) → calm.
86
+ async function brandReveal(fast = false) {
87
+ if (fast) {
88
+ console.log('');
89
+ console.log(` ${d('😮\u200d💨')} ${d('🤫')}`);
90
+ console.log('');
91
+ console.log(` ${b(cream('█▀█ █░█ █▀▀ █░█ █▀ █░█'))}`);
92
+ console.log(` ${b(cream('█▀▀ █▀█ ██▄ ▀▄▀ ▄█ █▀█'))}`);
93
+ console.log('');
94
+ return;
95
+ }
96
+
97
+ process.stdout.write(hide);
98
+
99
+ // Phase 1: The inhale — brief stillness
100
+ console.log('');
101
+ await sleep(200);
102
+
103
+ // Phase 2: The exhale — particles drift outward
104
+ const exhaleStages = [
105
+ ' ·',
106
+ ' · · ·',
107
+ ' · · · ·',
108
+ ' · · · · ·',
109
+ ' · · · · ·',
110
+ ];
111
+
112
+ for (const stage of exhaleStages) {
113
+ process.stdout.write(`${clearLine} ${slate(stage)}`);
114
+ await sleep(70);
115
+ }
116
+
117
+ // Phase 3: Particles converge into the emoji
118
+ await sleep(100);
119
+ process.stdout.write(`${clearLine}`);
120
+ console.log(` ${d('😮\u200d💨')} ${d('🤫')}`);
121
+ console.log('');
122
+ await sleep(150);
66
123
 
67
- if (fast) {
68
- lines.forEach(l => console.log(l));
69
- resolve();
70
- return;
124
+ // Phase 4: Logo wave — each letter block appears left to right
125
+ const logoTop = ['█▀█', '█░█', '█▀▀', '█░█', '█▀', '█░█'];
126
+ const logoBot = ['█▀▀', '█▀█', '██▄', '▀▄▀', '▄█', '█▀█'];
127
+
128
+ let topLine = ' ';
129
+ let botLine = ' ';
130
+
131
+ for (let i = 0; i < logoTop.length; i++) {
132
+ topLine += cream(logoTop[i]) + ' ';
133
+ botLine += cream(logoBot[i]) + ' ';
134
+
135
+ // Overwrite both lines
136
+ if (i === 0) {
137
+ process.stdout.write(` ${b(topLine.trim())}`);
138
+ process.stdout.write('\n');
139
+ process.stdout.write(` ${b(botLine.trim())}`);
140
+ } else {
141
+ process.stdout.write(up(1));
142
+ process.stdout.write(`${clearLine} ${b(topLine.trim())}`);
143
+ process.stdout.write('\n');
144
+ process.stdout.write(`${clearLine} ${b(botLine.trim())}`);
71
145
  }
146
+ await sleep(55);
147
+ }
72
148
 
73
- let idx = 0;
74
- const interval = setInterval(() => {
75
- if (idx >= lines.length) {
76
- clearInterval(interval);
77
- resolve();
78
- return;
79
- }
80
- console.log(lines[idx]);
81
- idx++;
82
- }, 60);
83
- });
149
+ process.stdout.write('\n');
150
+ await sleep(100);
151
+
152
+ // Phase 5: Tagline fades in — dim → sage → cream
153
+ const tagline = '.intent/ is your project\'s working memory.';
154
+ process.stdout.write(` ${slate(tagline)}`);
155
+ await sleep(200);
156
+ process.stdout.write(`${clearLine} ${sage(tagline)}`);
157
+ await sleep(200);
158
+ process.stdout.write(`${clearLine} ${teal(tagline)}`);
159
+ await sleep(300);
160
+
161
+ console.log('');
162
+ console.log('');
163
+ process.stdout.write(show);
84
164
  }
85
165
 
86
166
  // ── Status panel ─────────────────────────────────────────
87
- // Draws a bordered status box with labeled rows.
88
167
  function statusPanel(title, rows) {
89
168
  const maxLabel = Math.max(...rows.map(r => r[0].length));
90
169
  console.log('');
91
- console.log(` ${b(w(title))}`);
92
- console.log(` ${g('─'.repeat(48))}`);
170
+ console.log(` ${b(cream(title))}`);
171
+ console.log(` ${slate('─'.repeat(48))}`);
93
172
  for (const [label, value, color] of rows) {
94
173
  const colorFn = color === 'green' ? green
95
- : color === 'yellow' ? yellow
96
- : color === 'cyan' ? cyan
174
+ : color === 'yellow' ? ember
175
+ : color === 'cyan' ? teal
97
176
  : color === 'red' ? red
177
+ : color === 'peach' ? peach
98
178
  : (s) => s;
99
- console.log(` ${g(label.padEnd(maxLabel + 2))} ${colorFn(value)}`);
179
+ console.log(` ${sage(label.padEnd(maxLabel + 2))} ${colorFn(value)}`);
100
180
  }
101
- console.log(` ${g('─'.repeat(48))}`);
181
+ console.log(` ${slate('─'.repeat(48))}`);
102
182
  console.log('');
103
183
  }
104
184
 
105
185
  // ── Interop badge line ───────────────────────────────────
106
- // Shows where phewsh is connected / can connect.
107
186
  function interopLine(config, intentFiles) {
108
187
  const parts = [];
109
- if (intentFiles.length > 0) parts.push(green('●') + ' .intent/');
110
- if (config?.apiKey) parts.push(green('●') + ' AI');
111
- if (config?.supabaseUserId) parts.push(green('●') + ' cloud');
188
+ if (intentFiles.length > 0) parts.push(teal('●') + sage(' .intent/'));
189
+ if (config?.apiKey) parts.push(teal('●') + sage(' AI'));
190
+ if (config?.supabaseUserId) parts.push(teal('●') + sage(' cloud'));
112
191
 
113
- // Always show what's available
114
- const available = [];
115
- available.push(g('Claude Code'));
116
- available.push(g('Cursor'));
117
- available.push(g('ChatGPT'));
118
- available.push(g('MCP'));
192
+ const available = [
193
+ sage('Claude Code'),
194
+ sage('Cursor'),
195
+ sage('ChatGPT'),
196
+ sage('MCP'),
197
+ ];
119
198
 
120
199
  if (parts.length > 0) {
121
- console.log(` ${g('connected')} ${parts.join(g(' · '))}`);
200
+ console.log(` ${slate('active')} ${parts.join(slate(' · '))}`);
122
201
  }
123
- console.log(` ${g('works with')} ${available.join(g(' · '))}`);
202
+ console.log(` ${slate('works in')} ${available.join(slate(' · '))}`);
124
203
  }
125
204
 
126
205
  // ── Divider ──────────────────────────────────────────────
127
- function divider(char = '·', width = 48) {
128
- console.log(` ${g(char.repeat(width))}`);
206
+ function divider(style = 'line', width = 48) {
207
+ const char = style === 'dots' ? '·' : style === 'fade' ? '░' : '─';
208
+ console.log(` ${slate(char.repeat(width))}`);
129
209
  }
130
210
 
131
211
  // ── Typewriter ───────────────────────────────────────────
132
- // Writes text character by character. Returns a promise.
133
- function typewrite(text, speed = 20) {
212
+ function typewrite(text, speed = 25) {
134
213
  return new Promise((resolve) => {
135
214
  let i = 0;
136
215
  const interval = setInterval(() => {
@@ -146,16 +225,16 @@ function typewrite(text, speed = 20) {
146
225
  });
147
226
  }
148
227
 
149
- // ── Welcome tips (rotates each session) ──────────────────
228
+ // ── Welcome tips ─────────────────────────────────────────
150
229
  const TIPS = [
151
- `${g('tip:')} Type ${w('/clarify')} to turn a messy idea into a structured spec`,
152
- `${g('tip:')} ${w('/gate')} lets you set budget, time, and skill constraints`,
153
- `${g('tip:')} Run ${w('phewsh watch')} in another tab for live sync to CLAUDE.md`,
154
- `${g('tip:')} ${w('/export')} creates a portable context file for any AI tool`,
155
- `${g('tip:')} ${w('/model opus')} switches to Claude Opus for complex reasoning`,
156
- `${g('tip:')} Your ${w('.intent/')} files are plain markdown edit them anytime`,
157
- `${g('tip:')} ${w('phewsh context --copy')} puts your project context on the clipboard`,
158
- `${g('tip:')} ${w('/tour')} walks you through everything PHEWSH can do`,
230
+ `${slate('·')} ${cream('/clarify')} ${sage('turns a messy idea into .intent/ artifacts')}`,
231
+ `${slate('·')} ${cream('/gate')} ${sage('sets constraints every AI response respects your budget and time')}`,
232
+ `${slate('·')} ${sage('Run')} ${cream('phewsh watch')} ${sage('in another tab keeps CLAUDE.md in sync with .intent/')}`,
233
+ `${slate('·')} ${cream('/export')} ${sage('exports .intent/ as portable context for any AI tool')}`,
234
+ `${slate('·')} ${sage('.intent/ files are plain markdown edit them directly anytime')}`,
235
+ `${slate('·')} ${cream('phewsh context --copy')} ${sage('puts your .intent/ context on the clipboard')}`,
236
+ `${slate('·')} ${cream('/tour')} ${sage('walks through the .intent/ workflow (no key needed)')}`,
237
+ `${slate('·')} ${sage('Everything works without an account. Account adds sync + sharing.')}`,
159
238
  ];
160
239
 
161
240
  function randomTip() {
@@ -165,88 +244,98 @@ function randomTip() {
165
244
  // ── Tour content ─────────────────────────────────────────
166
245
  const TOUR_PAGES = [
167
246
  {
168
- title: 'What is PHEWSH?',
247
+ title: 'What is .intent/?',
169
248
  body: [
170
- ` PHEWSH gives your project a ${b('portable identity')}.`,
171
- ` Define what you're building once — every AI tool reads it.`,
172
249
  '',
173
- ` It works ${w('standalone')} as its own AI shell,`,
174
- ` and ${w('inside')} Claude Code, Cursor, ChatGPT, and any MCP agent.`,
250
+ ` ${teal('.intent/')} ${sage('is your project\'s working memory.')}`,
251
+ ` Plain markdown files, committed with your code, read by every AI tool.`,
252
+ '',
253
+ ` ${cream('phew')} ${sage('— the relief of not re-explaining.')}`,
254
+ ` ${cream('shh')} ${sage('— it just works. No noise.')}`,
255
+ '',
256
+ ` PHEWSH is the tool that ${cream('authors')} and ${cream('syncs')} .intent/.`,
257
+ ` It works standalone, inside Claude Code, Cursor, ChatGPT, or any MCP agent.`,
175
258
  '',
176
- ` ${g('Your project context lives in')} ${cyan('.intent/')} ${g('— plain markdown files.')}`,
177
- ` ${g('You own them. They travel with your code.')}`,
259
+ ` ${sage('You own these files. They travel with your code.')}`,
260
+ ` ${sage('Everything works without an account. Account adds sync + sharing.')}`,
178
261
  ]
179
262
  },
180
263
  {
181
264
  title: 'The .intent/ directory',
182
265
  body: [
183
- ` ${cyan('.intent/')}`,
184
- ` ${green('vision.md')} ${g('What this project is and why it exists')}`,
185
- ` ${green('plan.md')} ${g('Strategy, phases, milestones')}`,
186
- ` ${green('next.md')} ${g('Current tasks and what to do right now')}`,
187
- ` ${yellow('gate.json')} ${g('Your constraints (budget, time, skill)')}`,
188
266
  '',
189
- ` ${g('Create these with')} /init ${g('or')} /clarify`,
267
+ ` ${teal('.intent/')}`,
268
+ ` ${peach('vision.md')} ${sage('What this project is and why it exists')}`,
269
+ ` ${peach('plan.md')} ${sage('Strategy, phases, milestones')}`,
270
+ ` ${peach('next.md')} ${sage('Current tasks and what to do right now')}`,
271
+ ` ${ember('gate.json')} ${sage('Your constraints (budget, time, skill)')}`,
272
+ '',
273
+ ` ${sage('Create these with')} ${cream('/init')} ${sage('or')} ${cream('/clarify')}`,
190
274
  ]
191
275
  },
192
276
  {
193
277
  title: 'Standalone mode',
194
278
  body: [
195
- ` When you run ${w('phewsh')} on its own, you get an AI shell`,
196
- ` that knows your project inside and out.`,
197
279
  '',
198
- ` Just type naturally:`,
199
- ` ${cyan('>')} what should I focus on today?`,
200
- ` ${cyan('>')} is my plan realistic given my budget?`,
201
- ` ${cyan('>')} break this feature into tasks`,
280
+ ` Run ${cream('phewsh')} and type naturally.`,
281
+ ` Every message carries your .intent/ context automatically.`,
282
+ '',
283
+ ` ${teal('phewsh')} ${sage('>')} what should I focus on today?`,
284
+ ` ${teal('phewsh')} ${sage('>')} is my plan realistic given my budget?`,
285
+ ` ${teal('phewsh')} ${sage('>')} break this feature into tasks`,
202
286
  '',
203
- ` ${g('Every message includes your vision, plan, and constraints.')}`,
287
+ ` ${sage('The AI reads .intent/ no warmup needed.')}`,
204
288
  ]
205
289
  },
206
290
  {
207
- title: 'Inside other tools',
291
+ title: '.intent/ in other tools',
208
292
  body: [
209
- ` ${b('Claude Code')} ${g('phewsh watch → auto-updates CLAUDE.md')}`,
210
- ` ${b('Cursor')} ${g('phewsh context --file → .phewsh.context')}`,
211
- ` ${b('ChatGPT')} ${g('phewsh context --copy → paste into Custom Instructions')}`,
212
- ` ${b('MCP agents')} ${g('phewsh mcp setup → agents pull tasks automatically')}`,
213
293
  '',
214
- ` ${g('Same project identity, every tool. No re-explaining.')}`,
294
+ ` ${b(cream('Claude Code'))} ${sage('phewsh watch CLAUDE.md stays in sync with .intent/')}`,
295
+ ` ${b(cream('Cursor'))} ${sage('phewsh context --file → exports .intent/ to .phewsh.context')}`,
296
+ ` ${b(cream('ChatGPT'))} ${sage('phewsh context --copy → .intent/ on your clipboard')}`,
297
+ ` ${b(cream('MCP agents'))} ${sage('phewsh mcp setup → agents read .intent/ automatically')}`,
298
+ '',
299
+ ` ${sage('Same .intent/. Every tool. Switch mid-thought. Nothing lost.')}`,
215
300
  ]
216
301
  },
217
302
  {
218
303
  title: 'The Decision Gate',
219
304
  body: [
220
- ` Before you build, decide ${b('whether')} to build.`,
305
+ '',
306
+ ` Before you build, decide ${b(cream('whether'))} to build.`,
221
307
  ` The gate captures what you can actually spend:`,
222
308
  '',
223
- ` ${g('Budget')} ${w('$50')} ${g('Skill')} ${w('expert')}`,
224
- ` ${g('Time')} ${w('15 hrs/week')} ${g('Urgency')} ${w('high')}`,
309
+ ` ${sage('Budget')} ${cream('$50')} ${sage('Skill')} ${cream('expert')}`,
310
+ ` ${sage('Time')} ${cream('15 hrs/week')} ${sage('Urgency')} ${cream('high')}`,
225
311
  '',
226
- ` ${g('These constraints shape every AI response.')}`,
227
- ` ${g('Run')} /gate activate ${g('to set yours.')}`,
312
+ ` ${sage('These constraints shape every AI response.')}`,
313
+ ` ${sage('Run')} ${cream('/gate activate')} ${sage('to set yours.')}`,
228
314
  ]
229
315
  },
230
316
  {
231
317
  title: 'You\'re ready',
232
318
  body: [
233
- ` ${green('●')} Type naturally to chat with your project context`,
234
- ` ${green('●')} ${w('/init')} or ${w('/clarify')} to create .intent/ artifacts`,
235
- ` ${green('●')} ${w('/gate')} to set your constraints`,
236
- ` ${green('●')} ${w('/help')} for all commands`,
237
319
  '',
238
- ` ${g('PHEWSH is your project\'s home base.')}`,
239
- ` ${g('The AI that knows you doesn\'t need to be re-taught.')}`,
320
+ ` ${teal('●')} ${cream('/init')} or ${cream('/clarify')} to create .intent/ artifacts`,
321
+ ` ${teal('●')} Type naturally .intent/ context is always loaded`,
322
+ ` ${teal('●')} ${cream('/gate')} to set your constraints`,
323
+ ` ${teal('●')} ${cream('phewsh watch')} to keep AI tools in sync`,
324
+ ` ${teal('●')} ${cream('/help')} for all commands`,
325
+ '',
326
+ ` ${sage('.intent/ is your project\'s working memory. PHEWSH keeps it useful.')}`,
240
327
  ]
241
328
  },
242
329
  ];
243
330
 
244
331
  module.exports = {
245
- // Colors
332
+ // Brand palette
333
+ teal, peach, sage, slate, cream, ember,
334
+ // Standard ANSI
246
335
  b, d, w, g, green, cyan, yellow, magenta, blue, red,
247
336
  // Components
248
337
  spinner, brandReveal, statusPanel, interopLine, divider, typewrite,
249
338
  randomTip, TOUR_PAGES,
250
339
  // ANSI helpers
251
- hide, show, up, clearLine,
340
+ hide, show, up, clearLine, sleep,
252
341
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phewsh",
3
- "version": "0.11.11",
3
+ "version": "0.11.13",
4
4
  "description": "Turn intent into action. Structure your thinking, execute your next step.",
5
5
  "bin": {
6
6
  "phewsh": "bin/phewsh.js"