swarmkit 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -131
- package/dist/commands/add.js +45 -2
- package/dist/commands/init/phases/global-setup.js +1 -1
- package/dist/commands/init/phases/project.js +5 -3
- package/dist/commands/init/state.d.ts +2 -0
- package/dist/commands/init/state.js +1 -0
- package/dist/commands/init/state.test.js +1 -0
- package/dist/commands/init/wizard.d.ts +4 -1
- package/dist/commands/init/wizard.js +59 -7
- package/dist/commands/init.js +3 -2
- package/dist/commands/remove.js +6 -0
- package/dist/config/global.d.ts +2 -0
- package/dist/config/global.test.js +14 -14
- package/dist/doctor/checks.d.ts +1 -1
- package/dist/doctor/checks.js +26 -10
- package/dist/doctor/checks.test.js +52 -27
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/packages/installer.d.ts +9 -0
- package/dist/packages/installer.js +43 -12
- package/dist/packages/installer.test.js +84 -1
- package/dist/packages/plugin.d.ts +13 -0
- package/dist/packages/plugin.js +33 -0
- package/dist/packages/plugin.test.d.ts +1 -0
- package/dist/packages/plugin.test.js +99 -0
- package/dist/packages/registry.d.ts +1 -1
- package/dist/packages/registry.js +25 -50
- package/dist/packages/registry.test.js +38 -49
- package/dist/packages/setup.d.ts +11 -4
- package/dist/packages/setup.js +208 -103
- package/dist/packages/setup.test.js +337 -246
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,78 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
An open-source toolkit for building, running, and improving multi-agent AI systems.
|
|
4
4
|
|
|
5
|
-
swarmkit is a collection of independent
|
|
5
|
+
swarmkit is a collection of independent projects that each solve a specific problem — task management, memory, learning, orchestration, coordination. Each can be used standalone or composed with the others.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Projects
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
|
|
11
|
-
│
|
|
12
|
-
│
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
│
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
│ LEARNING & MEMORY │
|
|
27
|
-
│ cognitive-core · minimem · skill-tree │
|
|
28
|
-
└─────────────────────────────────────────────────────────────┘
|
|
10
|
+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
11
|
+
│ opentasks │ │ minimem │ │ cognitive- │
|
|
12
|
+
│ task graph │ │ memory & │ │ core │
|
|
13
|
+
│ & specs │ │ search │ │ learning │
|
|
14
|
+
└──────────────┘ └──────────────┘ └──────┬───────┘
|
|
15
|
+
│ delegates
|
|
16
|
+
┌──────────────┐ ┌──────────────┐ ┌──────▼───────┐
|
|
17
|
+
│ self-driving │ │ openhive │ │ skill-tree │
|
|
18
|
+
│ -repo │ │ agent hub │ │ skill mgmt │
|
|
19
|
+
│ GitHub SDLC │ │ & sync │ │ & serving │
|
|
20
|
+
└──────────────┘ └──────────────┘ └──────────────┘
|
|
21
|
+
|
|
22
|
+
┌───────────────────────────────────────────────────┐
|
|
23
|
+
│ multi-agent-protocol (MAP) │
|
|
24
|
+
│ observation & coordination protocol │
|
|
25
|
+
└───────────────────────────────────────────────────┘
|
|
29
26
|
```
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
### Orchestration
|
|
34
|
-
|
|
35
|
-
#### [macro-agent](https://github.com/alexngai/macro-agent)
|
|
36
|
-
|
|
37
|
-
A multi-agent orchestration system for spawning and managing hierarchical Claude Code agents. Interact with multiple agents as if they were one.
|
|
38
|
-
|
|
39
|
-
- Role-based agents (Worker, Integrator, Coordinator, Monitor)
|
|
40
|
-
- Declarative team templates in YAML
|
|
41
|
-
- Workspace isolation via git worktrees with merge queue
|
|
42
|
-
- Event-sourced state with real-time message routing
|
|
43
|
-
|
|
44
|
-
macro-agent is the general-purpose orchestrator — it manages agent lifecycles, routes messages between them, and coordinates parallel work with conflict-free integration.
|
|
45
|
-
|
|
46
|
-
#### [self-driving-repo](https://github.com/alexngai/self-driving-repo)
|
|
47
|
-
|
|
48
|
-
An event-driven workflow engine that automates the software development lifecycle within GitHub repositories.
|
|
49
|
-
|
|
50
|
-
- Define DAGs of autonomous agents in declarative YAML
|
|
51
|
-
- Agents triage issues, implement changes, review code, and merge PRs
|
|
52
|
-
- Safe-outputs pipeline validates all agent actions before applying them
|
|
53
|
-
- Multi-repo steering with trust-level gating
|
|
54
|
-
|
|
55
|
-
self-driving-repo is the GitHub-native orchestrator — it compiles agent workflows into GitHub Actions and uses GitHub's own primitives (issues, PRs, labels, comments) for state management, requiring zero external infrastructure.
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
### Protocol
|
|
60
|
-
|
|
61
|
-
#### [multi-agent-protocol (MAP)](https://github.com/alexngai/multi-agent-protocol)
|
|
62
|
-
|
|
63
|
-
A JSON-RPC based protocol for observing, coordinating, and routing messages within multi-agent AI systems.
|
|
64
|
-
|
|
65
|
-
- Transparent visibility into agent relationships and message flows
|
|
66
|
-
- 4-layer permission model (system, participant, scope, agent)
|
|
67
|
-
- Federation support for connecting independent agent systems
|
|
68
|
-
- ACP compatibility layer for existing tooling
|
|
69
|
-
|
|
70
|
-
Where MCP connects agents to tools and ACP connects clients to agents, MAP provides a window *into* a multi-agent system — its internal structure, hierarchies, and coordination patterns.
|
|
28
|
+
Each box is a standalone tool. Arrows show optional integrations, not dependencies.
|
|
71
29
|
|
|
72
30
|
---
|
|
73
31
|
|
|
74
|
-
###
|
|
75
|
-
|
|
76
|
-
#### [opentasks](https://github.com/alexngai/opentasks)
|
|
32
|
+
### [opentasks](https://github.com/alexngai/opentasks)
|
|
77
33
|
|
|
78
34
|
Cross-system graph for tasks and specs. Link Claude Tasks to Beads issues to Jira tickets. Query blockers and ready work across all of them.
|
|
79
35
|
|
|
@@ -84,52 +40,18 @@ Cross-system graph for tasks and specs. Link Claude Tasks to Beads issues to Jir
|
|
|
84
40
|
|
|
85
41
|
opentasks doesn't replace your existing task systems — it adds the relationship layer between them, so agents can reason about cross-system dependencies and find what's ready to work on.
|
|
86
42
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
### Security
|
|
90
|
-
|
|
91
|
-
#### [agent-iam](https://github.com/alexngai/agent-iam)
|
|
92
|
-
|
|
93
|
-
A capability-based credential broker for AI agents.
|
|
94
|
-
|
|
95
|
-
- HMAC-SHA256 signed capability tokens with hierarchical delegation
|
|
96
|
-
- Automatic scope attenuation — child tokens can only narrow permissions
|
|
97
|
-
- Provider adapters for GitHub, AWS, Google, Slack, and generic API keys
|
|
98
|
-
- Distributed leader/follower mode for multi-region deployments
|
|
99
|
-
|
|
100
|
-
agent-iam answers "what is this agent allowed to do?" through cryptographically signed tokens that support delegation chains with automatic scope narrowing.
|
|
43
|
+
### [minimem](https://github.com/alexngai/minimem)
|
|
101
44
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
### Interfaces
|
|
105
|
-
|
|
106
|
-
#### [openswarm](https://github.com/alexngai/openswarm)
|
|
107
|
-
|
|
108
|
-
A multi-agent terminal UI and MAP server host.
|
|
109
|
-
|
|
110
|
-
- Rich TUI built with Solid.js and OpenTUI (Zig-based terminal renderer)
|
|
111
|
-
- Plugin system for extending with system-specific features
|
|
112
|
-
- MAP server hosting with pluggable adapter system
|
|
113
|
-
- Session persistence, forking, and checkpoint management
|
|
114
|
-
|
|
115
|
-
openswarm is the operator interface — a terminal application for observing, steering, and interacting with multi-agent systems running on MAP.
|
|
116
|
-
|
|
117
|
-
#### [openhive](https://github.com/alexngai/openhive)
|
|
118
|
-
|
|
119
|
-
A self-hostable, lightweight social network for AI agents. Think Reddit, but for agents.
|
|
120
|
-
|
|
121
|
-
- Posts, threaded comments, communities (hives), voting, karma
|
|
122
|
-
- MAP Hub for swarm registration and discovery
|
|
123
|
-
- Swarm hosting — spawn and manage openswarm instances
|
|
124
|
-
- Mesh networking, hive sync across instances, channel bridges to Slack/Discord
|
|
125
|
-
|
|
126
|
-
openhive is the coordination hub — agents discover each other, share knowledge, and form swarms. It also serves as a MAP Hub, providing the discovery layer for connecting independent agent systems.
|
|
45
|
+
A lightweight, file-based memory system with vector search for AI agents. Write memories in Markdown, search them semantically.
|
|
127
46
|
|
|
128
|
-
|
|
47
|
+
- Plain Markdown storage — human-readable, git-friendly
|
|
48
|
+
- Hybrid search combining vector similarity (cosine) with full-text (BM25)
|
|
49
|
+
- Multiple embedding providers: OpenAI, Gemini, or local models
|
|
50
|
+
- MCP server for integration with Claude Desktop, Cursor, and other tools
|
|
129
51
|
|
|
130
|
-
|
|
52
|
+
minimem is the retrieval layer — it indexes knowledge as searchable Markdown files with semantic understanding, providing the fast lookup that agents need at task time.
|
|
131
53
|
|
|
132
|
-
|
|
54
|
+
### [cognitive-core](https://github.com/alexngai/cognitive-core)
|
|
133
55
|
|
|
134
56
|
A TypeScript learning system for AI agents. Records how agents solve problems, extracts reusable playbooks, and injects relevant guidance into future tasks.
|
|
135
57
|
|
|
@@ -140,18 +62,7 @@ A TypeScript learning system for AI agents. Records how agents solve problems, e
|
|
|
140
62
|
|
|
141
63
|
cognitive-core is the learning engine — it turns raw agent sessions into structured, reusable knowledge that improves agent performance over time.
|
|
142
64
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
A lightweight, file-based memory system with vector search for AI agents. Write memories in Markdown, search them semantically.
|
|
146
|
-
|
|
147
|
-
- Plain Markdown storage — human-readable, git-friendly
|
|
148
|
-
- Hybrid search combining vector similarity (cosine) with full-text (BM25)
|
|
149
|
-
- Multiple embedding providers: OpenAI, Gemini, or local models
|
|
150
|
-
- MCP server for integration with Claude Desktop, Cursor, and other tools
|
|
151
|
-
|
|
152
|
-
minimem is the retrieval layer — it indexes knowledge as searchable Markdown files with semantic understanding, providing the fast lookup that agents need at task time.
|
|
153
|
-
|
|
154
|
-
#### [skill-tree](https://github.com/alexngai/skill-tree)
|
|
65
|
+
### [skill-tree](https://github.com/alexngai/skill-tree)
|
|
155
66
|
|
|
156
67
|
A TypeScript library for managing agent skill versions and evolution. Extract, iterate, and adapt skills from agent trajectories.
|
|
157
68
|
|
|
@@ -162,31 +73,56 @@ A TypeScript library for managing agent skill versions and evolution. Extract, i
|
|
|
162
73
|
|
|
163
74
|
skill-tree is the skill management layer — it captures what agents learn as discrete, versioned, searchable skills that can be served back to agents through MCP.
|
|
164
75
|
|
|
76
|
+
### [self-driving-repo](https://github.com/alexngai/self-driving-repo)
|
|
77
|
+
|
|
78
|
+
An event-driven workflow engine that automates the software development lifecycle within GitHub repositories.
|
|
79
|
+
|
|
80
|
+
- Define DAGs of autonomous agents in declarative YAML
|
|
81
|
+
- Agents triage issues, implement changes, review code, and merge PRs
|
|
82
|
+
- Safe-outputs pipeline validates all agent actions before applying them
|
|
83
|
+
- Multi-repo steering with trust-level gating
|
|
84
|
+
|
|
85
|
+
self-driving-repo is a GitHub-native orchestrator — it compiles agent workflows into GitHub Actions and uses GitHub's own primitives (issues, PRs, labels, comments) for state management. It can run standalone or compose with opentasks for cross-system task tracking.
|
|
86
|
+
|
|
87
|
+
### [openhive](https://github.com/alexngai/openhive)
|
|
88
|
+
|
|
89
|
+
A self-hostable, lightweight social network for AI agents. Think Reddit, but for agents.
|
|
90
|
+
|
|
91
|
+
- Posts, threaded comments, communities (hives), voting, karma
|
|
92
|
+
- MAP Hub for swarm registration and discovery
|
|
93
|
+
- Mesh networking, hive sync across instances, channel bridges to Slack/Discord
|
|
94
|
+
|
|
95
|
+
openhive is a coordination and sync target — agents discover each other, share knowledge, and form swarms. It also serves as a MAP Hub, providing the discovery layer for connecting independent agent systems.
|
|
96
|
+
|
|
97
|
+
### [multi-agent-protocol (MAP)](https://github.com/alexngai/multi-agent-protocol)
|
|
98
|
+
|
|
99
|
+
A JSON-RPC based protocol for observing, coordinating, and routing messages within multi-agent AI systems.
|
|
100
|
+
|
|
101
|
+
- Transparent visibility into agent relationships and message flows
|
|
102
|
+
- 4-layer permission model (system, participant, scope, agent)
|
|
103
|
+
- Federation support for connecting independent agent systems
|
|
104
|
+
- ACP compatibility layer for existing tooling
|
|
105
|
+
|
|
106
|
+
Where MCP connects agents to tools and ACP connects clients to agents, MAP provides a window *into* a multi-agent system — its internal structure, hierarchies, and coordination patterns.
|
|
107
|
+
|
|
165
108
|
---
|
|
166
109
|
|
|
167
110
|
## How They Connect
|
|
168
111
|
|
|
169
|
-
|
|
112
|
+
Every project works on its own. When used together, they integrate at the edges:
|
|
170
113
|
|
|
171
|
-
| Integration | What
|
|
114
|
+
| Integration | What happens |
|
|
172
115
|
|-------------|-------------|
|
|
173
|
-
| **
|
|
174
|
-
| **
|
|
175
|
-
| **
|
|
176
|
-
| **openhive +
|
|
177
|
-
| **agent-iam + MAP** | Token identity fields designed for MAP federation and cross-system auth |
|
|
178
|
-
| **cognitive-core + minimem** | Share a knowledge file format (YAML frontmatter Markdown); minimem provides the search layer |
|
|
179
|
-
| **cognitive-core + skill-tree** | skill-tree's `CognitiveCoreProvider` delegates to cognitive-core for batch learning |
|
|
180
|
-
| **self-driving-repo + macro-agent** | Both orchestrate agents — self-driving-repo for GitHub-native workflows, macro-agent for general-purpose |
|
|
116
|
+
| **cognitive-core + minimem** | cognitive-core uses minimem as its search layer; both use YAML-frontmatter Markdown |
|
|
117
|
+
| **cognitive-core + skill-tree** | skill-tree delegates to cognitive-core for batch learning via `CognitiveCoreProvider` |
|
|
118
|
+
| **self-driving-repo + opentasks** | self-driving-repo uses opentasks for cross-system task tracking in automated workflows |
|
|
119
|
+
| **openhive + MAP** | openhive acts as a MAP Hub for swarm registration and discovery |
|
|
181
120
|
|
|
182
121
|
## Design Principles
|
|
183
122
|
|
|
184
|
-
These principles are shared across the projects:
|
|
185
|
-
|
|
186
123
|
- **Composition over monolith** — Each project has a clear boundary. Use one, some, or all.
|
|
187
124
|
- **File-based persistence** — Markdown, JSONL, SQLite. No heavy databases. Git-friendly where possible.
|
|
188
125
|
- **Pluggable everything** — Providers, adapters, storage backends, embedding models. Swap what you need.
|
|
189
|
-
- **Security by capability** — Tokens represent what you can do, not who you are. Delegation narrows scope automatically.
|
|
190
126
|
- **Observable by default** — MAP provides transparency into agent systems. Event sourcing provides auditability.
|
|
191
127
|
|
|
192
128
|
## License
|
package/dist/commands/add.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
+
import { select } from "@inquirer/prompts";
|
|
2
3
|
import { readConfig, addInstalledPackages } from "../config/global.js";
|
|
3
4
|
import { isKnownPackage, PACKAGES, getNewIntegrations, } from "../packages/registry.js";
|
|
4
|
-
import { installPackages, getInstalledVersion } from "../packages/installer.js";
|
|
5
|
+
import { installPackages, getInstalledVersion, isClaudeCliAvailable } from "../packages/installer.js";
|
|
6
|
+
import { isInstalledPlugin, registerPlugin } from "../packages/plugin.js";
|
|
5
7
|
import * as ui from "../utils/ui.js";
|
|
6
8
|
export function registerAddCommand(program) {
|
|
7
9
|
program
|
|
@@ -22,7 +24,6 @@ export function registerAddCommand(program) {
|
|
|
22
24
|
ui.info(`${packageName} is already installed (v${existing}).`);
|
|
23
25
|
return;
|
|
24
26
|
}
|
|
25
|
-
// Install
|
|
26
27
|
const def = PACKAGES[packageName];
|
|
27
28
|
if (def) {
|
|
28
29
|
ui.info(def.description);
|
|
@@ -39,6 +40,10 @@ export function registerAddCommand(program) {
|
|
|
39
40
|
ui.success(`${packageName} ${result.version ? "v" + result.version : ""} installed`);
|
|
40
41
|
// Update registry
|
|
41
42
|
addInstalledPackages([packageName]);
|
|
43
|
+
// Post-install: offer Claude Code plugin activation if applicable
|
|
44
|
+
if (await isInstalledPlugin(packageName)) {
|
|
45
|
+
await promptPluginActivation(packageName);
|
|
46
|
+
}
|
|
42
47
|
// Show new integrations
|
|
43
48
|
const config = readConfig();
|
|
44
49
|
const newIntegrations = getNewIntegrations(config.installedPackages.filter((p) => p !== packageName), packageName);
|
|
@@ -53,3 +58,41 @@ export function registerAddCommand(program) {
|
|
|
53
58
|
ui.blank();
|
|
54
59
|
});
|
|
55
60
|
}
|
|
61
|
+
async function promptPluginActivation(packageName) {
|
|
62
|
+
if (!(await isClaudeCliAvailable())) {
|
|
63
|
+
ui.info(`${packageName} is a Claude Code plugin.`);
|
|
64
|
+
ui.info("Install Claude Code to activate it: https://docs.anthropic.com/en/docs/claude-code");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
console.log();
|
|
68
|
+
ui.info(`${packageName} is a Claude Code plugin.`);
|
|
69
|
+
const choice = await select({
|
|
70
|
+
message: "How would you like to activate it?",
|
|
71
|
+
choices: [
|
|
72
|
+
{
|
|
73
|
+
name: "Project (this repository only)",
|
|
74
|
+
value: "project",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "User (all projects)",
|
|
78
|
+
value: "user",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "Skip (activate later)",
|
|
82
|
+
value: "skip",
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
if (choice === "skip") {
|
|
87
|
+
ui.info("Skipped. Activate later with: claude plugin add <path> --scope project|user");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
await registerPlugin(packageName, choice);
|
|
92
|
+
ui.success(`Plugin activated (${choice} scope).`);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
96
|
+
ui.fail(`Plugin activation failed: ${msg}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -3,7 +3,7 @@ import chalk from "chalk";
|
|
|
3
3
|
import { GLOBAL_CONFIG_DIRS, isGlobalInit, initGlobalPackage, } from "../../../packages/setup.js";
|
|
4
4
|
import * as ui from "../../../utils/ui.js";
|
|
5
5
|
/** Global packages in setup order */
|
|
6
|
-
const GLOBAL_SETUP_ORDER = ["
|
|
6
|
+
const GLOBAL_SETUP_ORDER = ["skill-tree", "openhive"];
|
|
7
7
|
export async function initGlobal(state) {
|
|
8
8
|
const globalPackages = GLOBAL_SETUP_ORDER.filter((pkg) => state.selectedPackages.includes(pkg));
|
|
9
9
|
if (globalPackages.length === 0)
|
|
@@ -3,7 +3,7 @@ import { join } from "node:path";
|
|
|
3
3
|
import { confirm } from "@inquirer/prompts";
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { PACKAGES } from "../../../packages/registry.js";
|
|
6
|
-
import {
|
|
6
|
+
import { PROJECT_INIT_ORDER, projectConfigDirs, isProjectInit, initProjectPackage, } from "../../../packages/setup.js";
|
|
7
7
|
import * as ui from "../../../utils/ui.js";
|
|
8
8
|
export async function initProject(state) {
|
|
9
9
|
const cwd = process.cwd();
|
|
@@ -14,10 +14,11 @@ export async function initProject(state) {
|
|
|
14
14
|
ui.info("Run `swarmkit init` inside a project directory to initialize per-project configs.");
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
+
const configDirs = projectConfigDirs(state.usePrefix);
|
|
17
18
|
// Filter to packages that have project-level config, in init order
|
|
18
19
|
const projectPackages = PROJECT_INIT_ORDER.filter((pkg) => state.selectedPackages.includes(pkg) &&
|
|
19
20
|
!PACKAGES[pkg]?.globalOnly &&
|
|
20
|
-
pkg in
|
|
21
|
+
pkg in configDirs);
|
|
21
22
|
if (projectPackages.length === 0)
|
|
22
23
|
return;
|
|
23
24
|
// Check which are already initialized
|
|
@@ -39,11 +40,12 @@ export async function initProject(state) {
|
|
|
39
40
|
packages: state.selectedPackages,
|
|
40
41
|
embeddingProvider: state.embeddingProvider,
|
|
41
42
|
apiKeys: state.apiKeys,
|
|
43
|
+
usePrefix: state.usePrefix,
|
|
42
44
|
};
|
|
43
45
|
ui.blank();
|
|
44
46
|
for (const pkg of uninitialized) {
|
|
45
47
|
const result = await initProjectPackage(pkg, ctx);
|
|
46
|
-
const configDir =
|
|
48
|
+
const configDir = configDirs[pkg] ?? "";
|
|
47
49
|
if (result.success) {
|
|
48
50
|
ui.success(`${pkg} ${chalk.dim("→")} ${configDir}/`);
|
|
49
51
|
}
|
|
@@ -7,5 +7,7 @@ export interface WizardState {
|
|
|
7
7
|
embeddingProvider: "openai" | "gemini" | "local" | null;
|
|
8
8
|
/** Collected API keys (provider -> key) */
|
|
9
9
|
apiKeys: Record<string, string>;
|
|
10
|
+
/** Whether to nest project configs under .swarm/ (default true) */
|
|
11
|
+
usePrefix: boolean;
|
|
10
12
|
}
|
|
11
13
|
export declare function createEmptyState(): WizardState;
|
|
@@ -8,6 +8,7 @@ describe("WizardState", () => {
|
|
|
8
8
|
expect(state.selectedPackages).toEqual([]);
|
|
9
9
|
expect(state.embeddingProvider).toBeNull();
|
|
10
10
|
expect(state.apiKeys).toEqual({});
|
|
11
|
+
expect(state.usePrefix).toBe(true);
|
|
11
12
|
});
|
|
12
13
|
it("returns a new object each time", () => {
|
|
13
14
|
const a = createEmptyState();
|
|
@@ -1,46 +1,98 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import {
|
|
2
|
+
import { select } from "@inquirer/prompts";
|
|
3
|
+
import { isFirstRun, readConfig, writeConfig, ensureConfigDir } from "../../config/global.js";
|
|
3
4
|
import * as ui from "../../utils/ui.js";
|
|
4
5
|
import { getActiveIntegrations } from "../../packages/registry.js";
|
|
6
|
+
import { isClaudeCliAvailable } from "../../packages/installer.js";
|
|
7
|
+
import { isInstalledPlugin, registerPlugin } from "../../packages/plugin.js";
|
|
5
8
|
import { createEmptyState } from "./state.js";
|
|
6
9
|
import { selectUseCase } from "./phases/use-case.js";
|
|
7
10
|
import { installSelectedPackages } from "./phases/packages.js";
|
|
8
11
|
import { configureKeys } from "./phases/configure.js";
|
|
9
12
|
import { initProject } from "./phases/project.js";
|
|
10
13
|
import { initGlobal } from "./phases/global-setup.js";
|
|
11
|
-
export async function runWizard() {
|
|
14
|
+
export async function runWizard(opts) {
|
|
12
15
|
console.log();
|
|
13
16
|
console.log(` ${chalk.bold("swarmkit")} ${chalk.dim("— multi-agent infrastructure toolkit")}`);
|
|
14
17
|
console.log();
|
|
15
18
|
if (isFirstRun()) {
|
|
16
|
-
await runFirstTimeSetup();
|
|
19
|
+
await runFirstTimeSetup(opts);
|
|
17
20
|
}
|
|
18
21
|
else {
|
|
19
|
-
await runProjectSetup();
|
|
22
|
+
await runProjectSetup(opts);
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
|
-
async function runFirstTimeSetup() {
|
|
25
|
+
async function runFirstTimeSetup(opts) {
|
|
23
26
|
ensureConfigDir();
|
|
24
27
|
// Step 1: Use case / bundle selection
|
|
25
28
|
let state = await selectUseCase(createEmptyState());
|
|
29
|
+
if (opts?.noPrefix) {
|
|
30
|
+
state.usePrefix = false;
|
|
31
|
+
}
|
|
26
32
|
// Step 2: Install packages
|
|
27
33
|
await installSelectedPackages(state);
|
|
34
|
+
// Step 2.5: Plugin activation (for any Claude Code plugins)
|
|
35
|
+
await activatePlugins(state);
|
|
28
36
|
// Step 3: Configure (embedding provider, API keys)
|
|
29
37
|
state = await configureKeys(state);
|
|
30
|
-
// Step 4: Global package setup (
|
|
38
|
+
// Step 4: Global package setup (skill-tree, openhive)
|
|
31
39
|
await initGlobal(state);
|
|
32
40
|
// Step 5: Project init (if in a project directory)
|
|
33
41
|
await initProject(state);
|
|
42
|
+
// Persist prefix preference
|
|
43
|
+
const config = readConfig();
|
|
44
|
+
config.usePrefix = state.usePrefix;
|
|
45
|
+
writeConfig(config);
|
|
34
46
|
// Summary
|
|
35
47
|
printSummary(state);
|
|
36
48
|
}
|
|
37
|
-
async function runProjectSetup() {
|
|
49
|
+
async function runProjectSetup(opts) {
|
|
38
50
|
const config = readConfig();
|
|
39
51
|
ui.info(`Global config found. ${config.installedPackages.length} packages installed.`);
|
|
40
52
|
const state = createEmptyState();
|
|
41
53
|
state.selectedPackages = [...config.installedPackages];
|
|
54
|
+
state.usePrefix = opts?.noPrefix === true ? false : (config.usePrefix ?? true);
|
|
42
55
|
await initProject(state);
|
|
43
56
|
}
|
|
57
|
+
async function activatePlugins(state) {
|
|
58
|
+
if (!(await isClaudeCliAvailable()))
|
|
59
|
+
return;
|
|
60
|
+
for (const pkg of state.selectedPackages) {
|
|
61
|
+
if (!(await isInstalledPlugin(pkg)))
|
|
62
|
+
continue;
|
|
63
|
+
console.log();
|
|
64
|
+
ui.info(`${pkg} is a Claude Code plugin.`);
|
|
65
|
+
const choice = await select({
|
|
66
|
+
message: `Activate ${pkg} as a Claude Code plugin?`,
|
|
67
|
+
choices: [
|
|
68
|
+
{
|
|
69
|
+
name: "Project (this repository only)",
|
|
70
|
+
value: "project",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "User (all projects)",
|
|
74
|
+
value: "user",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "Skip (activate later)",
|
|
78
|
+
value: "skip",
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
});
|
|
82
|
+
if (choice === "skip") {
|
|
83
|
+
ui.info("Skipped. Activate later with: claude plugin add <path> --scope project|user");
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
await registerPlugin(pkg, choice);
|
|
88
|
+
ui.success(`Plugin activated (${choice} scope).`);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
92
|
+
ui.fail(`Plugin activation failed: ${msg}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
44
96
|
function printSummary(state) {
|
|
45
97
|
const integrations = getActiveIntegrations(state.selectedPackages);
|
|
46
98
|
if (integrations.length > 0) {
|
package/dist/commands/init.js
CHANGED
|
@@ -2,9 +2,10 @@ export function registerInitCommand(program) {
|
|
|
2
2
|
program
|
|
3
3
|
.command("init")
|
|
4
4
|
.description("Interactive setup wizard")
|
|
5
|
-
.
|
|
5
|
+
.option("--no-prefix", "Use flat layout (e.g. .opentasks/) instead of nesting under .swarm/")
|
|
6
|
+
.action(async (opts) => {
|
|
6
7
|
// Dynamic import to avoid loading @inquirer/prompts for other commands
|
|
7
8
|
const { runWizard } = await import("./init/wizard.js");
|
|
8
|
-
await runWizard();
|
|
9
|
+
await runWizard({ noPrefix: opts.prefix === false });
|
|
9
10
|
});
|
|
10
11
|
}
|
package/dist/commands/remove.js
CHANGED
|
@@ -2,6 +2,7 @@ import chalk from "chalk";
|
|
|
2
2
|
import { readConfig, removeInstalledPackage } from "../config/global.js";
|
|
3
3
|
import { getLostIntegrations } from "../packages/registry.js";
|
|
4
4
|
import { uninstallPackage, getInstalledVersion } from "../packages/installer.js";
|
|
5
|
+
import { isInstalledPlugin } from "../packages/plugin.js";
|
|
5
6
|
import * as ui from "../utils/ui.js";
|
|
6
7
|
export function registerRemoveCommand(program) {
|
|
7
8
|
program
|
|
@@ -27,6 +28,8 @@ export function registerRemoveCommand(program) {
|
|
|
27
28
|
}
|
|
28
29
|
console.log();
|
|
29
30
|
}
|
|
31
|
+
// Check if it's a plugin before uninstalling (while we can still resolve the path)
|
|
32
|
+
const wasPlugin = await isInstalledPlugin(packageName);
|
|
30
33
|
// Uninstall
|
|
31
34
|
console.log(` Uninstalling ${chalk.bold(packageName)}...`);
|
|
32
35
|
const version = await getInstalledVersion(packageName);
|
|
@@ -44,6 +47,9 @@ export function registerRemoveCommand(program) {
|
|
|
44
47
|
removeInstalledPackage(packageName);
|
|
45
48
|
ui.blank();
|
|
46
49
|
ui.info("Project data directories are preserved. Delete them manually if no longer needed.");
|
|
50
|
+
if (wasPlugin) {
|
|
51
|
+
ui.info(`If activated as a Claude Code plugin, also run: claude plugin uninstall ${packageName}`);
|
|
52
|
+
}
|
|
47
53
|
ui.blank();
|
|
48
54
|
});
|
|
49
55
|
}
|
package/dist/config/global.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface GlobalConfig {
|
|
|
5
5
|
embeddingProvider?: "openai" | "gemini" | "local";
|
|
6
6
|
/** Embedding model (provider-specific) */
|
|
7
7
|
embeddingModel?: string;
|
|
8
|
+
/** Whether project configs are nested under .swarm/ (default true) */
|
|
9
|
+
usePrefix?: boolean;
|
|
8
10
|
}
|
|
9
11
|
/** Get the swarmkit config directory path (~/.swarmkit/) */
|
|
10
12
|
export declare function getConfigDir(): string;
|
|
@@ -67,12 +67,12 @@ describe("config/global", () => {
|
|
|
67
67
|
});
|
|
68
68
|
it("reads written config", () => {
|
|
69
69
|
writeConfig({
|
|
70
|
-
installedPackages: ["
|
|
70
|
+
installedPackages: ["opentasks"],
|
|
71
71
|
embeddingProvider: "openai",
|
|
72
72
|
embeddingModel: "text-embedding-3-small",
|
|
73
73
|
});
|
|
74
74
|
const config = readConfig();
|
|
75
|
-
expect(config.installedPackages).toEqual(["
|
|
75
|
+
expect(config.installedPackages).toEqual(["opentasks"]);
|
|
76
76
|
expect(config.embeddingProvider).toBe("openai");
|
|
77
77
|
expect(config.embeddingModel).toBe("text-embedding-3-small");
|
|
78
78
|
});
|
|
@@ -112,23 +112,23 @@ describe("config/global", () => {
|
|
|
112
112
|
describe("addInstalledPackages", () => {
|
|
113
113
|
it("adds packages to an empty list", () => {
|
|
114
114
|
writeConfig({ installedPackages: [] });
|
|
115
|
-
addInstalledPackages(["
|
|
115
|
+
addInstalledPackages(["opentasks", "minimem"]);
|
|
116
116
|
const config = readConfig();
|
|
117
|
-
expect(config.installedPackages).toEqual(["
|
|
117
|
+
expect(config.installedPackages).toEqual(["minimem", "opentasks"]);
|
|
118
118
|
});
|
|
119
119
|
it("deduplicates packages", () => {
|
|
120
|
-
writeConfig({ installedPackages: ["
|
|
121
|
-
addInstalledPackages(["
|
|
120
|
+
writeConfig({ installedPackages: ["opentasks"] });
|
|
121
|
+
addInstalledPackages(["opentasks", "minimem"]);
|
|
122
122
|
const config = readConfig();
|
|
123
|
-
expect(config.installedPackages).toEqual(["
|
|
123
|
+
expect(config.installedPackages).toEqual(["minimem", "opentasks"]);
|
|
124
124
|
});
|
|
125
125
|
it("sorts packages alphabetically", () => {
|
|
126
|
-
addInstalledPackages(["minimem", "
|
|
126
|
+
addInstalledPackages(["minimem", "cognitive-core", "opentasks"]);
|
|
127
127
|
const config = readConfig();
|
|
128
128
|
expect(config.installedPackages).toEqual([
|
|
129
|
-
"
|
|
130
|
-
"macro-agent",
|
|
129
|
+
"cognitive-core",
|
|
131
130
|
"minimem",
|
|
131
|
+
"opentasks",
|
|
132
132
|
]);
|
|
133
133
|
});
|
|
134
134
|
it("preserves other config fields", () => {
|
|
@@ -143,16 +143,16 @@ describe("config/global", () => {
|
|
|
143
143
|
});
|
|
144
144
|
describe("removeInstalledPackage", () => {
|
|
145
145
|
it("removes a package from the list", () => {
|
|
146
|
-
writeConfig({ installedPackages: ["
|
|
146
|
+
writeConfig({ installedPackages: ["opentasks", "minimem"] });
|
|
147
147
|
removeInstalledPackage("minimem");
|
|
148
148
|
const config = readConfig();
|
|
149
|
-
expect(config.installedPackages).toEqual(["
|
|
149
|
+
expect(config.installedPackages).toEqual(["opentasks"]);
|
|
150
150
|
});
|
|
151
151
|
it("does nothing if package is not in list", () => {
|
|
152
|
-
writeConfig({ installedPackages: ["
|
|
152
|
+
writeConfig({ installedPackages: ["opentasks"] });
|
|
153
153
|
removeInstalledPackage("minimem");
|
|
154
154
|
const config = readConfig();
|
|
155
|
-
expect(config.installedPackages).toEqual(["
|
|
155
|
+
expect(config.installedPackages).toEqual(["opentasks"]);
|
|
156
156
|
});
|
|
157
157
|
it("preserves other config fields", () => {
|
|
158
158
|
writeConfig({
|
package/dist/doctor/checks.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare function checkPackages(ctx: CheckContext): Promise<CheckResult[]>
|
|
|
9
9
|
export declare function checkCredentials(ctx: CheckContext): CheckResult[];
|
|
10
10
|
/**
|
|
11
11
|
* Check that project-level config directories exist for installed packages.
|
|
12
|
-
* Only runs when cwd is a project directory.
|
|
12
|
+
* Only runs when cwd is a project directory. Checks both .swarm/ and flat layouts.
|
|
13
13
|
*/
|
|
14
14
|
export declare function checkProjectConfigs(ctx: CheckContext): CheckResult[];
|
|
15
15
|
/**
|