phewsh 0.11.0 → 0.11.8

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/README.md CHANGED
@@ -12,6 +12,23 @@ npm install -g phewsh
12
12
 
13
13
  ```bash
14
14
  phewsh # enter the interactive shell
15
+ phewsh serve # start live execution bridge for phewsh.com/intent
16
+ ```
17
+
18
+ ## Live Execution
19
+
20
+ Connect the web app to your local machine for real-time task execution:
21
+
22
+ ```bash
23
+ phewsh serve
24
+ ```
25
+
26
+ This starts a bridge on `localhost:7483`. Open [phewsh.com/intent](https://phewsh.com/intent) and go to the Work tab — you'll see a green "Live" indicator. Agent tasks get a "Run Live" button that executes via Claude Code on your machine.
27
+
28
+ ## Interactive Shell
29
+
30
+ ```bash
31
+ phewsh
15
32
  ```
16
33
 
17
34
  Inside the shell:
@@ -22,7 +39,6 @@ Inside the shell:
22
39
  /push Sync local to cloud
23
40
  /pull Sync cloud to local
24
41
  /context View loaded artifacts
25
- /sync Check sync status
26
42
  /help All commands
27
43
  ```
28
44
 
@@ -36,9 +52,25 @@ Creates three structured artifacts in `.intent/`:
36
52
 
37
53
  These artifacts become persistent context for AI conversations, both in the shell and across tools.
38
54
 
55
+ ## All Commands
56
+
57
+ ```bash
58
+ phewsh # Interactive AI session with .intent/ context
59
+ phewsh serve # Live execution bridge for web app
60
+ phewsh clarify # AI-assisted artifact generation
61
+ phewsh intent --init # Create .intent/ without entering the shell
62
+ phewsh intent --status # Check artifact state
63
+ phewsh ai run "prompt" # One-shot AI with .intent/ context
64
+ phewsh login # Authenticate + set API key
65
+ phewsh push # Sync local .intent/ to cloud
66
+ phewsh pull # Sync cloud to local
67
+ phewsh mcp setup # Configure MCP server for agent connectivity
68
+ phewsh style # Build your style identity
69
+ ```
70
+
39
71
  ## Sync
40
72
 
41
- CLI and web (phewsh.com/intent) share the same cloud via Supabase.
73
+ CLI and web ([phewsh.com/intent](https://phewsh.com/intent)) share the same cloud via Supabase.
42
74
 
43
75
  ```bash
44
76
  phewsh login # authenticate
@@ -46,26 +78,7 @@ phewsh push # upload .intent/ to cloud
46
78
  phewsh pull # download from cloud
47
79
  ```
48
80
 
49
- Sync is manual. The CLI shows status on startup:
50
-
51
- ```
52
- ↓ Cloud is newer (2h ago) — run /pull
53
- ↑ Local changes not pushed (15m ago) — run /push
54
- ↕ synced
55
- ```
56
-
57
- The `/intent` Claude Code skill writes local files only — run `phewsh push` after using it.
58
-
59
- ## Non-interactive mode
60
-
61
- ```bash
62
- phewsh intent --init # Create .intent/ without entering the shell
63
- phewsh intent --status # Check artifact state
64
- phewsh clarify # AI-assisted artifact generation
65
- phewsh ai run "prompt" # One-shot AI with .intent/ context
66
- phewsh push # Sync to cloud
67
- phewsh pull # Sync from cloud
68
- ```
81
+ Sync is manual. The CLI shows status on startup.
69
82
 
70
83
  ## Web app
71
84
 
package/bin/phewsh.js CHANGED
@@ -47,7 +47,10 @@ const COMMANDS = {
47
47
  ai: () => require('../commands/ai'),
48
48
  style: () => require('../commands/style'),
49
49
  mbhd: () => require('../commands/mbhd'),
50
+ context: () => require('../commands/context'),
51
+ gate: () => require('../commands/gate'),
50
52
  sap: () => require('../commands/sap'),
53
+ watch: () => require('../commands/watch')(),
51
54
  mcp: () => require('../commands/mcp')(),
52
55
  serve: () => require('../commands/serve')(),
53
56
  help: showHelp,
@@ -73,7 +76,10 @@ function showHelp() {
73
76
  console.log(` ${w('link')} Link local .intent/ to a cloud project`);
74
77
  console.log(` ${w('intent')} Manage .intent/ artifacts — status, open, evolve`);
75
78
  console.log(` ${w('ai')} One-shot AI prompt (reads .intent/)`);
79
+ console.log(` ${w('gate')} Declare operational constraints (budget, time, skill)`);
80
+ console.log(` ${w('context')} Export portable context for any AI tool`);
76
81
  console.log(` ${w('login')} Set up identity, API key, and cloud sync`);
82
+ console.log(` ${w('watch')} Live sync — .intent/ changes push to cloud + CLAUDE.md`);
77
83
  console.log(` ${w('serve')} Start live execution bridge for the web app`);
78
84
  console.log(` ${w('mcp')} Connect AI agents — setup, sync, status`);
79
85
  console.log(` ${w('sap')} Sustainable AI Protocol — usage and accountability`);
@@ -0,0 +1,359 @@
1
+ // phewsh context
2
+ // Export portable adaptive context for any AI tool.
3
+ // Reads .intent/ artifacts + gate.json and generates an operational briefing.
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+
8
+ const INTENT_DIR = path.join(process.cwd(), '.intent');
9
+
10
+ const args = process.argv.slice(3);
11
+ const flags = {
12
+ full: args.includes('--full') || args.includes('-f'),
13
+ claude: args.includes('--claude'),
14
+ clipboard: args.includes('--copy') || args.includes('-c'),
15
+ file: args.includes('--file') || args.includes('-o'),
16
+ help: args.includes('--help') || args.includes('-h'),
17
+ };
18
+
19
+ function loadArtifact(name) {
20
+ const p = path.join(INTENT_DIR, name);
21
+ if (!fs.existsSync(p)) return null;
22
+ return fs.readFileSync(p, 'utf-8');
23
+ }
24
+
25
+ function loadGate() {
26
+ const p = path.join(INTENT_DIR, 'gate.json');
27
+ if (!fs.existsSync(p)) return null;
28
+ try { return JSON.parse(fs.readFileSync(p, 'utf-8')); } catch { return null; }
29
+ }
30
+
31
+ function extractExecutionState(nextContent) {
32
+ const items = [];
33
+ const stateMap = { ' ': 'todo', '-': 'in_progress', 'x': 'done', '!': 'blocked', '~': 'skipped' };
34
+
35
+ for (const line of nextContent.split('\n')) {
36
+ const match = line.match(/^[-*]\s*\[([ x!\-~])\]\s*\*?\*?(.+?)\*?\*?\s*$/);
37
+ if (match) {
38
+ const char = match[1] === '-' ? '-' : match[1];
39
+ items.push({ title: match[2].replace(/\*\*/g, '').trim(), state: stateMap[char] || 'todo' });
40
+ }
41
+ }
42
+
43
+ return {
44
+ total: items.length,
45
+ done: items.filter(i => i.state === 'done').length,
46
+ doing: items.filter(i => i.state === 'in_progress').length,
47
+ blocked: items.filter(i => i.state === 'blocked').length,
48
+ skipped: items.filter(i => i.state === 'skipped').length,
49
+ items,
50
+ };
51
+ }
52
+
53
+ function buildConstraintInstructions(c) {
54
+ const lines = [];
55
+
56
+ if (c.budget > 0) {
57
+ lines.push(`- Budget: $${c.budget} total. ${
58
+ c.budget < 100 ? 'Extremely tight — free/open-source only.'
59
+ : c.budget < 500 ? 'Limited — justify any paid tool.'
60
+ : c.budget < 2000 ? 'Moderate — strategic spending OK.'
61
+ : 'Substantial — professional tools welcome.'
62
+ }`);
63
+ }
64
+
65
+ if (c.timeHoursPerWeek > 0) {
66
+ lines.push(`- Time: ${c.timeHoursPerWeek} hrs/week. ${
67
+ c.timeHoursPerWeek <= 5 ? 'Micro-steps only. Each task < 2 hours.'
68
+ : c.timeHoursPerWeek <= 15 ? 'Part-time. Clear stopping points.'
69
+ : c.timeHoursPerWeek <= 30 ? 'Near full-time. Sustained work OK.'
70
+ : 'Full-time+. Ambitious scope OK.'
71
+ }`);
72
+ }
73
+
74
+ lines.push(`- Skill: ${c.skillLevel}. ${
75
+ c.skillLevel === 'beginner' ? 'Explain everything. Simplest architecture wins.'
76
+ : c.skillLevel === 'intermediate' ? 'Reference docs, flag gotchas.'
77
+ : c.skillLevel === 'advanced' ? 'Focus on strategic decisions.'
78
+ : 'Deep expertise. Advanced patterns welcome.'
79
+ }`);
80
+
81
+ lines.push(`- Urgency: ${c.urgency}. ${
82
+ c.urgency === 'relaxed' ? 'Thoroughness over speed.'
83
+ : c.urgency === 'moderate' ? 'Weeks not months. Proven approaches.'
84
+ : c.urgency === 'urgent' ? 'Days matter. Cut scope aggressively.'
85
+ : 'BLOCKING. Strip to essentials.'
86
+ }`);
87
+
88
+ lines.push(`- Autonomy: ${c.autonomy}. ${
89
+ c.autonomy === 'hands-on' ? 'Present options, not recommendations.'
90
+ : c.autonomy === 'guided' ? 'Opinionated suggestions with reasoning.'
91
+ : c.autonomy === 'delegated' ? 'Be decisive. Only escalate irreversible decisions.'
92
+ : 'Maximum automation.'
93
+ }`);
94
+
95
+ return lines.join('\n');
96
+ }
97
+
98
+ function generateContext(includeArtifacts = false) {
99
+ const vision = loadArtifact('vision.md');
100
+ const plan = loadArtifact('plan.md');
101
+ const next = loadArtifact('next.md');
102
+ const gate = loadGate();
103
+ const projectName = path.basename(process.cwd());
104
+
105
+ if (!vision && !plan && !next) return null;
106
+
107
+ const sections = [];
108
+ const constraints = gate?.constraints;
109
+ const hasConstraints = constraints && (
110
+ constraints.budget > 0 ||
111
+ constraints.timeHoursPerWeek > 0 ||
112
+ constraints.skillLevel !== 'intermediate' ||
113
+ constraints.urgency !== 'moderate' ||
114
+ constraints.autonomy !== 'guided'
115
+ );
116
+
117
+ // Header
118
+ sections.push(`# PHEWSH Adaptive Context — ${projectName}`);
119
+ sections.push(`> Generated ${new Date().toISOString().split('T')[0]} | phewsh.com/intent`);
120
+ sections.push(`> Drop this into CLAUDE.md, .cursorrules, or agent config.`);
121
+ sections.push('');
122
+
123
+ // Project identity
124
+ sections.push('## Project');
125
+ sections.push(`- **Name**: ${projectName}`);
126
+ if (gate?.archetype) sections.push(`- **Type**: ${gate.archetype}`);
127
+
128
+ // Extract TLDR from vision first line
129
+ if (vision) {
130
+ const firstMeaningful = vision.split('\n').find(l => l.trim().length > 20 && !l.startsWith('#'));
131
+ if (firstMeaningful) sections.push(`- **TLDR**: ${firstMeaningful.trim()}`);
132
+ }
133
+ sections.push('');
134
+
135
+ // Operational constraints
136
+ if (hasConstraints) {
137
+ sections.push('## Operational Reality');
138
+ sections.push('These constraints MUST shape every suggestion and implementation decision:');
139
+ sections.push('');
140
+ sections.push(buildConstraintInstructions(constraints));
141
+ sections.push('');
142
+
143
+ // Execution Reality Map
144
+ if (gate?.executionMap) {
145
+ const map = gate.executionMap;
146
+ sections.push('### Execution Assessment');
147
+ sections.push(`- **Feasibility**: ${gate.feasibility}`);
148
+ if (map.recommendedMode) sections.push(`- **Recommended mode**: ${map.recommendedMode}`);
149
+ if (map.primaryBottleneck) sections.push(`- **Primary bottleneck**: ${map.primaryBottleneck}`);
150
+ if (map.highestLeveragePath) sections.push(`- **Highest leverage move**: ${map.highestLeveragePath}`);
151
+ if (map.estimatedTimeline) sections.push(`- **Timeline**: ${map.estimatedTimeline}`);
152
+ if (map.majorRisks?.length > 0) sections.push(`- **Risks**: ${map.majorRisks.join('; ')}`);
153
+ sections.push('');
154
+ }
155
+ }
156
+
157
+ // Execution state
158
+ if (next) {
159
+ const exec = extractExecutionState(next);
160
+ if (exec.total > 0) {
161
+ sections.push('## Current Execution State');
162
+ sections.push(`Progress: ${exec.done}/${exec.total} done${exec.doing ? `, ${exec.doing} in progress` : ''}${exec.blocked ? `, ${exec.blocked} blocked` : ''}`);
163
+ sections.push('');
164
+
165
+ const doing = exec.items.filter(i => i.state === 'in_progress');
166
+ if (doing.length > 0) {
167
+ sections.push('**Currently working on:**');
168
+ doing.forEach(i => sections.push(`- ${i.title}`));
169
+ sections.push('');
170
+ }
171
+
172
+ const blocked = exec.items.filter(i => i.state === 'blocked');
173
+ if (blocked.length > 0) {
174
+ sections.push('**Blocked:**');
175
+ blocked.forEach(i => sections.push(`- ${i.title}`));
176
+ sections.push('');
177
+ }
178
+
179
+ const todo = exec.items.filter(i => i.state === 'todo');
180
+ if (todo.length > 0) {
181
+ sections.push('**Remaining:**');
182
+ todo.forEach(i => sections.push(`- ${i.title}`));
183
+ sections.push('');
184
+ }
185
+ }
186
+ }
187
+
188
+ // Constraint drift
189
+ if (gate?.constraintHistory?.length > 0) {
190
+ sections.push('### Constraint Drift');
191
+ sections.push('Reality changed during this project:');
192
+ sections.push('');
193
+ for (const ch of gate.constraintHistory.slice(-10)) {
194
+ const date = ch.timestamp.split('T')[0];
195
+ sections.push(`- **${ch.field}**: ${ch.from} → ${ch.to}${ch.reason ? ` (${ch.reason})` : ''} — ${date}`);
196
+ }
197
+ sections.push('');
198
+ }
199
+
200
+ // Responsibility split
201
+ if (gate?.responsibilitySplit) {
202
+ sections.push('## Responsibility Split');
203
+ if (gate.responsibilitySplit.ai?.length > 0) {
204
+ sections.push('**AI/agents can handle:**');
205
+ gate.responsibilitySplit.ai.forEach(r => sections.push(`- ${r}`));
206
+ }
207
+ if (gate.responsibilitySplit.human?.length > 0) {
208
+ sections.push('**Requires human action:**');
209
+ gate.responsibilitySplit.human.forEach(r => sections.push(`- ${r}`));
210
+ }
211
+ sections.push('');
212
+ }
213
+
214
+ // AI instructions
215
+ sections.push('## Instructions for AI Tools');
216
+ sections.push('When working on this project:');
217
+ const instructions = [];
218
+
219
+ if (hasConstraints) {
220
+ instructions.push('- Adapt ALL suggestions to the operational constraints above.');
221
+ if (constraints.budget > 0 && constraints.budget < 500) {
222
+ instructions.push('- Never recommend paid services without noting cost and a free alternative.');
223
+ }
224
+ if (constraints.timeHoursPerWeek > 0 && constraints.timeHoursPerWeek <= 10) {
225
+ instructions.push('- Break every task into steps completable in a single sitting.');
226
+ }
227
+ if (constraints.skillLevel === 'beginner') {
228
+ instructions.push('- Explain every tool, concept, and command. No assumed knowledge.');
229
+ }
230
+ if (constraints.urgency === 'urgent' || constraints.urgency === 'critical') {
231
+ instructions.push('- Prioritize shipping over polish. Cut scope ruthlessly.');
232
+ }
233
+ }
234
+
235
+ if (next) {
236
+ const exec = extractExecutionState(next);
237
+ const blockedCount = exec.items.filter(i => i.state === 'blocked').length;
238
+ if (blockedCount > 0) {
239
+ instructions.push(`- ${blockedCount} task(s) are blocked. Suggest alternative approaches if relevant.`);
240
+ }
241
+ if (exec.done > 0 && exec.total > 0) {
242
+ const pct = Math.round((exec.done / exec.total) * 100);
243
+ instructions.push(`- Project is ${pct}% complete. Focus on remaining work.`);
244
+ }
245
+ }
246
+
247
+ if (instructions.length === 0) {
248
+ instructions.push('- Follow the project vision and plan. Check execution state for current progress.');
249
+ }
250
+ sections.push(instructions.join('\n'));
251
+ sections.push('');
252
+
253
+ // Full artifacts (optional)
254
+ if (includeArtifacts) {
255
+ if (vision) { sections.push('## Vision'); sections.push(vision); sections.push(''); }
256
+ if (plan) { sections.push('## Plan'); sections.push(plan); sections.push(''); }
257
+ if (next) { sections.push('## Next Actions'); sections.push(next); sections.push(''); }
258
+ }
259
+
260
+ sections.push('---');
261
+ sections.push('*Exported from [PHEWSH Intent](https://phewsh.com/intent) — software that adapts to you.*');
262
+
263
+ return sections.join('\n');
264
+ }
265
+
266
+ function showHelp() {
267
+ console.log(`
268
+ phewsh context — Export portable adaptive context
269
+
270
+ Usage:
271
+ phewsh context Generate context to stdout
272
+ phewsh context --full Include full artifact text
273
+ phewsh context --copy Copy to clipboard
274
+ phewsh context --file Write to .phewsh.context in current directory
275
+ phewsh context --claude Write to CLAUDE.md (for Claude Code)
276
+
277
+ What it does:
278
+ Reads .intent/ artifacts + gate.json and produces an operational
279
+ briefing that makes any AI tool constraint-aware.
280
+
281
+ Drop the output into CLAUDE.md, .cursorrules, or agent config.
282
+ `);
283
+ }
284
+
285
+ async function main() {
286
+ if (flags.help) { showHelp(); return; }
287
+
288
+ if (!fs.existsSync(INTENT_DIR)) {
289
+ console.log('\n No .intent/ found. Run `phewsh intent --init` first.\n');
290
+ process.exit(1);
291
+ }
292
+
293
+ const content = generateContext(flags.full);
294
+ if (!content) {
295
+ console.log('\n No artifacts found in .intent/\n');
296
+ process.exit(1);
297
+ }
298
+
299
+ if (flags.file) {
300
+ const outPath = path.join(process.cwd(), '.phewsh.context');
301
+ fs.writeFileSync(outPath, content);
302
+ console.log(`\n ✓ Written to ${outPath}\n`);
303
+ return;
304
+ }
305
+
306
+ if (flags.claude) {
307
+ const outPath = path.join(process.cwd(), 'CLAUDE.md');
308
+ const START_MARKER = '<!-- PHEWSH:START -->';
309
+ const END_MARKER = '<!-- PHEWSH:END -->';
310
+ const wrapped = `${START_MARKER}\n${content}\n${END_MARKER}`;
311
+
312
+ if (fs.existsSync(outPath)) {
313
+ let existing = fs.readFileSync(outPath, 'utf-8');
314
+ const startIdx = existing.indexOf(START_MARKER);
315
+ const endIdx = existing.indexOf(END_MARKER);
316
+ if (startIdx !== -1 && endIdx !== -1) {
317
+ existing = existing.slice(0, startIdx) + wrapped + existing.slice(endIdx + END_MARKER.length);
318
+ fs.writeFileSync(outPath, existing);
319
+ console.log('\n ✓ Updated PHEWSH section in CLAUDE.md\n');
320
+ } else {
321
+ fs.writeFileSync(outPath, existing.trimEnd() + '\n\n' + wrapped + '\n');
322
+ console.log('\n ✓ Appended to CLAUDE.md\n');
323
+ }
324
+ } else {
325
+ fs.writeFileSync(outPath, wrapped + '\n');
326
+ console.log('\n ✓ Created CLAUDE.md\n');
327
+ }
328
+ console.log(' Tip: Run `phewsh watch` to keep this section auto-synced.\n');
329
+ return;
330
+ }
331
+
332
+ if (flags.clipboard) {
333
+ try {
334
+ const { execSync } = require('child_process');
335
+ if (process.platform === 'darwin') {
336
+ execSync('pbcopy', { input: content });
337
+ } else if (process.platform === 'linux') {
338
+ execSync('xclip -selection clipboard', { input: content });
339
+ } else {
340
+ execSync('clip', { input: content });
341
+ }
342
+ console.log('\n ✓ Copied to clipboard\n');
343
+ } catch {
344
+ // Fallback: print to stdout
345
+ console.log(content);
346
+ }
347
+ return;
348
+ }
349
+
350
+ // Default: print to stdout
351
+ console.log(content);
352
+ }
353
+
354
+ module.exports = { main, generateContext };
355
+
356
+ main().catch(err => {
357
+ console.error('\n Error:', err.message);
358
+ process.exit(1);
359
+ });