squads-cli 0.4.10 → 0.4.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.
package/README.md CHANGED
@@ -1,13 +1,22 @@
1
1
  # squads-cli
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/squads-cli)](https://www.npmjs.com/package/squads-cli)
4
+ [![npm downloads](https://img.shields.io/npm/dw/squads-cli)](https://www.npmjs.com/package/squads-cli)
5
+ [![GitHub stars](https://img.shields.io/github/stars/agents-squads/squads-cli?style=social)](https://github.com/agents-squads/squads-cli)
4
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
5
- [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
6
7
 
7
- **Organize, run, and track autonomous AI agents.** Built for Claude Code.
8
+ **Open source CLI for AI agent coordination.** Organize agents into domain-aligned squads with persistent memory, goal tracking, and coordinated execution.
9
+
10
+ ```bash
11
+ npm install -g squads-cli && squads init
12
+ ```
13
+
14
+ > **Why squads?** AI agents are powerful alone, but real work needs coordination. Squads organizes agents by business domain, gives them persistent memory, tracks goals, and delivers outcomes—not just answers. Works with any AI coding assistant.
8
15
 
9
16
  ![squads dashboard](./assets/dashboard.png)
10
17
 
18
+ ⭐ **If you find this useful, [star the repo](https://github.com/agents-squads/squads-cli)** — it helps others discover it!
19
+
11
20
  ```
12
21
  $ squads status
13
22
 
@@ -29,13 +38,24 @@ $ squads status
29
38
 
30
39
  ## Why squads-cli?
31
40
 
32
- AI agents are powerful individually. But real work requires coordination.
41
+ | Other Frameworks | squads-cli |
42
+ |------------------|------------|
43
+ | Framework lock-in | Markdown files you own |
44
+ | Complex setup | `npm install -g` and go |
45
+ | No memory | Persistent state across sessions |
46
+ | Single agent focus | Domain-aligned teams |
47
+ | Code-heavy | CLI-first, zero code to start |
48
+
49
+ **Works with:** Claude Code, Cursor, Aider, Gemini, GitHub Copilot, and more.
50
+
51
+ ## Key Features
33
52
 
34
53
  - **Squads** — Group agents by domain (engineering, research, marketing)
35
54
  - **Memory** — Persistent state that survives across sessions
36
55
  - **Goals** — Track objectives and measure progress
37
56
  - **Sessions** — Real-time detection of running AI assistants
38
- - **Stack** — Local infrastructure for telemetry and memory
57
+ - **Hooks** — Inject context at session start, sync memory at session end
58
+ - **Stack** — Optional local infrastructure for telemetry and cost tracking
39
59
 
40
60
  No complex infrastructure. Just markdown files and a CLI.
41
61
 
@@ -285,6 +305,36 @@ squads memory show engineering
285
305
  squads memory query "performance"
286
306
  ```
287
307
 
308
+ ### Learning Loop
309
+
310
+ Capture insights that persist across sessions:
311
+
312
+ ```bash
313
+ # After fixing a bug
314
+ squads learn "PostgreSQL connection pool exhaustion was caused by unclosed transactions"
315
+
316
+ # With metadata
317
+ squads learn "Always check memory before researching" --squad engineering --category pattern
318
+
319
+ # View learnings
320
+ squads learnings show engineering
321
+ squads learnings search "postgres"
322
+ ```
323
+
324
+ Learnings are stored in `.agents/memory/<squad>/shared/learnings.md` and sync with `squads memory sync`.
325
+
326
+ **Categories:**
327
+ - `success` — What worked well
328
+ - `failure` — What didn't work (learn from mistakes)
329
+ - `pattern` — Reusable approach
330
+ - `tip` — General advice
331
+
332
+ **The learning loop:**
333
+ 1. Session starts → hooks inject squad status + memory
334
+ 2. Work happens → you solve problems, discover things
335
+ 3. Session ends → Stop hook prompts "Capture learnings: squads learn..."
336
+ 4. Next session → Previous learnings compound via memory queries
337
+
288
338
  ### Goals with Metrics
289
339
 
290
340
  Goals can include optional metric annotations for tracking KPIs:
@@ -436,6 +486,19 @@ squads feedback show research -n 10 # Show more entries
436
486
  squads feedback stats # Summary across all squads
437
487
  ```
438
488
 
489
+ ### Learnings
490
+
491
+ ```bash
492
+ squads learn "Insight here" # Capture a learning
493
+ squads learn "Pattern" -s engineering -c pattern # With squad and category
494
+ squads learn "Tip" -t "cli,perf" # With tags
495
+ squads learnings show engineering # View squad learnings
496
+ squads learnings show engineering -n 5 # Limit results
497
+ squads learnings show engineering --category pattern # Filter by category
498
+ squads learnings show engineering --tag perf # Filter by tag
499
+ squads learnings search "postgres" # Search all learnings
500
+ ```
501
+
439
502
  ### Session Management
440
503
 
441
504
  ```bash
@@ -729,6 +792,18 @@ squads feedback show <squad> View history
729
792
  -n, --limit <n> Entries to show (default: 5)
730
793
  squads feedback stats Summary across squads
731
794
 
795
+ squads learn <insight> Capture a learning
796
+ -s, --squad <squad> Associate with squad (default: general)
797
+ -c, --category <category> Category: success, failure, pattern, tip
798
+ -t, --tags <tags> Comma-separated tags
799
+ --context <context> Additional context
800
+ squads learnings show <squad> View squad learnings
801
+ -n, --limit <n> Entries to show (default: 10)
802
+ --category <category> Filter by category
803
+ --tag <tag> Filter by tag
804
+ squads learnings search <query> Search all learnings
805
+ -n, --limit <n> Results to show (default: 10)
806
+
732
807
  squads sessions List active sessions
733
808
  -v, --verbose Session details
734
809
  -j, --json JSON output
@@ -869,7 +944,7 @@ squads whoami Show user
869
944
 
870
945
  ## Claude Code Integration
871
946
 
872
- ### Option 1: Session Hook (Recommended)
947
+ ### Option 1: Session Hooks (Recommended)
873
948
 
874
949
  Add to `.claude/settings.json`:
875
950
 
@@ -882,12 +957,21 @@ Add to `.claude/settings.json`:
882
957
  "command": "squads status",
883
958
  "timeout": 10
884
959
  }]
960
+ }],
961
+ "Stop": [{
962
+ "hooks": [{
963
+ "type": "command",
964
+ "command": "squads memory sync && echo \"\\n💡 Capture learnings: squads learn \\\"<insight>\\\"\\n\"",
965
+ "timeout": 15
966
+ }]
885
967
  }]
886
968
  }
887
969
  }
888
970
  ```
889
971
 
890
- Now every Claude Code session starts with squad context.
972
+ Now every Claude Code session:
973
+ - **Starts** with squad status injected
974
+ - **Ends** with memory synced and a prompt to capture learnings
891
975
 
892
976
  ### Option 2: CLAUDE.md Instructions
893
977
 
@@ -0,0 +1,473 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/squad-parser.ts
4
+ import { readFileSync as readFileSync2, existsSync as existsSync2, readdirSync, writeFileSync as writeFileSync2 } from "fs";
5
+ import { join as join2, basename } from "path";
6
+ import matter from "gray-matter";
7
+
8
+ // src/lib/mcp-config.ts
9
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
10
+ import { join, dirname } from "path";
11
+ var SERVER_REGISTRY = {};
12
+ function getHome() {
13
+ return process.env.HOME || process.env.USERPROFILE || "";
14
+ }
15
+ function getContextsDir() {
16
+ return join(getHome(), ".claude", "contexts");
17
+ }
18
+ function getMcpConfigsDir() {
19
+ return join(getHome(), ".claude", "mcp-configs");
20
+ }
21
+ function generateMcpConfig(mcpServers) {
22
+ const config = { mcpServers: {} };
23
+ for (const server of mcpServers) {
24
+ const def = SERVER_REGISTRY[server];
25
+ if (def) {
26
+ config.mcpServers[server] = def;
27
+ }
28
+ }
29
+ return config;
30
+ }
31
+ function writeMcpConfig(config, path) {
32
+ const dir = dirname(path);
33
+ if (!existsSync(dir)) {
34
+ mkdirSync(dir, { recursive: true });
35
+ }
36
+ writeFileSync(path, JSON.stringify(config, null, 2));
37
+ }
38
+ function readMcpConfig(path) {
39
+ if (!existsSync(path)) return null;
40
+ try {
41
+ const content = readFileSync(path, "utf-8");
42
+ return JSON.parse(content);
43
+ } catch {
44
+ return null;
45
+ }
46
+ }
47
+ function resolveMcpConfig(squadName, mcpServers, forceRegenerate = false) {
48
+ const home = getHome();
49
+ const userOverride = join(getMcpConfigsDir(), `${squadName}.json`);
50
+ if (existsSync(userOverride)) {
51
+ const config = readMcpConfig(userOverride);
52
+ return {
53
+ path: userOverride,
54
+ source: "user-override",
55
+ servers: config ? Object.keys(config.mcpServers) : void 0
56
+ };
57
+ }
58
+ if (mcpServers && mcpServers.length > 0) {
59
+ const generatedPath = join(getContextsDir(), `${squadName}.mcp.json`);
60
+ const shouldGenerate = forceRegenerate || !existsSync(generatedPath);
61
+ if (shouldGenerate) {
62
+ const config2 = generateMcpConfig(mcpServers);
63
+ writeMcpConfig(config2, generatedPath);
64
+ return {
65
+ path: generatedPath,
66
+ source: "generated",
67
+ servers: Object.keys(config2.mcpServers),
68
+ generated: true
69
+ };
70
+ }
71
+ const config = readMcpConfig(generatedPath);
72
+ return {
73
+ path: generatedPath,
74
+ source: "generated",
75
+ servers: config ? Object.keys(config.mcpServers) : mcpServers,
76
+ generated: false
77
+ };
78
+ }
79
+ return {
80
+ path: join(home, ".claude.json"),
81
+ source: "fallback"
82
+ };
83
+ }
84
+ function resolveMcpConfigPath(squadName, mcpServers) {
85
+ return resolveMcpConfig(squadName, mcpServers).path;
86
+ }
87
+
88
+ // src/lib/squad-parser.ts
89
+ function findSquadsDir() {
90
+ let dir = process.cwd();
91
+ for (let i = 0; i < 5; i++) {
92
+ const squadsPath = join2(dir, ".agents", "squads");
93
+ if (existsSync2(squadsPath)) {
94
+ return squadsPath;
95
+ }
96
+ const parent = join2(dir, "..");
97
+ if (parent === dir) break;
98
+ dir = parent;
99
+ }
100
+ return null;
101
+ }
102
+ function findProjectRoot() {
103
+ const squadsDir = findSquadsDir();
104
+ if (!squadsDir) return null;
105
+ return join2(squadsDir, "..", "..");
106
+ }
107
+ function hasLocalInfraConfig() {
108
+ const projectRoot = findProjectRoot();
109
+ if (!projectRoot) return false;
110
+ const envPath = join2(projectRoot, ".env");
111
+ if (!existsSync2(envPath)) return false;
112
+ const content = readFileSync2(envPath, "utf-8");
113
+ const infraKeys = ["LANGFUSE_", "SQUADS_BRIDGE", "SQUADS_POSTGRES", "SQUADS_REDIS"];
114
+ return infraKeys.some((key) => content.includes(key));
115
+ }
116
+ function listSquads(squadsDir) {
117
+ const squads = [];
118
+ const entries = readdirSync(squadsDir, { withFileTypes: true });
119
+ for (const entry of entries) {
120
+ if (entry.isDirectory() && !entry.name.startsWith("_")) {
121
+ const squadFile = join2(squadsDir, entry.name, "SQUAD.md");
122
+ if (existsSync2(squadFile)) {
123
+ squads.push(entry.name);
124
+ }
125
+ }
126
+ }
127
+ return squads;
128
+ }
129
+ function listAgents(squadsDir, squadName) {
130
+ const agents = [];
131
+ const dirs = squadName ? [squadName] : readdirSync(squadsDir, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith("_")).map((e) => e.name);
132
+ for (const dir of dirs) {
133
+ const squadPath = join2(squadsDir, dir);
134
+ if (!existsSync2(squadPath)) continue;
135
+ const files = readdirSync(squadPath);
136
+ for (const file of files) {
137
+ if (file.endsWith(".md") && file !== "SQUAD.md") {
138
+ const agentName = file.replace(".md", "");
139
+ agents.push({
140
+ name: agentName,
141
+ role: `Agent in ${dir}`,
142
+ trigger: "manual",
143
+ filePath: join2(squadPath, file)
144
+ });
145
+ }
146
+ }
147
+ }
148
+ return agents;
149
+ }
150
+ function parseSquadFile(filePath) {
151
+ const rawContent = readFileSync2(filePath, "utf-8");
152
+ const { data: frontmatter, content: bodyContent } = matter(rawContent);
153
+ const fm = frontmatter;
154
+ const lines = bodyContent.split("\n");
155
+ const squad = {
156
+ name: fm.name || basename(filePath).replace(".md", ""),
157
+ mission: fm.mission || "",
158
+ agents: [],
159
+ pipelines: [],
160
+ triggers: { scheduled: [], event: [], manual: [] },
161
+ routines: [],
162
+ dependencies: [],
163
+ outputPath: "",
164
+ goals: [],
165
+ // Apply frontmatter fields
166
+ effort: fm.effort,
167
+ context: fm.context,
168
+ repo: fm.repo,
169
+ stack: fm.stack,
170
+ providers: fm.providers,
171
+ // Preserve raw frontmatter for KPIs and other custom fields
172
+ frontmatter
173
+ };
174
+ let currentSection = "";
175
+ let inTable = false;
176
+ let tableHeaders = [];
177
+ for (const line of lines) {
178
+ if (line.startsWith("# Squad:")) {
179
+ squad.name = line.replace("# Squad:", "").trim().toLowerCase();
180
+ continue;
181
+ }
182
+ if (line.startsWith("## ")) {
183
+ currentSection = line.replace("## ", "").trim().toLowerCase();
184
+ inTable = false;
185
+ continue;
186
+ }
187
+ if (currentSection === "mission" && line.trim() && !line.startsWith("#")) {
188
+ if (!squad.mission) {
189
+ squad.mission = line.trim();
190
+ }
191
+ }
192
+ const effortMatch = line.match(/^effort:\s*(high|medium|low)/i);
193
+ if (effortMatch && !squad.effort) {
194
+ squad.effort = effortMatch[1].toLowerCase();
195
+ }
196
+ if (currentSection.includes("agent") || currentSection.includes("orchestrator") || currentSection.includes("evaluator") || currentSection.includes("builder") || currentSection.includes("priority")) {
197
+ if (line.includes("|") && line.includes("Agent")) {
198
+ inTable = true;
199
+ tableHeaders = line.split("|").map((h) => h.trim().toLowerCase());
200
+ continue;
201
+ }
202
+ if (inTable && line.includes("|") && !line.includes("---")) {
203
+ const cells = line.split("|").map((c) => c.trim().replace(/`/g, ""));
204
+ const agentIdx = tableHeaders.findIndex((h) => h === "agent");
205
+ const roleIdx = tableHeaders.findIndex((h) => h === "role");
206
+ const triggerIdx = tableHeaders.findIndex((h) => h === "trigger");
207
+ const statusIdx = tableHeaders.findIndex((h) => h === "status");
208
+ const effortIdx = tableHeaders.findIndex((h) => h === "effort");
209
+ if (agentIdx >= 0 && cells[agentIdx]) {
210
+ const effortValue = effortIdx >= 0 ? cells[effortIdx]?.toLowerCase() : void 0;
211
+ const effort = ["high", "medium", "low"].includes(effortValue || "") ? effortValue : void 0;
212
+ squad.agents.push({
213
+ name: cells[agentIdx],
214
+ role: roleIdx >= 0 ? cells[roleIdx] : "",
215
+ trigger: triggerIdx >= 0 ? cells[triggerIdx] : "manual",
216
+ status: statusIdx >= 0 ? cells[statusIdx] : "active",
217
+ effort
218
+ });
219
+ }
220
+ }
221
+ }
222
+ if (line.includes("\u2192") && line.includes("`")) {
223
+ const pipelineMatch = line.match(/`([^`]+)`\s*→\s*`([^`]+)`/g);
224
+ if (pipelineMatch) {
225
+ const agentNames = line.match(/`([^`]+)`/g)?.map((m) => m.replace(/`/g, "")) || [];
226
+ if (agentNames.length >= 2) {
227
+ squad.pipelines.push({
228
+ name: "default",
229
+ agents: agentNames
230
+ });
231
+ }
232
+ }
233
+ }
234
+ if (line.toLowerCase().includes("pipeline:")) {
235
+ const pipelineContent = line.split(":")[1];
236
+ if (pipelineContent && pipelineContent.includes("\u2192")) {
237
+ const agentNames = pipelineContent.match(/`([^`]+)`/g)?.map((m) => m.replace(/`/g, "")) || [];
238
+ if (agentNames.length >= 2) {
239
+ squad.pipelines.push({
240
+ name: "default",
241
+ agents: agentNames
242
+ });
243
+ }
244
+ }
245
+ }
246
+ if (line.toLowerCase().includes("primary") && line.includes("`")) {
247
+ const match = line.match(/`([^`]+)`/);
248
+ if (match) {
249
+ squad.outputPath = match[1].replace(/\/$/, "");
250
+ }
251
+ }
252
+ if (currentSection === "goals") {
253
+ const goalMatch = line.match(/^-\s*\[([ x])\]\s*(.+)$/);
254
+ if (goalMatch) {
255
+ const completed = goalMatch[1] === "x";
256
+ let description = goalMatch[2].trim();
257
+ let progress;
258
+ const progressMatch = description.match(/\(progress:\s*([^)]+)\)/i);
259
+ if (progressMatch) {
260
+ progress = progressMatch[1];
261
+ description = description.replace(progressMatch[0], "").trim();
262
+ }
263
+ squad.goals.push({
264
+ description,
265
+ completed,
266
+ progress
267
+ });
268
+ }
269
+ }
270
+ }
271
+ return squad;
272
+ }
273
+ function loadSquad(squadName) {
274
+ const squadsDir = findSquadsDir();
275
+ if (!squadsDir) return null;
276
+ const squadFile = join2(squadsDir, squadName, "SQUAD.md");
277
+ if (!existsSync2(squadFile)) return null;
278
+ return parseSquadFile(squadFile);
279
+ }
280
+ function loadAgentDefinition(agentPath) {
281
+ if (!existsSync2(agentPath)) return "";
282
+ return readFileSync2(agentPath, "utf-8");
283
+ }
284
+ function parseAgentProvider(agentPath) {
285
+ if (!existsSync2(agentPath)) return void 0;
286
+ const content = readFileSync2(agentPath, "utf-8");
287
+ try {
288
+ const { data: frontmatter } = matter(content);
289
+ if (frontmatter?.provider && typeof frontmatter.provider === "string") {
290
+ return frontmatter.provider.toLowerCase();
291
+ }
292
+ } catch {
293
+ }
294
+ const providerHeaderMatch = content.match(/##\s*Provider\s*\n+([a-zA-Z0-9_-]+)/i);
295
+ if (providerHeaderMatch) {
296
+ return providerHeaderMatch[1].toLowerCase();
297
+ }
298
+ return void 0;
299
+ }
300
+ function addGoalToSquad(squadName, goal) {
301
+ const squadsDir = findSquadsDir();
302
+ if (!squadsDir) return false;
303
+ const squadFile = join2(squadsDir, squadName, "SQUAD.md");
304
+ if (!existsSync2(squadFile)) return false;
305
+ let content = readFileSync2(squadFile, "utf-8");
306
+ if (!content.includes("## Goals")) {
307
+ const insertPoint = content.indexOf("## Dependencies");
308
+ if (insertPoint > 0) {
309
+ content = content.slice(0, insertPoint) + `## Goals
310
+
311
+ - [ ] ${goal}
312
+
313
+ ` + content.slice(insertPoint);
314
+ } else {
315
+ content += `
316
+ ## Goals
317
+
318
+ - [ ] ${goal}
319
+ `;
320
+ }
321
+ } else {
322
+ const goalsIdx = content.indexOf("## Goals");
323
+ const nextSectionIdx = content.indexOf("\n## ", goalsIdx + 1);
324
+ const endIdx = nextSectionIdx > 0 ? nextSectionIdx : content.length;
325
+ const goalsSection = content.slice(goalsIdx, endIdx);
326
+ const lastGoalMatch = goalsSection.match(/^-\s*\[[ x]\].+$/gm);
327
+ if (lastGoalMatch) {
328
+ const lastGoal = lastGoalMatch[lastGoalMatch.length - 1];
329
+ const lastGoalIdx = content.lastIndexOf(lastGoal, endIdx);
330
+ const insertPos = lastGoalIdx + lastGoal.length;
331
+ content = content.slice(0, insertPos) + `
332
+ - [ ] ${goal}` + content.slice(insertPos);
333
+ } else {
334
+ const headerEnd = goalsIdx + "## Goals".length;
335
+ content = content.slice(0, headerEnd) + `
336
+
337
+ - [ ] ${goal}` + content.slice(headerEnd);
338
+ }
339
+ }
340
+ writeFileSync2(squadFile, content);
341
+ return true;
342
+ }
343
+ function updateGoalInSquad(squadName, goalIndex, updates) {
344
+ const squadsDir = findSquadsDir();
345
+ if (!squadsDir) return false;
346
+ const squadFile = join2(squadsDir, squadName, "SQUAD.md");
347
+ if (!existsSync2(squadFile)) return false;
348
+ const content = readFileSync2(squadFile, "utf-8");
349
+ const lines = content.split("\n");
350
+ let currentSection = "";
351
+ let goalCount = 0;
352
+ for (let i = 0; i < lines.length; i++) {
353
+ const line = lines[i];
354
+ if (line.startsWith("## ")) {
355
+ currentSection = line.replace("## ", "").trim().toLowerCase();
356
+ continue;
357
+ }
358
+ if (currentSection === "goals") {
359
+ const goalMatch = line.match(/^-\s*\[([ x])\]\s*(.+)$/);
360
+ if (goalMatch) {
361
+ if (goalCount === goalIndex) {
362
+ let newLine = "- [" + (updates.completed ? "x" : " ") + "] " + goalMatch[2];
363
+ if (updates.progress !== void 0) {
364
+ newLine = newLine.replace(/\s*\(progress:\s*[^)]+\)/i, "");
365
+ if (updates.progress) {
366
+ newLine += ` (progress: ${updates.progress})`;
367
+ }
368
+ }
369
+ lines[i] = newLine;
370
+ writeFileSync2(squadFile, lines.join("\n"));
371
+ return true;
372
+ }
373
+ goalCount++;
374
+ }
375
+ }
376
+ }
377
+ return false;
378
+ }
379
+ function findSkillsDir() {
380
+ const projectRoot = findProjectRoot();
381
+ if (!projectRoot) return null;
382
+ const skillsDir = join2(projectRoot, ".claude", "skills");
383
+ return existsSync2(skillsDir) ? skillsDir : null;
384
+ }
385
+ function findMemoryDir() {
386
+ const projectRoot = findProjectRoot();
387
+ if (!projectRoot) return null;
388
+ const memoryDir = join2(projectRoot, ".agents", "memory");
389
+ return existsSync2(memoryDir) ? memoryDir : null;
390
+ }
391
+ function resolveSkillPath(skillName) {
392
+ const skillsDir = findSkillsDir();
393
+ if (!skillsDir) return null;
394
+ const skillPath = join2(skillsDir, skillName);
395
+ return existsSync2(skillPath) ? skillPath : null;
396
+ }
397
+ function resolveMemoryPaths(patterns) {
398
+ const memoryDir = findMemoryDir();
399
+ if (!memoryDir) return [];
400
+ const resolved = [];
401
+ for (const pattern of patterns) {
402
+ if (pattern.endsWith("/*")) {
403
+ const subdir = pattern.slice(0, -2);
404
+ const subdirPath = join2(memoryDir, subdir);
405
+ if (existsSync2(subdirPath)) {
406
+ try {
407
+ const files = readdirSync(subdirPath);
408
+ for (const file of files) {
409
+ if (file.endsWith(".md")) {
410
+ resolved.push(join2(subdirPath, file));
411
+ }
412
+ }
413
+ } catch {
414
+ }
415
+ }
416
+ } else {
417
+ const fullPath = join2(memoryDir, pattern);
418
+ if (existsSync2(fullPath)) {
419
+ resolved.push(fullPath);
420
+ }
421
+ }
422
+ }
423
+ return resolved;
424
+ }
425
+ function resolveExecutionContext(squad, forceRegenerate = false) {
426
+ const ctx = squad.context || {};
427
+ const mcpResolution = resolveMcpConfig(
428
+ squad.name,
429
+ ctx.mcp,
430
+ forceRegenerate
431
+ );
432
+ const skillPaths = [];
433
+ if (ctx.skills) {
434
+ for (const skill of ctx.skills) {
435
+ const path = resolveSkillPath(skill);
436
+ if (path) {
437
+ skillPaths.push(path);
438
+ }
439
+ }
440
+ }
441
+ const memoryPaths = ctx.memory?.load ? resolveMemoryPaths(ctx.memory.load) : [];
442
+ return {
443
+ // Copy all SquadContext fields
444
+ ...ctx,
445
+ // Add squad name
446
+ squadName: squad.name,
447
+ // Add resolved paths
448
+ resolved: {
449
+ mcpConfigPath: mcpResolution.path,
450
+ mcpSource: mcpResolution.source,
451
+ mcpServers: mcpResolution.servers || [],
452
+ skillPaths,
453
+ memoryPaths
454
+ }
455
+ };
456
+ }
457
+
458
+ export {
459
+ resolveMcpConfigPath,
460
+ findSquadsDir,
461
+ findProjectRoot,
462
+ hasLocalInfraConfig,
463
+ listSquads,
464
+ listAgents,
465
+ parseSquadFile,
466
+ loadSquad,
467
+ loadAgentDefinition,
468
+ parseAgentProvider,
469
+ addGoalToSquad,
470
+ updateGoalInSquad,
471
+ resolveExecutionContext
472
+ };
473
+ //# sourceMappingURL=chunk-3TSY2K7R.js.map