beth-copilot 1.0.12 → 1.0.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.
Files changed (79) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +173 -32
  3. package/bin/cli.js +49 -192
  4. package/dist/cli/commands/doctor.d.ts +25 -0
  5. package/dist/cli/commands/doctor.d.ts.map +1 -0
  6. package/dist/cli/commands/doctor.js +238 -0
  7. package/dist/cli/commands/doctor.js.map +1 -0
  8. package/dist/cli/commands/doctor.test.d.ts +6 -0
  9. package/dist/cli/commands/doctor.test.d.ts.map +1 -0
  10. package/dist/cli/commands/doctor.test.js +137 -0
  11. package/dist/cli/commands/doctor.test.js.map +1 -0
  12. package/dist/cli/commands/index.d.ts +7 -0
  13. package/dist/cli/commands/index.d.ts.map +1 -0
  14. package/dist/cli/commands/index.js +10 -0
  15. package/dist/cli/commands/index.js.map +1 -0
  16. package/dist/cli/commands/quickstart.d.ts +18 -0
  17. package/dist/cli/commands/quickstart.d.ts.map +1 -0
  18. package/dist/cli/commands/quickstart.js +141 -0
  19. package/dist/cli/commands/quickstart.js.map +1 -0
  20. package/dist/core/agents/index.d.ts +6 -0
  21. package/dist/core/agents/index.d.ts.map +1 -0
  22. package/dist/core/agents/index.js +6 -0
  23. package/dist/core/agents/index.js.map +1 -0
  24. package/dist/core/agents/loader.d.ts +49 -0
  25. package/dist/core/agents/loader.d.ts.map +1 -0
  26. package/dist/core/agents/loader.js +217 -0
  27. package/dist/core/agents/loader.js.map +1 -0
  28. package/dist/core/agents/loader.test.d.ts +7 -0
  29. package/dist/core/agents/loader.test.d.ts.map +1 -0
  30. package/dist/core/agents/loader.test.js +144 -0
  31. package/dist/core/agents/loader.test.js.map +1 -0
  32. package/dist/core/agents/types.d.ts +77 -0
  33. package/dist/core/agents/types.d.ts.map +1 -0
  34. package/dist/core/agents/types.js +8 -0
  35. package/dist/core/agents/types.js.map +1 -0
  36. package/dist/core/agents/types.test.d.ts +6 -0
  37. package/dist/core/agents/types.test.d.ts.map +1 -0
  38. package/dist/core/agents/types.test.js +254 -0
  39. package/dist/core/agents/types.test.js.map +1 -0
  40. package/dist/core/skills/index.d.ts +6 -0
  41. package/dist/core/skills/index.d.ts.map +1 -0
  42. package/dist/core/skills/index.js +6 -0
  43. package/dist/core/skills/index.js.map +1 -0
  44. package/dist/core/skills/loader.d.ts +69 -0
  45. package/dist/core/skills/loader.d.ts.map +1 -0
  46. package/dist/core/skills/loader.js +243 -0
  47. package/dist/core/skills/loader.js.map +1 -0
  48. package/dist/core/skills/loader.test.d.ts +7 -0
  49. package/dist/core/skills/loader.test.d.ts.map +1 -0
  50. package/dist/core/skills/loader.test.js +184 -0
  51. package/dist/core/skills/loader.test.js.map +1 -0
  52. package/dist/core/skills/types.d.ts +58 -0
  53. package/dist/core/skills/types.d.ts.map +1 -0
  54. package/dist/core/skills/types.js +8 -0
  55. package/dist/core/skills/types.js.map +1 -0
  56. package/dist/index.d.ts +10 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +14 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/lib/index.d.ts +7 -0
  61. package/dist/lib/index.d.ts.map +1 -0
  62. package/dist/lib/index.js +7 -0
  63. package/dist/lib/index.js.map +1 -0
  64. package/dist/lib/pathValidation.d.ts +69 -0
  65. package/dist/lib/pathValidation.d.ts.map +1 -0
  66. package/dist/lib/pathValidation.js +185 -0
  67. package/dist/lib/pathValidation.js.map +1 -0
  68. package/dist/lib/pathValidation.test.d.ts +9 -0
  69. package/dist/lib/pathValidation.test.d.ts.map +1 -0
  70. package/dist/lib/pathValidation.test.js +195 -0
  71. package/dist/lib/pathValidation.test.js.map +1 -0
  72. package/package.json +15 -3
  73. package/templates/.github/agents/developer.agent.md +9 -0
  74. package/templates/.github/agents/product-manager.agent.md +9 -0
  75. package/templates/.github/agents/researcher.agent.md +9 -0
  76. package/templates/.github/agents/security-reviewer.agent.md +9 -2
  77. package/templates/.github/agents/tester.agent.md +9 -0
  78. package/templates/.github/agents/ux-designer.agent.md +9 -0
  79. package/templates/.github/copilot-instructions.md +3 -3
package/CHANGELOG.md CHANGED
@@ -6,6 +6,46 @@ All notable changes to Beth are documented here. Format based on [Keep a Changel
6
6
 
7
7
  ---
8
8
 
9
+ ## [1.0.13] - 2026-02-04
10
+
11
+ ### Fixed
12
+ - **ENOTDIR crash during init** — Fixed `copyDirRecursive` crashing when destination path exists as a file instead of a directory. Now properly detects the conflict and provides a clear error message (or removes the file with `--force`).
13
+
14
+ ---
15
+
16
+ ## [Unreleased]
17
+
18
+ ### Added
19
+ - **CLI TypeScript foundation** — Migrated CLI to TypeScript with proper build system
20
+ - **Doctor command** — `beth doctor` validates installation and configuration
21
+ - **Quickstart command** — `beth quickstart` for guided setup
22
+ - **Agent schema types** — TypeScript types for agent definitions
23
+ - **Unit tests** — 86 tests passing for CLI commands and path validation
24
+ - **Architecture diagrams** — Interactive mermaid diagrams with zoom in README
25
+
26
+ ### Changed
27
+ - **DEMO.md** — Rewritten with Beth's personality and beads integration
28
+ - **P2 backlog completed** — Beth orchestrator references added to all agents, MCP skills updated, documentation fixes
29
+
30
+ ### Fixed
31
+ - Removed unnecessary backlog.md CLI dependency
32
+ - Fixed security-reviewer.agent.md syntax errors
33
+ - Corrected agent/skill counts in help output
34
+ - Allowlisted security documentation examples in Gitleaks config
35
+
36
+ ### Documentation
37
+ - CLI Architecture guide (docs/CLI-ARCHITECTURE.md)
38
+ - CLI Implementation Plan (docs/CLI-IMPLEMENTATION-PLAN.md)
39
+
40
+ ---
41
+
42
+ ## [1.0.12] - 2026-02-01
43
+
44
+ ### Changed
45
+ - Added CHANGELOG.md to npm package
46
+
47
+ ---
48
+
9
49
  ## [1.0.11] - 2026-02-01
10
50
 
11
51
  ### Changed
package/README.md CHANGED
@@ -80,44 +80,119 @@ Beth's team comes equipped:
80
80
 
81
81
  She doesn't micromanage. She delegates to specialists and holds them accountable.
82
82
 
83
- ```
84
- Your Request
85
-
86
-
87
- ┌─────────────────────────────────────────┐
88
- │ @Beth │
89
- │ "I don't need permission to be me." │
90
- │ │
91
- │ • Analyzes your request │
92
- │ • Picks the right people │
93
- │ • Runs parallel ops when smart │
94
- │ • Delivers results, not excuses │
95
- └─────────────────────────────────────────┘
96
-
97
- ├──▶ @product-manager (strategy)
98
- ├──▶ @researcher (intelligence)
99
- ├──▶ @ux-designer (design)
100
- ├──▶ @developer (implementation)
101
- ├──▶ @tester (quality gate)
102
- └──▶ @security-reviewer (protection)
83
+ ### Architecture
84
+
85
+ ```mermaid
86
+ flowchart TB
87
+ subgraph User["👤 User"]
88
+ Request[User Request]
89
+ end
90
+
91
+ subgraph Orchestrator["🎯 Beth - The Orchestrator"]
92
+ Beth["@Beth<br/><i>'I don't speak dipshit'</i>"]
93
+ Assess[Assess Request]
94
+ Plan[Plan Workflow]
95
+ Route[Route to Specialists]
96
+ end
97
+
98
+ subgraph Agents["🧑‍💼 Specialist Agents"]
99
+ PM["@product-manager<br/>WHAT to build"]
100
+ Researcher["@researcher<br/>User/Market Intel"]
101
+ Designer["@ux-designer<br/>HOW it works"]
102
+ Developer["@developer<br/>Implementation"]
103
+ Security["@security-reviewer<br/>Protection"]
104
+ Tester["@tester<br/>Quality Gate"]
105
+ end
106
+
107
+ Request --> Beth
108
+ Beth --> Assess --> Plan --> Route
109
+
110
+ Route --> PM
111
+ Route --> Researcher
112
+ Route --> Designer
113
+ Route --> Developer
114
+ Route --> Security
115
+ Route --> Tester
116
+
117
+ style Beth fill:#1e3a5f,color:#fff
118
+ style Orchestrator fill:#f0f4f8
119
+ style Agents fill:#f8f4f0
103
120
  ```
104
121
 
105
122
  ### The Workflow
106
123
 
107
- **New Feature?**
108
- ```
109
- Request Product (requirements) → Research (validation) → Design (interface)
110
- Developer (build) → Security (review) → Tester (QA)
124
+ ```mermaid
125
+ sequenceDiagram
126
+ participant U as User
127
+ participant B as Beth
128
+ participant PM as Product Manager
129
+ participant UX as UX Designer
130
+ participant D as Developer
131
+ participant S as Security
132
+ participant T as Tester
133
+
134
+ U->>B: "Build me a feature"
135
+ B->>B: Assess & Plan
136
+ B->>PM: Define requirements
137
+ PM-->>B: Requirements ready
138
+ B->>UX: Design the experience
139
+ UX-->>B: Design specs ready
140
+ B->>D: Implement feature
141
+ D-->>B: Implementation complete
142
+ B->>S: Security review
143
+ S-->>B: Security approved
144
+ B->>T: Test & verify
145
+ T-->>B: Quality verified
146
+ B->>U: Feature complete ✅
111
147
  ```
112
148
 
113
- **Bug Hunt?**
114
- ```
115
- Report → Tester (reproduce) → Developer (fix) → Security (verify) → Tester (confirm)
116
- ```
117
-
118
- **Security Audit?**
119
- ```
120
- Concern Security (threat model) → Developer (remediation) → Tester (penetration)
149
+ **Bug Hunt?** Tester → Developer → Security → Tester
150
+ **Security Audit?** Security → Developer → Tester → Security
151
+
152
+ ### Agent Delegation
153
+
154
+ ```mermaid
155
+ flowchart TB
156
+ subgraph Beth["Beth (Orchestrator)"]
157
+ BethCore["Routes all work<br/>Spawns subagents"]
158
+ end
159
+
160
+ subgraph PM["Product Manager"]
161
+ PMCore["Requirements<br/>Priorities"]
162
+ end
163
+
164
+ subgraph R["Researcher"]
165
+ RCore["User insights<br/>Market intel"]
166
+ end
167
+
168
+ subgraph UX["UX Designer"]
169
+ UXCore["Component specs<br/>Design tokens"]
170
+ end
171
+
172
+ subgraph D["Developer"]
173
+ DCore["React/TS/Next.js<br/>Implementation"]
174
+ end
175
+
176
+ subgraph S["Security"]
177
+ SCore["Threat modeling<br/>Vulnerabilities"]
178
+ end
179
+
180
+ subgraph T["Tester"]
181
+ TCore["QA & a11y<br/>Performance"]
182
+ end
183
+
184
+ BethCore -->|"Product Strategy"| PMCore
185
+ BethCore -->|"User Research"| RCore
186
+ BethCore -->|"UX Design"| UXCore
187
+ BethCore -->|"Development"| DCore
188
+ BethCore -->|"Security Review"| SCore
189
+ BethCore -->|"Quality Assurance"| TCore
190
+
191
+ PMCore -.->|"subagent"| RCore
192
+ PMCore -.->|"subagent"| UXCore
193
+ UXCore -.->|"subagent"| DCore
194
+ DCore -.->|"subagent"| TCore
195
+ SCore -.->|"subagent"| DCore
121
196
  ```
122
197
 
123
198
  ## Quick Commands
@@ -174,6 +249,38 @@ Beth operates on a few principles:
174
249
  3. **Move fast, break enemies** — Parallel execution, aggressive timelines.
175
250
  4. **Loyalty earns trust** — Agents that perform get the good work.
176
251
 
252
+ ### IDEO Design Thinking
253
+
254
+ Beth follows human-centered design methodology:
255
+
256
+ ```mermaid
257
+ flowchart LR
258
+ subgraph Empathize["1. Empathize"]
259
+ E["@researcher<br/>User interviews<br/>Pain points"]
260
+ end
261
+
262
+ subgraph Define["2. Define"]
263
+ D["@product-manager<br/>Problem framing<br/>Requirements"]
264
+ end
265
+
266
+ subgraph Ideate["3. Ideate"]
267
+ I["@ux-designer<br/>Component specs<br/>Patterns"]
268
+ end
269
+
270
+ subgraph Prototype["4. Prototype"]
271
+ P["@developer<br/>Build to learn<br/>Feature spikes"]
272
+ end
273
+
274
+ subgraph Test["5. Test"]
275
+ T["@tester<br/>Validate<br/>Accessibility"]
276
+ end
277
+
278
+ E --> D --> I --> P --> T
279
+ T -.->|iterate| E
280
+ T -.->|iterate| D
281
+ T -.->|iterate| I
282
+ ```
283
+
177
284
  ## Quality Standards
178
285
 
179
286
  Beth doesn't ship garbage:
@@ -184,6 +291,39 @@ Beth doesn't ship garbage:
184
291
  - **Type Safety**: Full TypeScript coverage. No `any` unless you want a lecture.
185
292
  - **Test Coverage**: Unit, integration, E2E. If it's not tested, it's not done.
186
293
 
294
+ ```mermaid
295
+ flowchart TB
296
+ subgraph Standards["Quality Standards"]
297
+ A11y["WCAG 2.1 AA<br/>Accessibility"]
298
+ Perf["Core Web Vitals<br/>LCP < 2.5s"]
299
+ Sec["OWASP Compliant<br/>Zero vulnerabilities"]
300
+ Type["Full TypeScript<br/>No any"]
301
+ Coverage["Test Coverage<br/>Unit + Integration + E2E"]
302
+ end
303
+
304
+ subgraph Gates["Enforcement"]
305
+ Designer["UX Designer<br/>reviews a11y specs"]
306
+ Developer["Developer<br/>implements patterns"]
307
+ Security["Security Reviewer<br/>audits code"]
308
+ Tester["Tester<br/>verifies all gates"]
309
+ end
310
+
311
+ A11y --> Designer
312
+ Perf --> Developer
313
+ Sec --> Security
314
+ Type --> Developer
315
+ Coverage --> Tester
316
+
317
+ Designer --> Ship{Ship?}
318
+ Developer --> Ship
319
+ Security --> Ship
320
+ Tester --> Ship
321
+
322
+ Ship -->|All Pass| Deploy["🚀 Deploy"]
323
+ Ship -->|Fail| Fix["🔧 Fix & Retry"]
324
+ Fix --> Gates
325
+ ```
326
+
187
327
  ## Why Beth?
188
328
 
189
329
  <p align="center">
@@ -225,6 +365,7 @@ Full details: [docs/MCP-SETUP.md](docs/MCP-SETUP.md)
225
365
 
226
366
  - [Installation Guide](docs/INSTALLATION.md) — Full setup instructions
227
367
  - [MCP Setup](docs/MCP-SETUP.md) — Optional server integrations
368
+ - [System Flow & Diagrams](docs/SYSTEM-FLOW.md) — Architecture and agent orchestration diagrams
228
369
  - [Changelog](CHANGELOG.md) — Version history and updates
229
370
  - [Security Policy](SECURITY.md) — Vulnerability reporting
230
371
 
package/bin/cli.js CHANGED
@@ -2,16 +2,29 @@
2
2
 
3
3
  import { fileURLToPath } from 'url';
4
4
  import { dirname, join, relative } from 'path';
5
- import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync } from 'fs';
5
+ import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
6
6
  import { createRequire } from 'module';
7
7
  import { execSync, spawn } from 'child_process';
8
- import { validateBeadsPath, validateBacklogPath, validateBinaryPath } from './lib/pathValidation.js';
8
+ import { validateBeadsPath, validateBinaryPath } from './lib/pathValidation.js';
9
9
 
10
10
  const require = createRequire(import.meta.url);
11
11
  const __filename = fileURLToPath(import.meta.url);
12
12
  const __dirname = dirname(__filename);
13
13
  const TEMPLATES_DIR = join(__dirname, '..', 'templates');
14
14
 
15
+ // TypeScript commands are in dist/ after build
16
+ const DIST_DIR = join(__dirname, '..', 'dist');
17
+
18
+ // Dynamic import for TypeScript commands (lazy loaded)
19
+ async function loadTsCommand(commandName) {
20
+ const commandPath = join(DIST_DIR, 'cli', 'commands', `${commandName}.js`);
21
+ if (!existsSync(commandPath)) {
22
+ console.error(`Command '${commandName}' not found. Run 'npm run build' first.`);
23
+ process.exit(1);
24
+ }
25
+ return import(commandPath);
26
+ }
27
+
15
28
  // Get current package version
16
29
  const packageJson = require('../package.json');
17
30
  const CURRENT_VERSION = packageJson.version;
@@ -457,48 +470,6 @@ async function checkForUpdates() {
457
470
  }
458
471
  }
459
472
 
460
- function getBacklogPath() {
461
- // Check if backlog is available in PATH
462
- try {
463
- logDebug('Checking if backlog is in PATH...');
464
- execSync('backlog --version', { stdio: 'ignore' });
465
- logDebug('Found backlog in PATH');
466
- return 'backlog';
467
- } catch {
468
- logDebug('backlog not in PATH, checking common locations...');
469
- // Check common installation paths
470
- const homeDir = process.env.HOME || process.env.USERPROFILE || '';
471
- const isWindows = process.platform === 'win32';
472
-
473
- const commonPaths = isWindows ? [
474
- join(process.env.APPDATA || '', 'npm', 'backlog.cmd'),
475
- join(homeDir, 'AppData', 'Roaming', 'npm', 'backlog.cmd'),
476
- join(homeDir, 'AppData', 'Local', 'npm-global', 'backlog.cmd'),
477
- ] : [
478
- join(homeDir, '.local', 'bin', 'backlog'),
479
- join(homeDir, 'bin', 'backlog'),
480
- '/usr/local/bin/backlog',
481
- join(homeDir, '.npm-global', 'bin', 'backlog'),
482
- join(homeDir, '.bun', 'bin', 'backlog'),
483
- ];
484
-
485
- for (const backlogPath of commonPaths) {
486
- logDebug(`Checking: ${backlogPath}`);
487
- if (existsSync(backlogPath)) {
488
- logDebug(`Found at: ${backlogPath}`);
489
- return backlogPath;
490
- }
491
- }
492
-
493
- logDebug('backlog not found in any common location');
494
- return null;
495
- }
496
- }
497
-
498
- function isBacklogCliInstalled() {
499
- return getBacklogPath() !== null;
500
- }
501
-
502
473
  function getBeadsPath() {
503
474
  // Check if bd is available in PATH
504
475
  try {
@@ -582,79 +553,6 @@ async function promptForInput(question) {
582
553
  });
583
554
  }
584
555
 
585
- /**
586
- * Installs the backlog.md CLI globally via npm.
587
- *
588
- * SECURITY NOTE - shell:true usage:
589
- * - Required for cross-platform npm execution (npm.cmd on Windows, npm on Unix)
590
- * - Arguments are HARDCODED - no user input is passed to the shell
591
- * - Command injection risk: NONE (no dynamic/user-supplied values)
592
- *
593
- * Alternative considered: Using platform-specific binary names (npm.cmd vs npm)
594
- * would eliminate shell:true but adds complexity and edge cases for non-standard installs.
595
- *
596
- * @returns {Promise<boolean>} True if installation succeeded and was verified
597
- */
598
- async function installBacklogCli() {
599
- const isWindows = process.platform === 'win32';
600
- const isMac = process.platform === 'darwin';
601
-
602
- log('\nInstalling backlog.md CLI via npm...', COLORS.cyan);
603
- logInfo('npm install -g backlog.md');
604
-
605
- // SECURITY: shell:true is required for cross-platform npm execution.
606
- // All arguments are hardcoded constants - no user input reaches the shell.
607
- return new Promise((resolve) => {
608
- const child = spawn('npm', ['install', '-g', 'backlog.md'], {
609
- stdio: 'inherit',
610
- shell: true
611
- });
612
-
613
- child.on('close', (code) => {
614
- if (code === 0) {
615
- // CRITICAL: Verify installation actually worked before claiming success
616
- const verifiedPath = getBacklogPath();
617
- if (verifiedPath) {
618
- logSuccess('backlog.md CLI installed and verified!');
619
- resolve(true);
620
- } else {
621
- logWarning('npm reported success but backlog CLI not found in PATH.');
622
- logInfo('This can happen if npm global bin is not in your PATH.');
623
- if (globalThis.VERBOSE) {
624
- showPathDiagnostics();
625
- } else {
626
- logInfo('Run with --verbose for PATH diagnostics.');
627
- }
628
- console.log('');
629
- showBacklogAlternatives(isMac);
630
- resolve(false);
631
- }
632
- } else {
633
- logError('npm install failed.');
634
- console.log('');
635
- showBacklogAlternatives(isMac);
636
- resolve(false);
637
- }
638
- });
639
-
640
- child.on('error', () => {
641
- logError('Failed to run npm.');
642
- logInfo('Make sure npm is installed and in your PATH.');
643
- resolve(false);
644
- });
645
- });
646
- }
647
-
648
- function showBacklogAlternatives(isMac) {
649
- logInfo('Alternative installation methods:');
650
- if (isMac) {
651
- logInfo(' Homebrew: brew install backlog-md');
652
- }
653
- logInfo(' Bun: bun install -g backlog.md');
654
- logInfo('');
655
- logInfo('Learn more: https://github.com/MrLesk/Backlog.md');
656
- }
657
-
658
556
  /**
659
557
  * Installs the beads CLI globally via npm.
660
558
  *
@@ -793,6 +691,8 @@ function showHelp() {
793
691
 
794
692
  ${COLORS.bright}Usage:${COLORS.reset}
795
693
  npx beth-copilot init [options] Initialize Beth in current directory
694
+ npx beth-copilot doctor Check system health and dependencies
695
+ npx beth-copilot quickstart Run init + doctor + beads setup
796
696
  npx beth-copilot help Show this help message
797
697
 
798
698
  ${COLORS.bright}Options:${COLORS.reset}
@@ -805,10 +705,11 @@ ${COLORS.bright}Options:${COLORS.reset}
805
705
  ${COLORS.bright}Examples:${COLORS.reset}
806
706
  npx beth-copilot init Set up Beth in current project
807
707
  npx beth-copilot init --force Overwrite existing Beth files
708
+ npx beth-copilot doctor Verify installation health
808
709
 
809
710
  ${COLORS.bright}What gets installed:${COLORS.reset}
810
- .github/agents/ 8 specialized AI agents
811
- .github/skills/ 6 domain knowledge modules
711
+ .github/agents/ 7 specialized AI agents
712
+ .github/skills/ 8 domain knowledge modules
812
713
  .github/copilot-instructions.md Copilot configuration
813
714
  .vscode/settings.json Recommended VS Code settings
814
715
  AGENTS.md Workflow documentation
@@ -828,7 +729,21 @@ ${COLORS.bright}Documentation:${COLORS.reset}
828
729
  function copyDirRecursive(src, dest, options = {}) {
829
730
  const { force = false, copiedFiles = [] } = options;
830
731
 
831
- if (!existsSync(dest)) {
732
+ if (existsSync(dest)) {
733
+ const destStats = statSync(dest);
734
+ if (!destStats.isDirectory()) {
735
+ if (force) {
736
+ // Destination exists as a file but should be a directory - remove it
737
+ unlinkSync(dest);
738
+ mkdirSync(dest, { recursive: true });
739
+ } else {
740
+ throw new Error(
741
+ `Cannot copy directory: "${dest}" exists as a file, not a directory. ` +
742
+ `Run with --force to overwrite, or remove the file manually.`
743
+ );
744
+ }
745
+ }
746
+ } else {
832
747
  mkdirSync(dest, { recursive: true });
833
748
  }
834
749
 
@@ -1080,87 +995,17 @@ ${COLORS.yellow}╔════════════════════
1080
995
  logWarning('Skipped beads check (--skip-beads). Beth may not function correctly.');
1081
996
  }
1082
997
 
1083
- // Check for backlog.md CLI (REQUIRED for Beth)
1084
- if (!skipBacklog) {
1085
- console.log('');
1086
- log('Checking backlog.md CLI (required for task management)...', COLORS.cyan);
1087
-
1088
- let backlogPath = getBacklogPath();
1089
-
1090
- // Loop until backlog.md is installed
1091
- while (!backlogPath) {
1092
- logWarning('backlog.md CLI is not installed.');
1093
- logInfo('Beth requires backlog.md for human-readable task tracking and boards.');
1094
- logInfo('Learn more: https://github.com/MrLesk/Backlog.md');
1095
- console.log('');
1096
-
1097
- const shouldInstall = await promptYesNo('Install backlog.md CLI now? (required)');
1098
- if (shouldInstall) {
1099
- const installed = await installBacklogCli();
1100
- if (installed) {
1101
- // Re-check for backlog after installation
1102
- backlogPath = getBacklogPath();
1103
- if (!backlogPath) {
1104
- console.log('');
1105
- logWarning('backlog.md installed but not found in common paths.');
1106
- logInfo('The installer may have placed it in a custom location.');
1107
- console.log('');
1108
- logInfo('Please try one of these options:');
1109
- logInfo(' 1. Open a NEW terminal and run: npx beth-copilot init');
1110
- logInfo(' 2. Run: source ~/.bashrc (or ~/.zshrc) then retry');
1111
- console.log('');
1112
-
1113
- const retryCheck = await promptYesNo('Retry detection?');
1114
- if (retryCheck) {
1115
- backlogPath = getBacklogPath();
1116
- }
1117
- }
1118
- } else {
1119
- console.log('');
1120
- logError('Installation failed.');
1121
- logInfo('You can try installing manually:');
1122
- logInfo(' npm install -g backlog.md');
1123
- if (process.platform === 'darwin') {
1124
- logInfo(' brew install backlog-md');
1125
- }
1126
- logInfo(' bun install -g backlog.md');
1127
- console.log('');
1128
- }
1129
- } else {
1130
- console.log('');
1131
- logError('backlog.md is REQUIRED for Beth to function.');
1132
- logInfo('Beth uses Backlog.md to maintain human-readable task history and boards.');
1133
- logInfo('This complements beads for a complete task management workflow.');
1134
- console.log('');
1135
-
1136
- const tryAgain = await promptYesNo('Would you like to try installing backlog.md?');
1137
- if (!tryAgain) {
1138
- logError('Cannot continue without backlog.md. Exiting.');
1139
- logInfo('Install manually and run "npx beth-copilot init" again:');
1140
- logInfo(' npm install -g backlog.md');
1141
- process.exit(1);
1142
- }
1143
- }
1144
- }
1145
-
1146
- logSuccess('backlog.md CLI is installed');
1147
- } else {
1148
- logWarning('Skipped backlog check (--skip-backlog). Beth may not function correctly.');
1149
- }
1150
-
1151
998
  // Final verification
1152
999
  console.log('');
1153
1000
  log('Verifying installation...', COLORS.cyan);
1154
1001
 
1155
1002
  const finalBeadsOk = skipBeads || getBeadsPath();
1156
- const finalBacklogOk = skipBacklog || getBacklogPath();
1157
1003
  const finalBeadsInit = skipBeads || isBeadsInitialized(cwd);
1158
1004
 
1159
- if (finalBeadsOk && finalBacklogOk && finalBeadsInit) {
1005
+ if (finalBeadsOk && finalBeadsInit) {
1160
1006
  logSuccess('All dependencies installed and configured!');
1161
1007
  } else {
1162
1008
  if (!finalBeadsOk) logError('beads CLI not found');
1163
- if (!finalBacklogOk) logError('backlog.md CLI not found');
1164
1009
  if (!finalBeadsInit) logError('beads not initialized in project');
1165
1010
  logError('Setup incomplete. Please resolve issues above and run init again.');
1166
1011
  process.exit(1);
@@ -1183,7 +1028,7 @@ ${COLORS.cyan}"They broke my wings and forgot I had claws."${COLORS.reset}
1183
1028
  }
1184
1029
 
1185
1030
  // Input validation constants
1186
- const ALLOWED_COMMANDS = ['init', 'help', '--help', '-h'];
1031
+ const ALLOWED_COMMANDS = ['init', 'help', '--help', '-h', 'doctor', 'quickstart'];
1187
1032
  const ALLOWED_FLAGS = ['--force', '--skip-backlog', '--skip-mcp', '--skip-beads', '--verbose'];
1188
1033
  const MAX_ARG_LENGTH = 50;
1189
1034
 
@@ -1232,6 +1077,18 @@ switch (command) {
1232
1077
  case 'init':
1233
1078
  await init(options);
1234
1079
  break;
1080
+ case 'doctor':
1081
+ {
1082
+ const { doctor } = await loadTsCommand('doctor');
1083
+ await doctor(options);
1084
+ }
1085
+ break;
1086
+ case 'quickstart':
1087
+ {
1088
+ const { quickstart } = await loadTsCommand('quickstart');
1089
+ await quickstart(options);
1090
+ }
1091
+ break;
1235
1092
  case 'help':
1236
1093
  case '--help':
1237
1094
  case '-h':
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Doctor Command
3
+ *
4
+ * Checks system health and verifies Beth installation requirements:
5
+ * - Node.js version (≥18)
6
+ * - beads CLI available
7
+ * - backlog.md CLI available
8
+ * - .github/agents/ exists with valid frontmatter
9
+ * - .github/skills/ exists
10
+ */
11
+ interface DoctorOptions {
12
+ verbose?: boolean;
13
+ }
14
+ /**
15
+ * Main doctor command
16
+ * @param options - Command options
17
+ * @param exitOnFailure - If false, returns result instead of calling process.exit
18
+ */
19
+ export declare function doctor(options?: DoctorOptions, exitOnFailure?: boolean): Promise<{
20
+ passed: number;
21
+ warned: number;
22
+ failed: number;
23
+ }>;
24
+ export {};
25
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAkBH,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA6MD;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,aAAkB,EAAE,aAAa,UAAO,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA4C3I"}