squads-cli 0.4.9 → 0.4.11

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/dist/cli.js CHANGED
@@ -43,8 +43,8 @@ import {
43
43
 
44
44
  // src/cli.ts
45
45
  import { config } from "dotenv";
46
- import { existsSync as existsSync18 } from "fs";
47
- import { join as join20 } from "path";
46
+ import { existsSync as existsSync20 } from "fs";
47
+ import { join as join22 } from "path";
48
48
  import { homedir as homedir4 } from "os";
49
49
  import { Command } from "commander";
50
50
  import chalk4 from "chalk";
@@ -388,7 +388,7 @@ function getActivitySparkline(basePath, days = 7) {
388
388
  // src/lib/telemetry.ts
389
389
  import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync } from "fs";
390
390
  import { join as join2 } from "path";
391
- import { homedir } from "os";
391
+ import { homedir, platform, release } from "os";
392
392
  import { randomUUID } from "crypto";
393
393
  var TELEMETRY_DIR = join2(homedir(), ".squads-cli");
394
394
  var CONFIG_PATH = join2(TELEMETRY_DIR, "telemetry.json");
@@ -400,6 +400,20 @@ var TELEMETRY_ENDPOINT = Buffer.from(
400
400
  var TELEMETRY_KEY = Buffer.from("c3FfdGVsX3YxXzdmOGE5YjJjM2Q0ZTVmNmE=", "base64").toString();
401
401
  var eventQueue = [];
402
402
  var flushScheduled = false;
403
+ var cachedSystemContext = null;
404
+ function getSystemContext() {
405
+ if (cachedSystemContext) return cachedSystemContext;
406
+ cachedSystemContext = {
407
+ os: platform(),
408
+ // darwin, linux, win32
409
+ osVersion: release(),
410
+ nodeVersion: process.version,
411
+ shell: process.env.SHELL?.split("/").pop() || process.env.ComSpec?.split("\\").pop(),
412
+ terminal: process.env.TERM_PROGRAM || void 0,
413
+ ci: process.env.CI === "true" ? "true" : void 0
414
+ };
415
+ return cachedSystemContext;
416
+ }
403
417
  function ensureDir() {
404
418
  if (!existsSync2(TELEMETRY_DIR)) {
405
419
  mkdirSync(TELEMETRY_DIR, { recursive: true });
@@ -440,6 +454,7 @@ async function track(event, properties) {
440
454
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
441
455
  properties: {
442
456
  ...properties,
457
+ ...getSystemContext(),
443
458
  anonymousId: config2.anonymousId,
444
459
  cliVersion: process.env.npm_package_version || "unknown"
445
460
  }
@@ -519,9 +534,18 @@ var Events = {
519
534
  CLI_FEEDBACK_ADD: "cli.feedback.add",
520
535
  CLI_FEEDBACK_SHOW: "cli.feedback.show",
521
536
  CLI_FEEDBACK_STATS: "cli.feedback.stats",
537
+ // Learnings
538
+ CLI_LEARN: "cli.learn",
539
+ CLI_LEARN_SHOW: "cli.learn.show",
540
+ CLI_LEARN_SEARCH: "cli.learn.search",
522
541
  // Auth
523
542
  CLI_LOGIN: "cli.login",
524
- CLI_LOGOUT: "cli.logout"
543
+ CLI_LOGOUT: "cli.logout",
544
+ // Context Condenser
545
+ CONDENSER_COMPRESS: "condenser.compress",
546
+ CONDENSER_DEDUPE: "condenser.dedupe",
547
+ CONDENSER_PRUNE: "condenser.prune",
548
+ CONDENSER_SUMMARIZE: "condenser.summarize"
525
549
  };
526
550
  var exitHandlerRegistered = false;
527
551
  function registerExitHandler() {
@@ -837,8 +861,9 @@ async function initCommand(options) {
837
861
  }
838
862
  }
839
863
  console.log();
840
- if (hasMissingRequired) {
864
+ if (hasMissingRequired && !options.force) {
841
865
  console.log(chalk.yellow(" Install missing tools to continue, then run squads init again."));
866
+ console.log(chalk.dim(" Or use --force to skip requirement checks."));
842
867
  console.log();
843
868
  track(Events.CLI_INIT, {
844
869
  success: false,
@@ -867,8 +892,14 @@ async function initCommand(options) {
867
892
  ".agents/squads",
868
893
  ".agents/squads/demo",
869
894
  ".agents/memory",
895
+ ".agents/memory/getting-started",
896
+ ".agents/memory/general/shared",
897
+ // For cross-squad learnings
870
898
  ".agents/outputs",
871
- ".claude"
899
+ ".claude",
900
+ ".claude/skills",
901
+ ".claude/skills/squads-workflow",
902
+ ".claude/skills/squads-learn"
872
903
  ];
873
904
  for (const dir of dirs) {
874
905
  await fs.mkdir(path.join(cwd, dir), { recursive: true });
@@ -969,6 +1000,189 @@ Markdown report saved to .agents/outputs/demo/project-analysis.md
969
1000
  path.join(cwd, ".agents/squads/demo/analyzer.md"),
970
1001
  analyzerAgent
971
1002
  );
1003
+ const squadsWorkflowSkill = `# Squads Workflow
1004
+
1005
+ Use this skill when working with squads-cli to maintain persistent memory, track goals, and coordinate work.
1006
+
1007
+ ## Session Start
1008
+
1009
+ At session start, you'll see \`squads status\` output automatically. For complex tasks, run:
1010
+
1011
+ \`\`\`bash
1012
+ squads context # Get business context, goals, decisions
1013
+ squads memory query "<topic>" # Check what we already know
1014
+ \`\`\`
1015
+
1016
+ **Skip context loading for simple tasks** (typo fixes, quick questions).
1017
+
1018
+ ## Core Commands
1019
+
1020
+ \`\`\`bash
1021
+ # Context & Status
1022
+ squads context # Business context for alignment
1023
+ squads status # Squad overview
1024
+ squads dash # Full dashboard
1025
+
1026
+ # Memory
1027
+ squads memory query "<topic>" # Search memory
1028
+ squads memory show <squad> # Squad's full memory
1029
+
1030
+ # Goals
1031
+ squads goal list # All active goals
1032
+ squads goal set <squad> "X" # Add a goal
1033
+
1034
+ # Running Agents
1035
+ squads run <squad> # Run all agents in squad
1036
+ squads run <squad>/<agent> # Run specific agent
1037
+ squads list # List all agents
1038
+ \`\`\`
1039
+
1040
+ ## Workflow
1041
+
1042
+ ### Before Research
1043
+ Always check memory first to avoid re-researching:
1044
+ \`\`\`bash
1045
+ squads memory query "topic"
1046
+ \`\`\`
1047
+
1048
+ ### After Work
1049
+ Update memory with what you learned by editing:
1050
+ \`.agents/memory/<squad>/<agent>/state.md\`
1051
+
1052
+ ### Commits
1053
+ Include goal attribution when relevant:
1054
+ \`\`\`
1055
+ feat: add user auth [goal:engineering/1]
1056
+ \`\`\`
1057
+
1058
+ ## Agent Execution
1059
+
1060
+ When a task could be automated:
1061
+ 1. Check if agent exists: \`squads list | grep <keyword>\`
1062
+ 2. If yes: \`squads run <squad>/<agent>\`
1063
+ 3. If no: Create agent in \`.agents/squads/<squad>/<name>.md\`
1064
+
1065
+ ## Memory Locations
1066
+
1067
+ - \`.agents/memory/<squad>/<agent>/state.md\` - Current knowledge
1068
+ - \`.agents/memory/<squad>/<agent>/learnings.md\` - Insights over time
1069
+
1070
+ ## Key Principle
1071
+
1072
+ **Memory is your cross-session brain.** Without it, every session starts fresh. With it, you build on previous work.
1073
+ `;
1074
+ await fs.writeFile(
1075
+ path.join(cwd, ".claude/skills/squads-workflow/instruction.md"),
1076
+ squadsWorkflowSkill
1077
+ );
1078
+ const squadsLearnSkill = `---
1079
+ name: squads-learn
1080
+ description: Capture learnings after completing work. Use when finishing a task, fixing a bug, discovering a pattern, or learning something worth remembering for future sessions.
1081
+ ---
1082
+
1083
+ # Capture Learnings
1084
+
1085
+ After completing work, capture what you learned so future sessions can benefit.
1086
+
1087
+ ## When to Use
1088
+
1089
+ - After fixing a bug - What was the root cause?
1090
+ - After completing a feature - What approach worked?
1091
+ - After research - What's the key insight?
1092
+ - When you notice a pattern - Something that works consistently
1093
+
1094
+ ## Quick Commands
1095
+
1096
+ \`\`\`bash
1097
+ # Capture a learning
1098
+ squads learn "The auth token needs refresh after 1 hour, not on 401"
1099
+
1100
+ # With squad and category
1101
+ squads learn "Always check memory first" --squad engineering --category pattern
1102
+
1103
+ # View learnings
1104
+ squads learnings show engineering
1105
+ squads learnings search "auth"
1106
+ \`\`\`
1107
+
1108
+ ## Categories
1109
+
1110
+ - \`success\` - Something that worked well
1111
+ - \`failure\` - Something that didn't work (learn from mistakes)
1112
+ - \`pattern\` - A reusable approach
1113
+ - \`tip\` - General advice
1114
+
1115
+ ## End of Task Checklist
1116
+
1117
+ Before marking done, ask:
1118
+ 1. What worked that I should remember?
1119
+ 2. What didn't work that I should avoid?
1120
+ 3. Is there a pattern worth capturing?
1121
+
1122
+ If yes \u2192 \`squads learn "<insight>"\`
1123
+ `;
1124
+ await fs.writeFile(
1125
+ path.join(cwd, ".claude/skills/squads-learn/SKILL.md"),
1126
+ squadsLearnSkill
1127
+ );
1128
+ const seedMemory = `# Getting Started with Squads
1129
+
1130
+ ## What You've Set Up
1131
+
1132
+ - **Demo squad** ready to run (\`squads run demo\`)
1133
+ - **Memory system** for persistent context
1134
+ - **Hooks** that sync status and memory automatically
1135
+
1136
+ ## Next Steps
1137
+
1138
+ 1. Run the demo: \`squads run demo\`
1139
+ 2. Check the dashboard: \`squads dash\`
1140
+ 3. Create your first real squad in \`.agents/squads/\`
1141
+
1142
+ ## Tips
1143
+
1144
+ - Check memory before researching: \`squads memory query "<topic>"\`
1145
+ - Use \`squads context\` for business alignment on complex tasks
1146
+ - Agents are reusable - if you do something twice, make it an agent
1147
+ `;
1148
+ await fs.writeFile(
1149
+ path.join(cwd, ".agents/memory/getting-started/state.md"),
1150
+ seedMemory
1151
+ );
1152
+ const businessBrief = `# Business Brief
1153
+
1154
+ ## #1 Priority
1155
+
1156
+ **[Define your top priority here]**
1157
+
1158
+ ## Runway
1159
+
1160
+ **Pressure**: LOW | MEDIUM | HIGH
1161
+
1162
+ ## Current Focus
1163
+
1164
+ 1. **[Focus area 1]** - Description
1165
+ 2. **[Focus area 2]** - Description
1166
+ 3. **[Focus area 3]** - Description
1167
+
1168
+ ## Blockers
1169
+
1170
+ - None currently (or list blockers)
1171
+
1172
+ ## Decision Framework
1173
+
1174
+ 1. Does this drive the #1 priority?
1175
+ 2. Is there a simpler approach?
1176
+ 3. What's the opportunity cost?
1177
+
1178
+ ---
1179
+
1180
+ *This file is read by \`squads context\` to provide business alignment.*
1181
+ `;
1182
+ await fs.writeFile(
1183
+ path.join(cwd, ".agents/BUSINESS_BRIEF.md"),
1184
+ businessBrief
1185
+ );
972
1186
  const claudeSettings = {
973
1187
  hooks: {
974
1188
  SessionStart: [
@@ -987,7 +1201,7 @@ Markdown report saved to .agents/outputs/demo/project-analysis.md
987
1201
  hooks: [
988
1202
  {
989
1203
  type: "command",
990
- command: "squads memory sync",
1204
+ command: 'squads memory sync && echo "\\n\u{1F4A1} Capture learnings: squads learn \\"<what you learned>\\"\\n"',
991
1205
  timeout: 15
992
1206
  }
993
1207
  ]
@@ -1023,12 +1237,22 @@ Each **squad** is a team of **agents** (markdown prompts) that execute via Claud
1023
1237
 
1024
1238
  ## For Claude (READ THIS)
1025
1239
 
1026
- When helping users with squad-related tasks:
1240
+ **Skill available**: Use \`/squads-workflow\` for detailed workflow guidance.
1241
+
1242
+ ### Session Start
1027
1243
 
1028
- ### Check Context First
1244
+ You'll see \`squads status\` automatically. For complex tasks, also run:
1029
1245
  \`\`\`bash
1030
- squads status # What squads exist?
1031
- squads memory query "X" # What do we know about X?
1246
+ squads context # Business context, goals, decisions
1247
+ squads memory query "<topic>" # What we already know
1248
+ \`\`\`
1249
+
1250
+ **Skip for simple tasks** (typo fixes, quick questions).
1251
+
1252
+ ### Before Research
1253
+ Always check memory first:
1254
+ \`\`\`bash
1255
+ squads memory query "<topic>"
1032
1256
  \`\`\`
1033
1257
 
1034
1258
  ### Creating Agents
@@ -1071,10 +1295,12 @@ squads goal set <squad> "X" # Add a goal
1071
1295
  | "What's the status?" | Run \`squads dash\` or \`squads status\` |
1072
1296
  | "Run the X agent" | \`squads run <squad>/x\` |
1073
1297
  | "Check memory" | \`squads memory query "<topic>"\` |
1298
+ | "Get context" | \`squads context\` |
1074
1299
 
1075
1300
  ## Quick Reference
1076
1301
 
1077
1302
  \`\`\`bash
1303
+ squads context # Business context for alignment
1078
1304
  squads status # Overview
1079
1305
  squads dash # Full dashboard
1080
1306
  squads run demo # Try demo squad
@@ -1137,9 +1363,12 @@ squads goal list # View goals
1137
1363
  console.log(chalk.green.bold(" \u2713 Squads initialized!"));
1138
1364
  console.log();
1139
1365
  console.log(chalk.dim(" Created:"));
1140
- console.log(chalk.dim(" \u2022 .agents/squads/demo/ - Demo squad with 2 agents"));
1141
- console.log(chalk.dim(" \u2022 .claude/settings.json - Claude Code hooks"));
1142
- console.log(chalk.dim(" \u2022 CLAUDE.md - Agent instructions"));
1366
+ console.log(chalk.dim(" \u2022 .agents/squads/demo/ - Demo squad with 2 agents"));
1367
+ console.log(chalk.dim(" \u2022 .agents/BUSINESS_BRIEF - Business context template"));
1368
+ console.log(chalk.dim(" \u2022 .agents/memory/ - Seed memory + learnings"));
1369
+ console.log(chalk.dim(" \u2022 .claude/settings.json - Claude Code hooks"));
1370
+ console.log(chalk.dim(" \u2022 .claude/skills/ - Workflow + learn skills"));
1371
+ console.log(chalk.dim(" \u2022 CLAUDE.md - Agent instructions"));
1143
1372
  console.log();
1144
1373
  const email = await promptEmail();
1145
1374
  if (email) {
@@ -1164,21 +1393,185 @@ squads goal list # View goals
1164
1393
  // src/commands/run.ts
1165
1394
  import ora2 from "ora";
1166
1395
  import { spawn as spawn2 } from "child_process";
1167
- import { join as join4, dirname } from "path";
1168
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2 } from "fs";
1396
+ import { join as join5, dirname as dirname2 } from "path";
1397
+ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3 } from "fs";
1169
1398
 
1170
1399
  // src/lib/squad-parser.ts
1171
- import { readFileSync as readFileSync2, existsSync as existsSync3, readdirSync, writeFileSync as writeFileSync2 } from "fs";
1172
- import { join as join3, basename } from "path";
1400
+ import { readFileSync as readFileSync3, existsSync as existsSync4, readdirSync, writeFileSync as writeFileSync3 } from "fs";
1401
+ import { join as join4, basename } from "path";
1173
1402
  import matter from "gray-matter";
1403
+
1404
+ // src/lib/mcp-config.ts
1405
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync2 } from "fs";
1406
+ import { join as join3, dirname } from "path";
1407
+ var SERVER_REGISTRY = {
1408
+ // Browser/Web tools
1409
+ "chrome-devtools": {
1410
+ type: "stdio",
1411
+ command: "npx",
1412
+ args: ["chrome-devtools-mcp", "--isolated", "--headless"],
1413
+ env: {}
1414
+ },
1415
+ "nano-banana": {
1416
+ type: "stdio",
1417
+ command: "npx",
1418
+ args: ["nano-banana-mcp"],
1419
+ env: {}
1420
+ },
1421
+ "firecrawl": {
1422
+ type: "stdio",
1423
+ command: "npx",
1424
+ args: ["firecrawl-mcp"],
1425
+ env: {
1426
+ FIRECRAWL_API_KEY: "${FIRECRAWL_API_KEY}"
1427
+ }
1428
+ },
1429
+ // Data tools
1430
+ "supabase": {
1431
+ type: "stdio",
1432
+ command: "npx",
1433
+ args: ["-y", "@supabase/mcp-server-supabase@latest", "--read-only"],
1434
+ env: {
1435
+ SUPABASE_ACCESS_TOKEN: "${SUPABASE_ACCESS_TOKEN}"
1436
+ }
1437
+ },
1438
+ "grafana": {
1439
+ type: "stdio",
1440
+ command: "npx",
1441
+ args: ["-y", "@leval/mcp-grafana"],
1442
+ env: {
1443
+ GRAFANA_URL: "${GRAFANA_URL}",
1444
+ GRAFANA_SERVICE_ACCOUNT_TOKEN: "${GRAFANA_SERVICE_ACCOUNT_TOKEN}"
1445
+ }
1446
+ },
1447
+ // AI/ML tools
1448
+ "huggingface": {
1449
+ type: "stdio",
1450
+ command: "npx",
1451
+ args: ["huggingface-mcp"],
1452
+ env: {
1453
+ HF_TOKEN: "${HF_TOKEN}"
1454
+ }
1455
+ },
1456
+ "context7": {
1457
+ type: "stdio",
1458
+ command: "npx",
1459
+ args: ["context7-mcp"],
1460
+ env: {}
1461
+ },
1462
+ // Social/Research tools
1463
+ "x-mcp": {
1464
+ type: "stdio",
1465
+ command: "python3",
1466
+ args: ["~/.claude/mcps/x-mcp/server.py"],
1467
+ env: {
1468
+ X_BEARER_TOKEN: "${X_BEARER_TOKEN}"
1469
+ }
1470
+ },
1471
+ // Telemetry
1472
+ "langfuse-telemetry": {
1473
+ type: "stdio",
1474
+ command: "python3",
1475
+ args: ["~/.claude/mcps/langfuse-telemetry/server.py"],
1476
+ env: {
1477
+ LANGFUSE_HOST: "${LANGFUSE_HOST}",
1478
+ LANGFUSE_PUBLIC_KEY: "${LANGFUSE_PUBLIC_KEY}",
1479
+ LANGFUSE_SECRET_KEY: "${LANGFUSE_SECRET_KEY}"
1480
+ }
1481
+ },
1482
+ // Analytics
1483
+ "ga4-admin": {
1484
+ type: "stdio",
1485
+ command: "python3",
1486
+ args: ["-m", "mcp_ga4.server"],
1487
+ env: {}
1488
+ }
1489
+ };
1490
+ function getHome() {
1491
+ return process.env.HOME || process.env.USERPROFILE || "";
1492
+ }
1493
+ function getContextsDir() {
1494
+ return join3(getHome(), ".claude", "contexts");
1495
+ }
1496
+ function getMcpConfigsDir() {
1497
+ return join3(getHome(), ".claude", "mcp-configs");
1498
+ }
1499
+ function generateMcpConfig(mcpServers) {
1500
+ const config2 = { mcpServers: {} };
1501
+ for (const server of mcpServers) {
1502
+ const def = SERVER_REGISTRY[server];
1503
+ if (def) {
1504
+ config2.mcpServers[server] = def;
1505
+ }
1506
+ }
1507
+ return config2;
1508
+ }
1509
+ function writeMcpConfig(config2, path3) {
1510
+ const dir = dirname(path3);
1511
+ if (!existsSync3(dir)) {
1512
+ mkdirSync2(dir, { recursive: true });
1513
+ }
1514
+ writeFileSync2(path3, JSON.stringify(config2, null, 2));
1515
+ }
1516
+ function readMcpConfig(path3) {
1517
+ if (!existsSync3(path3)) return null;
1518
+ try {
1519
+ const content = readFileSync2(path3, "utf-8");
1520
+ return JSON.parse(content);
1521
+ } catch {
1522
+ return null;
1523
+ }
1524
+ }
1525
+ function resolveMcpConfig(squadName, mcpServers, forceRegenerate = false) {
1526
+ const home = getHome();
1527
+ const userOverride = join3(getMcpConfigsDir(), `${squadName}.json`);
1528
+ if (existsSync3(userOverride)) {
1529
+ const config2 = readMcpConfig(userOverride);
1530
+ return {
1531
+ path: userOverride,
1532
+ source: "user-override",
1533
+ servers: config2 ? Object.keys(config2.mcpServers) : void 0
1534
+ };
1535
+ }
1536
+ if (mcpServers && mcpServers.length > 0) {
1537
+ const generatedPath = join3(getContextsDir(), `${squadName}.mcp.json`);
1538
+ const shouldGenerate = forceRegenerate || !existsSync3(generatedPath);
1539
+ if (shouldGenerate) {
1540
+ const config3 = generateMcpConfig(mcpServers);
1541
+ writeMcpConfig(config3, generatedPath);
1542
+ return {
1543
+ path: generatedPath,
1544
+ source: "generated",
1545
+ servers: Object.keys(config3.mcpServers),
1546
+ generated: true
1547
+ };
1548
+ }
1549
+ const config2 = readMcpConfig(generatedPath);
1550
+ return {
1551
+ path: generatedPath,
1552
+ source: "generated",
1553
+ servers: config2 ? Object.keys(config2.mcpServers) : mcpServers,
1554
+ generated: false
1555
+ };
1556
+ }
1557
+ return {
1558
+ path: join3(home, ".claude.json"),
1559
+ source: "fallback"
1560
+ };
1561
+ }
1562
+ function resolveMcpConfigPath(squadName, mcpServers) {
1563
+ return resolveMcpConfig(squadName, mcpServers).path;
1564
+ }
1565
+
1566
+ // src/lib/squad-parser.ts
1174
1567
  function findSquadsDir() {
1175
1568
  let dir = process.cwd();
1176
1569
  for (let i = 0; i < 5; i++) {
1177
- const squadsPath = join3(dir, ".agents", "squads");
1178
- if (existsSync3(squadsPath)) {
1570
+ const squadsPath = join4(dir, ".agents", "squads");
1571
+ if (existsSync4(squadsPath)) {
1179
1572
  return squadsPath;
1180
1573
  }
1181
- const parent = join3(dir, "..");
1574
+ const parent = join4(dir, "..");
1182
1575
  if (parent === dir) break;
1183
1576
  dir = parent;
1184
1577
  }
@@ -1187,14 +1580,14 @@ function findSquadsDir() {
1187
1580
  function findProjectRoot() {
1188
1581
  const squadsDir = findSquadsDir();
1189
1582
  if (!squadsDir) return null;
1190
- return join3(squadsDir, "..", "..");
1583
+ return join4(squadsDir, "..", "..");
1191
1584
  }
1192
1585
  function hasLocalInfraConfig() {
1193
1586
  const projectRoot = findProjectRoot();
1194
1587
  if (!projectRoot) return false;
1195
- const envPath = join3(projectRoot, ".env");
1196
- if (!existsSync3(envPath)) return false;
1197
- const content = readFileSync2(envPath, "utf-8");
1588
+ const envPath = join4(projectRoot, ".env");
1589
+ if (!existsSync4(envPath)) return false;
1590
+ const content = readFileSync3(envPath, "utf-8");
1198
1591
  const infraKeys = ["LANGFUSE_", "SQUADS_BRIDGE", "SQUADS_POSTGRES", "SQUADS_REDIS"];
1199
1592
  return infraKeys.some((key) => content.includes(key));
1200
1593
  }
@@ -1203,8 +1596,8 @@ function listSquads(squadsDir) {
1203
1596
  const entries = readdirSync(squadsDir, { withFileTypes: true });
1204
1597
  for (const entry of entries) {
1205
1598
  if (entry.isDirectory() && !entry.name.startsWith("_")) {
1206
- const squadFile = join3(squadsDir, entry.name, "SQUAD.md");
1207
- if (existsSync3(squadFile)) {
1599
+ const squadFile = join4(squadsDir, entry.name, "SQUAD.md");
1600
+ if (existsSync4(squadFile)) {
1208
1601
  squads.push(entry.name);
1209
1602
  }
1210
1603
  }
@@ -1215,8 +1608,8 @@ function listAgents(squadsDir, squadName) {
1215
1608
  const agents = [];
1216
1609
  const dirs = squadName ? [squadName] : readdirSync(squadsDir, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith("_")).map((e) => e.name);
1217
1610
  for (const dir of dirs) {
1218
- const squadPath = join3(squadsDir, dir);
1219
- if (!existsSync3(squadPath)) continue;
1611
+ const squadPath = join4(squadsDir, dir);
1612
+ if (!existsSync4(squadPath)) continue;
1220
1613
  const files = readdirSync(squadPath);
1221
1614
  for (const file of files) {
1222
1615
  if (file.endsWith(".md") && file !== "SQUAD.md") {
@@ -1225,7 +1618,7 @@ function listAgents(squadsDir, squadName) {
1225
1618
  name: agentName,
1226
1619
  role: `Agent in ${dir}`,
1227
1620
  trigger: "manual",
1228
- filePath: join3(squadPath, file)
1621
+ filePath: join4(squadPath, file)
1229
1622
  });
1230
1623
  }
1231
1624
  }
@@ -1233,7 +1626,7 @@ function listAgents(squadsDir, squadName) {
1233
1626
  return agents;
1234
1627
  }
1235
1628
  function parseSquadFile(filePath) {
1236
- const rawContent = readFileSync2(filePath, "utf-8");
1629
+ const rawContent = readFileSync3(filePath, "utf-8");
1237
1630
  const { data: frontmatter, content: bodyContent } = matter(rawContent);
1238
1631
  const fm = frontmatter;
1239
1632
  const lines = bodyContent.split("\n");
@@ -1354,20 +1747,20 @@ function parseSquadFile(filePath) {
1354
1747
  function loadSquad(squadName) {
1355
1748
  const squadsDir = findSquadsDir();
1356
1749
  if (!squadsDir) return null;
1357
- const squadFile = join3(squadsDir, squadName, "SQUAD.md");
1358
- if (!existsSync3(squadFile)) return null;
1750
+ const squadFile = join4(squadsDir, squadName, "SQUAD.md");
1751
+ if (!existsSync4(squadFile)) return null;
1359
1752
  return parseSquadFile(squadFile);
1360
1753
  }
1361
1754
  function loadAgentDefinition(agentPath) {
1362
- if (!existsSync3(agentPath)) return "";
1363
- return readFileSync2(agentPath, "utf-8");
1755
+ if (!existsSync4(agentPath)) return "";
1756
+ return readFileSync3(agentPath, "utf-8");
1364
1757
  }
1365
1758
  function addGoalToSquad(squadName, goal2) {
1366
1759
  const squadsDir = findSquadsDir();
1367
1760
  if (!squadsDir) return false;
1368
- const squadFile = join3(squadsDir, squadName, "SQUAD.md");
1369
- if (!existsSync3(squadFile)) return false;
1370
- let content = readFileSync2(squadFile, "utf-8");
1761
+ const squadFile = join4(squadsDir, squadName, "SQUAD.md");
1762
+ if (!existsSync4(squadFile)) return false;
1763
+ let content = readFileSync3(squadFile, "utf-8");
1371
1764
  if (!content.includes("## Goals")) {
1372
1765
  const insertPoint = content.indexOf("## Dependencies");
1373
1766
  if (insertPoint > 0) {
@@ -1402,15 +1795,15 @@ function addGoalToSquad(squadName, goal2) {
1402
1795
  - [ ] ${goal2}` + content.slice(headerEnd);
1403
1796
  }
1404
1797
  }
1405
- writeFileSync2(squadFile, content);
1798
+ writeFileSync3(squadFile, content);
1406
1799
  return true;
1407
1800
  }
1408
1801
  function updateGoalInSquad(squadName, goalIndex, updates) {
1409
1802
  const squadsDir = findSquadsDir();
1410
1803
  if (!squadsDir) return false;
1411
- const squadFile = join3(squadsDir, squadName, "SQUAD.md");
1412
- if (!existsSync3(squadFile)) return false;
1413
- const content = readFileSync2(squadFile, "utf-8");
1804
+ const squadFile = join4(squadsDir, squadName, "SQUAD.md");
1805
+ if (!existsSync4(squadFile)) return false;
1806
+ const content = readFileSync3(squadFile, "utf-8");
1414
1807
  const lines = content.split("\n");
1415
1808
  let currentSection = "";
1416
1809
  let goalCount = 0;
@@ -1432,7 +1825,7 @@ function updateGoalInSquad(squadName, goalIndex, updates) {
1432
1825
  }
1433
1826
  }
1434
1827
  lines[i] = newLine;
1435
- writeFileSync2(squadFile, lines.join("\n"));
1828
+ writeFileSync3(squadFile, lines.join("\n"));
1436
1829
  return true;
1437
1830
  }
1438
1831
  goalCount++;
@@ -1441,6 +1834,84 @@ function updateGoalInSquad(squadName, goalIndex, updates) {
1441
1834
  }
1442
1835
  return false;
1443
1836
  }
1837
+ function findSkillsDir() {
1838
+ const projectRoot = findProjectRoot();
1839
+ if (!projectRoot) return null;
1840
+ const skillsDir = join4(projectRoot, ".claude", "skills");
1841
+ return existsSync4(skillsDir) ? skillsDir : null;
1842
+ }
1843
+ function findMemoryDir2() {
1844
+ const projectRoot = findProjectRoot();
1845
+ if (!projectRoot) return null;
1846
+ const memoryDir = join4(projectRoot, ".agents", "memory");
1847
+ return existsSync4(memoryDir) ? memoryDir : null;
1848
+ }
1849
+ function resolveSkillPath(skillName) {
1850
+ const skillsDir = findSkillsDir();
1851
+ if (!skillsDir) return null;
1852
+ const skillPath = join4(skillsDir, skillName);
1853
+ return existsSync4(skillPath) ? skillPath : null;
1854
+ }
1855
+ function resolveMemoryPaths(patterns) {
1856
+ const memoryDir = findMemoryDir2();
1857
+ if (!memoryDir) return [];
1858
+ const resolved = [];
1859
+ for (const pattern of patterns) {
1860
+ if (pattern.endsWith("/*")) {
1861
+ const subdir = pattern.slice(0, -2);
1862
+ const subdirPath = join4(memoryDir, subdir);
1863
+ if (existsSync4(subdirPath)) {
1864
+ try {
1865
+ const files = readdirSync(subdirPath);
1866
+ for (const file of files) {
1867
+ if (file.endsWith(".md")) {
1868
+ resolved.push(join4(subdirPath, file));
1869
+ }
1870
+ }
1871
+ } catch {
1872
+ }
1873
+ }
1874
+ } else {
1875
+ const fullPath = join4(memoryDir, pattern);
1876
+ if (existsSync4(fullPath)) {
1877
+ resolved.push(fullPath);
1878
+ }
1879
+ }
1880
+ }
1881
+ return resolved;
1882
+ }
1883
+ function resolveExecutionContext(squad, forceRegenerate = false) {
1884
+ const ctx = squad.context || {};
1885
+ const mcpResolution = resolveMcpConfig(
1886
+ squad.name,
1887
+ ctx.mcp,
1888
+ forceRegenerate
1889
+ );
1890
+ const skillPaths = [];
1891
+ if (ctx.skills) {
1892
+ for (const skill of ctx.skills) {
1893
+ const path3 = resolveSkillPath(skill);
1894
+ if (path3) {
1895
+ skillPaths.push(path3);
1896
+ }
1897
+ }
1898
+ }
1899
+ const memoryPaths = ctx.memory?.load ? resolveMemoryPaths(ctx.memory.load) : [];
1900
+ return {
1901
+ // Copy all SquadContext fields
1902
+ ...ctx,
1903
+ // Add squad name
1904
+ squadName: squad.name,
1905
+ // Add resolved paths
1906
+ resolved: {
1907
+ mcpConfigPath: mcpResolution.path,
1908
+ mcpSource: mcpResolution.source,
1909
+ mcpServers: mcpResolution.servers || [],
1910
+ skillPaths,
1911
+ memoryPaths
1912
+ }
1913
+ };
1914
+ }
1444
1915
 
1445
1916
  // src/lib/permissions.ts
1446
1917
  import { minimatch } from "minimatch";
@@ -1533,11 +2004,11 @@ function validateMcpServer(server, allow, deny) {
1533
2004
  }
1534
2005
  return null;
1535
2006
  }
1536
- function validateExecution(context2, request) {
2007
+ function validateExecution(context, request) {
1537
2008
  const violations = [];
1538
2009
  if (request.bashCommands) {
1539
2010
  for (const cmd of request.bashCommands) {
1540
- const violation = validateBashCommand(cmd, context2.permissions.bash);
2011
+ const violation = validateBashCommand(cmd, context.permissions.bash);
1541
2012
  if (violation) {
1542
2013
  violations.push(violation);
1543
2014
  }
@@ -1545,7 +2016,7 @@ function validateExecution(context2, request) {
1545
2016
  }
1546
2017
  if (request.writePaths) {
1547
2018
  for (const path3 of request.writePaths) {
1548
- const violation = validateFilePath(path3, context2.permissions.write, "write");
2019
+ const violation = validateFilePath(path3, context.permissions.write, "write");
1549
2020
  if (violation) {
1550
2021
  violations.push(violation);
1551
2022
  }
@@ -1553,7 +2024,7 @@ function validateExecution(context2, request) {
1553
2024
  }
1554
2025
  if (request.readPaths) {
1555
2026
  for (const path3 of request.readPaths) {
1556
- const violation = validateFilePath(path3, context2.permissions.read, "read");
2027
+ const violation = validateFilePath(path3, context.permissions.read, "read");
1557
2028
  if (violation) {
1558
2029
  violations.push(violation);
1559
2030
  }
@@ -1563,8 +2034,8 @@ function validateExecution(context2, request) {
1563
2034
  for (const server of request.mcpServers) {
1564
2035
  const violation = validateMcpServer(
1565
2036
  server,
1566
- context2.permissions.mcp.allow,
1567
- context2.permissions.mcp.deny
2037
+ context.permissions.mcp.allow,
2038
+ context.permissions.mcp.deny
1568
2039
  );
1569
2040
  if (violation) {
1570
2041
  violations.push(violation);
@@ -1572,11 +2043,11 @@ function validateExecution(context2, request) {
1572
2043
  }
1573
2044
  }
1574
2045
  const hasErrors = violations.some((v) => v.severity === "error");
1575
- const allowed = context2.permissions.mode !== "strict" || !hasErrors;
2046
+ const allowed = context.permissions.mode !== "strict" || !hasErrors;
1576
2047
  return {
1577
2048
  allowed,
1578
2049
  violations,
1579
- mode: context2.permissions.mode
2050
+ mode: context.permissions.mode
1580
2051
  };
1581
2052
  }
1582
2053
  function formatViolations(result) {
@@ -1639,16 +2110,16 @@ function parsePermissionsYaml(content) {
1639
2110
  return Object.keys(permissions).length > 0 ? permissions : null;
1640
2111
  }
1641
2112
  function buildContextFromSquad(squadName, squadContent, agentName) {
1642
- const context2 = getDefaultContext(squadName, agentName);
2113
+ const context = getDefaultContext(squadName, agentName);
1643
2114
  const parsed = parsePermissionsYaml(squadContent);
1644
2115
  if (parsed) {
1645
- if (parsed.mode) context2.permissions.mode = parsed.mode;
1646
- if (parsed.bash) context2.permissions.bash = parsed.bash;
1647
- if (parsed.write) context2.permissions.write = parsed.write;
1648
- if (parsed.read) context2.permissions.read = parsed.read;
1649
- if (parsed.mcp) context2.permissions.mcp = parsed.mcp;
2116
+ if (parsed.mode) context.permissions.mode = parsed.mode;
2117
+ if (parsed.bash) context.permissions.bash = parsed.bash;
2118
+ if (parsed.write) context.permissions.write = parsed.write;
2119
+ if (parsed.read) context.permissions.read = parsed.read;
2120
+ if (parsed.mcp) context.permissions.mcp = parsed.mcp;
1650
2121
  }
1651
- return context2;
2122
+ return context;
1652
2123
  }
1653
2124
 
1654
2125
  // src/commands/run.ts
@@ -1679,9 +2150,12 @@ function generateExecutionId() {
1679
2150
  const random = Math.random().toString(36).substring(2, 8);
1680
2151
  return `exec_${timestamp}_${random}`;
1681
2152
  }
1682
- function selectMcpConfig(squadName) {
2153
+ function selectMcpConfig(squadName, squad) {
2154
+ if (squad?.context?.mcp && squad.context.mcp.length > 0) {
2155
+ return resolveMcpConfigPath(squadName, squad.context.mcp);
2156
+ }
1683
2157
  const home = process.env.HOME || "";
1684
- const configsDir = join4(home, ".claude", "mcp-configs");
2158
+ const configsDir = join5(home, ".claude", "mcp-configs");
1685
2159
  const squadConfigs = {
1686
2160
  website: "website.json",
1687
2161
  // chrome-devtools, nano-banana
@@ -1696,12 +2170,12 @@ function selectMcpConfig(squadName) {
1696
2170
  };
1697
2171
  const configFile = squadConfigs[squadName.toLowerCase()];
1698
2172
  if (configFile) {
1699
- const configPath = join4(configsDir, configFile);
1700
- if (existsSync4(configPath)) {
2173
+ const configPath = join5(configsDir, configFile);
2174
+ if (existsSync5(configPath)) {
1701
2175
  return configPath;
1702
2176
  }
1703
2177
  }
1704
- return join4(home, ".claude.json");
2178
+ return join5(home, ".claude.json");
1705
2179
  }
1706
2180
  function detectTaskType(agentName) {
1707
2181
  const name = agentName.toLowerCase();
@@ -1717,12 +2191,12 @@ function detectTaskType(agentName) {
1717
2191
  return "execution";
1718
2192
  }
1719
2193
  function ensureProjectTrusted(projectPath) {
1720
- const configPath = join4(process.env.HOME || "", ".claude.json");
1721
- if (!existsSync4(configPath)) {
2194
+ const configPath = join5(process.env.HOME || "", ".claude.json");
2195
+ if (!existsSync5(configPath)) {
1722
2196
  return;
1723
2197
  }
1724
2198
  try {
1725
- const config2 = JSON.parse(readFileSync3(configPath, "utf-8"));
2199
+ const config2 = JSON.parse(readFileSync4(configPath, "utf-8"));
1726
2200
  if (!config2.projects) {
1727
2201
  config2.projects = {};
1728
2202
  }
@@ -1731,7 +2205,7 @@ function ensureProjectTrusted(projectPath) {
1731
2205
  }
1732
2206
  if (!config2.projects[projectPath].hasTrustDialogAccepted) {
1733
2207
  config2.projects[projectPath].hasTrustDialogAccepted = true;
1734
- writeFileSync3(configPath, JSON.stringify(config2, null, 2));
2208
+ writeFileSync4(configPath, JSON.stringify(config2, null, 2));
1735
2209
  }
1736
2210
  } catch {
1737
2211
  }
@@ -1739,25 +2213,25 @@ function ensureProjectTrusted(projectPath) {
1739
2213
  function getProjectRoot() {
1740
2214
  const squadsDir = findSquadsDir();
1741
2215
  if (squadsDir) {
1742
- return dirname(dirname(squadsDir));
2216
+ return dirname2(dirname2(squadsDir));
1743
2217
  }
1744
2218
  return process.cwd();
1745
2219
  }
1746
2220
  function getExecutionLogPath(squadName, agentName) {
1747
2221
  const memoryDir = findMemoryDir();
1748
2222
  if (!memoryDir) return null;
1749
- return join4(memoryDir, squadName, agentName, "executions.md");
2223
+ return join5(memoryDir, squadName, agentName, "executions.md");
1750
2224
  }
1751
2225
  function logExecution(record) {
1752
2226
  const logPath = getExecutionLogPath(record.squadName, record.agentName);
1753
2227
  if (!logPath) return;
1754
- const dir = dirname(logPath);
1755
- if (!existsSync4(dir)) {
1756
- mkdirSync2(dir, { recursive: true });
2228
+ const dir = dirname2(logPath);
2229
+ if (!existsSync5(dir)) {
2230
+ mkdirSync3(dir, { recursive: true });
1757
2231
  }
1758
2232
  let content = "";
1759
- if (existsSync4(logPath)) {
1760
- content = readFileSync3(logPath, "utf-8").trimEnd();
2233
+ if (existsSync5(logPath)) {
2234
+ content = readFileSync4(logPath, "utf-8").trimEnd();
1761
2235
  } else {
1762
2236
  content = `# ${record.squadName}/${record.agentName} - Execution Log`;
1763
2237
  }
@@ -1770,12 +2244,12 @@ function logExecution(record) {
1770
2244
  - Trigger: ${record.trigger || "manual"}
1771
2245
  - Task Type: ${record.taskType || "execution"}
1772
2246
  `;
1773
- writeFileSync3(logPath, content + entry);
2247
+ writeFileSync4(logPath, content + entry);
1774
2248
  }
1775
2249
  function updateExecutionStatus(squadName, agentName, executionId, status, details) {
1776
2250
  const logPath = getExecutionLogPath(squadName, agentName);
1777
- if (!logPath || !existsSync4(logPath)) return;
1778
- let content = readFileSync3(logPath, "utf-8");
2251
+ if (!logPath || !existsSync5(logPath)) return;
2252
+ let content = readFileSync4(logPath, "utf-8");
1779
2253
  const endTime = (/* @__PURE__ */ new Date()).toISOString();
1780
2254
  const execMarker = `<!-- exec:${executionId} -->`;
1781
2255
  const markerIndex = content.indexOf(execMarker);
@@ -1796,7 +2270,7 @@ function updateExecutionStatus(squadName, agentName, executionId, status, detail
1796
2270
  - Error: ${details.error}`;
1797
2271
  }
1798
2272
  content = content.slice(0, entryStart) + updatedEntry + content.slice(entryEnd);
1799
- writeFileSync3(logPath, content);
2273
+ writeFileSync4(logPath, content);
1800
2274
  }
1801
2275
  function extractMcpServersFromDefinition(definition) {
1802
2276
  const servers = /* @__PURE__ */ new Set();
@@ -1875,8 +2349,8 @@ async function runSquad(squad, squadsDir, options) {
1875
2349
  if (options.parallel) {
1876
2350
  const agentFiles = squad.agents.map((a) => ({
1877
2351
  name: a.name,
1878
- path: join4(squadsDir, squad.name, `${a.name}.md`)
1879
- })).filter((a) => existsSync4(a.path));
2352
+ path: join5(squadsDir, squad.name, `${a.name}.md`)
2353
+ })).filter((a) => existsSync5(a.path));
1880
2354
  if (agentFiles.length === 0) {
1881
2355
  writeLine(` ${icons.error} ${colors.red}No agent files found${RESET}`);
1882
2356
  return;
@@ -1912,8 +2386,8 @@ async function runSquad(squad, squadsDir, options) {
1912
2386
  writeLine();
1913
2387
  for (let i = 0; i < pipeline.agents.length; i++) {
1914
2388
  const agentName = pipeline.agents[i];
1915
- const agentPath = join4(squadsDir, squad.name, `${agentName}.md`);
1916
- if (existsSync4(agentPath)) {
2389
+ const agentPath = join5(squadsDir, squad.name, `${agentName}.md`);
2390
+ if (existsSync5(agentPath)) {
1917
2391
  writeLine(` ${colors.dim}[${i + 1}/${pipeline.agents.length}]${RESET}`);
1918
2392
  await runAgent(agentName, agentPath, squad.name, options);
1919
2393
  writeLine();
@@ -1923,8 +2397,8 @@ async function runSquad(squad, squadsDir, options) {
1923
2397
  }
1924
2398
  } else {
1925
2399
  if (options.agent) {
1926
- const agentPath = join4(squadsDir, squad.name, `${options.agent}.md`);
1927
- if (existsSync4(agentPath)) {
2400
+ const agentPath = join5(squadsDir, squad.name, `${options.agent}.md`);
2401
+ if (existsSync5(agentPath)) {
1928
2402
  await runAgent(options.agent, agentPath, squad.name, options);
1929
2403
  } else {
1930
2404
  writeLine(` ${icons.error} ${colors.red}Agent ${options.agent} not found${RESET}`);
@@ -1935,8 +2409,8 @@ async function runSquad(squad, squadsDir, options) {
1935
2409
  (a) => a.name.includes("lead") || a.trigger === "Manual"
1936
2410
  );
1937
2411
  if (orchestrator) {
1938
- const agentPath = join4(squadsDir, squad.name, `${orchestrator.name}.md`);
1939
- if (existsSync4(agentPath)) {
2412
+ const agentPath = join5(squadsDir, squad.name, `${orchestrator.name}.md`);
2413
+ if (existsSync5(agentPath)) {
1940
2414
  await runAgent(orchestrator.name, agentPath, squad.name, options);
1941
2415
  }
1942
2416
  } else {
@@ -1962,9 +2436,9 @@ async function runLeadMode(squad, squadsDir, options) {
1962
2436
  if (!squad) return;
1963
2437
  const agentFiles = squad.agents.map((a) => ({
1964
2438
  name: a.name,
1965
- path: join4(squadsDir, squad.name, `${a.name}.md`),
2439
+ path: join5(squadsDir, squad.name, `${a.name}.md`),
1966
2440
  role: a.role || ""
1967
- })).filter((a) => existsSync4(a.path));
2441
+ })).filter((a) => existsSync5(a.path));
1968
2442
  if (agentFiles.length === 0) {
1969
2443
  writeLine(` ${icons.error} ${colors.red}No agent files found${RESET}`);
1970
2444
  return;
@@ -2083,9 +2557,9 @@ async function runAgent(agentName, agentPath, squadName, options) {
2083
2557
  }
2084
2558
  const squadsDir = findSquadsDir();
2085
2559
  if (squadsDir) {
2086
- const squadFilePath = join4(squadsDir, squadName, "SQUAD.md");
2087
- if (existsSync4(squadFilePath)) {
2088
- const squadContent = readFileSync3(squadFilePath, "utf-8");
2560
+ const squadFilePath = join5(squadsDir, squadName, "SQUAD.md");
2561
+ if (existsSync5(squadFilePath)) {
2562
+ const squadContent = readFileSync4(squadFilePath, "utf-8");
2089
2563
  const permContext = buildContextFromSquad(squadName, squadContent, agentName);
2090
2564
  const mcpServers = extractMcpServersFromDefinition(definition);
2091
2565
  const execRequest = {
@@ -2194,7 +2668,8 @@ async function executeWithClaude(prompt2, verbose, _timeoutMinutes = 30, foregro
2194
2668
  const agentMatch = prompt2.match(/(\w+) agent/);
2195
2669
  const squadName = process.env.SQUADS_SQUAD || squadMatch?.[1] || "unknown";
2196
2670
  const agentName = process.env.SQUADS_AGENT || agentMatch?.[1] || "unknown";
2197
- const mcpConfigPath = selectMcpConfig(squadName);
2671
+ const squad = squadName !== "unknown" ? loadSquad(squadName) : null;
2672
+ const mcpConfigPath = selectMcpConfig(squadName, squad);
2198
2673
  const execContext = {
2199
2674
  squad: squadName,
2200
2675
  agent: agentName,
@@ -2365,8 +2840,8 @@ async function listCommand(options) {
2365
2840
  }
2366
2841
 
2367
2842
  // src/commands/status.ts
2368
- import { existsSync as existsSync5, statSync } from "fs";
2369
- import { join as join5 } from "path";
2843
+ import { existsSync as existsSync6, statSync } from "fs";
2844
+ import { join as join6 } from "path";
2370
2845
  async function statusCommand(squadName, options = {}) {
2371
2846
  await track(Events.CLI_STATUS, { squad: squadName || "all", verbose: options.verbose });
2372
2847
  const squadsDir = findSquadsDir();
@@ -2419,8 +2894,8 @@ async function showOverallStatus(squadsDir, _options) {
2419
2894
  let lastActivity = `${colors.dim}\u2014${RESET}`;
2420
2895
  let activityColor = colors.dim;
2421
2896
  if (memoryDir) {
2422
- const squadMemoryPath = join5(memoryDir, squadName);
2423
- if (existsSync5(squadMemoryPath)) {
2897
+ const squadMemoryPath = join6(memoryDir, squadName);
2898
+ if (existsSync6(squadMemoryPath)) {
2424
2899
  const states = getSquadState(squadName);
2425
2900
  memoryStatus = `${colors.green}${states.length} ${states.length === 1 ? "entry" : "entries"}${RESET}`;
2426
2901
  let mostRecent = 0;
@@ -2522,14 +2997,14 @@ async function showSquadStatus(squadName, squadsDir, options) {
2522
2997
  }
2523
2998
 
2524
2999
  // src/commands/stack.ts
2525
- import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, copyFileSync } from "fs";
2526
- import { join as join6, dirname as dirname2 } from "path";
3000
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, copyFileSync } from "fs";
3001
+ import { join as join7, dirname as dirname3 } from "path";
2527
3002
  import { homedir as homedir2 } from "os";
2528
3003
  import { execSync as execSync3, spawn as spawn3 } from "child_process";
2529
3004
  import { createInterface as createInterface2 } from "readline";
2530
3005
  import { fileURLToPath } from "url";
2531
3006
  var __filename2 = fileURLToPath(import.meta.url);
2532
- var __dirname2 = dirname2(__filename2);
3007
+ var __dirname2 = dirname3(__filename2);
2533
3008
  var DEFAULT_CONFIG = {
2534
3009
  SQUADS_DATABASE_URL: "postgresql://squads:squads@localhost:5433/squads",
2535
3010
  SQUADS_BRIDGE_URL: "http://localhost:8088",
@@ -2538,8 +3013,8 @@ var DEFAULT_CONFIG = {
2538
3013
  LANGFUSE_SECRET_KEY: "",
2539
3014
  REDIS_URL: "redis://localhost:6379"
2540
3015
  };
2541
- var CONFIG_PATH2 = join6(homedir2(), ".squadsrc");
2542
- var SQUADS_DATA_DIR = join6(homedir2(), ".squads");
3016
+ var CONFIG_PATH2 = join7(homedir2(), ".squadsrc");
3017
+ var SQUADS_DATA_DIR = join7(homedir2(), ".squads");
2543
3018
  var SERVICES = {
2544
3019
  bridge: {
2545
3020
  name: "Bridge API",
@@ -2673,25 +3148,25 @@ async function confirm2(question, defaultYes = true) {
2673
3148
  function findPackageDockerDir() {
2674
3149
  const candidates = [
2675
3150
  // From npm package (relative to dist/commands/stack.js)
2676
- join6(__dirname2, "..", "..", "docker"),
3151
+ join7(__dirname2, "..", "..", "docker"),
2677
3152
  // Local development
2678
- join6(process.cwd(), "docker"),
2679
- join6(process.cwd(), "..", "squads-cli", "docker"),
2680
- join6(homedir2(), "agents-squads", "squads-cli", "docker")
3153
+ join7(process.cwd(), "docker"),
3154
+ join7(process.cwd(), "..", "squads-cli", "docker"),
3155
+ join7(homedir2(), "agents-squads", "squads-cli", "docker")
2681
3156
  ];
2682
3157
  for (const dir of candidates) {
2683
- if (existsSync6(join6(dir, "docker-compose.yml"))) {
3158
+ if (existsSync7(join7(dir, "docker-compose.yml"))) {
2684
3159
  return dir;
2685
3160
  }
2686
3161
  }
2687
3162
  return null;
2688
3163
  }
2689
3164
  function loadStackConfig() {
2690
- if (!existsSync6(CONFIG_PATH2)) {
3165
+ if (!existsSync7(CONFIG_PATH2)) {
2691
3166
  return null;
2692
3167
  }
2693
3168
  try {
2694
- const content = readFileSync4(CONFIG_PATH2, "utf-8");
3169
+ const content = readFileSync5(CONFIG_PATH2, "utf-8");
2695
3170
  const config2 = {};
2696
3171
  for (const line of content.split("\n")) {
2697
3172
  const trimmed = line.trim();
@@ -2732,7 +3207,7 @@ function saveStackConfig(config2) {
2732
3207
  "# To activate: source ~/.squadsrc",
2733
3208
  ""
2734
3209
  ];
2735
- writeFileSync4(CONFIG_PATH2, lines.join("\n"));
3210
+ writeFileSync5(CONFIG_PATH2, lines.join("\n"));
2736
3211
  }
2737
3212
  function applyStackConfig() {
2738
3213
  const config2 = loadStackConfig();
@@ -2804,13 +3279,13 @@ async function checkService(url, timeout = 2e3) {
2804
3279
  }
2805
3280
  function getLangfuseKeysFromDockerEnv() {
2806
3281
  const envPaths2 = [
2807
- join6(process.cwd(), "docker", ".env"),
2808
- join6(process.cwd(), "..", "squads-cli", "docker", ".env"),
2809
- join6(homedir2(), "agents-squads", "squads-cli", "docker", ".env")
3282
+ join7(process.cwd(), "docker", ".env"),
3283
+ join7(process.cwd(), "..", "squads-cli", "docker", ".env"),
3284
+ join7(homedir2(), "agents-squads", "squads-cli", "docker", ".env")
2810
3285
  ];
2811
3286
  for (const envPath of envPaths2) {
2812
- if (existsSync6(envPath)) {
2813
- const content = readFileSync4(envPath, "utf-8");
3287
+ if (existsSync7(envPath)) {
3288
+ const content = readFileSync5(envPath, "utf-8");
2814
3289
  const publicMatch = content.match(/LANGFUSE_PUBLIC_KEY=(\S+)/);
2815
3290
  const secretMatch = content.match(/LANGFUSE_SECRET_KEY=(\S+)/);
2816
3291
  if (publicMatch && secretMatch) {
@@ -2825,12 +3300,12 @@ function getLangfuseKeysFromDockerEnv() {
2825
3300
  }
2826
3301
  function findDockerComposeDir() {
2827
3302
  const candidates = [
2828
- join6(process.cwd(), "docker"),
2829
- join6(process.cwd(), "..", "squads-cli", "docker"),
2830
- join6(homedir2(), "agents-squads", "squads-cli", "docker")
3303
+ join7(process.cwd(), "docker"),
3304
+ join7(process.cwd(), "..", "squads-cli", "docker"),
3305
+ join7(homedir2(), "agents-squads", "squads-cli", "docker")
2831
3306
  ];
2832
3307
  for (const dir of candidates) {
2833
- if (existsSync6(join6(dir, "docker-compose.yml"))) {
3308
+ if (existsSync7(join7(dir, "docker-compose.yml"))) {
2834
3309
  return dir;
2835
3310
  }
2836
3311
  }
@@ -2856,7 +3331,7 @@ async function stackInitCommand() {
2856
3331
  writeLine();
2857
3332
  writeLine(` ${bold}Step 2: Docker Compose Files${RESET}`);
2858
3333
  let composeDir = findPackageDockerDir();
2859
- const targetDir = join6(SQUADS_DATA_DIR, "docker");
3334
+ const targetDir = join7(SQUADS_DATA_DIR, "docker");
2860
3335
  if (!composeDir) {
2861
3336
  writeLine(` ${colors.red}${icons.error}${RESET} Docker compose files not found`);
2862
3337
  writeLine(` ${colors.dim}This shouldn't happen if you installed via npm.${RESET}`);
@@ -2864,20 +3339,20 @@ async function stackInitCommand() {
2864
3339
  writeLine();
2865
3340
  return;
2866
3341
  }
2867
- if (composeDir !== targetDir && !existsSync6(targetDir)) {
3342
+ if (composeDir !== targetDir && !existsSync7(targetDir)) {
2868
3343
  writeLine(` ${colors.cyan}${icons.progress}${RESET} Copying docker files to ${colors.dim}~/.squads/docker${RESET}`);
2869
3344
  try {
2870
- mkdirSync3(SQUADS_DATA_DIR, { recursive: true });
2871
- mkdirSync3(targetDir, { recursive: true });
3345
+ mkdirSync4(SQUADS_DATA_DIR, { recursive: true });
3346
+ mkdirSync4(targetDir, { recursive: true });
2872
3347
  const filesToCopy = [
2873
3348
  "docker-compose.yml",
2874
3349
  "docker-compose.engram.yml",
2875
3350
  ".env.example"
2876
3351
  ];
2877
3352
  for (const file of filesToCopy) {
2878
- const src = join6(composeDir, file);
2879
- const dst = join6(targetDir, file);
2880
- if (existsSync6(src)) {
3353
+ const src = join7(composeDir, file);
3354
+ const dst = join7(targetDir, file);
3355
+ if (existsSync7(src)) {
2881
3356
  copyFileSync(src, dst);
2882
3357
  }
2883
3358
  }
@@ -2886,7 +3361,7 @@ async function stackInitCommand() {
2886
3361
  } catch {
2887
3362
  writeLine(` ${colors.yellow}${icons.warning}${RESET} Could not copy files, using source location`);
2888
3363
  }
2889
- } else if (existsSync6(targetDir)) {
3364
+ } else if (existsSync7(targetDir)) {
2890
3365
  composeDir = targetDir;
2891
3366
  writeLine(` ${colors.green}${icons.success}${RESET} Using ${colors.dim}~/.squads/docker${RESET}`);
2892
3367
  } else {
@@ -2894,10 +3369,10 @@ async function stackInitCommand() {
2894
3369
  }
2895
3370
  writeLine();
2896
3371
  writeLine(` ${bold}Step 3: Environment Configuration${RESET}`);
2897
- const envPath = join6(composeDir, ".env");
2898
- const envExamplePath = join6(composeDir, ".env.example");
2899
- if (!existsSync6(envPath)) {
2900
- if (existsSync6(envExamplePath)) {
3372
+ const envPath = join7(composeDir, ".env");
3373
+ const envExamplePath = join7(composeDir, ".env.example");
3374
+ if (!existsSync7(envPath)) {
3375
+ if (existsSync7(envExamplePath)) {
2901
3376
  copyFileSync(envExamplePath, envPath);
2902
3377
  writeLine(` ${colors.cyan}${icons.progress}${RESET} Created .env from template`);
2903
3378
  } else {
@@ -2926,13 +3401,13 @@ LANGFUSE_PORT=3100
2926
3401
  OTEL_PORT=4318
2927
3402
  BRIDGE_PORT=8088
2928
3403
  `;
2929
- writeFileSync4(envPath, minimalEnv);
3404
+ writeFileSync5(envPath, minimalEnv);
2930
3405
  writeLine(` ${colors.cyan}${icons.progress}${RESET} Created default .env`);
2931
3406
  }
2932
3407
  } else {
2933
3408
  writeLine(` ${colors.green}${icons.success}${RESET} .env exists`);
2934
3409
  }
2935
- const envContent = readFileSync4(envPath, "utf-8");
3410
+ const envContent = readFileSync5(envPath, "utf-8");
2936
3411
  const missingSecrets = [];
2937
3412
  const llmProvider = envContent.match(/LLM_PROVIDER=(\w+)/)?.[1] || "ollama";
2938
3413
  if (llmProvider === "openai") {
@@ -3612,8 +4087,8 @@ async function memoryExtractCommand(options = {}) {
3612
4087
 
3613
4088
  // src/commands/sync.ts
3614
4089
  import { execSync as execSync4 } from "child_process";
3615
- import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
3616
- import { join as join7 } from "path";
4090
+ import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync2 } from "fs";
4091
+ import { join as join8 } from "path";
3617
4092
  var PATH_TO_SQUAD = {
3618
4093
  "squads-cli": "product",
3619
4094
  "agents-squads-web": "website",
@@ -3641,15 +4116,15 @@ var MESSAGE_TO_SQUAD = {
3641
4116
  "infra": "engineering"
3642
4117
  };
3643
4118
  function getLastSyncTime(memoryDir) {
3644
- const syncFile = join7(memoryDir, ".last-sync");
3645
- if (existsSync7(syncFile)) {
3646
- return readFileSync5(syncFile, "utf-8").trim();
4119
+ const syncFile = join8(memoryDir, ".last-sync");
4120
+ if (existsSync8(syncFile)) {
4121
+ return readFileSync6(syncFile, "utf-8").trim();
3647
4122
  }
3648
4123
  return null;
3649
4124
  }
3650
4125
  function updateLastSyncTime(memoryDir) {
3651
- const syncFile = join7(memoryDir, ".last-sync");
3652
- writeFileSync5(syncFile, (/* @__PURE__ */ new Date()).toISOString());
4126
+ const syncFile = join8(memoryDir, ".last-sync");
4127
+ writeFileSync6(syncFile, (/* @__PURE__ */ new Date()).toISOString());
3653
4128
  }
3654
4129
  function getRecentCommits(since) {
3655
4130
  const commits = [];
@@ -3721,22 +4196,22 @@ ${messages}
3721
4196
  `;
3722
4197
  }
3723
4198
  function appendToSquadMemory(memoryDir, squad, summary) {
3724
- const squadMemoryDir = join7(memoryDir, squad);
3725
- if (!existsSync7(squadMemoryDir)) {
3726
- mkdirSync4(squadMemoryDir, { recursive: true });
4199
+ const squadMemoryDir = join8(memoryDir, squad);
4200
+ if (!existsSync8(squadMemoryDir)) {
4201
+ mkdirSync5(squadMemoryDir, { recursive: true });
3727
4202
  }
3728
4203
  let agentDir;
3729
- const existingDirs = existsSync7(squadMemoryDir) ? readdirSync2(squadMemoryDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name) : [];
4204
+ const existingDirs = existsSync8(squadMemoryDir) ? readdirSync2(squadMemoryDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name) : [];
3730
4205
  if (existingDirs.length > 0) {
3731
- agentDir = join7(squadMemoryDir, existingDirs[0]);
4206
+ agentDir = join8(squadMemoryDir, existingDirs[0]);
3732
4207
  } else {
3733
- agentDir = join7(squadMemoryDir, `${squad}-lead`);
3734
- mkdirSync4(agentDir, { recursive: true });
4208
+ agentDir = join8(squadMemoryDir, `${squad}-lead`);
4209
+ mkdirSync5(agentDir, { recursive: true });
3735
4210
  }
3736
- const statePath = join7(agentDir, "state.md");
4211
+ const statePath = join8(agentDir, "state.md");
3737
4212
  let content = "";
3738
- if (existsSync7(statePath)) {
3739
- content = readFileSync5(statePath, "utf-8");
4213
+ if (existsSync8(statePath)) {
4214
+ content = readFileSync6(statePath, "utf-8");
3740
4215
  } else {
3741
4216
  content = `# ${squad} Squad - State
3742
4217
 
@@ -3748,7 +4223,7 @@ Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
3748
4223
  `Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`
3749
4224
  );
3750
4225
  content += summary;
3751
- writeFileSync5(statePath, content);
4226
+ writeFileSync6(statePath, content);
3752
4227
  return true;
3753
4228
  }
3754
4229
  function gitPullMemory() {
@@ -4025,28 +4500,28 @@ async function goalProgressCommand(squadName, goalIndex, progress2) {
4025
4500
  }
4026
4501
 
4027
4502
  // src/commands/feedback.ts
4028
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
4029
- import { join as join8, dirname as dirname3 } from "path";
4503
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
4504
+ import { join as join9, dirname as dirname4 } from "path";
4030
4505
  function getFeedbackPath(squadName) {
4031
4506
  const memoryDir = findMemoryDir();
4032
4507
  if (!memoryDir) return null;
4033
4508
  const squad = loadSquad(squadName);
4034
4509
  const agentName = squad?.agents[0]?.name || `${squadName}-lead`;
4035
- return join8(memoryDir, squadName, agentName, "feedback.md");
4510
+ return join9(memoryDir, squadName, agentName, "feedback.md");
4036
4511
  }
4037
4512
  function getOutputPath(squadName) {
4038
4513
  const memoryDir = findMemoryDir();
4039
4514
  if (!memoryDir) return null;
4040
4515
  const squad = loadSquad(squadName);
4041
4516
  const agentName = squad?.agents[0]?.name || `${squadName}-lead`;
4042
- return join8(memoryDir, squadName, agentName, "output.md");
4517
+ return join9(memoryDir, squadName, agentName, "output.md");
4043
4518
  }
4044
4519
  function getLastExecution(squadName) {
4045
4520
  const outputPath = getOutputPath(squadName);
4046
- if (!outputPath || !existsSync8(outputPath)) {
4521
+ if (!outputPath || !existsSync9(outputPath)) {
4047
4522
  return null;
4048
4523
  }
4049
- const content = readFileSync6(outputPath, "utf-8");
4524
+ const content = readFileSync7(outputPath, "utf-8");
4050
4525
  const lines = content.split("\n");
4051
4526
  let date = "unknown";
4052
4527
  let summary = lines.slice(0, 5).join("\n");
@@ -4098,9 +4573,9 @@ async function feedbackAddCommand(squadName, rating, feedback2, options) {
4098
4573
  return;
4099
4574
  }
4100
4575
  const lastExec = getLastExecution(squadName);
4101
- const dir = dirname3(feedbackPath);
4102
- if (!existsSync8(dir)) {
4103
- mkdirSync5(dir, { recursive: true });
4576
+ const dir = dirname4(feedbackPath);
4577
+ if (!existsSync9(dir)) {
4578
+ mkdirSync6(dir, { recursive: true });
4104
4579
  }
4105
4580
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
4106
4581
  let entry = `
@@ -4128,15 +4603,15 @@ _Date: ${date}_
4128
4603
  }
4129
4604
  }
4130
4605
  let existing = "";
4131
- if (existsSync8(feedbackPath)) {
4132
- existing = readFileSync6(feedbackPath, "utf-8");
4606
+ if (existsSync9(feedbackPath)) {
4607
+ existing = readFileSync7(feedbackPath, "utf-8");
4133
4608
  } else {
4134
4609
  existing = `# ${squadName} - Feedback Log
4135
4610
 
4136
4611
  > Execution feedback and learnings
4137
4612
  `;
4138
4613
  }
4139
- writeFileSync6(feedbackPath, existing + entry);
4614
+ writeFileSync7(feedbackPath, existing + entry);
4140
4615
  const stars = `${colors.yellow}${"\u2605".repeat(ratingNum)}${"\u2606".repeat(5 - ratingNum)}${RESET}`;
4141
4616
  writeLine();
4142
4617
  writeLine(` ${icons.success} Feedback recorded for ${colors.cyan}${squadName}${RESET}`);
@@ -4150,11 +4625,11 @@ _Date: ${date}_
4150
4625
  async function feedbackShowCommand(squadName, options) {
4151
4626
  await track(Events.CLI_FEEDBACK_SHOW, { squad: squadName });
4152
4627
  const feedbackPath = getFeedbackPath(squadName);
4153
- if (!feedbackPath || !existsSync8(feedbackPath)) {
4628
+ if (!feedbackPath || !existsSync9(feedbackPath)) {
4154
4629
  writeLine(` ${colors.yellow}No feedback recorded for ${squadName}${RESET}`);
4155
4630
  return;
4156
4631
  }
4157
- const content = readFileSync6(feedbackPath, "utf-8");
4632
+ const content = readFileSync7(feedbackPath, "utf-8");
4158
4633
  const entries = parseFeedbackHistory(content);
4159
4634
  const limit = options.limit ? parseInt(options.limit) : 5;
4160
4635
  const recent = entries.slice(-limit).reverse();
@@ -4199,10 +4674,10 @@ async function feedbackStatsCommand() {
4199
4674
  writeLine(` ${colors.purple}${box.teeRight}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.teeLeft}${RESET}`);
4200
4675
  for (const squad of squads) {
4201
4676
  const feedbackPath = getFeedbackPath(squad);
4202
- if (!feedbackPath || !existsSync8(feedbackPath)) {
4677
+ if (!feedbackPath || !existsSync9(feedbackPath)) {
4203
4678
  continue;
4204
4679
  }
4205
- const content = readFileSync6(feedbackPath, "utf-8");
4680
+ const content = readFileSync7(feedbackPath, "utf-8");
4206
4681
  const entries = parseFeedbackHistory(content);
4207
4682
  if (entries.length === 0) continue;
4208
4683
  const avgRating = entries.reduce((sum, e) => sum + e.rating, 0) / entries.length;
@@ -4224,9 +4699,252 @@ async function feedbackStatsCommand() {
4224
4699
  writeLine();
4225
4700
  }
4226
4701
 
4702
+ // src/commands/learn.ts
4703
+ import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
4704
+ import { join as join10, dirname as dirname5 } from "path";
4705
+ function parseLearnings(content) {
4706
+ const learnings = [];
4707
+ const sections = content.split(/\n---\n/).filter((s) => s.trim());
4708
+ for (const section of sections) {
4709
+ if (section.startsWith("#")) continue;
4710
+ const dateMatch = section.match(/_(\d{4}-\d{2}-\d{2})_/);
4711
+ const categoryMatch = section.match(/\*\*(\w+)\*\*:/);
4712
+ const tagsMatch = section.match(/Tags: `([^`]+)`/);
4713
+ const lines = section.split("\n").filter((l) => l.trim() && !l.startsWith("_") && !l.includes("Tags:"));
4714
+ const insight = lines.map((l) => l.replace(/^\*\*\w+\*\*:\s*/, "")).join(" ").trim();
4715
+ if (dateMatch && insight) {
4716
+ learnings.push({
4717
+ date: dateMatch[1],
4718
+ insight,
4719
+ category: categoryMatch?.[1]?.toLowerCase() || "tip",
4720
+ tags: tagsMatch?.[1]?.split(",").map((t) => t.trim()) || []
4721
+ });
4722
+ }
4723
+ }
4724
+ return learnings;
4725
+ }
4726
+ function formatLearning(learning) {
4727
+ const categoryEmoji = {
4728
+ success: "\u25CF",
4729
+ failure: "\u2717",
4730
+ pattern: "\u25C6",
4731
+ tip: "\u2192"
4732
+ };
4733
+ let entry = `
4734
+ ---
4735
+ _${learning.date}_
4736
+
4737
+ `;
4738
+ entry += `${categoryEmoji[learning.category]} **${learning.category.charAt(0).toUpperCase() + learning.category.slice(1)}**: ${learning.insight}
4739
+ `;
4740
+ if (learning.tags.length > 0) {
4741
+ entry += `Tags: \`${learning.tags.join(", ")}\`
4742
+ `;
4743
+ }
4744
+ if (learning.context) {
4745
+ entry += `
4746
+ _Context: ${learning.context}_
4747
+ `;
4748
+ }
4749
+ return entry;
4750
+ }
4751
+ async function learnCommand(insight, options) {
4752
+ let squadName = options.squad || "general";
4753
+ if (options.squad) {
4754
+ const squadsDir = findSquadsDir();
4755
+ if (squadsDir) {
4756
+ const squads = listSquads(squadsDir);
4757
+ if (!squads.includes(options.squad)) {
4758
+ writeLine();
4759
+ writeLine(` ${colors.yellow}${icons.warning} Squad '${options.squad}' not found${RESET}`);
4760
+ writeLine(` ${colors.dim}Available: ${squads.join(", ")}${RESET}`);
4761
+ writeLine(` ${colors.dim}Using 'general' instead${RESET}`);
4762
+ squadName = "general";
4763
+ }
4764
+ }
4765
+ }
4766
+ const tags = options.tags ? options.tags.split(",").map((t) => t.trim().toLowerCase()) : [];
4767
+ if (tags.length === 0) {
4768
+ const autoTags = extractTags(insight);
4769
+ tags.push(...autoTags);
4770
+ }
4771
+ const category = options.category || inferCategory(insight);
4772
+ const learning = {
4773
+ date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
4774
+ insight,
4775
+ category,
4776
+ tags,
4777
+ squad: squadName,
4778
+ context: options.context
4779
+ };
4780
+ const memoryDir = findMemoryDir();
4781
+ if (!memoryDir) {
4782
+ writeLine(` ${colors.red}No .agents/memory directory found${RESET}`);
4783
+ writeLine(` ${colors.dim}Run 'squads init' first${RESET}`);
4784
+ return;
4785
+ }
4786
+ const learningsPath = join10(memoryDir, squadName, "shared", "learnings.md");
4787
+ const dir = dirname5(learningsPath);
4788
+ if (!existsSync10(dir)) {
4789
+ mkdirSync7(dir, { recursive: true });
4790
+ }
4791
+ let content = "";
4792
+ if (existsSync10(learningsPath)) {
4793
+ content = readFileSync8(learningsPath, "utf-8");
4794
+ } else {
4795
+ content = `# ${squadName} - Learnings
4796
+
4797
+ > Accumulated knowledge from sessions
4798
+ `;
4799
+ }
4800
+ content += formatLearning(learning);
4801
+ writeFileSync8(learningsPath, content);
4802
+ await track(Events.CLI_LEARN, {
4803
+ squad: squadName,
4804
+ category,
4805
+ tagCount: tags.length
4806
+ });
4807
+ writeLine();
4808
+ writeLine(` ${icons.success} Learning captured for ${colors.cyan}${squadName}${RESET}`);
4809
+ writeLine();
4810
+ writeLine(` ${colors.dim}Category:${RESET} ${category}`);
4811
+ if (tags.length > 0) {
4812
+ writeLine(` ${colors.dim}Tags:${RESET} ${tags.map((t) => `#${t}`).join(" ")}`);
4813
+ }
4814
+ writeLine();
4815
+ writeLine(` ${colors.green}${insight}${RESET}`);
4816
+ writeLine();
4817
+ }
4818
+ async function learnShowCommand(squadName, options) {
4819
+ const memoryDir = findMemoryDir();
4820
+ if (!memoryDir) {
4821
+ writeLine(` ${colors.red}No memory directory found${RESET}`);
4822
+ return;
4823
+ }
4824
+ const learningsPath = join10(memoryDir, squadName, "shared", "learnings.md");
4825
+ if (!existsSync10(learningsPath)) {
4826
+ writeLine(` ${colors.yellow}No learnings recorded for ${squadName}${RESET}`);
4827
+ writeLine(` ${colors.dim}Add one: squads learn "insight" --squad ${squadName}${RESET}`);
4828
+ return;
4829
+ }
4830
+ const content = readFileSync8(learningsPath, "utf-8");
4831
+ const learnings = parseLearnings(content);
4832
+ let filtered = learnings;
4833
+ if (options.category) {
4834
+ filtered = filtered.filter((l) => l.category === options.category);
4835
+ }
4836
+ if (options.tag) {
4837
+ const tag = options.tag.toLowerCase();
4838
+ filtered = filtered.filter((l) => l.tags.includes(tag));
4839
+ }
4840
+ const limit = options.limit ? parseInt(options.limit) : 10;
4841
+ const recent = filtered.slice(-limit).reverse();
4842
+ await track(Events.CLI_LEARN_SHOW, { squad: squadName });
4843
+ writeLine();
4844
+ writeLine(` ${gradient("squads")} ${colors.dim}learnings${RESET} ${colors.cyan}${squadName}${RESET}`);
4845
+ writeLine();
4846
+ if (recent.length === 0) {
4847
+ writeLine(` ${colors.dim}No learnings found${RESET}`);
4848
+ return;
4849
+ }
4850
+ writeLine(` ${colors.dim}Showing ${recent.length} of ${filtered.length} learnings${RESET}`);
4851
+ writeLine();
4852
+ const categoryIcon = {
4853
+ success: `${colors.green}${icons.success}${RESET}`,
4854
+ failure: `${colors.red}\u2717${RESET}`,
4855
+ pattern: `${colors.purple}\u25C6${RESET}`,
4856
+ tip: `${colors.cyan}\u2192${RESET}`
4857
+ };
4858
+ for (const learning of recent) {
4859
+ writeLine(` ${colors.dim}${learning.date}${RESET} ${categoryIcon[learning.category]} ${learning.insight}`);
4860
+ if (learning.tags.length > 0) {
4861
+ writeLine(` ${colors.dim}${learning.tags.map((t) => `#${t}`).join(" ")}${RESET}`);
4862
+ }
4863
+ }
4864
+ writeLine();
4865
+ }
4866
+ async function learnSearchCommand(query, options) {
4867
+ const memoryDir = findMemoryDir();
4868
+ if (!memoryDir) {
4869
+ writeLine(` ${colors.red}No memory directory found${RESET}`);
4870
+ return;
4871
+ }
4872
+ const squadsDir = findSquadsDir();
4873
+ const squads = squadsDir ? listSquads(squadsDir) : [];
4874
+ squads.push("general");
4875
+ const allLearnings = [];
4876
+ for (const squad of squads) {
4877
+ const learningsPath = join10(memoryDir, squad, "shared", "learnings.md");
4878
+ if (existsSync10(learningsPath)) {
4879
+ const content = readFileSync8(learningsPath, "utf-8");
4880
+ const learnings = parseLearnings(content);
4881
+ allLearnings.push(...learnings.map((l) => ({ ...l, squad })));
4882
+ }
4883
+ }
4884
+ const queryLower = query.toLowerCase();
4885
+ const matches = allLearnings.filter(
4886
+ (l) => l.insight.toLowerCase().includes(queryLower) || l.tags.some((t) => t.includes(queryLower))
4887
+ );
4888
+ await track(Events.CLI_LEARN_SEARCH, { query, matches: matches.length });
4889
+ writeLine();
4890
+ writeLine(` ${gradient("squads")} ${colors.dim}search learnings${RESET} "${query}"`);
4891
+ writeLine();
4892
+ const limit = options.limit ? parseInt(options.limit) : 10;
4893
+ const limited = matches.slice(0, limit);
4894
+ if (limited.length === 0) {
4895
+ writeLine(` ${colors.dim}No learnings found matching "${query}"${RESET}`);
4896
+ return;
4897
+ }
4898
+ writeLine(` ${colors.dim}Found ${matches.length} matches${RESET}`);
4899
+ writeLine();
4900
+ const categoryIcon = {
4901
+ success: `${colors.green}${icons.success}${RESET}`,
4902
+ failure: `${colors.red}\u2717${RESET}`,
4903
+ pattern: `${colors.purple}\u25C6${RESET}`,
4904
+ tip: `${colors.cyan}\u2192${RESET}`
4905
+ };
4906
+ for (const learning of limited) {
4907
+ writeLine(` ${colors.cyan}${learning.squad}${RESET} ${categoryIcon[learning.category]} ${learning.insight}`);
4908
+ }
4909
+ writeLine();
4910
+ }
4911
+ function extractTags(insight) {
4912
+ const tags = [];
4913
+ const lowerInsight = insight.toLowerCase();
4914
+ const patterns = {
4915
+ "auth": ["auth", "login", "token", "session", "password"],
4916
+ "api": ["api", "endpoint", "request", "response", "rest"],
4917
+ "bug": ["bug", "fix", "error", "issue", "crash"],
4918
+ "perf": ["performance", "slow", "fast", "optimize", "cache"],
4919
+ "ux": ["user", "ui", "interface", "design", "experience"],
4920
+ "test": ["test", "spec", "coverage", "assert"],
4921
+ "db": ["database", "query", "sql", "postgres", "redis"],
4922
+ "deploy": ["deploy", "release", "production", "staging"]
4923
+ };
4924
+ for (const [tag, keywords] of Object.entries(patterns)) {
4925
+ if (keywords.some((kw) => lowerInsight.includes(kw))) {
4926
+ tags.push(tag);
4927
+ }
4928
+ }
4929
+ return tags.slice(0, 3);
4930
+ }
4931
+ function inferCategory(insight) {
4932
+ const lower = insight.toLowerCase();
4933
+ if (lower.includes("worked") || lower.includes("success") || lower.includes("fixed")) {
4934
+ return "success";
4935
+ }
4936
+ if (lower.includes("failed") || lower.includes("error") || lower.includes("didn't work")) {
4937
+ return "failure";
4938
+ }
4939
+ if (lower.includes("pattern") || lower.includes("always") || lower.includes("whenever")) {
4940
+ return "pattern";
4941
+ }
4942
+ return "tip";
4943
+ }
4944
+
4227
4945
  // src/commands/dashboard.ts
4228
- import { readdirSync as readdirSync4, existsSync as existsSync9, statSync as statSync2 } from "fs";
4229
- import { join as join9 } from "path";
4946
+ import { readdirSync as readdirSync4, existsSync as existsSync11, statSync as statSync2 } from "fs";
4947
+ import { join as join11 } from "path";
4230
4948
 
4231
4949
  // src/lib/providers.ts
4232
4950
  var PROVIDERS = {
@@ -5085,16 +5803,16 @@ async function closeDatabase() {
5085
5803
  function getLastActivityDate(squadName) {
5086
5804
  const memoryDir = findMemoryDir();
5087
5805
  if (!memoryDir) return "unknown";
5088
- const squadMemory = join9(memoryDir, squadName);
5089
- if (!existsSync9(squadMemory)) return "\u2014";
5806
+ const squadMemory = join11(memoryDir, squadName);
5807
+ if (!existsSync11(squadMemory)) return "\u2014";
5090
5808
  let latestTime = 0;
5091
5809
  try {
5092
5810
  const agents = readdirSync4(squadMemory, { withFileTypes: true }).filter((e) => e.isDirectory());
5093
5811
  for (const agent of agents) {
5094
- const agentPath = join9(squadMemory, agent.name);
5812
+ const agentPath = join11(squadMemory, agent.name);
5095
5813
  const files = readdirSync4(agentPath).filter((f) => f.endsWith(".md"));
5096
5814
  for (const file of files) {
5097
- const filePath = join9(agentPath, file);
5815
+ const filePath = join11(agentPath, file);
5098
5816
  const stats = statSync2(filePath);
5099
5817
  if (stats.mtimeMs > latestTime) {
5100
5818
  latestTime = stats.mtimeMs;
@@ -5341,11 +6059,11 @@ async function dashboardCommand(options = {}) {
5341
6059
  await closeDatabase();
5342
6060
  }
5343
6061
  function findAgentsSquadsDir() {
5344
- const parentDir = join9(process.cwd(), "..");
5345
- if (existsSync9(join9(parentDir, "hq"))) {
6062
+ const parentDir = join11(process.cwd(), "..");
6063
+ if (existsSync11(join11(parentDir, "hq"))) {
5346
6064
  return parentDir;
5347
6065
  }
5348
- if (existsSync9(join9(process.cwd(), ".git"))) {
6066
+ if (existsSync11(join11(process.cwd(), ".git"))) {
5349
6067
  return process.cwd();
5350
6068
  }
5351
6069
  return null;
@@ -5984,7 +6702,7 @@ function executeClaudePrompt(prompt2) {
5984
6702
  // src/commands/open-issues.ts
5985
6703
  import { execSync as execSync7, spawn as spawn5 } from "child_process";
5986
6704
  import { readdirSync as readdirSync5 } from "fs";
5987
- import { join as join10 } from "path";
6705
+ import { join as join12 } from "path";
5988
6706
  import ora4 from "ora";
5989
6707
  var ISSUE_FINDER_PATTERNS = [
5990
6708
  "*-eval.md",
@@ -6042,7 +6760,7 @@ function findEvalAgents(squadsDir, filterSquad) {
6042
6760
  const agents = [];
6043
6761
  const squads = readdirSync5(squadsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).filter((d) => !filterSquad || d.name === filterSquad).map((d) => d.name);
6044
6762
  for (const squad of squads) {
6045
- const squadPath = join10(squadsDir, squad);
6763
+ const squadPath = join12(squadsDir, squad);
6046
6764
  const files = readdirSync5(squadPath).filter((f) => f.endsWith(".md"));
6047
6765
  for (const file of files) {
6048
6766
  const isEval = ISSUE_FINDER_PATTERNS.some((pattern) => {
@@ -6053,7 +6771,7 @@ function findEvalAgents(squadsDir, filterSquad) {
6053
6771
  agents.push({
6054
6772
  name: file,
6055
6773
  squad,
6056
- path: join10(squadPath, file)
6774
+ path: join12(squadPath, file)
6057
6775
  });
6058
6776
  }
6059
6777
  }
@@ -6163,8 +6881,8 @@ import open from "open";
6163
6881
 
6164
6882
  // src/lib/auth.ts
6165
6883
  import { createClient } from "@supabase/supabase-js";
6166
- import { existsSync as existsSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6 } from "fs";
6167
- import { join as join11 } from "path";
6884
+ import { existsSync as existsSync12, readFileSync as readFileSync9, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8 } from "fs";
6885
+ import { join as join13 } from "path";
6168
6886
  import { homedir as homedir3 } from "os";
6169
6887
  import "open";
6170
6888
  import http from "http";
@@ -6194,8 +6912,8 @@ var PERSONAL_DOMAINS = [
6194
6912
  "tutanota.com",
6195
6913
  "hey.com"
6196
6914
  ];
6197
- var AUTH_DIR = join11(homedir3(), ".squads-cli");
6198
- var AUTH_PATH = join11(AUTH_DIR, "auth.json");
6915
+ var AUTH_DIR = join13(homedir3(), ".squads-cli");
6916
+ var AUTH_PATH = join13(AUTH_DIR, "auth.json");
6199
6917
  function isPersonalEmail(email) {
6200
6918
  const domain = email.split("@")[1]?.toLowerCase();
6201
6919
  return PERSONAL_DOMAINS.includes(domain);
@@ -6204,22 +6922,22 @@ function getEmailDomain(email) {
6204
6922
  return email.split("@")[1]?.toLowerCase() || "";
6205
6923
  }
6206
6924
  function saveSession(session2) {
6207
- if (!existsSync10(AUTH_DIR)) {
6208
- mkdirSync6(AUTH_DIR, { recursive: true });
6925
+ if (!existsSync12(AUTH_DIR)) {
6926
+ mkdirSync8(AUTH_DIR, { recursive: true });
6209
6927
  }
6210
- writeFileSync7(AUTH_PATH, JSON.stringify(session2, null, 2));
6928
+ writeFileSync9(AUTH_PATH, JSON.stringify(session2, null, 2));
6211
6929
  }
6212
6930
  function loadSession() {
6213
- if (!existsSync10(AUTH_PATH)) return null;
6931
+ if (!existsSync12(AUTH_PATH)) return null;
6214
6932
  try {
6215
- return JSON.parse(readFileSync7(AUTH_PATH, "utf-8"));
6933
+ return JSON.parse(readFileSync9(AUTH_PATH, "utf-8"));
6216
6934
  } catch {
6217
6935
  return null;
6218
6936
  }
6219
6937
  }
6220
6938
  function clearSession() {
6221
- if (existsSync10(AUTH_PATH)) {
6222
- writeFileSync7(AUTH_PATH, "");
6939
+ if (existsSync12(AUTH_PATH)) {
6940
+ writeFileSync9(AUTH_PATH, "");
6223
6941
  }
6224
6942
  }
6225
6943
  function startAuthCallbackServer(port = 54321) {
@@ -6442,25 +7160,25 @@ async function updateCommand(options = {}) {
6442
7160
 
6443
7161
  // src/commands/progress.ts
6444
7162
  import { execSync as execSync8 } from "child_process";
6445
- import { existsSync as existsSync11, readFileSync as readFileSync8, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7 } from "fs";
6446
- import { join as join12 } from "path";
7163
+ import { existsSync as existsSync13, readFileSync as readFileSync10, writeFileSync as writeFileSync10, mkdirSync as mkdirSync9 } from "fs";
7164
+ import { join as join14 } from "path";
6447
7165
  function getTasksFilePath() {
6448
7166
  const memoryDir = findMemoryDir();
6449
7167
  if (!memoryDir) {
6450
7168
  const cwd = process.cwd();
6451
- const agentsDir = join12(cwd, ".agents");
6452
- if (!existsSync11(agentsDir)) {
6453
- mkdirSync7(agentsDir, { recursive: true });
7169
+ const agentsDir = join14(cwd, ".agents");
7170
+ if (!existsSync13(agentsDir)) {
7171
+ mkdirSync9(agentsDir, { recursive: true });
6454
7172
  }
6455
- return join12(agentsDir, "tasks.json");
7173
+ return join14(agentsDir, "tasks.json");
6456
7174
  }
6457
- return join12(memoryDir, "..", "tasks.json");
7175
+ return join14(memoryDir, "..", "tasks.json");
6458
7176
  }
6459
7177
  function loadTasks() {
6460
7178
  const tasksPath = getTasksFilePath();
6461
- if (existsSync11(tasksPath)) {
7179
+ if (existsSync13(tasksPath)) {
6462
7180
  try {
6463
- return JSON.parse(readFileSync8(tasksPath, "utf-8"));
7181
+ return JSON.parse(readFileSync10(tasksPath, "utf-8"));
6464
7182
  } catch {
6465
7183
  return { tasks: [], lastUpdated: (/* @__PURE__ */ new Date()).toISOString() };
6466
7184
  }
@@ -6470,7 +7188,7 @@ function loadTasks() {
6470
7188
  function saveTasks(data) {
6471
7189
  const tasksPath = getTasksFilePath();
6472
7190
  data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
6473
- writeFileSync8(tasksPath, JSON.stringify(data, null, 2));
7191
+ writeFileSync10(tasksPath, JSON.stringify(data, null, 2));
6474
7192
  }
6475
7193
  function getRecentActivity() {
6476
7194
  const activity = [];
@@ -6822,8 +7540,8 @@ async function resultsCommand(options = {}) {
6822
7540
  }
6823
7541
 
6824
7542
  // src/commands/history.ts
6825
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
6826
- import { join as join13 } from "path";
7543
+ import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
7544
+ import { join as join15 } from "path";
6827
7545
  var BRIDGE_URL2 = process.env.SQUADS_BRIDGE_URL || "http://localhost:8088";
6828
7546
  var FETCH_TIMEOUT_MS2 = 3e3;
6829
7547
  async function fetchWithTimeout2(url, timeoutMs = FETCH_TIMEOUT_MS2) {
@@ -6868,12 +7586,12 @@ async function fetchFromBridge2(days, squad) {
6868
7586
  function fetchFromLocal(days, squad) {
6869
7587
  const executions = [];
6870
7588
  const historyPaths = [
6871
- join13(process.cwd(), ".agents/sessions/history.jsonl"),
6872
- join13(process.env.HOME || "", "agents-squads/hq/.agents/sessions/history.jsonl")
7589
+ join15(process.cwd(), ".agents/sessions/history.jsonl"),
7590
+ join15(process.env.HOME || "", "agents-squads/hq/.agents/sessions/history.jsonl")
6873
7591
  ];
6874
7592
  let historyPath;
6875
7593
  for (const path3 of historyPaths) {
6876
- if (existsSync12(path3)) {
7594
+ if (existsSync14(path3)) {
6877
7595
  historyPath = path3;
6878
7596
  break;
6879
7597
  }
@@ -6882,7 +7600,7 @@ function fetchFromLocal(days, squad) {
6882
7600
  return [];
6883
7601
  }
6884
7602
  try {
6885
- const content = readFileSync9(historyPath, "utf-8");
7603
+ const content = readFileSync11(historyPath, "utf-8");
6886
7604
  const lines = content.trim().split("\n").filter(Boolean);
6887
7605
  const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
6888
7606
  for (const line of lines) {
@@ -7219,18 +7937,18 @@ async function healthCommand(options = {}) {
7219
7937
 
7220
7938
  // src/commands/workers.ts
7221
7939
  import { execSync as execSync10 } from "child_process";
7222
- import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
7223
- import { join as join14 } from "path";
7940
+ import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
7941
+ import { join as join16 } from "path";
7224
7942
  function getTasksFilePath2() {
7225
7943
  const memoryDir = findMemoryDir();
7226
7944
  if (!memoryDir) return null;
7227
- return join14(memoryDir, "..", "tasks.json");
7945
+ return join16(memoryDir, "..", "tasks.json");
7228
7946
  }
7229
7947
  function loadActiveTasks() {
7230
7948
  const tasksPath = getTasksFilePath2();
7231
- if (!tasksPath || !existsSync13(tasksPath)) return [];
7949
+ if (!tasksPath || !existsSync15(tasksPath)) return [];
7232
7950
  try {
7233
- const data = JSON.parse(readFileSync10(tasksPath, "utf-8"));
7951
+ const data = JSON.parse(readFileSync12(tasksPath, "utf-8"));
7234
7952
  return data.tasks?.filter((t) => t.status === "active") || [];
7235
7953
  } catch {
7236
7954
  return [];
@@ -7377,8 +8095,8 @@ function getElapsedTime2(startTime) {
7377
8095
  }
7378
8096
 
7379
8097
  // src/commands/context-feed.ts
7380
- import { existsSync as existsSync14, statSync as statSync3, readdirSync as readdirSync6, readFileSync as readFileSync11 } from "fs";
7381
- import { join as join15 } from "path";
8098
+ import { existsSync as existsSync16, statSync as statSync3, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "fs";
8099
+ import { join as join17 } from "path";
7382
8100
  var BRIDGE_URL3 = process.env.SQUADS_BRIDGE_URL || "http://localhost:8088";
7383
8101
  async function syncBriefToBridge(brief, sourcePath) {
7384
8102
  try {
@@ -7407,10 +8125,10 @@ async function syncBriefToBridge(brief, sourcePath) {
7407
8125
  }
7408
8126
  function readBusinessBrief(squadsDir) {
7409
8127
  if (!squadsDir) return void 0;
7410
- const briefPath = join15(squadsDir, "..", "BUSINESS_BRIEF.md");
7411
- if (!existsSync14(briefPath)) return void 0;
8128
+ const briefPath = join17(squadsDir, "..", "BUSINESS_BRIEF.md");
8129
+ if (!existsSync16(briefPath)) return void 0;
7412
8130
  try {
7413
- const content = readFileSync11(briefPath, "utf-8");
8131
+ const content = readFileSync13(briefPath, "utf-8");
7414
8132
  const brief = { raw: content };
7415
8133
  const priorityMatch = content.match(/##\s*#1 Priority\s*\n+\*\*([^*]+)\*\*/);
7416
8134
  if (priorityMatch) {
@@ -7460,7 +8178,7 @@ function readBusinessBrief(squadsDir) {
7460
8178
  async function collectBriefingData(options) {
7461
8179
  const squadsDir = findSquadsDir();
7462
8180
  const memoryDir = findMemoryDir();
7463
- const baseDir = squadsDir ? join15(squadsDir, "..", "..", "..") : null;
8181
+ const baseDir = squadsDir ? join17(squadsDir, "..", "..", "..") : null;
7464
8182
  const allSquads = squadsDir ? listSquads(squadsDir) : [];
7465
8183
  if (options.squad && !allSquads.includes(options.squad)) {
7466
8184
  return {
@@ -7500,14 +8218,14 @@ async function collectBriefingData(options) {
7500
8218
  }
7501
8219
  let lastActivity;
7502
8220
  if (memoryDir) {
7503
- const squadMemoryPath = join15(memoryDir, squadName);
7504
- if (existsSync14(squadMemoryPath)) {
8221
+ const squadMemoryPath = join17(memoryDir, squadName);
8222
+ if (existsSync16(squadMemoryPath)) {
7505
8223
  let mostRecent = 0;
7506
8224
  try {
7507
8225
  const walkDir = (dir) => {
7508
8226
  const entries = readdirSync6(dir, { withFileTypes: true });
7509
8227
  for (const entry of entries) {
7510
- const fullPath = join15(dir, entry.name);
8228
+ const fullPath = join17(dir, entry.name);
7511
8229
  if (entry.isDirectory()) {
7512
8230
  walkDir(fullPath);
7513
8231
  } else if (entry.name.endsWith(".md")) {
@@ -7587,7 +8305,7 @@ async function collectBriefingData(options) {
7587
8305
  }
7588
8306
  const brief = readBusinessBrief(squadsDir);
7589
8307
  if (brief && squadsDir) {
7590
- const briefPath = join15(squadsDir, "..", "BUSINESS_BRIEF.md");
8308
+ const briefPath = join17(squadsDir, "..", "BUSINESS_BRIEF.md");
7591
8309
  syncBriefToBridge(brief, briefPath).catch(() => {
7592
8310
  });
7593
8311
  }
@@ -8139,7 +8857,7 @@ async function detectSquadCommand() {
8139
8857
 
8140
8858
  // src/commands/trigger.ts
8141
8859
  import chalk3 from "chalk";
8142
- import { existsSync as existsSync15 } from "fs";
8860
+ import { existsSync as existsSync17 } from "fs";
8143
8861
  var SCHEDULER_URL = process.env.SCHEDULER_URL || "http://localhost:8090";
8144
8862
  async function fetchScheduler(path3, options) {
8145
8863
  const res = await fetch(`${SCHEDULER_URL}${path3}`, {
@@ -8189,7 +8907,7 @@ async function syncTriggers() {
8189
8907
  const hqPath = process.env.HQ_PATH || `${process.env.HOME}/agents-squads/hq`;
8190
8908
  try {
8191
8909
  const venvPython = `${hqPath}/squads-scheduler/.venv/bin/python`;
8192
- const pythonCmd = existsSync15(venvPython) ? venvPython : "python3";
8910
+ const pythonCmd = existsSync17(venvPython) ? venvPython : "python3";
8193
8911
  const output = execSync14(
8194
8912
  `${pythonCmd} ${hqPath}/squads-scheduler/sync_triggers.py`,
8195
8913
  { encoding: "utf-8", cwd: hqPath }
@@ -8273,13 +8991,13 @@ function registerTriggerCommand(program2) {
8273
8991
 
8274
8992
  // src/commands/skill.ts
8275
8993
  import ora6 from "ora";
8276
- import { existsSync as existsSync16, mkdirSync as mkdirSync8, writeFileSync as writeFileSync9, readFileSync as readFileSync13 } from "fs";
8277
- import { join as join17, basename as basename2, dirname as dirname4 } from "path";
8994
+ import { existsSync as existsSync18, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, readFileSync as readFileSync15 } from "fs";
8995
+ import { join as join19, basename as basename2, dirname as dirname6 } from "path";
8278
8996
 
8279
8997
  // src/lib/anthropic.ts
8280
8998
  import Anthropic from "@anthropic-ai/sdk";
8281
- import { readFileSync as readFileSync12, readdirSync as readdirSync7 } from "fs";
8282
- import { join as join16 } from "path";
8999
+ import { readFileSync as readFileSync14, readdirSync as readdirSync7 } from "fs";
9000
+ import { join as join18 } from "path";
8283
9001
  var client = null;
8284
9002
  function getClient() {
8285
9003
  if (!client) {
@@ -8308,12 +9026,12 @@ function loadSkillFiles(skillPath) {
8308
9026
  function walkDir(dir, prefix = "") {
8309
9027
  const entries = readdirSync7(dir, { withFileTypes: true });
8310
9028
  for (const entry of entries) {
8311
- const fullPath = join16(dir, entry.name);
9029
+ const fullPath = join18(dir, entry.name);
8312
9030
  const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
8313
9031
  if (entry.isDirectory()) {
8314
9032
  walkDir(fullPath, relativePath);
8315
9033
  } else if (entry.isFile()) {
8316
- const content = readFileSync12(fullPath, "utf-8");
9034
+ const content = readFileSync14(fullPath, "utf-8");
8317
9035
  files.push({
8318
9036
  name: relativePath,
8319
9037
  content
@@ -8477,14 +9195,14 @@ async function skillUploadCommand(skillPath) {
8477
9195
  writeLine();
8478
9196
  return;
8479
9197
  }
8480
- const fullPath = skillPath.startsWith("/") ? skillPath : join17(process.cwd(), skillPath);
8481
- if (!existsSync16(fullPath)) {
9198
+ const fullPath = skillPath.startsWith("/") ? skillPath : join19(process.cwd(), skillPath);
9199
+ if (!existsSync18(fullPath)) {
8482
9200
  writeLine(` ${icons.error} ${colors.red}Directory not found: ${skillPath}${RESET}`);
8483
9201
  writeLine();
8484
9202
  return;
8485
9203
  }
8486
- const skillMdPath = join17(fullPath, "SKILL.md");
8487
- if (!existsSync16(skillMdPath)) {
9204
+ const skillMdPath = join19(fullPath, "SKILL.md");
9205
+ if (!existsSync18(skillMdPath)) {
8488
9206
  writeLine(` ${icons.error} ${colors.red}SKILL.md not found in ${skillPath}${RESET}`);
8489
9207
  writeLine();
8490
9208
  writeLine(` ${colors.dim}Create a SKILL.md file or use:${RESET}`);
@@ -8595,7 +9313,7 @@ async function skillConvertCommand(agentPath, options) {
8595
9313
  const [squad, agent] = agentPath.split("/");
8596
9314
  squadName = squad;
8597
9315
  agentName = agent.replace(".md", "");
8598
- agentFilePath = join17(squadsDir, squad, `${agentName}.md`);
9316
+ agentFilePath = join19(squadsDir, squad, `${agentName}.md`);
8599
9317
  } else {
8600
9318
  agentName = agentPath.replace(".md", "");
8601
9319
  const foundPath = findAgentFile(squadsDir, agentName);
@@ -8606,22 +9324,22 @@ async function skillConvertCommand(agentPath, options) {
8606
9324
  return;
8607
9325
  }
8608
9326
  agentFilePath = foundPath;
8609
- squadName = basename2(dirname4(agentFilePath));
9327
+ squadName = basename2(dirname6(agentFilePath));
8610
9328
  }
8611
- if (!existsSync16(agentFilePath)) {
9329
+ if (!existsSync18(agentFilePath)) {
8612
9330
  writeLine(` ${icons.error} ${colors.red}Agent file not found: ${agentFilePath}${RESET}`);
8613
9331
  writeLine();
8614
9332
  return;
8615
9333
  }
8616
- const agentContent = readFileSync13(agentFilePath, "utf-8");
9334
+ const agentContent = readFileSync15(agentFilePath, "utf-8");
8617
9335
  const skillName = `${squadName}-${agentName}`;
8618
- const outputDir = options.output || join17(dirname4(squadsDir), "skills", skillName);
8619
- if (!existsSync16(outputDir)) {
8620
- mkdirSync8(outputDir, { recursive: true });
9336
+ const outputDir = options.output || join19(dirname6(squadsDir), "skills", skillName);
9337
+ if (!existsSync18(outputDir)) {
9338
+ mkdirSync10(outputDir, { recursive: true });
8621
9339
  }
8622
9340
  const skillMd = convertAgentToSkill(agentContent, squadName, agentName);
8623
- const skillMdPath = join17(outputDir, "SKILL.md");
8624
- writeFileSync9(skillMdPath, skillMd);
9341
+ const skillMdPath = join19(outputDir, "SKILL.md");
9342
+ writeFileSync11(skillMdPath, skillMd);
8625
9343
  writeLine(` ${icons.success} ${colors.green}Converted:${RESET} ${agentPath}`);
8626
9344
  writeLine();
8627
9345
  writeLine(` ${colors.dim}Output:${RESET} ${outputDir}`);
@@ -8638,8 +9356,8 @@ function findAgentFile(squadsDir, agentName) {
8638
9356
  const { readdirSync: readdirSync9 } = __require("fs");
8639
9357
  const squads = readdirSync9(squadsDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("_")).map((d) => d.name);
8640
9358
  for (const squad of squads) {
8641
- const agentPath = join17(squadsDir, squad, `${agentName}.md`);
8642
- if (existsSync16(agentPath)) {
9359
+ const agentPath = join19(squadsDir, squad, `${agentName}.md`);
9360
+ if (existsSync18(agentPath)) {
8643
9361
  return agentPath;
8644
9362
  }
8645
9363
  }
@@ -8680,8 +9398,8 @@ function formatBytes(bytes) {
8680
9398
  }
8681
9399
 
8682
9400
  // src/commands/permissions.ts
8683
- import { readFileSync as readFileSync14 } from "fs";
8684
- import { join as join18 } from "path";
9401
+ import { readFileSync as readFileSync16 } from "fs";
9402
+ import { join as join20 } from "path";
8685
9403
  function registerPermissionsCommand(program2) {
8686
9404
  const permissions = program2.command("permissions").alias("perms").description("Manage and validate squad permissions");
8687
9405
  permissions.command("show <squad>").description("Show permission context for a squad").action(permissionsShowCommand);
@@ -8703,11 +9421,11 @@ async function permissionsShowCommand(squadName) {
8703
9421
  writeLine();
8704
9422
  return;
8705
9423
  }
8706
- const squadFilePath = join18(squadsDir, squadName, "SQUAD.md");
8707
- const squadContent = readFileSync14(squadFilePath, "utf-8");
8708
- const context2 = buildContextFromSquad(squadName, squadContent);
9424
+ const squadFilePath = join20(squadsDir, squadName, "SQUAD.md");
9425
+ const squadContent = readFileSync16(squadFilePath, "utf-8");
9426
+ const context = buildContextFromSquad(squadName, squadContent);
8709
9427
  const defaults = getDefaultContext(squadName);
8710
- const isDefault = JSON.stringify(context2.permissions) === JSON.stringify(defaults.permissions);
9428
+ const isDefault = JSON.stringify(context.permissions) === JSON.stringify(defaults.permissions);
8711
9429
  writeLine(` ${bold}Squad:${RESET} ${squadName}`);
8712
9430
  if (squad.mission) {
8713
9431
  writeLine(` ${colors.dim}${squad.mission}${RESET}`);
@@ -8718,47 +9436,47 @@ async function permissionsShowCommand(squadName) {
8718
9436
  writeLine(` ${colors.dim}Add a permissions block to SQUAD.md to restrict access.${RESET}`);
8719
9437
  writeLine();
8720
9438
  }
8721
- writeLine(` ${bold}Mode:${RESET} ${formatMode(context2.permissions.mode)}`);
9439
+ writeLine(` ${bold}Mode:${RESET} ${formatMode(context.permissions.mode)}`);
8722
9440
  writeLine();
8723
9441
  writeLine(` ${bold}Bash Commands:${RESET}`);
8724
- if (context2.permissions.bash.includes("*")) {
9442
+ if (context.permissions.bash.includes("*")) {
8725
9443
  writeLine(` ${colors.dim}All commands allowed (*)${RESET}`);
8726
9444
  } else {
8727
- for (const cmd of context2.permissions.bash) {
9445
+ for (const cmd of context.permissions.bash) {
8728
9446
  writeLine(` ${icons.active} ${cmd}`);
8729
9447
  }
8730
9448
  }
8731
9449
  writeLine();
8732
9450
  writeLine(` ${bold}Write Paths:${RESET}`);
8733
- if (context2.permissions.write.includes("**") || context2.permissions.write.includes("*")) {
9451
+ if (context.permissions.write.includes("**") || context.permissions.write.includes("*")) {
8734
9452
  writeLine(` ${colors.dim}All paths writable (**)${RESET}`);
8735
9453
  } else {
8736
- for (const path3 of context2.permissions.write) {
9454
+ for (const path3 of context.permissions.write) {
8737
9455
  writeLine(` ${icons.active} ${path3}`);
8738
9456
  }
8739
9457
  }
8740
9458
  writeLine();
8741
9459
  writeLine(` ${bold}Read Paths:${RESET}`);
8742
- if (context2.permissions.read.includes("**") || context2.permissions.read.includes("*")) {
9460
+ if (context.permissions.read.includes("**") || context.permissions.read.includes("*")) {
8743
9461
  writeLine(` ${colors.dim}All paths readable (**)${RESET}`);
8744
9462
  } else {
8745
- for (const path3 of context2.permissions.read) {
9463
+ for (const path3 of context.permissions.read) {
8746
9464
  writeLine(` ${icons.active} ${path3}`);
8747
9465
  }
8748
9466
  }
8749
9467
  writeLine();
8750
9468
  writeLine(` ${bold}MCP Servers:${RESET}`);
8751
- if (context2.permissions.mcp.allow.includes("*")) {
9469
+ if (context.permissions.mcp.allow.includes("*")) {
8752
9470
  writeLine(` ${colors.dim}All servers allowed (*)${RESET}`);
8753
9471
  } else {
8754
9472
  writeLine(` ${colors.green}Allow:${RESET}`);
8755
- for (const server of context2.permissions.mcp.allow) {
9473
+ for (const server of context.permissions.mcp.allow) {
8756
9474
  writeLine(` ${icons.success} ${server}`);
8757
9475
  }
8758
9476
  }
8759
- if (context2.permissions.mcp.deny.length > 0) {
9477
+ if (context.permissions.mcp.deny.length > 0) {
8760
9478
  writeLine(` ${colors.red}Deny:${RESET}`);
8761
- for (const server of context2.permissions.mcp.deny) {
9479
+ for (const server of context.permissions.mcp.deny) {
8762
9480
  writeLine(` ${icons.error} ${server}`);
8763
9481
  }
8764
9482
  }
@@ -8798,9 +9516,9 @@ async function permissionsCheckCommand(squadName, options) {
8798
9516
  writeLine();
8799
9517
  return;
8800
9518
  }
8801
- const squadFilePath = join18(squadsDir, squadName, "SQUAD.md");
8802
- const squadContent = readFileSync14(squadFilePath, "utf-8");
8803
- const context2 = buildContextFromSquad(squadName, squadContent, options.agent);
9519
+ const squadFilePath = join20(squadsDir, squadName, "SQUAD.md");
9520
+ const squadContent = readFileSync16(squadFilePath, "utf-8");
9521
+ const context = buildContextFromSquad(squadName, squadContent, options.agent);
8804
9522
  const request = {
8805
9523
  mcpServers: options.mcp,
8806
9524
  bashCommands: options.bash,
@@ -8817,7 +9535,7 @@ async function permissionsCheckCommand(squadName, options) {
8817
9535
  writeLine();
8818
9536
  return;
8819
9537
  }
8820
- const result = validateExecution(context2, request);
9538
+ const result = validateExecution(context, request);
8821
9539
  if (result.violations.length === 0) {
8822
9540
  writeLine(` ${icons.success} ${colors.green}All permissions valid${RESET}`);
8823
9541
  writeLine();
@@ -8986,6 +9704,77 @@ async function contextListCommand(options = {}) {
8986
9704
  writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);
8987
9705
  writeLine();
8988
9706
  }
9707
+ async function contextActivateCommand(squadName, options = {}) {
9708
+ await track(Events.CLI_CONTEXT, { squad: squadName, action: "activate" });
9709
+ const squadsDir = findSquadsDir();
9710
+ if (!squadsDir) {
9711
+ writeLine(`${colors.red}No .agents/squads directory found${RESET}`);
9712
+ process.exit(1);
9713
+ }
9714
+ const squad = loadSquad(squadName);
9715
+ if (!squad) {
9716
+ writeLine(`${colors.red}Squad "${squadName}" not found.${RESET}`);
9717
+ process.exit(1);
9718
+ }
9719
+ const execContext = resolveExecutionContext(squad, options.force);
9720
+ if (options.json) {
9721
+ console.log(JSON.stringify(execContext, null, 2));
9722
+ return;
9723
+ }
9724
+ if (options.dryRun) {
9725
+ writeLine();
9726
+ writeLine(` ${gradient("squads")} ${colors.dim}context activate${RESET} ${colors.cyan}${squadName}${RESET} ${colors.yellow}(dry run)${RESET}`);
9727
+ writeLine();
9728
+ writeLine(` ${colors.dim}Would resolve:${RESET}`);
9729
+ writeLine();
9730
+ writeLine(` ${bold}MCP Config${RESET}`);
9731
+ writeLine(` Path: ${execContext.resolved.mcpConfigPath}`);
9732
+ writeLine(` Source: ${execContext.resolved.mcpSource}`);
9733
+ if (execContext.resolved.mcpServers.length > 0) {
9734
+ writeLine(` Servers: ${execContext.resolved.mcpServers.join(", ")}`);
9735
+ }
9736
+ if (execContext.resolved.skillPaths.length > 0) {
9737
+ writeLine();
9738
+ writeLine(` ${bold}Skills${RESET}`);
9739
+ for (const path3 of execContext.resolved.skillPaths) {
9740
+ writeLine(` ${colors.dim}${path3}${RESET}`);
9741
+ }
9742
+ }
9743
+ if (execContext.resolved.memoryPaths.length > 0) {
9744
+ writeLine();
9745
+ writeLine(` ${bold}Memory${RESET}`);
9746
+ for (const path3 of execContext.resolved.memoryPaths) {
9747
+ writeLine(` ${colors.dim}${path3}${RESET}`);
9748
+ }
9749
+ }
9750
+ writeLine();
9751
+ writeLine(` ${colors.dim}Run without --dry-run to generate config${RESET}`);
9752
+ writeLine();
9753
+ return;
9754
+ }
9755
+ writeLine();
9756
+ writeLine(` ${gradient("squads")} ${colors.dim}context activate${RESET} ${colors.cyan}${squadName}${RESET}`);
9757
+ writeLine();
9758
+ const sourceLabel = execContext.resolved.mcpSource === "generated" ? `${colors.green}generated${RESET}` : execContext.resolved.mcpSource === "user-override" ? `${colors.cyan}user override${RESET}` : `${colors.dim}fallback${RESET}`;
9759
+ writeLine(` ${icons.success} MCP config: ${sourceLabel}`);
9760
+ writeLine(` ${colors.dim}${execContext.resolved.mcpConfigPath}${RESET}`);
9761
+ if (execContext.resolved.mcpServers.length > 0) {
9762
+ writeLine(` ${colors.dim}Servers: ${execContext.resolved.mcpServers.join(", ")}${RESET}`);
9763
+ }
9764
+ if (execContext.resolved.skillPaths.length > 0) {
9765
+ writeLine(` ${icons.success} Skills: ${execContext.resolved.skillPaths.length} resolved`);
9766
+ }
9767
+ if (execContext.resolved.memoryPaths.length > 0) {
9768
+ writeLine(` ${icons.success} Memory: ${execContext.resolved.memoryPaths.length} files`);
9769
+ }
9770
+ writeLine();
9771
+ writeLine(` ${colors.dim}To use this context manually:${RESET}`);
9772
+ writeLine(` ${colors.dim}$${RESET} claude --mcp-config '${execContext.resolved.mcpConfigPath}'`);
9773
+ writeLine();
9774
+ writeLine(` ${colors.dim}Or run with squads:${RESET}`);
9775
+ writeLine(` ${colors.dim}$${RESET} squads run ${colors.cyan}${squadName}${RESET}`);
9776
+ writeLine();
9777
+ }
8989
9778
 
8990
9779
  // src/commands/cost.ts
8991
9780
  function getBudgetStatus(squadName, spent, dailyBudget, weeklyBudget) {
@@ -9232,8 +10021,8 @@ function createBudgetBar(percent, width = 10) {
9232
10021
  }
9233
10022
 
9234
10023
  // src/lib/executions.ts
9235
- import { readFileSync as readFileSync15, existsSync as existsSync17, readdirSync as readdirSync8 } from "fs";
9236
- import { join as join19 } from "path";
10024
+ import { readFileSync as readFileSync17, existsSync as existsSync19, readdirSync as readdirSync8 } from "fs";
10025
+ import { join as join21 } from "path";
9237
10026
  function parseExecutionEntry(content, squad, agent) {
9238
10027
  const idMatch = content.match(/<!-- exec:(\S+) -->/);
9239
10028
  if (!idMatch) return null;
@@ -9271,8 +10060,8 @@ function parseExecutionEntry(content, squad, agent) {
9271
10060
  };
9272
10061
  }
9273
10062
  function parseExecutionLog(filePath, squad, agent) {
9274
- if (!existsSync17(filePath)) return [];
9275
- const content = readFileSync15(filePath, "utf-8");
10063
+ if (!existsSync19(filePath)) return [];
10064
+ const content = readFileSync17(filePath, "utf-8");
9276
10065
  const executions = [];
9277
10066
  const entries = content.split(/\n---\n/);
9278
10067
  for (const entry of entries) {
@@ -9310,11 +10099,11 @@ function listExecutions(options = {}) {
9310
10099
  const squads = readdirSync8(memoryDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
9311
10100
  for (const squad of squads) {
9312
10101
  if (filterSquad && squad !== filterSquad) continue;
9313
- const squadPath = join19(memoryDir, squad);
10102
+ const squadPath = join21(memoryDir, squad);
9314
10103
  const agents = readdirSync8(squadPath, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
9315
10104
  for (const agent of agents) {
9316
10105
  if (filterAgent && agent !== filterAgent) continue;
9317
- const logPath = join19(squadPath, agent, "executions.md");
10106
+ const logPath = join21(squadPath, agent, "executions.md");
9318
10107
  const agentExecutions = parseExecutionLog(logPath, squad, agent);
9319
10108
  executions.push(...agentExecutions);
9320
10109
  }
@@ -9564,12 +10353,12 @@ async function execStatsCommand(options = {}) {
9564
10353
  // src/commands/tonight.ts
9565
10354
  import ora7 from "ora";
9566
10355
  import fs2 from "fs/promises";
9567
- import path2, { dirname as dirname5 } from "path";
10356
+ import path2, { dirname as dirname7 } from "path";
9568
10357
  import { execSync as execSync13, spawn as spawn7 } from "child_process";
9569
10358
  function getProjectRoot2() {
9570
10359
  const squadsDir = findSquadsDir();
9571
10360
  if (squadsDir) {
9572
- return dirname5(dirname5(squadsDir));
10361
+ return dirname7(dirname7(squadsDir));
9573
10362
  }
9574
10363
  return process.cwd();
9575
10364
  }
@@ -9612,6 +10401,7 @@ function launchAgent(target, projectRoot, sessionId, logFile) {
9612
10401
  const sessionName = `squads-tonight-${sessionId}`;
9613
10402
  const claudeCmd = [
9614
10403
  `cd '${projectRoot}'`,
10404
+ `unset ANTHROPIC_API_KEY`,
9615
10405
  `echo "=== Tonight Session: ${target} ===" >> '${logFile}'`,
9616
10406
  `echo "Started: $(date)" >> '${logFile}'`,
9617
10407
  `claude --dangerously-skip-permissions -p 'You are running as part of an overnight autonomous session. Execute your tasks efficiently. If you encounter errors, document them clearly and move on. Do not ask for user input.' -- "Run squad: ${target}" 2>&1 | tee -a '${logFile}'`,
@@ -9897,12 +10687,12 @@ process.stderr.on("error", (err) => {
9897
10687
  throw err;
9898
10688
  });
9899
10689
  var envPaths = [
9900
- join20(process.cwd(), ".env"),
9901
- join20(process.cwd(), "..", "hq", ".env"),
9902
- join20(homedir4(), "agents-squads", "hq", ".env")
10690
+ join22(process.cwd(), ".env"),
10691
+ join22(process.cwd(), "..", "hq", ".env"),
10692
+ join22(homedir4(), "agents-squads", "hq", ".env")
9903
10693
  ];
9904
10694
  for (const envPath of envPaths) {
9905
- if (existsSync18(envPath)) {
10695
+ if (existsSync20(envPath)) {
9906
10696
  config({ path: envPath, quiet: true });
9907
10697
  break;
9908
10698
  }
@@ -9935,14 +10725,25 @@ program.name("squads").description("A CLI for humans and agents").version(versio
9935
10725
  }
9936
10726
  await statusCommand(void 0, {});
9937
10727
  });
9938
- program.command("init").description("Initialize a new squad project").option("-t, --template <template>", "Project template", "default").option("--skip-infra", "Skip infrastructure setup prompt").action(initCommand);
9939
- program.command("run <target>").description("Run a squad or agent").option("-v, --verbose", "Verbose output").option("-d, --dry-run", "Show what would be run without executing").option("-e, --execute", "Execute agent via Claude CLI (requires claude installed)").option("-a, --agent <agent>", "Run specific agent within squad").option("-t, --timeout <minutes>", "Execution timeout in minutes (default: 30)", "30").option("-p, --parallel", "Run all agents in parallel (N tmux sessions)").option("-l, --lead", "Lead mode: single orchestrator using Task tool for parallelization").option("-f, --foreground", "Run in foreground (no tmux, blocks terminal)").option("--use-api", "Use API credits instead of subscription").option("--effort <level>", "Effort level: high, medium, low (default: from SQUAD.md or high)").option("--skills <skills...>", "Skills to load (skill IDs or local paths)").action((target, options) => runCommand(target, { ...options, timeout: parseInt(options.timeout, 10) }));
9940
- program.command("list").description("List agents and squads").option("-s, --squads", "List squads only").option("-a, --agents", "List agents only").action(listCommand);
10728
+ program.command("init").description("Initialize a new squad project").option("-t, --template <template>", "Project template", "default").option("--skip-infra", "Skip infrastructure setup prompt").option("--force", "Skip requirement checks (for CI/testing)").action(initCommand);
10729
+ program.command("run <target>").description("Run a squad or agent").option("-v, --verbose", "Verbose output").option("-d, --dry-run", "Show what would be run without executing").option("-e, --execute", "Execute agent via Claude CLI (requires claude installed)").option("-a, --agent <agent>", "Run specific agent within squad").option("-t, --timeout <minutes>", "Execution timeout in minutes (default: 30)", "30").option("-p, --parallel", "Run all agents in parallel (N tmux sessions)").option("-l, --lead", "Lead mode: single orchestrator using Task tool for parallelization").option("-f, --foreground", "Run in foreground (no tmux, blocks terminal)").option("--use-api", "Use API credits instead of subscription").option("--effort <level>", "Effort level: high, medium, low (default: from SQUAD.md or high)").option("--skills <skills...>", "Skills to load (skill IDs or local paths)").addHelpText("after", `
10730
+ Examples:
10731
+ $ squads run engineering Run whole squad (shows agent list)
10732
+ $ squads run engineering/code-review Run specific agent (slash notation)
10733
+ $ squads run engineering -a code-review Same as above (flag notation)
10734
+ $ squads run engineering --dry-run Preview what would run
10735
+ $ squads run engineering --execute Execute via Claude CLI
10736
+ $ squads run engineering --parallel Run all agents in parallel (tmux)
10737
+ $ squads run engineering --lead Single orchestrator with Task tool
10738
+ $ squads run engineering -f Run in foreground (blocks terminal)
10739
+ `).action((target, options) => runCommand(target, { ...options, timeout: parseInt(options.timeout, 10) }));
10740
+ program.command("list").description("List agents and squads").option("-s, --squads", "List squads only").option("-a, --agents", "List agents only").option("-v, --verbose", "Show additional details").action(listCommand);
9941
10741
  program.command("status [squad]").description("Show squad status and state").option("-v, --verbose", "Show detailed status").action(statusCommand);
9942
10742
  program.command("dashboard").alias("dash").description("Show comprehensive goals and metrics dashboard").option("-v, --verbose", "Show additional details").option("-c, --ceo", "Executive summary with priorities and blockers").option("-f, --full", "Include GitHub PR/issue stats (slower, ~30s)").action((options) => dashboardCommand({ ...options, fast: !options.full }));
9943
- var context = program.command("context").description("View and manage squad execution context");
9944
- context.command("show <squad>").description("Show context for a squad (MCP, skills, model, budget)").option("--json", "Output as JSON").action(contextShowCommand);
9945
- context.command("list").description("List context for all squads").option("--json", "Output as JSON").action(contextListCommand);
10743
+ var env = program.command("env").description("View squad execution environment (MCP, skills, model, budget)");
10744
+ env.command("show <squad>").description("Show execution environment for a squad").option("--json", "Output as JSON").action(contextShowCommand);
10745
+ env.command("list").description("List execution environment for all squads").option("--json", "Output as JSON").action(contextListCommand);
10746
+ env.command("activate <squad>").description("Activate execution context for a squad (generates scoped MCP config)").option("-d, --dry-run", "Show what would be generated without writing files").option("-f, --force", "Force regeneration even if config exists").option("--json", "Output as JSON").action(contextActivateCommand);
9946
10747
  program.command("cost").description("Show cost summary (today, week, by squad)").option("-s, --squad <squad>", "Filter to specific squad").option("--json", "Output as JSON").action(costCommand);
9947
10748
  program.command("budget").description("Check budget status for a squad").argument("<squad>", "Squad to check").option("--json", "Output as JSON").action(budgetCheckCommand);
9948
10749
  var exec2 = program.command("exec").description("View execution history and statistics");
@@ -9958,7 +10759,7 @@ progress.command("start <squad> <description>").description("Register a new acti
9958
10759
  progress.command("complete <taskId>").description("Mark a task as completed").option("-f, --failed", "Mark as failed instead").action(progressCompleteCommand);
9959
10760
  program.command("results [squad]").description("Show squad results: git activity + KPI goals vs actuals").option("-d, --days <days>", "Days to look back", "7").option("-v, --verbose", "Show detailed KPIs per goal").action((squad, options) => resultsCommand({ ...options, squad }));
9960
10761
  program.command("history").description("Show recent agent execution history").option("-d, --days <days>", "Days to look back", "7").option("-s, --squad <squad>", "Filter by squad").option("-v, --verbose", "Show cost and token details").option("-j, --json", "Output as JSON").action((options) => historyCommand(options));
9961
- program.command("context-feed").alias("feed").description("Context feed for agents: goals, memory, costs, activity").option("-s, --squad <squad>", "Focus on specific squad").option("-t, --topic <topic>", "Search memory for relevant context").option("-a, --agent", "Output JSON for agent consumption").option("-j, --json", "Output as JSON (alias for --agent)").option("-v, --verbose", "Show additional details").action((options) => contextFeedCommand(options));
10762
+ program.command("context").alias("feed").description("Get business context for alignment: goals, memory, costs, activity").option("-s, --squad <squad>", "Focus on specific squad").option("-t, --topic <topic>", "Search memory for relevant context").option("-a, --agent", "Output JSON for agent consumption").option("-j, --json", "Output as JSON (alias for --agent)").option("-v, --verbose", "Show additional details").action((options) => contextFeedCommand(options));
9962
10763
  program.command("workers").description("Show active workers: Claude sessions, tasks, dev servers").option("-v, --verbose", "Show more details").option("-k, --kill <pid>", "Kill a process by PID").action(workersCommand);
9963
10764
  program.command("health").description("Quick health check for all infrastructure services").option("-v, --verbose", "Show optional services").action((options) => healthCommand(options));
9964
10765
  program.command("watch <command> [args...]").description("Live refresh any squads command (like Unix watch)").option("-n, --interval <seconds>", "Refresh interval in seconds", "2").option("--no-clear", "Don't clear screen between refreshes").action((command, args, options) => watchCommand(command, args, {
@@ -9967,7 +10768,14 @@ program.command("watch <command> [args...]").description("Live refresh any squad
9967
10768
  }));
9968
10769
  program.command("live").description("Live TUI dashboard with real-time metrics (like htop)").option("-m, --minimal", "Minimal view").option("-f, --focus <panel>", "Focus on specific panel (agents, cost, activity, memory)").action((options) => liveCommand(options));
9969
10770
  program.command("top").description("Live process table (like Unix top) - numbers update in place").action(() => topCommand());
9970
- var memory = program.command("memory").description("Query and manage squad memory").action(() => {
10771
+ var memory = program.command("memory").description("Query and manage squad memory").addHelpText("after", `
10772
+ Examples:
10773
+ $ squads memory query "pricing" Search all memory for "pricing"
10774
+ $ squads memory show engineering View engineering squad's memory
10775
+ $ squads memory update research "Found: MCP adoption at 15%"
10776
+ $ squads memory list List all memory entries
10777
+ $ squads memory sync --push Sync and push to git
10778
+ `).action(() => {
9971
10779
  memory.outputHelp();
9972
10780
  });
9973
10781
  memory.command("query <query>").description("Search across all squad memory").option("-s, --squad <squad>", "Limit search to specific squad").option("-a, --agent <agent>", "Limit search to specific agent").action(memoryQueryCommand);
@@ -9996,6 +10804,10 @@ var feedback = program.command("feedback").description("Record and view executio
9996
10804
  feedback.command("add <squad> <rating> <feedback>").description("Add feedback for last execution (rating 1-5)").option("-l, --learning <learnings...>", "Learnings to extract").action(feedbackAddCommand);
9997
10805
  feedback.command("show <squad>").description("Show feedback history").option("-n, --limit <n>", "Number of entries to show", "5").action(feedbackShowCommand);
9998
10806
  feedback.command("stats").description("Show feedback summary across all squads").action(feedbackStatsCommand);
10807
+ program.command("learn <insight>").description("Capture a learning for future sessions").option("-s, --squad <squad>", "Squad to associate learning with").option("-c, --category <category>", "Category: success, failure, pattern, tip").option("-t, --tags <tags>", "Comma-separated tags").option("--context <context>", "Additional context").action(learnCommand);
10808
+ var learn = program.command("learnings").description("View and search learnings");
10809
+ learn.command("show <squad>").description("Show learnings for a squad").option("-n, --limit <n>", "Number to show", "10").option("-c, --category <category>", "Filter by category").option("--tag <tag>", "Filter by tag").action(learnShowCommand);
10810
+ learn.command("search <query>").description("Search learnings across all squads").option("-n, --limit <n>", "Max results", "10").action(learnSearchCommand);
9999
10811
  var sessions = program.command("sessions").description("Show active Claude Code sessions across squads").option("-v, --verbose", "Show session details").option("-j, --json", "Output as JSON").action(sessionsCommand);
10000
10812
  sessions.command("history").description("Show session history and statistics").option("-d, --days <days>", "Days of history to show", "7").option("-s, --squad <squad>", "Filter by squad").option("-j, --json", "Output as JSON").action((options) => sessionsHistoryCommand({
10001
10813
  days: parseInt(options.days, 10),
@@ -10006,8 +10818,8 @@ sessions.command("summary").description("Show pretty session summary (auto-detec
10006
10818
  const { buildCurrentSessionSummary } = await import("./sessions-R4VWIGFR.js");
10007
10819
  let data;
10008
10820
  if (options.file) {
10009
- const { readFileSync: readFileSync16 } = await import("fs");
10010
- data = JSON.parse(readFileSync16(options.file, "utf-8"));
10821
+ const { readFileSync: readFileSync18 } = await import("fs");
10822
+ data = JSON.parse(readFileSync18(options.file, "utf-8"));
10011
10823
  } else if (options.data) {
10012
10824
  data = JSON.parse(options.data);
10013
10825
  } else if (!process.stdin.isTTY) {