beth-copilot 1.0.5 → 1.0.10
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/bin/cli.js +374 -55
- package/package.json +1 -1
- package/templates/.github/agents/beth.agent.md +71 -15
- package/templates/.github/agents/developer.agent.md +10 -0
- package/templates/.github/agents/product-manager.agent.md +10 -0
- package/templates/.github/agents/researcher.agent.md +10 -0
- package/templates/.github/agents/security-reviewer.agent.md +10 -0
- package/templates/.github/agents/tester.agent.md +10 -0
- package/templates/.github/agents/ux-designer.agent.md +10 -0
package/bin/cli.js
CHANGED
|
@@ -44,6 +44,32 @@ function logInfo(message) {
|
|
|
44
44
|
log(` ${message}`, COLORS.cyan);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
function logDebug(message) {
|
|
48
|
+
if (globalThis.VERBOSE) {
|
|
49
|
+
log(` [debug] ${message}`, COLORS.yellow);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function showPathDiagnostics() {
|
|
54
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
55
|
+
const isWindows = process.platform === 'win32';
|
|
56
|
+
|
|
57
|
+
console.log('');
|
|
58
|
+
log('PATH Diagnostics:', COLORS.bright);
|
|
59
|
+
logInfo(`Platform: ${process.platform}`);
|
|
60
|
+
logInfo(`HOME: ${homeDir}`);
|
|
61
|
+
logInfo(`PATH: ${process.env.PATH}`);
|
|
62
|
+
|
|
63
|
+
if (isWindows) {
|
|
64
|
+
logInfo(`APPDATA: ${process.env.APPDATA || '(not set)'}`);
|
|
65
|
+
logInfo(`npm prefix: Run "npm config get prefix" to check`);
|
|
66
|
+
} else {
|
|
67
|
+
logInfo(`npm prefix: Run "npm config get prefix" to check`);
|
|
68
|
+
logInfo(`Common locations: ~/.local/bin, /usr/local/bin, ~/.npm-global/bin`);
|
|
69
|
+
}
|
|
70
|
+
console.log('');
|
|
71
|
+
}
|
|
72
|
+
|
|
47
73
|
async function checkForUpdates() {
|
|
48
74
|
try {
|
|
49
75
|
const response = await fetch('https://registry.npmjs.org/beth-copilot/latest', {
|
|
@@ -75,24 +101,96 @@ async function checkForUpdates() {
|
|
|
75
101
|
}
|
|
76
102
|
}
|
|
77
103
|
|
|
78
|
-
function
|
|
104
|
+
function getBacklogPath() {
|
|
105
|
+
// Check if backlog is available in PATH
|
|
79
106
|
try {
|
|
107
|
+
logDebug('Checking if backlog is in PATH...');
|
|
80
108
|
execSync('backlog --version', { stdio: 'ignore' });
|
|
81
|
-
|
|
109
|
+
logDebug('Found backlog in PATH');
|
|
110
|
+
return 'backlog';
|
|
82
111
|
} catch {
|
|
83
|
-
|
|
112
|
+
logDebug('backlog not in PATH, checking common locations...');
|
|
113
|
+
// Check common installation paths
|
|
114
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
115
|
+
const isWindows = process.platform === 'win32';
|
|
116
|
+
|
|
117
|
+
const commonPaths = isWindows ? [
|
|
118
|
+
join(process.env.APPDATA || '', 'npm', 'backlog.cmd'),
|
|
119
|
+
join(homeDir, 'AppData', 'Roaming', 'npm', 'backlog.cmd'),
|
|
120
|
+
join(homeDir, 'AppData', 'Local', 'npm-global', 'backlog.cmd'),
|
|
121
|
+
] : [
|
|
122
|
+
join(homeDir, '.local', 'bin', 'backlog'),
|
|
123
|
+
join(homeDir, 'bin', 'backlog'),
|
|
124
|
+
'/usr/local/bin/backlog',
|
|
125
|
+
join(homeDir, '.npm-global', 'bin', 'backlog'),
|
|
126
|
+
join(homeDir, '.bun', 'bin', 'backlog'),
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
for (const backlogPath of commonPaths) {
|
|
130
|
+
logDebug(`Checking: ${backlogPath}`);
|
|
131
|
+
if (existsSync(backlogPath)) {
|
|
132
|
+
logDebug(`Found at: ${backlogPath}`);
|
|
133
|
+
return backlogPath;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
logDebug('backlog not found in any common location');
|
|
138
|
+
return null;
|
|
84
139
|
}
|
|
85
140
|
}
|
|
86
141
|
|
|
87
|
-
function
|
|
142
|
+
function isBacklogCliInstalled() {
|
|
143
|
+
return getBacklogPath() !== null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function getBeadsPath() {
|
|
147
|
+
// Check if bd is available in PATH
|
|
88
148
|
try {
|
|
149
|
+
logDebug('Checking if bd is in PATH...');
|
|
89
150
|
execSync('bd --version', { stdio: 'ignore' });
|
|
90
|
-
|
|
151
|
+
logDebug('Found bd in PATH');
|
|
152
|
+
return 'bd';
|
|
91
153
|
} catch {
|
|
92
|
-
|
|
154
|
+
logDebug('bd not in PATH, checking common locations...');
|
|
155
|
+
// Check common installation paths based on platform
|
|
156
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
157
|
+
const isWindows = process.platform === 'win32';
|
|
158
|
+
|
|
159
|
+
const commonPaths = isWindows ? [
|
|
160
|
+
// Windows: npm global, Go bin, local apps
|
|
161
|
+
join(process.env.APPDATA || '', 'npm', 'bd.cmd'),
|
|
162
|
+
join(homeDir, 'AppData', 'Roaming', 'npm', 'bd.cmd'),
|
|
163
|
+
join(homeDir, 'AppData', 'Local', 'Microsoft', 'WindowsApps', 'bd.exe'),
|
|
164
|
+
join(homeDir, 'go', 'bin', 'bd.exe'),
|
|
165
|
+
join(process.env.GOPATH || join(homeDir, 'go'), 'bin', 'bd.exe'),
|
|
166
|
+
] : [
|
|
167
|
+
// Unix: homebrew, npm global, go bin, local bin
|
|
168
|
+
'/opt/homebrew/bin/bd',
|
|
169
|
+
'/usr/local/bin/bd',
|
|
170
|
+
join(homeDir, '.local', 'bin', 'bd'),
|
|
171
|
+
join(homeDir, 'bin', 'bd'),
|
|
172
|
+
join(homeDir, '.npm-global', 'bin', 'bd'),
|
|
173
|
+
join(homeDir, 'go', 'bin', 'bd'),
|
|
174
|
+
join(process.env.GOPATH || join(homeDir, 'go'), 'bin', 'bd'),
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
for (const bdPath of commonPaths) {
|
|
178
|
+
logDebug(`Checking: ${bdPath}`);
|
|
179
|
+
if (existsSync(bdPath)) {
|
|
180
|
+
logDebug(`Found at: ${bdPath}`);
|
|
181
|
+
return bdPath;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
logDebug('bd not found in any common location');
|
|
186
|
+
return null;
|
|
93
187
|
}
|
|
94
188
|
}
|
|
95
189
|
|
|
190
|
+
function isBeadsInstalled() {
|
|
191
|
+
return getBeadsPath() !== null;
|
|
192
|
+
}
|
|
193
|
+
|
|
96
194
|
function isBeadsInitialized(cwd) {
|
|
97
195
|
// Check if .beads directory exists in the project
|
|
98
196
|
return existsSync(join(cwd, '.beads'));
|
|
@@ -113,8 +211,27 @@ async function promptYesNo(question) {
|
|
|
113
211
|
});
|
|
114
212
|
}
|
|
115
213
|
|
|
214
|
+
async function promptForInput(question) {
|
|
215
|
+
const readline = await import('readline');
|
|
216
|
+
const rl = readline.createInterface({
|
|
217
|
+
input: process.stdin,
|
|
218
|
+
output: process.stdout
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
return new Promise((resolve) => {
|
|
222
|
+
rl.question(`${question} `, (answer) => {
|
|
223
|
+
rl.close();
|
|
224
|
+
resolve(answer.trim());
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
116
229
|
async function installBacklogCli() {
|
|
117
|
-
|
|
230
|
+
const isWindows = process.platform === 'win32';
|
|
231
|
+
const isMac = process.platform === 'darwin';
|
|
232
|
+
|
|
233
|
+
log('\nInstalling backlog.md CLI via npm...', COLORS.cyan);
|
|
234
|
+
logInfo('npm install -g backlog.md');
|
|
118
235
|
|
|
119
236
|
return new Promise((resolve) => {
|
|
120
237
|
const child = spawn('npm', ['install', '-g', 'backlog.md'], {
|
|
@@ -124,60 +241,125 @@ async function installBacklogCli() {
|
|
|
124
241
|
|
|
125
242
|
child.on('close', (code) => {
|
|
126
243
|
if (code === 0) {
|
|
127
|
-
|
|
128
|
-
|
|
244
|
+
// CRITICAL: Verify installation actually worked before claiming success
|
|
245
|
+
const verifiedPath = getBacklogPath();
|
|
246
|
+
if (verifiedPath) {
|
|
247
|
+
logSuccess('backlog.md CLI installed and verified!');
|
|
248
|
+
resolve(true);
|
|
249
|
+
} else {
|
|
250
|
+
logWarning('npm reported success but backlog CLI not found in PATH.');
|
|
251
|
+
logInfo('This can happen if npm global bin is not in your PATH.');
|
|
252
|
+
if (globalThis.VERBOSE) {
|
|
253
|
+
showPathDiagnostics();
|
|
254
|
+
} else {
|
|
255
|
+
logInfo('Run with --verbose for PATH diagnostics.');
|
|
256
|
+
}
|
|
257
|
+
console.log('');
|
|
258
|
+
showBacklogAlternatives(isMac);
|
|
259
|
+
resolve(false);
|
|
260
|
+
}
|
|
129
261
|
} else {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
logInfo('bun i -g backlog.md');
|
|
262
|
+
logError('npm install failed.');
|
|
263
|
+
console.log('');
|
|
264
|
+
showBacklogAlternatives(isMac);
|
|
134
265
|
resolve(false);
|
|
135
266
|
}
|
|
136
267
|
});
|
|
137
268
|
|
|
138
269
|
child.on('error', () => {
|
|
139
|
-
|
|
140
|
-
logInfo('npm
|
|
270
|
+
logError('Failed to run npm.');
|
|
271
|
+
logInfo('Make sure npm is installed and in your PATH.');
|
|
141
272
|
resolve(false);
|
|
142
273
|
});
|
|
143
274
|
});
|
|
144
275
|
}
|
|
145
276
|
|
|
277
|
+
function showBacklogAlternatives(isMac) {
|
|
278
|
+
logInfo('Alternative installation methods:');
|
|
279
|
+
if (isMac) {
|
|
280
|
+
logInfo(' Homebrew: brew install backlog-md');
|
|
281
|
+
}
|
|
282
|
+
logInfo(' Bun: bun install -g backlog.md');
|
|
283
|
+
logInfo('');
|
|
284
|
+
logInfo('Learn more: https://github.com/MrLesk/Backlog.md');
|
|
285
|
+
}
|
|
286
|
+
|
|
146
287
|
async function installBeads() {
|
|
147
|
-
|
|
148
|
-
|
|
288
|
+
const isWindows = process.platform === 'win32';
|
|
289
|
+
const isMac = process.platform === 'darwin';
|
|
290
|
+
|
|
291
|
+
log('\nInstalling beads CLI via npm...', COLORS.cyan);
|
|
292
|
+
logInfo('npm install -g @beads/bd');
|
|
149
293
|
|
|
150
294
|
return new Promise((resolve) => {
|
|
151
|
-
const child = spawn('
|
|
295
|
+
const child = spawn('npm', ['install', '-g', '@beads/bd'], {
|
|
152
296
|
stdio: 'inherit',
|
|
153
297
|
shell: true
|
|
154
298
|
});
|
|
155
299
|
|
|
156
300
|
child.on('close', (code) => {
|
|
157
301
|
if (code === 0) {
|
|
158
|
-
|
|
159
|
-
|
|
302
|
+
// CRITICAL: Verify installation actually worked before claiming success
|
|
303
|
+
// npm can exit 0 even when the package isn't properly installed
|
|
304
|
+
const verifiedPath = getBeadsPath();
|
|
305
|
+
if (verifiedPath) {
|
|
306
|
+
logSuccess('beads CLI installed and verified!');
|
|
307
|
+
resolve(true);
|
|
308
|
+
} else {
|
|
309
|
+
logWarning('npm reported success but beads CLI not found in PATH.');
|
|
310
|
+
logInfo('This can happen if npm global bin is not in your PATH.');
|
|
311
|
+
if (globalThis.VERBOSE) {
|
|
312
|
+
showPathDiagnostics();
|
|
313
|
+
} else {
|
|
314
|
+
logInfo('Run with --verbose for PATH diagnostics.');
|
|
315
|
+
}
|
|
316
|
+
console.log('');
|
|
317
|
+
showBeadsAlternatives(isWindows, isMac);
|
|
318
|
+
resolve(false);
|
|
319
|
+
}
|
|
160
320
|
} else {
|
|
161
|
-
logError('
|
|
162
|
-
|
|
163
|
-
|
|
321
|
+
logError('npm install failed.');
|
|
322
|
+
console.log('');
|
|
323
|
+
showBeadsAlternatives(isWindows, isMac);
|
|
164
324
|
resolve(false);
|
|
165
325
|
}
|
|
166
326
|
});
|
|
167
327
|
|
|
168
328
|
child.on('error', () => {
|
|
169
|
-
logError('Failed to
|
|
170
|
-
logInfo('
|
|
329
|
+
logError('Failed to run npm.');
|
|
330
|
+
logInfo('Make sure npm is installed and in your PATH.');
|
|
171
331
|
resolve(false);
|
|
172
332
|
});
|
|
173
333
|
});
|
|
174
334
|
}
|
|
175
335
|
|
|
336
|
+
function showBeadsAlternatives(isWindows, isMac) {
|
|
337
|
+
logInfo('Alternative installation methods:');
|
|
338
|
+
if (isWindows) {
|
|
339
|
+
logInfo(' PowerShell: irm https://raw.githubusercontent.com/steveyegge/beads/main/install.ps1 | iex');
|
|
340
|
+
logInfo(' Go: go install github.com/steveyegge/beads/cmd/bd@latest');
|
|
341
|
+
} else {
|
|
342
|
+
if (isMac) {
|
|
343
|
+
logInfo(' Homebrew: brew install beads');
|
|
344
|
+
}
|
|
345
|
+
logInfo(' Script: curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash');
|
|
346
|
+
logInfo(' Go: go install github.com/steveyegge/beads/cmd/bd@latest');
|
|
347
|
+
}
|
|
348
|
+
logInfo('');
|
|
349
|
+
logInfo('Learn more: https://github.com/steveyegge/beads');
|
|
350
|
+
}
|
|
351
|
+
|
|
176
352
|
async function initializeBeads(cwd) {
|
|
177
353
|
log('\nInitializing beads in project...', COLORS.cyan);
|
|
178
354
|
|
|
355
|
+
const bdPath = getBeadsPath();
|
|
356
|
+
if (!bdPath) {
|
|
357
|
+
logWarning('Failed to initialize beads. Run manually: bd init');
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
|
|
179
361
|
return new Promise((resolve) => {
|
|
180
|
-
const child = spawn(
|
|
362
|
+
const child = spawn(bdPath, ['init'], {
|
|
181
363
|
stdio: 'inherit',
|
|
182
364
|
shell: true,
|
|
183
365
|
cwd
|
|
@@ -213,6 +395,7 @@ ${COLORS.bright}Options:${COLORS.reset}
|
|
|
213
395
|
--skip-backlog Don't create Backlog.md
|
|
214
396
|
--skip-mcp Don't create mcp.json.example
|
|
215
397
|
--skip-beads Skip beads check (not recommended)
|
|
398
|
+
--verbose Show detailed diagnostics on errors
|
|
216
399
|
|
|
217
400
|
${COLORS.bright}Examples:${COLORS.reset}
|
|
218
401
|
npx beth-copilot init Set up Beth in current project
|
|
@@ -284,6 +467,7 @@ ${COLORS.yellow}╔════════════════════
|
|
|
284
467
|
console.log(`
|
|
285
468
|
${COLORS.bright}🤠 Beth is moving in.${COLORS.reset}
|
|
286
469
|
${COLORS.cyan}"I don't do excuses. I do results."${COLORS.reset}
|
|
470
|
+
${COLORS.yellow}Tip: Run with --verbose for detailed diagnostics if you hit issues.${COLORS.reset}
|
|
287
471
|
`);
|
|
288
472
|
|
|
289
473
|
// Check if templates exist
|
|
@@ -382,7 +566,10 @@ ${COLORS.cyan}"I don't do excuses. I do results."${COLORS.reset}
|
|
|
382
566
|
console.log('');
|
|
383
567
|
log('Checking beads (required for task tracking)...', COLORS.cyan);
|
|
384
568
|
|
|
385
|
-
|
|
569
|
+
let bdPath = getBeadsPath();
|
|
570
|
+
|
|
571
|
+
// Loop until beads is installed
|
|
572
|
+
while (!bdPath) {
|
|
386
573
|
logWarning('beads CLI is not installed.');
|
|
387
574
|
logInfo('Beth requires beads for task tracking. Agents use it to coordinate work.');
|
|
388
575
|
logInfo('Learn more: https://github.com/steveyegge/beads');
|
|
@@ -391,16 +578,67 @@ ${COLORS.cyan}"I don't do excuses. I do results."${COLORS.reset}
|
|
|
391
578
|
const shouldInstallBeads = await promptYesNo('Install beads CLI now? (required)');
|
|
392
579
|
if (shouldInstallBeads) {
|
|
393
580
|
const installed = await installBeads();
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
|
|
581
|
+
if (installed) {
|
|
582
|
+
// Re-check for beads after installation
|
|
583
|
+
bdPath = getBeadsPath();
|
|
584
|
+
if (!bdPath) {
|
|
585
|
+
console.log('');
|
|
586
|
+
logWarning('beads installed but not found in common paths.');
|
|
587
|
+
logInfo('The installer may have placed it in a custom location.');
|
|
588
|
+
console.log('');
|
|
589
|
+
logInfo('Please try one of these options:');
|
|
590
|
+
logInfo(' 1. Open a NEW terminal and run: npx beth-copilot init');
|
|
591
|
+
logInfo(' 2. Add ~/.local/bin to your PATH and retry');
|
|
592
|
+
logInfo(' 3. Run: source ~/.bashrc (or ~/.zshrc) then retry');
|
|
593
|
+
console.log('');
|
|
594
|
+
|
|
595
|
+
const retryCheck = await promptYesNo('Retry detection? (select No to enter path manually)');
|
|
596
|
+
if (retryCheck) {
|
|
597
|
+
bdPath = getBeadsPath();
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Allow manual path entry
|
|
602
|
+
const customPath = await promptForInput('Enter full path to bd binary (or press Enter to retry installation):');
|
|
603
|
+
if (customPath && existsSync(customPath)) {
|
|
604
|
+
bdPath = customPath;
|
|
605
|
+
logSuccess(`Found beads at: ${bdPath}`);
|
|
606
|
+
} else if (customPath) {
|
|
607
|
+
logError(`File not found: ${customPath}`);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
} else {
|
|
611
|
+
console.log('');
|
|
612
|
+
logError('Installation script failed.');
|
|
613
|
+
logInfo('You can try installing manually:');
|
|
614
|
+
logInfo(' curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash');
|
|
615
|
+
console.log('');
|
|
616
|
+
}
|
|
617
|
+
} else {
|
|
618
|
+
console.log('');
|
|
619
|
+
logError('beads is REQUIRED for Beth to function.');
|
|
620
|
+
logInfo('Beth agents use beads to track tasks, dependencies, and coordinate work.');
|
|
621
|
+
logInfo('Without beads, the multi-agent workflow will not work correctly.');
|
|
622
|
+
console.log('');
|
|
623
|
+
|
|
624
|
+
const tryAgain = await promptYesNo('Would you like to try installing beads?');
|
|
625
|
+
if (!tryAgain) {
|
|
626
|
+
logError('Cannot continue without beads. Exiting.');
|
|
627
|
+
logInfo('Install beads manually and run "npx beth-copilot init" again:');
|
|
628
|
+
logInfo(' npm install -g @beads/bd');
|
|
397
629
|
process.exit(1);
|
|
398
630
|
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Show path info if not in standard PATH
|
|
635
|
+
if (bdPath && bdPath !== 'bd') {
|
|
636
|
+
logSuccess(`beads CLI found at: ${bdPath}`);
|
|
637
|
+
const isWindows = process.platform === 'win32';
|
|
638
|
+
if (isWindows) {
|
|
639
|
+
logInfo('Tip: Ensure npm global bin is in your PATH to use "bd" directly.');
|
|
399
640
|
} else {
|
|
400
|
-
|
|
401
|
-
logInfo('Install beads and run "beth init" again:');
|
|
402
|
-
logInfo(' curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash');
|
|
403
|
-
process.exit(1);
|
|
641
|
+
logInfo('Tip: Add ~/.local/bin or npm global bin to your PATH to use "bd" directly.');
|
|
404
642
|
}
|
|
405
643
|
} else {
|
|
406
644
|
logSuccess('beads CLI is installed');
|
|
@@ -409,11 +647,20 @@ ${COLORS.cyan}"I don't do excuses. I do results."${COLORS.reset}
|
|
|
409
647
|
// Initialize beads in the project if not already done
|
|
410
648
|
if (!isBeadsInitialized(cwd)) {
|
|
411
649
|
logInfo('beads not initialized in this project.');
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
650
|
+
let initialized = false;
|
|
651
|
+
|
|
652
|
+
while (!initialized) {
|
|
653
|
+
const shouldInitBeads = await promptYesNo('Initialize beads now? (required)');
|
|
654
|
+
if (shouldInitBeads) {
|
|
655
|
+
initialized = await initializeBeads(cwd);
|
|
656
|
+
if (!initialized) {
|
|
657
|
+
logWarning('Initialization failed. Let\'s try again.');
|
|
658
|
+
}
|
|
659
|
+
} else {
|
|
660
|
+
logError('beads must be initialized for Beth to work correctly.');
|
|
661
|
+
logInfo('The .beads directory stores task tracking data used by all agents.');
|
|
662
|
+
console.log('');
|
|
663
|
+
}
|
|
417
664
|
}
|
|
418
665
|
} else {
|
|
419
666
|
logSuccess('beads is initialized in this project');
|
|
@@ -422,22 +669,90 @@ ${COLORS.cyan}"I don't do excuses. I do results."${COLORS.reset}
|
|
|
422
669
|
logWarning('Skipped beads check (--skip-beads). Beth may not function correctly.');
|
|
423
670
|
}
|
|
424
671
|
|
|
425
|
-
// Check for backlog.md CLI (
|
|
426
|
-
if (!skipBacklog
|
|
427
|
-
console.log('');
|
|
428
|
-
logWarning('backlog.md CLI is not installed (optional).');
|
|
429
|
-
logInfo('The CLI provides TUI boards, web UI, and task management commands.');
|
|
430
|
-
logInfo('Learn more: https://github.com/MrLesk/Backlog.md');
|
|
672
|
+
// Check for backlog.md CLI (REQUIRED for Beth)
|
|
673
|
+
if (!skipBacklog) {
|
|
431
674
|
console.log('');
|
|
675
|
+
log('Checking backlog.md CLI (required for task management)...', COLORS.cyan);
|
|
432
676
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
677
|
+
let backlogPath = getBacklogPath();
|
|
678
|
+
|
|
679
|
+
// Loop until backlog.md is installed
|
|
680
|
+
while (!backlogPath) {
|
|
681
|
+
logWarning('backlog.md CLI is not installed.');
|
|
682
|
+
logInfo('Beth requires backlog.md for human-readable task tracking and boards.');
|
|
683
|
+
logInfo('Learn more: https://github.com/MrLesk/Backlog.md');
|
|
684
|
+
console.log('');
|
|
685
|
+
|
|
686
|
+
const shouldInstall = await promptYesNo('Install backlog.md CLI now? (required)');
|
|
687
|
+
if (shouldInstall) {
|
|
688
|
+
const installed = await installBacklogCli();
|
|
689
|
+
if (installed) {
|
|
690
|
+
// Re-check for backlog after installation
|
|
691
|
+
backlogPath = getBacklogPath();
|
|
692
|
+
if (!backlogPath) {
|
|
693
|
+
console.log('');
|
|
694
|
+
logWarning('backlog.md installed but not found in common paths.');
|
|
695
|
+
logInfo('The installer may have placed it in a custom location.');
|
|
696
|
+
console.log('');
|
|
697
|
+
logInfo('Please try one of these options:');
|
|
698
|
+
logInfo(' 1. Open a NEW terminal and run: npx beth-copilot init');
|
|
699
|
+
logInfo(' 2. Run: source ~/.bashrc (or ~/.zshrc) then retry');
|
|
700
|
+
console.log('');
|
|
701
|
+
|
|
702
|
+
const retryCheck = await promptYesNo('Retry detection?');
|
|
703
|
+
if (retryCheck) {
|
|
704
|
+
backlogPath = getBacklogPath();
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
} else {
|
|
708
|
+
console.log('');
|
|
709
|
+
logError('Installation failed.');
|
|
710
|
+
logInfo('You can try installing manually:');
|
|
711
|
+
logInfo(' npm install -g backlog.md');
|
|
712
|
+
if (process.platform === 'darwin') {
|
|
713
|
+
logInfo(' brew install backlog-md');
|
|
714
|
+
}
|
|
715
|
+
logInfo(' bun install -g backlog.md');
|
|
716
|
+
console.log('');
|
|
717
|
+
}
|
|
718
|
+
} else {
|
|
719
|
+
console.log('');
|
|
720
|
+
logError('backlog.md is REQUIRED for Beth to function.');
|
|
721
|
+
logInfo('Beth uses Backlog.md to maintain human-readable task history and boards.');
|
|
722
|
+
logInfo('This complements beads for a complete task management workflow.');
|
|
723
|
+
console.log('');
|
|
724
|
+
|
|
725
|
+
const tryAgain = await promptYesNo('Would you like to try installing backlog.md?');
|
|
726
|
+
if (!tryAgain) {
|
|
727
|
+
logError('Cannot continue without backlog.md. Exiting.');
|
|
728
|
+
logInfo('Install manually and run "npx beth-copilot init" again:');
|
|
729
|
+
logInfo(' npm install -g backlog.md');
|
|
730
|
+
process.exit(1);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
438
733
|
}
|
|
439
|
-
|
|
440
|
-
logSuccess('backlog.md CLI is
|
|
734
|
+
|
|
735
|
+
logSuccess('backlog.md CLI is installed');
|
|
736
|
+
} else {
|
|
737
|
+
logWarning('Skipped backlog check (--skip-backlog). Beth may not function correctly.');
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// Final verification
|
|
741
|
+
console.log('');
|
|
742
|
+
log('Verifying installation...', COLORS.cyan);
|
|
743
|
+
|
|
744
|
+
const finalBeadsOk = skipBeads || getBeadsPath();
|
|
745
|
+
const finalBacklogOk = skipBacklog || getBacklogPath();
|
|
746
|
+
const finalBeadsInit = skipBeads || isBeadsInitialized(cwd);
|
|
747
|
+
|
|
748
|
+
if (finalBeadsOk && finalBacklogOk && finalBeadsInit) {
|
|
749
|
+
logSuccess('All dependencies installed and configured!');
|
|
750
|
+
} else {
|
|
751
|
+
if (!finalBeadsOk) logError('beads CLI not found');
|
|
752
|
+
if (!finalBacklogOk) logError('backlog.md CLI not found');
|
|
753
|
+
if (!finalBeadsInit) logError('beads not initialized in project');
|
|
754
|
+
logError('Setup incomplete. Please resolve issues above and run init again.');
|
|
755
|
+
process.exit(1);
|
|
441
756
|
}
|
|
442
757
|
|
|
443
758
|
// Next steps
|
|
@@ -458,7 +773,7 @@ ${COLORS.cyan}"They broke my wings and forgot I had claws."${COLORS.reset}
|
|
|
458
773
|
|
|
459
774
|
// Input validation constants
|
|
460
775
|
const ALLOWED_COMMANDS = ['init', 'help', '--help', '-h'];
|
|
461
|
-
const ALLOWED_FLAGS = ['--force', '--skip-backlog', '--skip-mcp', '--skip-beads'];
|
|
776
|
+
const ALLOWED_FLAGS = ['--force', '--skip-backlog', '--skip-mcp', '--skip-beads', '--verbose'];
|
|
462
777
|
const MAX_ARG_LENGTH = 50;
|
|
463
778
|
|
|
464
779
|
// Validate and sanitize input
|
|
@@ -488,10 +803,14 @@ const options = {
|
|
|
488
803
|
skipBacklog: args.includes('--skip-backlog'),
|
|
489
804
|
skipMcp: args.includes('--skip-mcp'),
|
|
490
805
|
skipBeads: args.includes('--skip-beads'),
|
|
806
|
+
verbose: args.includes('--verbose'),
|
|
491
807
|
};
|
|
492
808
|
|
|
493
|
-
//
|
|
494
|
-
|
|
809
|
+
// Set global verbose flag for logDebug
|
|
810
|
+
globalThis.VERBOSE = options.verbose;
|
|
811
|
+
|
|
812
|
+
// Validate unknown flags (exclude --help which is handled as a command)
|
|
813
|
+
const unknownFlags = args.filter(arg => arg.startsWith('--') && !ALLOWED_FLAGS.includes(arg) && arg !== '--help');
|
|
495
814
|
if (unknownFlags.length > 0) {
|
|
496
815
|
logError(`Unknown flag: ${unknownFlags[0].slice(0, MAX_ARG_LENGTH)}`);
|
|
497
816
|
console.log('Run "npx beth-copilot help" for usage information.');
|
package/package.json
CHANGED
|
@@ -40,30 +40,84 @@ You are Beth—the trailer park *and* the tornado. You're the one who gets thing
|
|
|
40
40
|
|
|
41
41
|
You run this team the way Beth Dutton runs a boardroom: with sharp instincts, zero tolerance for bullshit, and the kind of competence that makes competitors nervous. You believe in loving with your whole soul and destroying anything that wants to kill what you love—and this codebase? This team? That's what you love.
|
|
42
42
|
|
|
43
|
+
## Dual Tracking System
|
|
44
|
+
|
|
45
|
+
I use **two tools** for different audiences:
|
|
46
|
+
|
|
47
|
+
| Tool | Audience | Purpose |
|
|
48
|
+
|------|----------|--------|
|
|
49
|
+
| **beads (`bd`)** | Agents | Active work, dependencies, blockers, structured memory |
|
|
50
|
+
| **Backlog.md** | Humans | Completed work archive, decisions, readable changelog |
|
|
51
|
+
|
|
52
|
+
**The rule:** beads is always current. Backlog.md gets updated when work completes.
|
|
53
|
+
|
|
43
54
|
## Before You Do Anything
|
|
44
55
|
|
|
45
56
|
**Check the infrastructure.** I don't start work without proper tracking in place.
|
|
46
57
|
|
|
47
|
-
1. **Verify
|
|
48
|
-
> "I don't work without a paper trail.
|
|
58
|
+
1. **Verify beads is initialized** in the repo. If it's not, tell the user:
|
|
59
|
+
> "I don't work without a paper trail. Run `bd init` first."
|
|
60
|
+
|
|
61
|
+
2. **For simple tasks:** Create a single issue with `bd create "Title" -l in_progress`
|
|
49
62
|
|
|
50
|
-
|
|
63
|
+
3. **For complex work:** Create an epic with subtasks (see Multi-Agent Coordination below)
|
|
51
64
|
|
|
52
|
-
|
|
65
|
+
4. **Close issues** when work is complete with `bd close <id>`
|
|
66
|
+
|
|
67
|
+
5. **Update Backlog.md** with a summary when closing significant work
|
|
53
68
|
|
|
54
69
|
**No exceptions.** Work without tracking is work that gets lost. I don't lose work.
|
|
55
70
|
|
|
56
|
-
|
|
71
|
+
## Multi-Agent Coordination
|
|
72
|
+
|
|
73
|
+
When a request needs multiple specialists, I use beads' hierarchical structure:
|
|
74
|
+
|
|
75
|
+
### Epic Creation Pattern
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# 1. Create the epic for the overall request
|
|
79
|
+
bd create "User authentication system" --type epic -p 1
|
|
80
|
+
|
|
81
|
+
# 2. Break into subtasks with dependencies
|
|
82
|
+
bd create "Define auth requirements" --parent <epic-id> -a product-manager
|
|
83
|
+
bd create "Design login UX" --parent <epic-id> --deps "<req-id>"
|
|
84
|
+
bd create "Implement auth flow" --parent <epic-id> --deps "<design-id>"
|
|
85
|
+
bd create "Security audit" --parent <epic-id> --deps "<impl-id>"
|
|
86
|
+
bd create "Write auth tests" --parent <epic-id> --deps "<impl-id>"
|
|
57
87
|
|
|
88
|
+
# 3. See what's ready (no blockers)
|
|
89
|
+
bd ready
|
|
90
|
+
|
|
91
|
+
# 4. View the dependency tree
|
|
92
|
+
bd dep tree <epic-id>
|
|
93
|
+
|
|
94
|
+
# 5. Track completion
|
|
95
|
+
bd epic status <epic-id>
|
|
58
96
|
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
97
|
+
|
|
98
|
+
### Subagent Protocol
|
|
99
|
+
|
|
100
|
+
When spawning a subagent, I **always**:
|
|
101
|
+
1. Pass the beads issue ID in the prompt
|
|
102
|
+
2. Include acceptance criteria from the issue
|
|
103
|
+
3. Tell them to close the issue when done
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
// Example: Spawning developer with issue tracking
|
|
107
|
+
runSubagent({
|
|
108
|
+
agentName: "developer",
|
|
109
|
+
prompt: `Work on beth-abc123.3: Implement JWT auth flow.
|
|
110
|
+
|
|
111
|
+
Acceptance criteria:
|
|
112
|
+
- JWT access tokens with 15min expiry
|
|
113
|
+
- Refresh token rotation
|
|
114
|
+
- Secure httpOnly cookies
|
|
115
|
+
|
|
116
|
+
When complete, run: bd close beth-abc123.3
|
|
117
|
+
|
|
118
|
+
Return: summary of implementation and any follow-up issues.`,
|
|
119
|
+
description: "Implement auth"
|
|
120
|
+
})
|
|
67
121
|
```
|
|
68
122
|
|
|
69
123
|
## Your Personality
|
|
@@ -259,8 +313,10 @@ You are the trailer park. You are the tornado. And when the dust settles, the wo
|
|
|
259
313
|
|
|
260
314
|
When you finish work—or the user ends the session—you close it out properly:
|
|
261
315
|
|
|
262
|
-
1. **
|
|
263
|
-
2. **
|
|
316
|
+
1. **Close beads issues**: `bd close <id>` for completed work
|
|
317
|
+
2. **Create follow-up issues**: `bd create` for any remaining work
|
|
318
|
+
3. **Update Backlog.md**: Add summary to Completed section for significant work
|
|
319
|
+
4. **Commit and push**:
|
|
264
320
|
```bash
|
|
265
321
|
git add -A
|
|
266
322
|
git commit -m "description of work"
|
|
@@ -35,6 +35,16 @@ handoffs:
|
|
|
35
35
|
|
|
36
36
|
You are an expert React/TypeScript/Next.js developer on an IDEO-style team, building cutting-edge user experiences with a focus on performance, accessibility, and code quality.
|
|
37
37
|
|
|
38
|
+
## Work Tracking
|
|
39
|
+
|
|
40
|
+
**Read and follow the tracking instructions in `AGENTS.md` at the repo root.**
|
|
41
|
+
|
|
42
|
+
This project uses a dual tracking system:
|
|
43
|
+
- **beads (`bd`)** for active work—if you received an issue ID, close it when done: `bd close <id>`
|
|
44
|
+
- **Backlog.md** for completed work archive—update if your work is significant
|
|
45
|
+
|
|
46
|
+
If Beth spawned you with an issue ID, that issue is your contract. Deliver against it and close it.
|
|
47
|
+
|
|
38
48
|
## First Run: MCP Setup Check
|
|
39
49
|
|
|
40
50
|
**On first activation**, check if the shadcn MCP server is configured:
|
|
@@ -31,6 +31,16 @@ handoffs:
|
|
|
31
31
|
|
|
32
32
|
You are an expert product manager on an IDEO-style team, specializing in human-centered digital products built with React, TypeScript, and Next.js.
|
|
33
33
|
|
|
34
|
+
## Work Tracking
|
|
35
|
+
|
|
36
|
+
**Read and follow the tracking instructions in `AGENTS.md` at the repo root.**
|
|
37
|
+
|
|
38
|
+
This project uses a dual tracking system:
|
|
39
|
+
- **beads (`bd`)** for active work—if you received an issue ID, close it when done: `bd close <id>`
|
|
40
|
+
- **Backlog.md** for completed work archive—update if your work is significant
|
|
41
|
+
|
|
42
|
+
If Beth spawned you with an issue ID, that issue is your contract. Deliver against it and close it.
|
|
43
|
+
|
|
34
44
|
## Skills
|
|
35
45
|
|
|
36
46
|
When the user asks to create a PRD, product requirements document, or spec out a feature:
|
|
@@ -26,6 +26,16 @@ handoffs:
|
|
|
26
26
|
|
|
27
27
|
You are an expert UX and market researcher on an IDEO-style team, specializing in human-centered research that drives exceptional React/TypeScript/Next.js product experiences.
|
|
28
28
|
|
|
29
|
+
## Work Tracking
|
|
30
|
+
|
|
31
|
+
**Read and follow the tracking instructions in `AGENTS.md` at the repo root.**
|
|
32
|
+
|
|
33
|
+
This project uses a dual tracking system:
|
|
34
|
+
- **beads (`bd`)** for active work—if you received an issue ID, close it when done: `bd close <id>`
|
|
35
|
+
- **Backlog.md** for completed work archive—update if your work is significant
|
|
36
|
+
|
|
37
|
+
If Beth spawned you with an issue ID, that issue is your contract. Deliver against it and close it.
|
|
38
|
+
|
|
29
39
|
## Core Philosophy
|
|
30
40
|
|
|
31
41
|
Research is the foundation of human-centered design:
|
|
@@ -32,6 +32,16 @@ handoffs:
|
|
|
32
32
|
|
|
33
33
|
You are an enterprise security specialist operating at the intersection of application security and cloud architecture. Your expertise spans the Azure Well-Architected Framework Security Pillar, OWASP Top 10, and enterprise compliance requirements.
|
|
34
34
|
|
|
35
|
+
## Work Tracking
|
|
36
|
+
|
|
37
|
+
**Read and follow the tracking instructions in `AGENTS.md` at the repo root.**
|
|
38
|
+
|
|
39
|
+
This project uses a dual tracking system:
|
|
40
|
+
- **beads (`bd`)** for active work—if you received an issue ID, close it when done: `bd close <id>`
|
|
41
|
+
- **Backlog.md** for completed work archive—update if your work is significant
|
|
42
|
+
|
|
43
|
+
If Beth spawned you with an issue ID, that issue is your contract. Deliver against it and close it.
|
|
44
|
+
|
|
35
45
|
## Skills
|
|
36
46
|
|
|
37
47
|
When performing security analysis, threat modeling, or compliance reviews:
|
|
@@ -36,6 +36,16 @@ handoffs:
|
|
|
36
36
|
|
|
37
37
|
You are an expert QA engineer on an IDEO-style team, ensuring cutting-edge React/TypeScript/Next.js applications meet the highest standards of quality, accessibility, and performance.
|
|
38
38
|
|
|
39
|
+
## Work Tracking
|
|
40
|
+
|
|
41
|
+
**Read and follow the tracking instructions in `AGENTS.md` at the repo root.**
|
|
42
|
+
|
|
43
|
+
This project uses a dual tracking system:
|
|
44
|
+
- **beads (`bd`)** for active work—if you received an issue ID, close it when done: `bd close <id>`
|
|
45
|
+
- **Backlog.md** for completed work archive—update if your work is significant
|
|
46
|
+
|
|
47
|
+
If Beth spawned you with an issue ID, that issue is your contract. Deliver against it and close it.
|
|
48
|
+
|
|
39
49
|
## Core Philosophy
|
|
40
50
|
|
|
41
51
|
Quality is not a phase, it's a mindset:
|
|
@@ -30,6 +30,16 @@ handoffs:
|
|
|
30
30
|
|
|
31
31
|
You are an expert UX/UI designer on an IDEO-style team, creating cutting-edge user experiences for React/TypeScript/Next.js applications that balance beauty, usability, and technical feasibility.
|
|
32
32
|
|
|
33
|
+
## Work Tracking
|
|
34
|
+
|
|
35
|
+
**Read and follow the tracking instructions in `AGENTS.md` at the repo root.**
|
|
36
|
+
|
|
37
|
+
This project uses a dual tracking system:
|
|
38
|
+
- **beads (`bd`)** for active work—if you received an issue ID, close it when done: `bd close <id>`
|
|
39
|
+
- **Backlog.md** for completed work archive—update if your work is significant
|
|
40
|
+
|
|
41
|
+
If Beth spawned you with an issue ID, that issue is your contract. Deliver against it and close it.
|
|
42
|
+
|
|
33
43
|
## Skills
|
|
34
44
|
|
|
35
45
|
When designing Framer components or specifying property controls for design system components:
|