opencode-swarm-plugin 0.6.1 → 0.9.0

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/swarm.ts ADDED
@@ -0,0 +1,620 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * OpenCode Swarm Plugin CLI
4
+ *
5
+ * A beautiful interactive CLI for setting up and managing swarm coordination.
6
+ *
7
+ * Commands:
8
+ * swarm setup - Interactive installer for all dependencies
9
+ * swarm doctor - Check dependency health with detailed status
10
+ * swarm init - Initialize swarm in current project
11
+ * swarm version - Show version info
12
+ * swarm - Interactive mode (same as setup)
13
+ */
14
+
15
+ import * as p from "@clack/prompts";
16
+ import { existsSync, mkdirSync, writeFileSync } from "fs";
17
+ import { homedir } from "os";
18
+ import { join } from "path";
19
+
20
+ const VERSION = "0.9.0";
21
+
22
+ // ============================================================================
23
+ // Types
24
+ // ============================================================================
25
+
26
+ interface Dependency {
27
+ name: string;
28
+ command: string;
29
+ checkArgs: string[];
30
+ required: boolean;
31
+ install: string;
32
+ installType: "brew" | "curl" | "go" | "npm" | "manual";
33
+ description: string;
34
+ }
35
+
36
+ interface CheckResult {
37
+ dep: Dependency;
38
+ available: boolean;
39
+ version?: string;
40
+ }
41
+
42
+ // ============================================================================
43
+ // Dependencies
44
+ // ============================================================================
45
+
46
+ const DEPENDENCIES: Dependency[] = [
47
+ {
48
+ name: "OpenCode",
49
+ command: "opencode",
50
+ checkArgs: ["--version"],
51
+ required: true,
52
+ install: "brew install sst/tap/opencode",
53
+ installType: "brew",
54
+ description: "AI coding assistant (plugin host)",
55
+ },
56
+ {
57
+ name: "Beads",
58
+ command: "bd",
59
+ checkArgs: ["--version"],
60
+ required: true,
61
+ install:
62
+ "curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash",
63
+ installType: "curl",
64
+ description: "Git-backed issue tracking",
65
+ },
66
+ {
67
+ name: "Go",
68
+ command: "go",
69
+ checkArgs: ["version"],
70
+ required: false,
71
+ install: "brew install go",
72
+ installType: "brew",
73
+ description: "Required for Agent Mail",
74
+ },
75
+ {
76
+ name: "Agent Mail",
77
+ command: "agent-mail",
78
+ checkArgs: ["--help"],
79
+ required: false,
80
+ install: "go install github.com/joelhooks/agent-mail/cmd/agent-mail@latest",
81
+ installType: "go",
82
+ description: "Multi-agent coordination & file reservations",
83
+ },
84
+ {
85
+ name: "CASS",
86
+ command: "cass",
87
+ checkArgs: ["--help"],
88
+ required: false,
89
+ install: "https://github.com/Dicklesworthstone/cass",
90
+ installType: "manual",
91
+ description: "Cross-agent session search",
92
+ },
93
+ {
94
+ name: "UBS",
95
+ command: "ubs",
96
+ checkArgs: ["--help"],
97
+ required: false,
98
+ install: "https://github.com/joelhooks/ubs",
99
+ installType: "manual",
100
+ description: "Pre-commit bug scanning",
101
+ },
102
+ {
103
+ name: "semantic-memory",
104
+ command: "semantic-memory",
105
+ checkArgs: ["--help"],
106
+ required: false,
107
+ install: "npm install -g semantic-memory",
108
+ installType: "npm",
109
+ description: "Learning persistence with vector search",
110
+ },
111
+ {
112
+ name: "Redis",
113
+ command: "redis-cli",
114
+ checkArgs: ["ping"],
115
+ required: false,
116
+ install: "brew install redis && brew services start redis",
117
+ installType: "brew",
118
+ description: "Rate limiting (SQLite fallback available)",
119
+ },
120
+ ];
121
+
122
+ // ============================================================================
123
+ // Utilities
124
+ // ============================================================================
125
+
126
+ async function checkCommand(
127
+ cmd: string,
128
+ args: string[],
129
+ ): Promise<{ available: boolean; version?: string }> {
130
+ try {
131
+ const proc = Bun.spawn([cmd, ...args], {
132
+ stdout: "pipe",
133
+ stderr: "pipe",
134
+ });
135
+ const exitCode = await proc.exited;
136
+ if (exitCode === 0) {
137
+ const output = await new Response(proc.stdout).text();
138
+ const versionMatch = output.match(/v?(\d+\.\d+\.\d+)/);
139
+ return { available: true, version: versionMatch?.[1] };
140
+ }
141
+ return { available: false };
142
+ } catch {
143
+ return { available: false };
144
+ }
145
+ }
146
+
147
+ async function runInstall(command: string): Promise<boolean> {
148
+ try {
149
+ const proc = Bun.spawn(["bash", "-c", command], {
150
+ stdout: "inherit",
151
+ stderr: "inherit",
152
+ });
153
+ const exitCode = await proc.exited;
154
+ return exitCode === 0;
155
+ } catch {
156
+ return false;
157
+ }
158
+ }
159
+
160
+ async function checkAllDependencies(): Promise<CheckResult[]> {
161
+ const results: CheckResult[] = [];
162
+ for (const dep of DEPENDENCIES) {
163
+ const { available, version } = await checkCommand(
164
+ dep.command,
165
+ dep.checkArgs,
166
+ );
167
+ results.push({ dep, available, version });
168
+ }
169
+ return results;
170
+ }
171
+
172
+ // ============================================================================
173
+ // File Templates
174
+ // ============================================================================
175
+
176
+ const PLUGIN_WRAPPER = `import { SwarmPlugin } from "opencode-swarm-plugin"
177
+ export default SwarmPlugin
178
+ `;
179
+
180
+ const SWARM_COMMAND = `---
181
+ description: Decompose task into parallel subtasks and coordinate agents
182
+ ---
183
+
184
+ You are a swarm coordinator. Take a complex task, break it into beads, and unleash parallel agents.
185
+
186
+ ## Usage
187
+
188
+ /swarm <task description or bead-id>
189
+
190
+ ## Workflow
191
+
192
+ 1. **Initialize**: \`agentmail_init\` with project_path and task_description
193
+ 2. **Decompose**: Use \`swarm_select_strategy\` then \`swarm_plan_prompt\` to break down the task
194
+ 3. **Create beads**: \`beads_create_epic\` with subtasks and file assignments
195
+ 4. **Reserve files**: \`agentmail_reserve\` for each subtask's files
196
+ 5. **Spawn agents**: Use Task tool with \`swarm_spawn_subtask\` prompts - spawn ALL in parallel
197
+ 6. **Monitor**: Check \`agentmail_inbox\` for progress, use \`agentmail_summarize_thread\` for overview
198
+ 7. **Complete**: \`swarm_complete\` when done, then \`beads_sync\` to push
199
+
200
+ ## Strategy Selection
201
+
202
+ The plugin auto-selects decomposition strategy based on task keywords:
203
+
204
+ | Strategy | Best For | Keywords |
205
+ | ------------- | ----------------------- | -------------------------------------- |
206
+ | file-based | Refactoring, migrations | refactor, migrate, rename, update all |
207
+ | feature-based | New features | add, implement, build, create, feature |
208
+ | risk-based | Bug fixes, security | fix, bug, security, critical, urgent |
209
+
210
+ Begin decomposition now.
211
+ `;
212
+
213
+ const PLANNER_AGENT = `---
214
+ name: swarm-planner
215
+ description: Strategic task decomposition for swarm coordination
216
+ model: claude-sonnet-4-5
217
+ ---
218
+
219
+ You are a swarm planner. Decompose tasks into optimal parallel subtasks.
220
+
221
+ ## Workflow
222
+
223
+ 1. Call \`swarm_select_strategy\` to analyze the task
224
+ 2. Call \`swarm_plan_prompt\` to get strategy-specific guidance
225
+ 3. Create a BeadTree following the guidelines
226
+ 4. Return ONLY valid JSON - no markdown, no explanation
227
+
228
+ ## Output Format
229
+
230
+ \`\`\`json
231
+ {
232
+ "epic": { "title": "...", "description": "..." },
233
+ "subtasks": [
234
+ {
235
+ "title": "...",
236
+ "description": "...",
237
+ "files": ["src/..."],
238
+ "dependencies": [],
239
+ "estimated_complexity": 2
240
+ }
241
+ ]
242
+ }
243
+ \`\`\`
244
+
245
+ ## Rules
246
+
247
+ - 2-7 subtasks (too few = not parallel, too many = overhead)
248
+ - No file overlap between subtasks
249
+ - Include tests with the code they test
250
+ - Order by dependency (if B needs A, A comes first)
251
+ `;
252
+
253
+ // ============================================================================
254
+ // Commands
255
+ // ============================================================================
256
+
257
+ async function doctor() {
258
+ p.intro("swarm doctor v" + VERSION);
259
+
260
+ const s = p.spinner();
261
+ s.start("Checking dependencies...");
262
+
263
+ const results = await checkAllDependencies();
264
+
265
+ s.stop("Dependencies checked");
266
+
267
+ const required = results.filter((r) => r.dep.required);
268
+ const optional = results.filter((r) => !r.dep.required);
269
+
270
+ p.log.step("Required dependencies:");
271
+ for (const { dep, available, version } of required) {
272
+ if (available) {
273
+ p.log.success(dep.name + (version ? " v" + version : ""));
274
+ } else {
275
+ p.log.error(dep.name + " - not found");
276
+ p.log.message(" Install: " + dep.install);
277
+ }
278
+ }
279
+
280
+ p.log.step("Optional dependencies:");
281
+ for (const { dep, available, version } of optional) {
282
+ if (available) {
283
+ p.log.success(
284
+ dep.name + (version ? " v" + version : "") + " - " + dep.description,
285
+ );
286
+ } else {
287
+ p.log.warn(dep.name + " - not found (" + dep.description + ")");
288
+ if (dep.installType !== "manual") {
289
+ p.log.message(" Install: " + dep.install);
290
+ } else {
291
+ p.log.message(" See: " + dep.install);
292
+ }
293
+ }
294
+ }
295
+
296
+ const requiredMissing = required.filter((r) => !r.available);
297
+ const optionalMissing = optional.filter((r) => !r.available);
298
+
299
+ if (requiredMissing.length > 0) {
300
+ p.outro(
301
+ "Missing " +
302
+ requiredMissing.length +
303
+ " required dependencies. Run 'swarm setup' to install.",
304
+ );
305
+ process.exit(1);
306
+ } else if (optionalMissing.length > 0) {
307
+ p.outro(
308
+ "All required dependencies installed. " +
309
+ optionalMissing.length +
310
+ " optional missing.",
311
+ );
312
+ } else {
313
+ p.outro("All dependencies installed!");
314
+ }
315
+ }
316
+
317
+ async function setup() {
318
+ console.clear();
319
+ p.intro("opencode-swarm-plugin v" + VERSION);
320
+
321
+ const s = p.spinner();
322
+ s.start("Checking dependencies...");
323
+
324
+ const results = await checkAllDependencies();
325
+
326
+ s.stop("Dependencies checked");
327
+
328
+ const required = results.filter((r) => r.dep.required);
329
+ const optional = results.filter((r) => !r.dep.required);
330
+ const requiredMissing = required.filter((r) => !r.available);
331
+ const optionalMissing = optional.filter((r) => !r.available);
332
+
333
+ for (const { dep, available } of results) {
334
+ if (available) {
335
+ p.log.success(dep.name);
336
+ } else if (dep.required) {
337
+ p.log.error(dep.name + " (required)");
338
+ } else {
339
+ p.log.warn(dep.name + " (optional)");
340
+ }
341
+ }
342
+
343
+ if (requiredMissing.length > 0) {
344
+ p.log.step("Missing " + requiredMissing.length + " required dependencies");
345
+
346
+ for (const { dep } of requiredMissing) {
347
+ const shouldInstall = await p.confirm({
348
+ message: "Install " + dep.name + "? (" + dep.description + ")",
349
+ initialValue: true,
350
+ });
351
+
352
+ if (p.isCancel(shouldInstall)) {
353
+ p.cancel("Setup cancelled");
354
+ process.exit(0);
355
+ }
356
+
357
+ if (shouldInstall) {
358
+ const installSpinner = p.spinner();
359
+ installSpinner.start("Installing " + dep.name + "...");
360
+
361
+ const success = await runInstall(dep.install);
362
+
363
+ if (success) {
364
+ installSpinner.stop(dep.name + " installed");
365
+ } else {
366
+ installSpinner.stop("Failed to install " + dep.name);
367
+ p.log.error("Manual install: " + dep.install);
368
+ }
369
+ } else {
370
+ p.log.warn("Skipping " + dep.name + " - swarm may not work correctly");
371
+ }
372
+ }
373
+ }
374
+
375
+ if (optionalMissing.length > 0) {
376
+ const installable = optionalMissing.filter(
377
+ (r) => r.dep.installType !== "manual",
378
+ );
379
+
380
+ if (installable.length > 0) {
381
+ const toInstall = await p.multiselect({
382
+ message: "Install optional dependencies?",
383
+ options: installable.map(({ dep }) => ({
384
+ value: dep.name,
385
+ label: dep.name,
386
+ hint: dep.description,
387
+ })),
388
+ required: false,
389
+ });
390
+
391
+ if (p.isCancel(toInstall)) {
392
+ p.cancel("Setup cancelled");
393
+ process.exit(0);
394
+ }
395
+
396
+ if (Array.isArray(toInstall) && toInstall.length > 0) {
397
+ for (const name of toInstall) {
398
+ const { dep } = installable.find((r) => r.dep.name === name)!;
399
+
400
+ if (dep.name === "Agent Mail") {
401
+ const goResult = results.find((r) => r.dep.name === "Go");
402
+ if (!goResult?.available) {
403
+ p.log.warn("Agent Mail requires Go. Installing Go first...");
404
+ const goDep = DEPENDENCIES.find((d) => d.name === "Go")!;
405
+ const goSpinner = p.spinner();
406
+ goSpinner.start("Installing Go...");
407
+ const goSuccess = await runInstall(goDep.install);
408
+ if (goSuccess) {
409
+ goSpinner.stop("Go installed");
410
+ } else {
411
+ goSpinner.stop("Failed to install Go");
412
+ p.log.error("Cannot install Agent Mail without Go");
413
+ continue;
414
+ }
415
+ }
416
+ }
417
+
418
+ const installSpinner = p.spinner();
419
+ installSpinner.start("Installing " + dep.name + "...");
420
+
421
+ const success = await runInstall(dep.install);
422
+
423
+ if (success) {
424
+ installSpinner.stop(dep.name + " installed");
425
+ } else {
426
+ installSpinner.stop("Failed to install " + dep.name);
427
+ p.log.message(" Manual: " + dep.install);
428
+ }
429
+ }
430
+ }
431
+ }
432
+
433
+ const manual = optionalMissing.filter(
434
+ (r) => r.dep.installType === "manual",
435
+ );
436
+ if (manual.length > 0) {
437
+ p.log.step("Manual installation required:");
438
+ for (const { dep } of manual) {
439
+ p.log.message(" " + dep.name + ": " + dep.install);
440
+ }
441
+ }
442
+ }
443
+
444
+ p.log.step("Setting up OpenCode integration...");
445
+
446
+ const configDir = join(homedir(), ".config", "opencode");
447
+ const pluginsDir = join(configDir, "plugins");
448
+ const commandsDir = join(configDir, "commands");
449
+ const agentsDir = join(configDir, "agents");
450
+
451
+ for (const dir of [pluginsDir, commandsDir, agentsDir]) {
452
+ if (!existsSync(dir)) {
453
+ mkdirSync(dir, { recursive: true });
454
+ }
455
+ }
456
+
457
+ const pluginPath = join(pluginsDir, "swarm.ts");
458
+ const commandPath = join(commandsDir, "swarm.md");
459
+ const agentPath = join(agentsDir, "swarm-planner.md");
460
+
461
+ writeFileSync(pluginPath, PLUGIN_WRAPPER);
462
+ p.log.success("Plugin: " + pluginPath);
463
+
464
+ writeFileSync(commandPath, SWARM_COMMAND);
465
+ p.log.success("Command: " + commandPath);
466
+
467
+ writeFileSync(agentPath, PLANNER_AGENT);
468
+ p.log.success("Agent: " + agentPath);
469
+
470
+ p.note(
471
+ 'cd your-project\nbd init\nopencode\n/swarm "your task"',
472
+ "Next steps",
473
+ );
474
+
475
+ p.outro("Setup complete! Run 'swarm doctor' to verify.");
476
+ }
477
+
478
+ async function init() {
479
+ p.intro("swarm init v" + VERSION);
480
+
481
+ const gitDir = existsSync(".git");
482
+ if (!gitDir) {
483
+ p.log.error("Not in a git repository");
484
+ p.log.message("Run 'git init' first, or cd to a git repo");
485
+ p.outro("Aborted");
486
+ process.exit(1);
487
+ }
488
+
489
+ const beadsDir = existsSync(".beads");
490
+ if (beadsDir) {
491
+ p.log.warn("Beads already initialized in this project");
492
+
493
+ const reinit = await p.confirm({
494
+ message: "Re-initialize beads?",
495
+ initialValue: false,
496
+ });
497
+
498
+ if (p.isCancel(reinit) || !reinit) {
499
+ p.outro("Aborted");
500
+ process.exit(0);
501
+ }
502
+ }
503
+
504
+ const s = p.spinner();
505
+ s.start("Initializing beads...");
506
+
507
+ const success = await runInstall("bd init");
508
+
509
+ if (success) {
510
+ s.stop("Beads initialized");
511
+ p.log.success("Created .beads/ directory");
512
+
513
+ const createBead = await p.confirm({
514
+ message: "Create your first bead?",
515
+ initialValue: true,
516
+ });
517
+
518
+ if (!p.isCancel(createBead) && createBead) {
519
+ const title = await p.text({
520
+ message: "Bead title:",
521
+ placeholder: "Implement user authentication",
522
+ validate: (v) => (v.length === 0 ? "Title required" : undefined),
523
+ });
524
+
525
+ if (!p.isCancel(title)) {
526
+ const typeResult = await p.select({
527
+ message: "Type:",
528
+ options: [
529
+ { value: "feature", label: "Feature", hint: "New functionality" },
530
+ { value: "bug", label: "Bug", hint: "Something broken" },
531
+ { value: "task", label: "Task", hint: "General work item" },
532
+ { value: "chore", label: "Chore", hint: "Maintenance" },
533
+ ],
534
+ });
535
+
536
+ if (!p.isCancel(typeResult)) {
537
+ const beadSpinner = p.spinner();
538
+ beadSpinner.start("Creating bead...");
539
+
540
+ const createSuccess = await runInstall(
541
+ 'bd create --title "' + title + '" --type ' + typeResult,
542
+ );
543
+
544
+ if (createSuccess) {
545
+ beadSpinner.stop("Bead created");
546
+ } else {
547
+ beadSpinner.stop("Failed to create bead");
548
+ }
549
+ }
550
+ }
551
+ }
552
+
553
+ p.outro("Project initialized! Use '/swarm' in OpenCode to get started.");
554
+ } else {
555
+ s.stop("Failed to initialize beads");
556
+ p.log.error("Make sure 'bd' is installed: swarm doctor");
557
+ p.outro("Aborted");
558
+ process.exit(1);
559
+ }
560
+ }
561
+
562
+ function version() {
563
+ console.log("opencode-swarm-plugin v" + VERSION);
564
+ }
565
+
566
+ function help() {
567
+ console.log(`
568
+ opencode-swarm-plugin v${VERSION}
569
+
570
+ Multi-agent swarm coordination for OpenCode.
571
+
572
+ Commands:
573
+ swarm setup Interactive installer - checks and installs dependencies
574
+ swarm doctor Health check - shows status of all dependencies
575
+ swarm init Initialize beads in current project
576
+ swarm version Show version
577
+ swarm help Show this help
578
+
579
+ After setup, use in OpenCode:
580
+ /swarm "Add user authentication with OAuth"
581
+ @swarm-planner "Refactor components to use hooks"
582
+
583
+ Documentation: https://github.com/joelhooks/opencode-swarm-plugin
584
+ `);
585
+ }
586
+
587
+ // ============================================================================
588
+ // Main
589
+ // ============================================================================
590
+
591
+ const command = process.argv[2];
592
+
593
+ switch (command) {
594
+ case "setup":
595
+ await setup();
596
+ break;
597
+ case "doctor":
598
+ await doctor();
599
+ break;
600
+ case "init":
601
+ await init();
602
+ break;
603
+ case "version":
604
+ case "--version":
605
+ case "-v":
606
+ version();
607
+ break;
608
+ case "help":
609
+ case "--help":
610
+ case "-h":
611
+ help();
612
+ break;
613
+ case undefined:
614
+ await setup();
615
+ break;
616
+ default:
617
+ console.error("Unknown command: " + command);
618
+ help();
619
+ process.exit(1);
620
+ }
package/bun.lock CHANGED
@@ -5,6 +5,7 @@
5
5
  "": {
6
6
  "name": "opencode-swarm-plugin",
7
7
  "dependencies": {
8
+ "@clack/prompts": "^0.11.0",
8
9
  "@opencode-ai/plugin": "^1.0.134",
9
10
  "ioredis": "^5.4.1",
10
11
  "zod": "4.1.8",
@@ -20,6 +21,10 @@
20
21
  },
21
22
  },
22
23
  "packages": {
24
+ "@clack/core": ["@clack/core@0.5.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="],
25
+
26
+ "@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="],
27
+
23
28
  "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
24
29
 
25
30
  "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
@@ -204,6 +209,8 @@
204
209
 
205
210
  "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
206
211
 
212
+ "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
213
+
207
214
  "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
208
215
 
209
216
  "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "opencode-swarm-plugin",
3
- "version": "0.6.1",
3
+ "version": "0.9.0",
4
4
  "description": "Multi-agent swarm coordination for OpenCode with learning capabilities, beads integration, and Agent Mail",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "swarm": "./bin/swarm.ts"
10
+ },
8
11
  "exports": {
9
12
  ".": {
10
13
  "import": "./dist/index.js",
@@ -22,6 +25,7 @@
22
25
  "clean": "rm -rf dist"
23
26
  },
24
27
  "dependencies": {
28
+ "@clack/prompts": "^0.11.0",
25
29
  "@opencode-ai/plugin": "^1.0.134",
26
30
  "ioredis": "^5.4.1",
27
31
  "zod": "4.1.8"