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 +35 -22
- package/bin/phewsh.js +6 -0
- package/commands/context.js +359 -0
- package/commands/gate.js +340 -0
- package/commands/intent.js +155 -6
- package/commands/mcp.js +2 -2
- package/commands/session.js +52 -5
- package/commands/sync.js +38 -0
- package/commands/watch.js +399 -0
- package/package.json +3 -2
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
|
+
});
|