@automagik/genie 0.260202.1901 → 0.260203.135

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 (104) hide show
  1. package/.beads/issues.jsonl +9 -0
  2. package/.claude/skills/brainstorm/SKILL.md +53 -0
  3. package/.claude/skills/genie-base/SKILL.md +66 -0
  4. package/.claude/skills/genie-base/assets/workspace/AGENTS.md +191 -0
  5. package/.claude/skills/genie-base/assets/workspace/ENVIRONMENT.md +18 -0
  6. package/.claude/skills/genie-base/assets/workspace/HEARTBEAT.md +4 -0
  7. package/.claude/skills/genie-base/assets/workspace/IDENTITY.md +17 -0
  8. package/.claude/skills/genie-base/assets/workspace/MEMORY.md +16 -0
  9. package/.claude/skills/genie-base/assets/workspace/ROLE.md +14 -0
  10. package/.claude/skills/genie-base/assets/workspace/SOUL.md +36 -0
  11. package/.claude/skills/genie-base/assets/workspace/TOOLS.md +25 -0
  12. package/.claude/skills/genie-base/assets/workspace/USER.md +13 -0
  13. package/.claude/skills/genie-base/assets/workspace/memory/2026-01-30.md +6 -0
  14. package/.claude/skills/genie-base/assets/workspace/memory/2026-01-31.md +16 -0
  15. package/.claude/skills/genie-base/assets/workspace/memory/882c22be-9710-41c1-91f8-ed82947ef6ce.txt +1 -0
  16. package/.claude/skills/genie-base/scripts/install-workspace.sh +107 -0
  17. package/.claude/skills/genie-base/scripts/sanity-sweep.sh +60 -0
  18. package/.claude/skills/genie-blank-init/SKILL.md +37 -0
  19. package/.claude/skills/genie-blank-init/assets/BOOTSTRAP.md +44 -0
  20. package/.claude/skills/genie-blank-init/assets/IDENTITY.md +9 -0
  21. package/.claude/skills/genie-blank-init/assets/SOUL.md +10 -0
  22. package/.claude/skills/genie-blank-init/assets/USER.md +9 -0
  23. package/.claude/skills/genie-blank-init/scripts/apply-blank-init.sh +117 -0
  24. package/.claude/skills/genie-forge/SKILL.md +171 -0
  25. package/.claude/skills/genie-plan-review/CLAUDE.md +11 -0
  26. package/.claude/skills/genie-plan-review/SKILL.md +53 -0
  27. package/.claude/skills/genie-review/SKILL.md +171 -0
  28. package/.claude/skills/genie-wish/SKILL.md +141 -0
  29. package/.claude-plugin/marketplace.json +18 -0
  30. package/.genie/.gitkeep +3 -0
  31. package/.genie/backlog/hooks-v2.md +82 -0
  32. package/.genie/wishes/upgrade-brainstorm-handoff/wish.md +124 -0
  33. package/.gitattributes +1 -1
  34. package/AGENTS.md +35 -0
  35. package/README.md +10 -5
  36. package/bun.lock +55 -0
  37. package/dist/claudio.js +1 -1
  38. package/dist/genie.js +1 -1
  39. package/dist/term.js +108 -85
  40. package/docs/CO-ORCHESTRATION-GUIDE.md +375 -0
  41. package/package.json +5 -1
  42. package/plugin/.claude-plugin/plugin.json +18 -0
  43. package/plugin/README.md +120 -0
  44. package/plugin/agents/implementor.md +92 -0
  45. package/plugin/agents/quality-reviewer.md +113 -0
  46. package/plugin/agents/spec-reviewer.md +90 -0
  47. package/plugin/hooks/hooks.json +3 -0
  48. package/plugin/hooks/postInstall.sh +10 -0
  49. package/plugin/references/review-criteria.md +72 -0
  50. package/plugin/references/wish-template.md +92 -0
  51. package/plugin/scripts/genie.cjs +141 -0
  52. package/plugin/scripts/smart-install.js +308 -0
  53. package/plugin/scripts/src/install-genie-cli.sh +120 -0
  54. package/plugin/scripts/src/validate-completion.ts +142 -0
  55. package/plugin/scripts/src/validate-wish.ts +137 -0
  56. package/plugin/scripts/term.cjs +231 -0
  57. package/plugin/scripts/validate-completion.cjs +16 -0
  58. package/plugin/scripts/validate-wish.cjs +17 -0
  59. package/plugin/scripts/worker-service.cjs +28 -0
  60. package/plugin/skills/brainstorm/SKILL.md +106 -0
  61. package/plugin/skills/forge/SKILL.md +171 -0
  62. package/plugin/skills/genie-base/SKILL.md +99 -0
  63. package/plugin/skills/genie-base/assets/workspace/AGENTS.md +191 -0
  64. package/plugin/skills/genie-base/assets/workspace/ENVIRONMENT.md +18 -0
  65. package/plugin/skills/genie-base/assets/workspace/HEARTBEAT.md +4 -0
  66. package/plugin/skills/genie-base/assets/workspace/IDENTITY.md +17 -0
  67. package/plugin/skills/genie-base/assets/workspace/MEMORY.md +16 -0
  68. package/plugin/skills/genie-base/assets/workspace/ROLE.md +14 -0
  69. package/plugin/skills/genie-base/assets/workspace/SOUL.md +36 -0
  70. package/plugin/skills/genie-base/assets/workspace/TOOLS.md +25 -0
  71. package/plugin/skills/genie-base/assets/workspace/USER.md +13 -0
  72. package/plugin/skills/genie-base/scripts/install-workspace.sh +107 -0
  73. package/plugin/skills/genie-base/scripts/sanity-sweep.sh +60 -0
  74. package/plugin/skills/genie-blank-init/SKILL.md +73 -0
  75. package/plugin/skills/genie-blank-init/assets/BOOTSTRAP.md +44 -0
  76. package/plugin/skills/genie-blank-init/assets/IDENTITY.md +9 -0
  77. package/plugin/skills/genie-blank-init/assets/SOUL.md +10 -0
  78. package/plugin/skills/genie-blank-init/assets/USER.md +9 -0
  79. package/plugin/skills/genie-blank-init/scripts/apply-blank-init.sh +117 -0
  80. package/plugin/skills/genie-cli-dev/CLAUDE.md +19 -0
  81. package/plugin/skills/genie-cli-dev/SKILL.md +295 -0
  82. package/plugin/skills/plan-review/SKILL.md +101 -0
  83. package/plugin/skills/review/SKILL.md +221 -0
  84. package/plugin/skills/wish/SKILL.md +110 -0
  85. package/plugin/skills/work-orchestration/SKILL.md +116 -0
  86. package/scripts/build.js +132 -0
  87. package/scripts/smart-install.js +308 -0
  88. package/scripts/sync.js +134 -0
  89. package/src/lib/beads-registry.ts +49 -0
  90. package/src/lib/orchestrator/event-monitor.ts +2 -0
  91. package/src/lib/skill-loader.ts +215 -0
  92. package/src/lib/tmux.ts +19 -14
  93. package/src/lib/version.ts +1 -1
  94. package/src/lib/worker-registry.ts +10 -0
  95. package/src/services/worker-service.ts +351 -0
  96. package/src/term-commands/close.ts +14 -4
  97. package/src/term-commands/create.ts +95 -0
  98. package/src/term-commands/kill.ts +15 -4
  99. package/src/term-commands/orchestrate.ts +3 -2
  100. package/src/term-commands/send.ts +43 -15
  101. package/src/term-commands/spawn.ts +446 -0
  102. package/src/term-commands/split.ts +14 -3
  103. package/src/term-commands/work.ts +217 -57
  104. package/src/term.ts +81 -6
@@ -0,0 +1,110 @@
1
+ ---
2
+ name: wish
3
+ description: "Use when starting non-trivial work that needs structured planning - converts ideas into wish documents with scope, acceptance criteria, and execution tasks."
4
+ ---
5
+
6
+ # Wish - Turn Ideas Into Plans
7
+
8
+ ## Overview
9
+
10
+ Convert a validated design (from `/brainstorm`) or direct request into a structured wish document. Create native Claude Code tasks for execution.
11
+
12
+ **Output:** `.genie/wishes/<slug>/wish.md` + native tasks ready for `/forge`
13
+
14
+ ---
15
+
16
+ ## The Flow
17
+
18
+ ### Phase 1: Brainstorm (if needed)
19
+
20
+ If coming from `/brainstorm`, the design is already validated. If starting fresh:
21
+
22
+ Enter plan mode to explore the codebase read-only. Understand the landscape before proposing anything.
23
+
24
+ **One question at a time. Multiple choice when possible.**
25
+
26
+ 1. **Resonate** - Understand the intent
27
+ - What does the user actually want? (not just what they said)
28
+ - Ask clarifying questions, one at a time
29
+ - Prefer multiple choice: "Which of these best describes what you want?"
30
+
31
+ 2. **Explore approaches** - Propose 2-3 alternatives
32
+ - Present options with trade-offs
33
+ - Lead with your recommendation and explain why
34
+ - Let the user choose (or propose something different)
35
+
36
+ 3. **Align on scope** - Define boundaries
37
+ - What's IN scope?
38
+ - What's explicitly OUT of scope?
39
+ - What assumptions are we making?
40
+
41
+ ### Phase 2: Design (200-300 Word Sections)
42
+
43
+ Present the design incrementally. Check after each section.
44
+
45
+ **Sections to cover:**
46
+ - Summary (what and why, 2-3 sentences)
47
+ - Architecture approach
48
+ - Key decisions with rationale
49
+ - Risks and mitigations
50
+
51
+ ### Phase 3: Plan (Bite-Sized Tasks)
52
+
53
+ Break the design into execution groups. Each task should be:
54
+ - **Small enough** to implement in one focused session
55
+ - **Testable** with clear acceptance criteria
56
+ - **Independent** where possible (minimize blocking dependencies)
57
+
58
+ **Per task, define:**
59
+ - What to do (deliverables)
60
+ - Acceptance criteria (checkboxes)
61
+ - Validation command (how to verify it worked)
62
+ - Files likely touched
63
+
64
+ ### Phase 4: Write the Wish Document
65
+
66
+ Write to `.genie/wishes/<slug>/wish.md` using the template from `references/wish-template.md`.
67
+
68
+ **Required sections:**
69
+ - Status, Slug, Created date
70
+ - Summary (what and why)
71
+ - Scope (IN and OUT - OUT must not be empty)
72
+ - Decisions with rationale
73
+ - Success Criteria (checkboxes)
74
+ - Execution Groups with acceptance criteria and validation commands
75
+
76
+ ### Phase 5: Create Native Tasks
77
+
78
+ After writing the wish document:
79
+ - Use `TaskCreate` for each execution group
80
+ - Set up `addBlockedBy` dependencies between tasks
81
+ - Include wish slug and group name in task description
82
+
83
+ ### Phase 6: Handoff
84
+
85
+ Output: **"Wish documented. Run `/plan-review` to validate, then `/forge` to begin execution."**
86
+
87
+ ---
88
+
89
+ ## Key Principles
90
+
91
+ - **One question at a time** - Never ask multiple questions in one message
92
+ - **Multiple choice preferred** - Easier for users to answer
93
+ - **YAGNI ruthlessly** - Remove unnecessary features from all designs
94
+ - **Acceptance criteria are king** - Every task must have testable criteria
95
+ - **Validation commands required** - Every task must have a way to verify completion
96
+ - **Explore before proposing** - Read code before designing changes
97
+ - **Small tasks** - If a task feels big, split it
98
+
99
+ ---
100
+
101
+ ## Never Do
102
+
103
+ - Skip brainstorming and jump to plan writing
104
+ - Ask more than one question per message
105
+ - Create tasks without acceptance criteria
106
+ - Create tasks without validation commands
107
+ - Write a wish without user agreement on scope
108
+ - Start implementation during wish creation (plan mode only)
109
+ - Create overly broad tasks ("implement everything")
110
+ - Leave OUT scope empty (always exclude something explicitly)
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: work-orchestration
3
+ description: "How to orchestrate real work with the human using term, claudio, and beads. Stop planning, start doing."
4
+ ---
5
+
6
+ # Work Orchestration
7
+
8
+ ## The Stack
9
+
10
+ - **term** - Terminal/tmux orchestration
11
+ - **claudio** - Claude Code API automation
12
+ - **beads** - Task/issue tracking (bd CLI)
13
+ - **worktrees** - Isolated git branches for parallel work
14
+
15
+ ## Start Working NOW
16
+
17
+ ### 1. Check Current State
18
+
19
+ ```bash
20
+ term ls # What sessions exist?
21
+ term workers # Any active workers?
22
+ bd ls # What issues are ready?
23
+ ```
24
+
25
+ ### 2. Pick or Create Work
26
+
27
+ ```bash
28
+ # Work on existing issue
29
+ term work <bd-id>
30
+
31
+ # Or create new issue and work it
32
+ term create "Fix the thing" && term work next
33
+ ```
34
+
35
+ ### 3. Execute
36
+
37
+ The worker spawns Claude in a pane. You can:
38
+ - Watch: `tmux attach -t genie` or `term watch genie`
39
+ - Approve: `term approve <worker>`
40
+ - Answer: `term answer <worker> <choice>`
41
+ - Check: `term orc status genie` (Claude state)
42
+ - Send: `term send genie "msg"` (sends with Enter)
43
+
44
+ ### 4. Close When Done
45
+
46
+ ```bash
47
+ term close <bd-id> # Closes issue, cleans worktree
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Parallel Work Pattern
53
+
54
+ Split work across multiple panes/workers:
55
+
56
+ ```bash
57
+ # In session "genie"
58
+ term split genie h # New pane (uses ACTIVE pane)
59
+ term spawn forge # Spawn Claude with skill
60
+ ```
61
+
62
+ Or use workers for tracked work:
63
+
64
+ ```bash
65
+ term work bd-001 # Worker 1
66
+ term work bd-002 # Worker 2 (parallel)
67
+ term workers # See both
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Human-AI Handoff
73
+
74
+ **Human does:**
75
+ - Approves permissions
76
+ - Answers questions
77
+ - Provides context when stuck
78
+ - Reviews before merge
79
+
80
+ **AI does:**
81
+ - Implements tasks
82
+ - Runs tests
83
+ - Creates commits (when asked)
84
+ - Reports blockers
85
+
86
+ ---
87
+
88
+ ## Quick Commands
89
+
90
+ | Action | Command |
91
+ |--------|---------|
92
+ | See sessions | `term ls` |
93
+ | See workers | `term workers` |
94
+ | See issues | `bd ls` |
95
+ | Start work | `term work <id>` |
96
+ | Split pane | `term split genie h` |
97
+ | Approve | `term approve <worker>` |
98
+ | Answer | `term answer <worker> 1` |
99
+ | Send message | `term send genie "msg"` |
100
+ | Send raw keys | `term send genie "q" --no-enter` |
101
+ | Watch events | `term watch genie` |
102
+ | Fire-and-forget | `term run genie "task"` |
103
+ | Session info | `term info genie` |
104
+ | Claude state | `term orc status genie` |
105
+ | Close work | `term close <id>` |
106
+
107
+ ---
108
+
109
+ ## Stop Planning, Start Doing
110
+
111
+ 1. What needs to be done? (one thing)
112
+ 2. Is there an issue? Create one if not
113
+ 3. `term work <id>` or just start coding
114
+ 4. Ship it
115
+
116
+ No more circles.
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Build script for automagik-genie plugin
5
+ * Bundles TypeScript CLIs into standalone CJS executables using esbuild
6
+ */
7
+
8
+ import { build } from 'esbuild';
9
+ import fs from 'fs';
10
+ import path from 'path';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
+ const rootDir = path.join(__dirname, '..');
15
+
16
+ const TARGETS = [
17
+ { name: 'genie', source: 'src/genie.ts' },
18
+ { name: 'term', source: 'src/term.ts' },
19
+ { name: 'worker-service', source: 'src/services/worker-service.ts' },
20
+ { name: 'validate-wish', source: '.claude-plugin/scripts/validate-wish.ts' },
21
+ { name: 'validate-completion', source: '.claude-plugin/scripts/validate-completion.ts' }
22
+ ];
23
+
24
+ async function buildPlugin() {
25
+ console.log('Building automagik-genie plugin...\n');
26
+
27
+ try {
28
+ // Read version from package.json
29
+ const packageJson = JSON.parse(fs.readFileSync(path.join(rootDir, 'package.json'), 'utf-8'));
30
+ const version = packageJson.version;
31
+ console.log(`Version: ${version}`);
32
+
33
+ // Create output directory
34
+ const scriptsDir = path.join(rootDir, 'plugin/scripts');
35
+ if (!fs.existsSync(scriptsDir)) {
36
+ fs.mkdirSync(scriptsDir, { recursive: true });
37
+ }
38
+
39
+ // Generate plugin/package.json for dependency installation
40
+ console.log('\nGenerating plugin package.json...');
41
+ const pluginPackageJson = {
42
+ name: 'automagik-genie-plugin',
43
+ version: version,
44
+ private: true,
45
+ description: 'Runtime dependencies for automagik-genie bundled CLIs',
46
+ type: 'module',
47
+ dependencies: {},
48
+ engines: {
49
+ node: '>=18.0.0',
50
+ bun: '>=1.0.0'
51
+ }
52
+ };
53
+ fs.writeFileSync(
54
+ path.join(rootDir, 'plugin/package.json'),
55
+ JSON.stringify(pluginPackageJson, null, 2) + '\n'
56
+ );
57
+ console.log('plugin/package.json generated');
58
+
59
+ // Build each target
60
+ for (const target of TARGETS) {
61
+ const sourcePath = path.join(rootDir, target.source);
62
+
63
+ // Check if source exists
64
+ if (!fs.existsSync(sourcePath)) {
65
+ console.log(`\nSkipping ${target.name} (source not found: ${target.source})`);
66
+ continue;
67
+ }
68
+
69
+ console.log(`\nBuilding ${target.name}...`);
70
+
71
+ const outfile = `${scriptsDir}/${target.name}.cjs`;
72
+
73
+ await build({
74
+ entryPoints: [sourcePath],
75
+ bundle: true,
76
+ platform: 'node',
77
+ target: 'node18',
78
+ format: 'cjs',
79
+ outfile,
80
+ minify: true,
81
+ logLevel: 'error',
82
+ external: ['bun', 'bun:*'],
83
+ define: {
84
+ '__GENIE_VERSION__': `"${version}"`
85
+ }
86
+ });
87
+
88
+ // Add shebang (esbuild banner can cause duplicates if source has shebang)
89
+ const content = fs.readFileSync(outfile, 'utf-8');
90
+ const shebang = '#!/usr/bin/env bun\n';
91
+ // Remove any existing shebangs and add fresh one
92
+ const cleanContent = content.replace(/^#!.*\n/gm, '');
93
+ fs.writeFileSync(outfile, shebang + cleanContent);
94
+
95
+ // Make executable
96
+ fs.chmodSync(outfile, 0o755);
97
+
98
+ const stats = fs.statSync(`${scriptsDir}/${target.name}.cjs`);
99
+ console.log(` ${target.name}.cjs (${(stats.size / 1024).toFixed(2)} KB)`);
100
+ }
101
+
102
+ // Copy smart-install.js (stays as Node.js, not bundled)
103
+ const smartInstallSrc = path.join(rootDir, 'scripts/smart-install.js');
104
+ const smartInstallDest = path.join(scriptsDir, 'smart-install.js');
105
+ if (fs.existsSync(smartInstallSrc)) {
106
+ fs.copyFileSync(smartInstallSrc, smartInstallDest);
107
+ console.log('\nCopied smart-install.js');
108
+ }
109
+
110
+ // Update plugin.json version
111
+ const pluginJsonPath = path.join(rootDir, 'plugin/.claude-plugin/plugin.json');
112
+ if (fs.existsSync(pluginJsonPath)) {
113
+ const pluginJson = JSON.parse(fs.readFileSync(pluginJsonPath, 'utf-8'));
114
+ pluginJson.version = version;
115
+ fs.writeFileSync(pluginJsonPath, JSON.stringify(pluginJson, null, 2) + '\n');
116
+ console.log('Updated plugin.json version');
117
+ }
118
+
119
+ console.log('\nBuild complete!');
120
+ console.log(`Output: plugin/scripts/`);
121
+
122
+ } catch (error) {
123
+ console.error('\nBuild failed:', error.message);
124
+ if (error.errors) {
125
+ console.error('\nBuild errors:');
126
+ error.errors.forEach(err => console.error(` - ${err.text}`));
127
+ }
128
+ process.exit(1);
129
+ }
130
+ }
131
+
132
+ buildPlugin();
@@ -0,0 +1,308 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Smart Install Script for automagik-genie
4
+ *
5
+ * Ensures required dependencies are installed:
6
+ * - Bun runtime (auto-installs if missing)
7
+ * - tmux (guides user if missing - can't auto-install)
8
+ * - beads (auto-installs if missing via npm)
9
+ *
10
+ * Also handles:
11
+ * - Dependency installation when version changes
12
+ * - CLI symlink creation for agent access
13
+ * - Version marker management
14
+ */
15
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, symlinkSync, unlinkSync } from 'fs';
16
+ import { execSync, spawnSync } from 'child_process';
17
+ import { join } from 'path';
18
+ import { homedir } from 'os';
19
+
20
+ const ROOT = process.env.CLAUDE_PLUGIN_ROOT || join(homedir(), '.claude', 'plugins', 'automagik-genie');
21
+ const GENIE_DIR = join(homedir(), '.genie');
22
+ const MARKER = join(GENIE_DIR, '.install-version');
23
+ const BIN_DIR = join(homedir(), '.local', 'bin');
24
+ const IS_WINDOWS = process.platform === 'win32';
25
+
26
+ // Common installation paths (handles fresh installs before PATH reload)
27
+ const BUN_COMMON_PATHS = IS_WINDOWS
28
+ ? [join(homedir(), '.bun', 'bin', 'bun.exe')]
29
+ : [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun', '/opt/homebrew/bin/bun'];
30
+
31
+ const BEADS_COMMON_PATHS = IS_WINDOWS
32
+ ? [join(homedir(), 'AppData', 'Roaming', 'npm', 'bd.cmd')]
33
+ : [join(homedir(), '.local', 'bin', 'bd'), '/usr/local/bin/bd', '/opt/homebrew/bin/bd'];
34
+
35
+ /**
36
+ * Get the Bun executable path
37
+ */
38
+ function getBunPath() {
39
+ // Try PATH first
40
+ try {
41
+ const result = spawnSync('bun', ['--version'], {
42
+ encoding: 'utf-8',
43
+ stdio: ['pipe', 'pipe', 'pipe'],
44
+ shell: IS_WINDOWS
45
+ });
46
+ if (result.status === 0) return 'bun';
47
+ } catch {
48
+ // Not in PATH
49
+ }
50
+ return BUN_COMMON_PATHS.find(existsSync) || null;
51
+ }
52
+
53
+ function isBunInstalled() {
54
+ return getBunPath() !== null;
55
+ }
56
+
57
+ function getBunVersion() {
58
+ const bunPath = getBunPath();
59
+ if (!bunPath) return null;
60
+ try {
61
+ const result = spawnSync(bunPath, ['--version'], {
62
+ encoding: 'utf-8',
63
+ stdio: ['pipe', 'pipe', 'pipe'],
64
+ shell: IS_WINDOWS
65
+ });
66
+ return result.status === 0 ? result.stdout.trim() : null;
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Install Bun automatically
74
+ */
75
+ function installBun() {
76
+ console.error('Installing Bun runtime...');
77
+ try {
78
+ if (IS_WINDOWS) {
79
+ execSync('powershell -c "irm bun.sh/install.ps1 | iex"', { stdio: 'inherit', shell: true });
80
+ } else {
81
+ execSync('curl -fsSL https://bun.sh/install | bash', { stdio: 'inherit', shell: true });
82
+ }
83
+ if (!isBunInstalled()) {
84
+ throw new Error('Bun installation completed but binary not found. Please restart your terminal.');
85
+ }
86
+ console.error(`Bun ${getBunVersion()} installed`);
87
+ } catch (error) {
88
+ console.error('Failed to install Bun. Please install manually:');
89
+ if (IS_WINDOWS) {
90
+ console.error(' winget install Oven-sh.Bun');
91
+ } else {
92
+ console.error(' curl -fsSL https://bun.sh/install | bash');
93
+ }
94
+ throw error;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Check if tmux is installed
100
+ */
101
+ function isTmuxInstalled() {
102
+ try {
103
+ const result = spawnSync('tmux', ['-V'], {
104
+ encoding: 'utf-8',
105
+ stdio: ['pipe', 'pipe', 'pipe'],
106
+ shell: IS_WINDOWS
107
+ });
108
+ return result.status === 0;
109
+ } catch {
110
+ return false;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Get tmux version
116
+ */
117
+ function getTmuxVersion() {
118
+ try {
119
+ const result = spawnSync('tmux', ['-V'], {
120
+ encoding: 'utf-8',
121
+ stdio: ['pipe', 'pipe', 'pipe'],
122
+ shell: IS_WINDOWS
123
+ });
124
+ return result.status === 0 ? result.stdout.trim() : null;
125
+ } catch {
126
+ return null;
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Check if beads (bd) is installed
132
+ */
133
+ function getBeadsPath() {
134
+ try {
135
+ const result = spawnSync('bd', ['--version'], {
136
+ encoding: 'utf-8',
137
+ stdio: ['pipe', 'pipe', 'pipe'],
138
+ shell: IS_WINDOWS
139
+ });
140
+ if (result.status === 0) return 'bd';
141
+ } catch {
142
+ // Not in PATH
143
+ }
144
+ return BEADS_COMMON_PATHS.find(existsSync) || null;
145
+ }
146
+
147
+ function isBeadsInstalled() {
148
+ return getBeadsPath() !== null;
149
+ }
150
+
151
+ /**
152
+ * Install beads via npm
153
+ */
154
+ function installBeads() {
155
+ console.error('Installing beads (bd)...');
156
+ try {
157
+ execSync('npm install -g @anthropic-ai/bd', { stdio: 'inherit', shell: true });
158
+ if (!isBeadsInstalled()) {
159
+ throw new Error('beads installation completed but bd not found.');
160
+ }
161
+ console.error('beads installed');
162
+ } catch (error) {
163
+ console.error('Failed to install beads. Please install manually:');
164
+ console.error(' npm install -g @anthropic-ai/bd');
165
+ throw error;
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Check if dependencies need to be installed
171
+ */
172
+ function needsInstall() {
173
+ if (!existsSync(join(ROOT, 'node_modules'))) return true;
174
+ if (!existsSync(join(ROOT, 'package.json'))) return false; // No package.json = no deps needed
175
+
176
+ try {
177
+ const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
178
+ if (!existsSync(MARKER)) return true;
179
+ const marker = JSON.parse(readFileSync(MARKER, 'utf-8'));
180
+ return pkg.version !== marker.version || getBunVersion() !== marker.bun;
181
+ } catch {
182
+ return true;
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Install dependencies using Bun
188
+ */
189
+ function installDeps() {
190
+ const bunPath = getBunPath();
191
+ if (!bunPath) {
192
+ throw new Error('Bun executable not found');
193
+ }
194
+
195
+ console.error('Installing dependencies...');
196
+
197
+ // Ensure .genie directory exists
198
+ if (!existsSync(GENIE_DIR)) {
199
+ mkdirSync(GENIE_DIR, { recursive: true });
200
+ }
201
+
202
+ const bunCmd = IS_WINDOWS && bunPath.includes(' ') ? `"${bunPath}"` : bunPath;
203
+ execSync(`${bunCmd} install`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
204
+
205
+ // Write version marker
206
+ let version = 'unknown';
207
+ try {
208
+ const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
209
+ version = pkg.version;
210
+ } catch {
211
+ // Ignore
212
+ }
213
+
214
+ writeFileSync(MARKER, JSON.stringify({
215
+ version,
216
+ bun: getBunVersion(),
217
+ tmux: getTmuxVersion(),
218
+ installedAt: new Date().toISOString()
219
+ }));
220
+ }
221
+
222
+ /**
223
+ * Create CLI symlinks for agent access
224
+ */
225
+ function createCliSymlinks() {
226
+ // Ensure bin directory exists
227
+ if (!existsSync(BIN_DIR)) {
228
+ mkdirSync(BIN_DIR, { recursive: true });
229
+ }
230
+
231
+ const links = [
232
+ { name: 'genie', target: join(ROOT, 'scripts', 'genie.cjs') },
233
+ { name: 'term', target: join(ROOT, 'scripts', 'term.cjs') }
234
+ ];
235
+
236
+ for (const { name, target } of links) {
237
+ const linkPath = join(BIN_DIR, name);
238
+
239
+ // Skip if target doesn't exist
240
+ if (!existsSync(target)) {
241
+ continue;
242
+ }
243
+
244
+ // Remove existing symlink if it exists
245
+ try {
246
+ if (existsSync(linkPath)) {
247
+ unlinkSync(linkPath);
248
+ }
249
+ } catch {
250
+ // Ignore errors
251
+ }
252
+
253
+ // Create symlink
254
+ try {
255
+ symlinkSync(target, linkPath);
256
+ console.error(`Created symlink: ${linkPath} -> ${target}`);
257
+ } catch (error) {
258
+ console.error(`Warning: Could not create symlink for ${name}: ${error.message}`);
259
+ }
260
+ }
261
+ }
262
+
263
+ // Main execution
264
+ try {
265
+ // 1. Check/install Bun
266
+ if (!isBunInstalled()) {
267
+ installBun();
268
+ }
269
+
270
+ // 2. Check tmux - REQUIRED, but can't auto-install
271
+ if (!isTmuxInstalled()) {
272
+ console.error('');
273
+ console.error('ERROR: tmux is required but not installed.');
274
+ console.error('');
275
+ console.error('Please install tmux manually:');
276
+ if (process.platform === 'darwin') {
277
+ console.error(' brew install tmux');
278
+ } else if (process.platform === 'linux') {
279
+ console.error(' sudo apt install tmux # Debian/Ubuntu');
280
+ console.error(' sudo dnf install tmux # Fedora/RHEL');
281
+ console.error(' sudo pacman -S tmux # Arch');
282
+ } else if (IS_WINDOWS) {
283
+ console.error(' WSL is required for tmux on Windows');
284
+ console.error(' Inside WSL: sudo apt install tmux');
285
+ }
286
+ console.error('');
287
+ console.error('Then restart Claude Code.');
288
+ process.exit(2); // Exit code 2 = blocking error for Claude to process
289
+ }
290
+
291
+ // 3. Check/install beads
292
+ if (!isBeadsInstalled()) {
293
+ installBeads();
294
+ }
295
+
296
+ // 4. Install dependencies if needed
297
+ if (needsInstall()) {
298
+ installDeps();
299
+ console.error('Dependencies installed');
300
+ }
301
+
302
+ // 5. Create CLI symlinks
303
+ createCliSymlinks();
304
+
305
+ } catch (e) {
306
+ console.error('Installation failed:', e.message);
307
+ process.exit(1);
308
+ }