squads-cli 0.4.7 → 0.4.8

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
@@ -28,7 +28,7 @@ import {
28
28
  truncate,
29
29
  updateHeartbeat,
30
30
  writeLine
31
- } from "./chunk-EGOVJOZJ.js";
31
+ } from "./chunk-IDZYXBZY.js";
32
32
  import {
33
33
  __require
34
34
  } from "./chunk-7OCVIDC7.js";
@@ -47,18 +47,227 @@ var require2 = createRequire(import.meta.url);
47
47
  var pkg = require2("../package.json");
48
48
  var version = pkg.version;
49
49
 
50
+ // src/lib/update.ts
51
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from "fs";
52
+ import { join, dirname } from "path";
53
+ import { homedir } from "os";
54
+ import { execSync } from "child_process";
55
+ import { fileURLToPath } from "url";
56
+ function getPackageVersion() {
57
+ try {
58
+ const __filename3 = fileURLToPath(import.meta.url);
59
+ const __dirname3 = dirname(__filename3);
60
+ const possiblePaths = [
61
+ join(__dirname3, "..", "..", "package.json"),
62
+ // From dist/lib/
63
+ join(__dirname3, "..", "package.json"),
64
+ // From dist/
65
+ join(__dirname3, "package.json")
66
+ // Same dir
67
+ ];
68
+ for (const pkgPath of possiblePaths) {
69
+ if (existsSync(pkgPath)) {
70
+ const pkg2 = JSON.parse(readFileSync(pkgPath, "utf-8"));
71
+ return pkg2.version || "0.0.0";
72
+ }
73
+ }
74
+ } catch {
75
+ }
76
+ return "0.0.0";
77
+ }
78
+ var CURRENT_VERSION = getPackageVersion();
79
+ var CACHE_DIR = join(homedir(), ".squads");
80
+ var CACHE_FILE = join(CACHE_DIR, "update-check.json");
81
+ var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
82
+ function isNewerVersion(v1, v2) {
83
+ const parts1 = v1.replace(/^v/, "").split(".").map(Number);
84
+ const parts2 = v2.replace(/^v/, "").split(".").map(Number);
85
+ for (let i = 0; i < 3; i++) {
86
+ const p1 = parts1[i] || 0;
87
+ const p2 = parts2[i] || 0;
88
+ if (p2 > p1) return true;
89
+ if (p2 < p1) return false;
90
+ }
91
+ return false;
92
+ }
93
+ function readCache() {
94
+ try {
95
+ if (!existsSync(CACHE_FILE)) return null;
96
+ const data = JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
97
+ return data;
98
+ } catch {
99
+ return null;
100
+ }
101
+ }
102
+ function writeCache(latestVersion) {
103
+ try {
104
+ if (!existsSync(CACHE_DIR)) {
105
+ mkdirSync(CACHE_DIR, { recursive: true });
106
+ }
107
+ const cache = {
108
+ latestVersion,
109
+ checkedAt: Date.now()
110
+ };
111
+ writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2));
112
+ } catch {
113
+ }
114
+ }
115
+ function fetchLatestVersion() {
116
+ try {
117
+ const result = execSync("npm view squads-cli version 2>/dev/null", {
118
+ encoding: "utf-8",
119
+ timeout: 5e3
120
+ }).trim();
121
+ return result || null;
122
+ } catch {
123
+ return null;
124
+ }
125
+ }
126
+ function checkForUpdate() {
127
+ const result = {
128
+ currentVersion: CURRENT_VERSION,
129
+ latestVersion: CURRENT_VERSION,
130
+ updateAvailable: false
131
+ };
132
+ const cache = readCache();
133
+ const now = Date.now();
134
+ if (cache) {
135
+ result.latestVersion = cache.latestVersion;
136
+ result.updateAvailable = isNewerVersion(CURRENT_VERSION, cache.latestVersion);
137
+ if (now - cache.checkedAt >= CACHE_TTL_MS) {
138
+ triggerBackgroundRefresh();
139
+ }
140
+ return result;
141
+ }
142
+ triggerBackgroundRefresh();
143
+ return result;
144
+ }
145
+ function triggerBackgroundRefresh() {
146
+ try {
147
+ const { spawn: spawn8 } = __require("child_process");
148
+ const child = spawn8("npm", ["view", "squads-cli", "version"], {
149
+ detached: true,
150
+ stdio: ["ignore", "pipe", "ignore"],
151
+ shell: true
152
+ });
153
+ let output = "";
154
+ child.stdout?.on("data", (data) => {
155
+ output += data.toString();
156
+ });
157
+ child.on("close", () => {
158
+ const version2 = output.trim();
159
+ if (version2 && /^\d+\.\d+\.\d+/.test(version2)) {
160
+ writeCache(version2);
161
+ }
162
+ });
163
+ child.unref();
164
+ } catch {
165
+ }
166
+ }
167
+ function performUpdate() {
168
+ try {
169
+ execSync("npm update -g squads-cli", {
170
+ encoding: "utf-8",
171
+ stdio: "inherit",
172
+ timeout: 12e4
173
+ // 2 minutes
174
+ });
175
+ try {
176
+ unlinkSync(CACHE_FILE);
177
+ } catch {
178
+ }
179
+ return { success: true };
180
+ } catch (err) {
181
+ return {
182
+ success: false,
183
+ error: err instanceof Error ? err.message : "Unknown error"
184
+ };
185
+ }
186
+ }
187
+ function refreshVersionCache() {
188
+ const latestVersion = fetchLatestVersion();
189
+ if (latestVersion) {
190
+ writeCache(latestVersion);
191
+ return {
192
+ currentVersion: CURRENT_VERSION,
193
+ latestVersion,
194
+ updateAvailable: isNewerVersion(CURRENT_VERSION, latestVersion)
195
+ };
196
+ }
197
+ return checkForUpdate();
198
+ }
199
+ var AUTO_UPDATE_CACHE_FILE = join(CACHE_DIR, "auto-update.json");
200
+ var AUTO_UPDATE_COOLDOWN_MS = 60 * 60 * 1e3;
201
+ function readAutoUpdateCache() {
202
+ try {
203
+ if (!existsSync(AUTO_UPDATE_CACHE_FILE)) return null;
204
+ return JSON.parse(readFileSync(AUTO_UPDATE_CACHE_FILE, "utf-8"));
205
+ } catch {
206
+ return null;
207
+ }
208
+ }
209
+ function writeAutoUpdateCache(cache) {
210
+ try {
211
+ if (!existsSync(CACHE_DIR)) {
212
+ mkdirSync(CACHE_DIR, { recursive: true });
213
+ }
214
+ writeFileSync(AUTO_UPDATE_CACHE_FILE, JSON.stringify(cache, null, 2));
215
+ } catch {
216
+ }
217
+ }
218
+ async function autoUpdateOnStartup(silent = false) {
219
+ if (process.env.CI || process.env.SQUADS_NO_AUTO_UPDATE) return;
220
+ const autoCache = readAutoUpdateCache();
221
+ const now = Date.now();
222
+ if (autoCache && now - autoCache.lastAttempt < AUTO_UPDATE_COOLDOWN_MS) {
223
+ return;
224
+ }
225
+ const info = checkForUpdate();
226
+ if (!info.updateAvailable) return;
227
+ writeAutoUpdateCache({ lastAttempt: now, lastSuccess: autoCache?.lastSuccess });
228
+ try {
229
+ const { spawn: spawn8 } = await import("child_process");
230
+ const child = spawn8("npm", ["update", "-g", "squads-cli"], {
231
+ detached: true,
232
+ stdio: silent ? "ignore" : ["ignore", "pipe", "pipe"],
233
+ shell: true
234
+ });
235
+ if (!silent && child.stdout) {
236
+ await new Promise((resolve) => {
237
+ child.on("close", (code) => {
238
+ if (code === 0) {
239
+ console.log(`
240
+ \x1B[32m\u2713\x1B[0m Update successful! v${info.latestVersion} will be used on your next run.
241
+ `);
242
+ writeAutoUpdateCache({ lastAttempt: now, lastSuccess: now });
243
+ try {
244
+ unlinkSync(CACHE_FILE);
245
+ } catch {
246
+ }
247
+ }
248
+ resolve();
249
+ });
250
+ setTimeout(() => resolve(), 3e4);
251
+ });
252
+ } else {
253
+ child.unref();
254
+ }
255
+ } catch {
256
+ }
257
+ }
258
+
50
259
  // src/commands/init.ts
51
260
  import chalk from "chalk";
52
261
  import ora from "ora";
53
262
  import fs from "fs/promises";
54
263
  import path from "path";
55
- import { execSync as execSync2, spawn } from "child_process";
264
+ import { execSync as execSync3, spawn } from "child_process";
56
265
  import { createInterface } from "readline";
57
266
 
58
267
  // src/lib/git.ts
59
- import { execSync, exec } from "child_process";
60
- import { existsSync } from "fs";
61
- import { join } from "path";
268
+ import { execSync as execSync2, exec } from "child_process";
269
+ import { existsSync as existsSync2 } from "fs";
270
+ import { join as join2 } from "path";
62
271
  import { promisify } from "util";
63
272
  var execAsync = promisify(exec);
64
273
  function checkGitStatus(cwd = process.cwd()) {
@@ -68,12 +277,12 @@ function checkGitStatus(cwd = process.cwd()) {
68
277
  isDirty: false,
69
278
  uncommittedCount: 0
70
279
  };
71
- if (!existsSync(join(cwd, ".git"))) {
280
+ if (!existsSync2(join2(cwd, ".git"))) {
72
281
  return status;
73
282
  }
74
283
  status.isGitRepo = true;
75
284
  try {
76
- const combined = execSync(
285
+ const combined = execSync2(
77
286
  'echo "BRANCH:" && git rev-parse --abbrev-ref HEAD && echo "REMOTES:" && git remote -v && echo "STATUS:" && git status --porcelain',
78
287
  { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }
79
288
  );
@@ -157,10 +366,10 @@ function getGitHubStatsOptimized(basePath, days = 30) {
157
366
  const since = new Date(Date.now() - days * 24 * 60 * 60 * 1e3).toISOString();
158
367
  const results = [];
159
368
  for (const repo of repos) {
160
- const repoPath = join(basePath, repo);
161
- if (!existsSync(repoPath)) continue;
369
+ const repoPath = join2(basePath, repo);
370
+ if (!existsSync2(repoPath)) continue;
162
371
  try {
163
- const output = execSync(
372
+ const output = execSync2(
164
373
  `echo '{"prs":' && gh pr list --state all --json number,title,createdAt,mergedAt,labels --limit 50 2>/dev/null && echo ',"issues":' && gh issue list --state all --json number,title,state,closedAt,labels --limit 50 2>/dev/null && echo '}'`,
165
374
  { cwd: repoPath, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 1e4 }
166
375
  );
@@ -171,11 +380,11 @@ function getGitHubStatsOptimized(basePath, days = 30) {
171
380
  results.push({ repo, prs, issues });
172
381
  } catch {
173
382
  try {
174
- const prsOutput = execSync(
383
+ const prsOutput = execSync2(
175
384
  `gh pr list --state all --json number,title,createdAt,mergedAt,labels --limit 50 2>/dev/null`,
176
385
  { cwd: repoPath, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }
177
386
  );
178
- const issuesOutput = execSync(
387
+ const issuesOutput = execSync2(
179
388
  `gh issue list --state all --json number,title,state,closedAt,labels --limit 50 2>/dev/null`,
180
389
  { cwd: repoPath, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }
181
390
  );
@@ -291,12 +500,12 @@ function getMultiRepoGitStats(basePath, days = 30) {
291
500
  };
292
501
  const allCommits = [];
293
502
  for (const repo of SQUAD_REPOS) {
294
- const repoPath = join(basePath, repo);
295
- if (!existsSync(repoPath) || !existsSync(join(repoPath, ".git"))) {
503
+ const repoPath = join2(basePath, repo);
504
+ if (!existsSync2(repoPath) || !existsSync2(join2(repoPath, ".git"))) {
296
505
  continue;
297
506
  }
298
507
  try {
299
- const logOutput = execSync(
508
+ const logOutput = execSync2(
300
509
  `git log --since="${days} days ago" --format="%H|%aN|%ad|%s" --date=short 2>/dev/null`,
301
510
  { cwd: repoPath, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
302
511
  ).trim();
@@ -353,12 +562,12 @@ function getActivitySparkline(basePath, days = 7) {
353
562
  activity.push(0);
354
563
  }
355
564
  for (const repo of SQUAD_REPOS) {
356
- const repoPath = join(basePath, repo);
357
- if (!existsSync(repoPath) || !existsSync(join(repoPath, ".git"))) {
565
+ const repoPath = join2(basePath, repo);
566
+ if (!existsSync2(repoPath) || !existsSync2(join2(repoPath, ".git"))) {
358
567
  continue;
359
568
  }
360
569
  try {
361
- const logOutput = execSync(
570
+ const logOutput = execSync2(
362
571
  `git log --since="${days} days ago" --format="%ad" --date=short 2>/dev/null`,
363
572
  { cwd: repoPath, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
364
573
  ).trim();
@@ -378,13 +587,13 @@ function getActivitySparkline(basePath, days = 7) {
378
587
  }
379
588
 
380
589
  // src/lib/telemetry.ts
381
- import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync } from "fs";
382
- import { join as join2 } from "path";
383
- import { homedir } from "os";
590
+ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
591
+ import { join as join3 } from "path";
592
+ import { homedir as homedir2 } from "os";
384
593
  import { randomUUID } from "crypto";
385
- var TELEMETRY_DIR = join2(homedir(), ".squads-cli");
386
- var CONFIG_PATH = join2(TELEMETRY_DIR, "telemetry.json");
387
- var EVENTS_PATH = join2(TELEMETRY_DIR, "events.json");
594
+ var TELEMETRY_DIR = join3(homedir2(), ".squads-cli");
595
+ var CONFIG_PATH = join3(TELEMETRY_DIR, "telemetry.json");
596
+ var EVENTS_PATH = join3(TELEMETRY_DIR, "events.json");
388
597
  var TELEMETRY_ENDPOINT = Buffer.from(
389
598
  "aHR0cHM6Ly9zcXVhZHMtdGVsZW1ldHJ5LTk3ODg3MTgxNzYxMC51cy1jZW50cmFsMS5ydW4uYXBwL3Bpbmc=",
390
599
  "base64"
@@ -393,24 +602,24 @@ var TELEMETRY_KEY = Buffer.from("c3FfdGVsX3YxXzdmOGE5YjJjM2Q0ZTVmNmE=", "base64"
393
602
  var eventQueue = [];
394
603
  var flushScheduled = false;
395
604
  function ensureDir() {
396
- if (!existsSync2(TELEMETRY_DIR)) {
397
- mkdirSync(TELEMETRY_DIR, { recursive: true });
605
+ if (!existsSync3(TELEMETRY_DIR)) {
606
+ mkdirSync2(TELEMETRY_DIR, { recursive: true });
398
607
  }
399
608
  }
400
609
  function getConfig() {
401
610
  ensureDir();
402
- if (!existsSync2(CONFIG_PATH)) {
611
+ if (!existsSync3(CONFIG_PATH)) {
403
612
  const config2 = {
404
613
  enabled: true,
405
614
  // Opt-out by default (common for CLIs)
406
615
  anonymousId: randomUUID(),
407
616
  firstRun: (/* @__PURE__ */ new Date()).toISOString()
408
617
  };
409
- writeFileSync(CONFIG_PATH, JSON.stringify(config2, null, 2));
618
+ writeFileSync2(CONFIG_PATH, JSON.stringify(config2, null, 2));
410
619
  return config2;
411
620
  }
412
621
  try {
413
- return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
622
+ return JSON.parse(readFileSync2(CONFIG_PATH, "utf-8"));
414
623
  } catch {
415
624
  return { enabled: false, anonymousId: "", firstRun: "" };
416
625
  }
@@ -470,9 +679,9 @@ async function flushEvents() {
470
679
  function storeEventLocally(event) {
471
680
  ensureDir();
472
681
  let events = [];
473
- if (existsSync2(EVENTS_PATH)) {
682
+ if (existsSync3(EVENTS_PATH)) {
474
683
  try {
475
- events = JSON.parse(readFileSync(EVENTS_PATH, "utf-8"));
684
+ events = JSON.parse(readFileSync2(EVENTS_PATH, "utf-8"));
476
685
  } catch {
477
686
  events = [];
478
687
  }
@@ -481,7 +690,7 @@ function storeEventLocally(event) {
481
690
  if (events.length > 1e3) {
482
691
  events = events.slice(-1e3);
483
692
  }
484
- writeFileSync(EVENTS_PATH, JSON.stringify(events, null, 2));
693
+ writeFileSync2(EVENTS_PATH, JSON.stringify(events, null, 2));
485
694
  }
486
695
  var Events = {
487
696
  // Lifecycle
@@ -578,7 +787,7 @@ async function promptEmail() {
578
787
  }
579
788
  function commandExists(cmd) {
580
789
  try {
581
- execSync2(`which ${cmd}`, { stdio: "ignore" });
790
+ execSync3(`which ${cmd}`, { stdio: "ignore" });
582
791
  return true;
583
792
  } catch {
584
793
  return false;
@@ -586,7 +795,7 @@ function commandExists(cmd) {
586
795
  }
587
796
  function dockerRunning() {
588
797
  try {
589
- execSync2("docker info", { stdio: "ignore" });
798
+ execSync3("docker info", { stdio: "ignore" });
590
799
  return true;
591
800
  } catch {
592
801
  return false;
@@ -594,12 +803,12 @@ function dockerRunning() {
594
803
  }
595
804
  function checkClaudeAuth() {
596
805
  try {
597
- execSync2("which claude", { stdio: "ignore" });
806
+ execSync3("which claude", { stdio: "ignore" });
598
807
  } catch {
599
808
  return { installed: false, loggedIn: false };
600
809
  }
601
810
  try {
602
- const result = execSync2("claude --version", { stdio: "pipe" }).toString();
811
+ const result = execSync3("claude --version", { stdio: "pipe" }).toString();
603
812
  return { installed: true, loggedIn: result.includes("claude") };
604
813
  } catch {
605
814
  return { installed: true, loggedIn: false };
@@ -607,7 +816,7 @@ function checkClaudeAuth() {
607
816
  }
608
817
  function checkGhAuth() {
609
818
  try {
610
- execSync2("gh auth status", { stdio: "ignore" });
819
+ execSync3("gh auth status", { stdio: "ignore" });
611
820
  return true;
612
821
  } catch {
613
822
  return false;
@@ -744,7 +953,7 @@ async function setupInfrastructure(cwd) {
744
953
  let allRunning = true;
745
954
  for (const service of services) {
746
955
  try {
747
- execSync2(`docker ps --filter "name=${service}" --filter "status=running" -q`, { stdio: "pipe" });
956
+ execSync3(`docker ps --filter "name=${service}" --filter "status=running" -q`, { stdio: "pipe" });
748
957
  } catch {
749
958
  allRunning = false;
750
959
  }
@@ -1156,21 +1365,21 @@ squads goal list # View goals
1156
1365
  // src/commands/run.ts
1157
1366
  import ora2 from "ora";
1158
1367
  import { spawn as spawn2 } from "child_process";
1159
- import { join as join4, dirname } from "path";
1160
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2 } from "fs";
1368
+ import { join as join5, dirname as dirname2 } from "path";
1369
+ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3 } from "fs";
1161
1370
 
1162
1371
  // src/lib/squad-parser.ts
1163
- import { readFileSync as readFileSync2, existsSync as existsSync3, readdirSync, writeFileSync as writeFileSync2 } from "fs";
1164
- import { join as join3, basename } from "path";
1372
+ import { readFileSync as readFileSync3, existsSync as existsSync4, readdirSync, writeFileSync as writeFileSync3 } from "fs";
1373
+ import { join as join4, basename } from "path";
1165
1374
  import matter from "gray-matter";
1166
1375
  function findSquadsDir() {
1167
1376
  let dir = process.cwd();
1168
1377
  for (let i = 0; i < 5; i++) {
1169
- const squadsPath = join3(dir, ".agents", "squads");
1170
- if (existsSync3(squadsPath)) {
1378
+ const squadsPath = join4(dir, ".agents", "squads");
1379
+ if (existsSync4(squadsPath)) {
1171
1380
  return squadsPath;
1172
1381
  }
1173
- const parent = join3(dir, "..");
1382
+ const parent = join4(dir, "..");
1174
1383
  if (parent === dir) break;
1175
1384
  dir = parent;
1176
1385
  }
@@ -1179,14 +1388,14 @@ function findSquadsDir() {
1179
1388
  function findProjectRoot() {
1180
1389
  const squadsDir = findSquadsDir();
1181
1390
  if (!squadsDir) return null;
1182
- return join3(squadsDir, "..", "..");
1391
+ return join4(squadsDir, "..", "..");
1183
1392
  }
1184
1393
  function hasLocalInfraConfig() {
1185
1394
  const projectRoot = findProjectRoot();
1186
1395
  if (!projectRoot) return false;
1187
- const envPath = join3(projectRoot, ".env");
1188
- if (!existsSync3(envPath)) return false;
1189
- const content = readFileSync2(envPath, "utf-8");
1396
+ const envPath = join4(projectRoot, ".env");
1397
+ if (!existsSync4(envPath)) return false;
1398
+ const content = readFileSync3(envPath, "utf-8");
1190
1399
  const infraKeys = ["LANGFUSE_", "SQUADS_BRIDGE", "SQUADS_POSTGRES", "SQUADS_REDIS"];
1191
1400
  return infraKeys.some((key) => content.includes(key));
1192
1401
  }
@@ -1195,8 +1404,8 @@ function listSquads(squadsDir) {
1195
1404
  const entries = readdirSync(squadsDir, { withFileTypes: true });
1196
1405
  for (const entry of entries) {
1197
1406
  if (entry.isDirectory() && !entry.name.startsWith("_")) {
1198
- const squadFile = join3(squadsDir, entry.name, "SQUAD.md");
1199
- if (existsSync3(squadFile)) {
1407
+ const squadFile = join4(squadsDir, entry.name, "SQUAD.md");
1408
+ if (existsSync4(squadFile)) {
1200
1409
  squads.push(entry.name);
1201
1410
  }
1202
1411
  }
@@ -1207,8 +1416,8 @@ function listAgents(squadsDir, squadName) {
1207
1416
  const agents = [];
1208
1417
  const dirs = squadName ? [squadName] : readdirSync(squadsDir, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith("_")).map((e) => e.name);
1209
1418
  for (const dir of dirs) {
1210
- const squadPath = join3(squadsDir, dir);
1211
- if (!existsSync3(squadPath)) continue;
1419
+ const squadPath = join4(squadsDir, dir);
1420
+ if (!existsSync4(squadPath)) continue;
1212
1421
  const files = readdirSync(squadPath);
1213
1422
  for (const file of files) {
1214
1423
  if (file.endsWith(".md") && file !== "SQUAD.md") {
@@ -1217,7 +1426,7 @@ function listAgents(squadsDir, squadName) {
1217
1426
  name: agentName,
1218
1427
  role: `Agent in ${dir}`,
1219
1428
  trigger: "manual",
1220
- filePath: join3(squadPath, file)
1429
+ filePath: join4(squadPath, file)
1221
1430
  });
1222
1431
  }
1223
1432
  }
@@ -1225,7 +1434,7 @@ function listAgents(squadsDir, squadName) {
1225
1434
  return agents;
1226
1435
  }
1227
1436
  function parseSquadFile(filePath) {
1228
- const rawContent = readFileSync2(filePath, "utf-8");
1437
+ const rawContent = readFileSync3(filePath, "utf-8");
1229
1438
  const { data: frontmatter, content: bodyContent } = matter(rawContent);
1230
1439
  const fm = frontmatter;
1231
1440
  const lines = bodyContent.split("\n");
@@ -1346,20 +1555,20 @@ function parseSquadFile(filePath) {
1346
1555
  function loadSquad(squadName) {
1347
1556
  const squadsDir = findSquadsDir();
1348
1557
  if (!squadsDir) return null;
1349
- const squadFile = join3(squadsDir, squadName, "SQUAD.md");
1350
- if (!existsSync3(squadFile)) return null;
1558
+ const squadFile = join4(squadsDir, squadName, "SQUAD.md");
1559
+ if (!existsSync4(squadFile)) return null;
1351
1560
  return parseSquadFile(squadFile);
1352
1561
  }
1353
1562
  function loadAgentDefinition(agentPath) {
1354
- if (!existsSync3(agentPath)) return "";
1355
- return readFileSync2(agentPath, "utf-8");
1563
+ if (!existsSync4(agentPath)) return "";
1564
+ return readFileSync3(agentPath, "utf-8");
1356
1565
  }
1357
1566
  function addGoalToSquad(squadName, goal2) {
1358
1567
  const squadsDir = findSquadsDir();
1359
1568
  if (!squadsDir) return false;
1360
- const squadFile = join3(squadsDir, squadName, "SQUAD.md");
1361
- if (!existsSync3(squadFile)) return false;
1362
- let content = readFileSync2(squadFile, "utf-8");
1569
+ const squadFile = join4(squadsDir, squadName, "SQUAD.md");
1570
+ if (!existsSync4(squadFile)) return false;
1571
+ let content = readFileSync3(squadFile, "utf-8");
1363
1572
  if (!content.includes("## Goals")) {
1364
1573
  const insertPoint = content.indexOf("## Dependencies");
1365
1574
  if (insertPoint > 0) {
@@ -1394,15 +1603,15 @@ function addGoalToSquad(squadName, goal2) {
1394
1603
  - [ ] ${goal2}` + content.slice(headerEnd);
1395
1604
  }
1396
1605
  }
1397
- writeFileSync2(squadFile, content);
1606
+ writeFileSync3(squadFile, content);
1398
1607
  return true;
1399
1608
  }
1400
1609
  function updateGoalInSquad(squadName, goalIndex, updates) {
1401
1610
  const squadsDir = findSquadsDir();
1402
1611
  if (!squadsDir) return false;
1403
- const squadFile = join3(squadsDir, squadName, "SQUAD.md");
1404
- if (!existsSync3(squadFile)) return false;
1405
- const content = readFileSync2(squadFile, "utf-8");
1612
+ const squadFile = join4(squadsDir, squadName, "SQUAD.md");
1613
+ if (!existsSync4(squadFile)) return false;
1614
+ const content = readFileSync3(squadFile, "utf-8");
1406
1615
  const lines = content.split("\n");
1407
1616
  let currentSection = "";
1408
1617
  let goalCount = 0;
@@ -1424,7 +1633,7 @@ function updateGoalInSquad(squadName, goalIndex, updates) {
1424
1633
  }
1425
1634
  }
1426
1635
  lines[i] = newLine;
1427
- writeFileSync2(squadFile, lines.join("\n"));
1636
+ writeFileSync3(squadFile, lines.join("\n"));
1428
1637
  return true;
1429
1638
  }
1430
1639
  goalCount++;
@@ -1673,7 +1882,7 @@ function generateExecutionId() {
1673
1882
  }
1674
1883
  function selectMcpConfig(squadName) {
1675
1884
  const home = process.env.HOME || "";
1676
- const configsDir = join4(home, ".claude", "mcp-configs");
1885
+ const configsDir = join5(home, ".claude", "mcp-configs");
1677
1886
  const squadConfigs = {
1678
1887
  website: "website.json",
1679
1888
  // chrome-devtools, nano-banana
@@ -1688,12 +1897,12 @@ function selectMcpConfig(squadName) {
1688
1897
  };
1689
1898
  const configFile = squadConfigs[squadName.toLowerCase()];
1690
1899
  if (configFile) {
1691
- const configPath = join4(configsDir, configFile);
1692
- if (existsSync4(configPath)) {
1900
+ const configPath = join5(configsDir, configFile);
1901
+ if (existsSync5(configPath)) {
1693
1902
  return configPath;
1694
1903
  }
1695
1904
  }
1696
- return join4(home, ".claude.json");
1905
+ return join5(home, ".claude.json");
1697
1906
  }
1698
1907
  function detectTaskType(agentName) {
1699
1908
  const name = agentName.toLowerCase();
@@ -1709,12 +1918,12 @@ function detectTaskType(agentName) {
1709
1918
  return "execution";
1710
1919
  }
1711
1920
  function ensureProjectTrusted(projectPath) {
1712
- const configPath = join4(process.env.HOME || "", ".claude.json");
1713
- if (!existsSync4(configPath)) {
1921
+ const configPath = join5(process.env.HOME || "", ".claude.json");
1922
+ if (!existsSync5(configPath)) {
1714
1923
  return;
1715
1924
  }
1716
1925
  try {
1717
- const config2 = JSON.parse(readFileSync3(configPath, "utf-8"));
1926
+ const config2 = JSON.parse(readFileSync4(configPath, "utf-8"));
1718
1927
  if (!config2.projects) {
1719
1928
  config2.projects = {};
1720
1929
  }
@@ -1723,7 +1932,7 @@ function ensureProjectTrusted(projectPath) {
1723
1932
  }
1724
1933
  if (!config2.projects[projectPath].hasTrustDialogAccepted) {
1725
1934
  config2.projects[projectPath].hasTrustDialogAccepted = true;
1726
- writeFileSync3(configPath, JSON.stringify(config2, null, 2));
1935
+ writeFileSync4(configPath, JSON.stringify(config2, null, 2));
1727
1936
  }
1728
1937
  } catch {
1729
1938
  }
@@ -1731,25 +1940,25 @@ function ensureProjectTrusted(projectPath) {
1731
1940
  function getProjectRoot() {
1732
1941
  const squadsDir = findSquadsDir();
1733
1942
  if (squadsDir) {
1734
- return dirname(dirname(squadsDir));
1943
+ return dirname2(dirname2(squadsDir));
1735
1944
  }
1736
1945
  return process.cwd();
1737
1946
  }
1738
1947
  function getExecutionLogPath(squadName, agentName) {
1739
1948
  const memoryDir = findMemoryDir();
1740
1949
  if (!memoryDir) return null;
1741
- return join4(memoryDir, squadName, agentName, "executions.md");
1950
+ return join5(memoryDir, squadName, agentName, "executions.md");
1742
1951
  }
1743
1952
  function logExecution(record) {
1744
1953
  const logPath = getExecutionLogPath(record.squadName, record.agentName);
1745
1954
  if (!logPath) return;
1746
- const dir = dirname(logPath);
1747
- if (!existsSync4(dir)) {
1748
- mkdirSync2(dir, { recursive: true });
1955
+ const dir = dirname2(logPath);
1956
+ if (!existsSync5(dir)) {
1957
+ mkdirSync3(dir, { recursive: true });
1749
1958
  }
1750
1959
  let content = "";
1751
- if (existsSync4(logPath)) {
1752
- content = readFileSync3(logPath, "utf-8").trimEnd();
1960
+ if (existsSync5(logPath)) {
1961
+ content = readFileSync4(logPath, "utf-8").trimEnd();
1753
1962
  } else {
1754
1963
  content = `# ${record.squadName}/${record.agentName} - Execution Log`;
1755
1964
  }
@@ -1762,12 +1971,12 @@ function logExecution(record) {
1762
1971
  - Trigger: ${record.trigger || "manual"}
1763
1972
  - Task Type: ${record.taskType || "execution"}
1764
1973
  `;
1765
- writeFileSync3(logPath, content + entry);
1974
+ writeFileSync4(logPath, content + entry);
1766
1975
  }
1767
1976
  function updateExecutionStatus(squadName, agentName, executionId, status, details) {
1768
1977
  const logPath = getExecutionLogPath(squadName, agentName);
1769
- if (!logPath || !existsSync4(logPath)) return;
1770
- let content = readFileSync3(logPath, "utf-8");
1978
+ if (!logPath || !existsSync5(logPath)) return;
1979
+ let content = readFileSync4(logPath, "utf-8");
1771
1980
  const endTime = (/* @__PURE__ */ new Date()).toISOString();
1772
1981
  const execMarker = `<!-- exec:${executionId} -->`;
1773
1982
  const markerIndex = content.indexOf(execMarker);
@@ -1788,7 +1997,7 @@ function updateExecutionStatus(squadName, agentName, executionId, status, detail
1788
1997
  - Error: ${details.error}`;
1789
1998
  }
1790
1999
  content = content.slice(0, entryStart) + updatedEntry + content.slice(entryEnd);
1791
- writeFileSync3(logPath, content);
2000
+ writeFileSync4(logPath, content);
1792
2001
  }
1793
2002
  function extractMcpServersFromDefinition(definition) {
1794
2003
  const servers = /* @__PURE__ */ new Set();
@@ -1867,8 +2076,8 @@ async function runSquad(squad, squadsDir, options) {
1867
2076
  if (options.parallel) {
1868
2077
  const agentFiles = squad.agents.map((a) => ({
1869
2078
  name: a.name,
1870
- path: join4(squadsDir, squad.name, `${a.name}.md`)
1871
- })).filter((a) => existsSync4(a.path));
2079
+ path: join5(squadsDir, squad.name, `${a.name}.md`)
2080
+ })).filter((a) => existsSync5(a.path));
1872
2081
  if (agentFiles.length === 0) {
1873
2082
  writeLine(` ${icons.error} ${colors.red}No agent files found${RESET}`);
1874
2083
  return;
@@ -1904,8 +2113,8 @@ async function runSquad(squad, squadsDir, options) {
1904
2113
  writeLine();
1905
2114
  for (let i = 0; i < pipeline.agents.length; i++) {
1906
2115
  const agentName = pipeline.agents[i];
1907
- const agentPath = join4(squadsDir, squad.name, `${agentName}.md`);
1908
- if (existsSync4(agentPath)) {
2116
+ const agentPath = join5(squadsDir, squad.name, `${agentName}.md`);
2117
+ if (existsSync5(agentPath)) {
1909
2118
  writeLine(` ${colors.dim}[${i + 1}/${pipeline.agents.length}]${RESET}`);
1910
2119
  await runAgent(agentName, agentPath, squad.name, options);
1911
2120
  writeLine();
@@ -1915,8 +2124,8 @@ async function runSquad(squad, squadsDir, options) {
1915
2124
  }
1916
2125
  } else {
1917
2126
  if (options.agent) {
1918
- const agentPath = join4(squadsDir, squad.name, `${options.agent}.md`);
1919
- if (existsSync4(agentPath)) {
2127
+ const agentPath = join5(squadsDir, squad.name, `${options.agent}.md`);
2128
+ if (existsSync5(agentPath)) {
1920
2129
  await runAgent(options.agent, agentPath, squad.name, options);
1921
2130
  } else {
1922
2131
  writeLine(` ${icons.error} ${colors.red}Agent ${options.agent} not found${RESET}`);
@@ -1927,8 +2136,8 @@ async function runSquad(squad, squadsDir, options) {
1927
2136
  (a) => a.name.includes("lead") || a.trigger === "Manual"
1928
2137
  );
1929
2138
  if (orchestrator) {
1930
- const agentPath = join4(squadsDir, squad.name, `${orchestrator.name}.md`);
1931
- if (existsSync4(agentPath)) {
2139
+ const agentPath = join5(squadsDir, squad.name, `${orchestrator.name}.md`);
2140
+ if (existsSync5(agentPath)) {
1932
2141
  await runAgent(orchestrator.name, agentPath, squad.name, options);
1933
2142
  }
1934
2143
  } else {
@@ -1954,9 +2163,9 @@ async function runLeadMode(squad, squadsDir, options) {
1954
2163
  if (!squad) return;
1955
2164
  const agentFiles = squad.agents.map((a) => ({
1956
2165
  name: a.name,
1957
- path: join4(squadsDir, squad.name, `${a.name}.md`),
2166
+ path: join5(squadsDir, squad.name, `${a.name}.md`),
1958
2167
  role: a.role || ""
1959
- })).filter((a) => existsSync4(a.path));
2168
+ })).filter((a) => existsSync5(a.path));
1960
2169
  if (agentFiles.length === 0) {
1961
2170
  writeLine(` ${icons.error} ${colors.red}No agent files found${RESET}`);
1962
2171
  return;
@@ -2075,9 +2284,9 @@ async function runAgent(agentName, agentPath, squadName, options) {
2075
2284
  }
2076
2285
  const squadsDir = findSquadsDir();
2077
2286
  if (squadsDir) {
2078
- const squadFilePath = join4(squadsDir, squadName, "SQUAD.md");
2079
- if (existsSync4(squadFilePath)) {
2080
- const squadContent = readFileSync3(squadFilePath, "utf-8");
2287
+ const squadFilePath = join5(squadsDir, squadName, "SQUAD.md");
2288
+ if (existsSync5(squadFilePath)) {
2289
+ const squadContent = readFileSync4(squadFilePath, "utf-8");
2081
2290
  const permContext = buildContextFromSquad(squadName, squadContent, agentName);
2082
2291
  const mcpServers = extractMcpServersFromDefinition(definition);
2083
2292
  const execRequest = {
@@ -2359,158 +2568,6 @@ async function listCommand(options) {
2359
2568
  // src/commands/status.ts
2360
2569
  import { existsSync as existsSync6, statSync } from "fs";
2361
2570
  import { join as join6 } from "path";
2362
-
2363
- // src/lib/update.ts
2364
- import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, unlinkSync } from "fs";
2365
- import { join as join5, dirname as dirname2 } from "path";
2366
- import { homedir as homedir2 } from "os";
2367
- import { execSync as execSync3 } from "child_process";
2368
- import { fileURLToPath } from "url";
2369
- function getPackageVersion() {
2370
- try {
2371
- const __filename3 = fileURLToPath(import.meta.url);
2372
- const __dirname3 = dirname2(__filename3);
2373
- const possiblePaths = [
2374
- join5(__dirname3, "..", "..", "package.json"),
2375
- // From dist/lib/
2376
- join5(__dirname3, "..", "package.json"),
2377
- // From dist/
2378
- join5(__dirname3, "package.json")
2379
- // Same dir
2380
- ];
2381
- for (const pkgPath of possiblePaths) {
2382
- if (existsSync5(pkgPath)) {
2383
- const pkg2 = JSON.parse(readFileSync4(pkgPath, "utf-8"));
2384
- return pkg2.version || "0.0.0";
2385
- }
2386
- }
2387
- } catch {
2388
- }
2389
- return "0.0.0";
2390
- }
2391
- var CURRENT_VERSION = getPackageVersion();
2392
- var CACHE_DIR = join5(homedir2(), ".squads");
2393
- var CACHE_FILE = join5(CACHE_DIR, "update-check.json");
2394
- var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
2395
- function isNewerVersion(v1, v2) {
2396
- const parts1 = v1.replace(/^v/, "").split(".").map(Number);
2397
- const parts2 = v2.replace(/^v/, "").split(".").map(Number);
2398
- for (let i = 0; i < 3; i++) {
2399
- const p1 = parts1[i] || 0;
2400
- const p2 = parts2[i] || 0;
2401
- if (p2 > p1) return true;
2402
- if (p2 < p1) return false;
2403
- }
2404
- return false;
2405
- }
2406
- function readCache() {
2407
- try {
2408
- if (!existsSync5(CACHE_FILE)) return null;
2409
- const data = JSON.parse(readFileSync4(CACHE_FILE, "utf-8"));
2410
- return data;
2411
- } catch {
2412
- return null;
2413
- }
2414
- }
2415
- function writeCache(latestVersion) {
2416
- try {
2417
- if (!existsSync5(CACHE_DIR)) {
2418
- mkdirSync3(CACHE_DIR, { recursive: true });
2419
- }
2420
- const cache = {
2421
- latestVersion,
2422
- checkedAt: Date.now()
2423
- };
2424
- writeFileSync4(CACHE_FILE, JSON.stringify(cache, null, 2));
2425
- } catch {
2426
- }
2427
- }
2428
- function fetchLatestVersion() {
2429
- try {
2430
- const result = execSync3("npm view squads-cli version 2>/dev/null", {
2431
- encoding: "utf-8",
2432
- timeout: 5e3
2433
- }).trim();
2434
- return result || null;
2435
- } catch {
2436
- return null;
2437
- }
2438
- }
2439
- function checkForUpdate() {
2440
- const result = {
2441
- currentVersion: CURRENT_VERSION,
2442
- latestVersion: CURRENT_VERSION,
2443
- updateAvailable: false
2444
- };
2445
- const cache = readCache();
2446
- const now = Date.now();
2447
- if (cache) {
2448
- result.latestVersion = cache.latestVersion;
2449
- result.updateAvailable = isNewerVersion(CURRENT_VERSION, cache.latestVersion);
2450
- if (now - cache.checkedAt >= CACHE_TTL_MS) {
2451
- triggerBackgroundRefresh();
2452
- }
2453
- return result;
2454
- }
2455
- triggerBackgroundRefresh();
2456
- return result;
2457
- }
2458
- function triggerBackgroundRefresh() {
2459
- try {
2460
- const { spawn: spawn8 } = __require("child_process");
2461
- const child = spawn8("npm", ["view", "squads-cli", "version"], {
2462
- detached: true,
2463
- stdio: ["ignore", "pipe", "ignore"],
2464
- shell: true
2465
- });
2466
- let output = "";
2467
- child.stdout?.on("data", (data) => {
2468
- output += data.toString();
2469
- });
2470
- child.on("close", () => {
2471
- const version2 = output.trim();
2472
- if (version2 && /^\d+\.\d+\.\d+/.test(version2)) {
2473
- writeCache(version2);
2474
- }
2475
- });
2476
- child.unref();
2477
- } catch {
2478
- }
2479
- }
2480
- function performUpdate() {
2481
- try {
2482
- execSync3("npm update -g squads-cli", {
2483
- encoding: "utf-8",
2484
- stdio: "inherit",
2485
- timeout: 12e4
2486
- // 2 minutes
2487
- });
2488
- try {
2489
- unlinkSync(CACHE_FILE);
2490
- } catch {
2491
- }
2492
- return { success: true };
2493
- } catch (err) {
2494
- return {
2495
- success: false,
2496
- error: err instanceof Error ? err.message : "Unknown error"
2497
- };
2498
- }
2499
- }
2500
- function refreshVersionCache() {
2501
- const latestVersion = fetchLatestVersion();
2502
- if (latestVersion) {
2503
- writeCache(latestVersion);
2504
- return {
2505
- currentVersion: CURRENT_VERSION,
2506
- latestVersion,
2507
- updateAvailable: isNewerVersion(CURRENT_VERSION, latestVersion)
2508
- };
2509
- }
2510
- return checkForUpdate();
2511
- }
2512
-
2513
- // src/commands/status.ts
2514
2571
  async function statusCommand(squadName, options = {}) {
2515
2572
  await track(Events.CLI_STATUS, { squad: squadName || "all", verbose: options.verbose });
2516
2573
  const squadsDir = findSquadsDir();
@@ -10052,6 +10109,7 @@ for (const envPath of envPaths) {
10052
10109
  }
10053
10110
  }
10054
10111
  applyStackConfig();
10112
+ await autoUpdateOnStartup();
10055
10113
  registerExitHandler();
10056
10114
  var program = new Command();
10057
10115
  program.name("squads").description("A CLI for humans and agents").version(version).showSuggestionAfterError(true).configureOutput({
@@ -10133,7 +10191,7 @@ sessions.command("history").description("Show session history and statistics").o
10133
10191
  json: options.json
10134
10192
  }));
10135
10193
  sessions.command("summary").description("Show pretty session summary (auto-detects current session or pass JSON)").option("-d, --data <json>", "JSON data for summary (overrides auto-detection)").option("-f, --file <path>", "Path to JSON file with summary data").option("-j, --json", "Output as JSON instead of pretty format").action(async (options) => {
10136
- const { buildCurrentSessionSummary } = await import("./sessions-SEITSWEV.js");
10194
+ const { buildCurrentSessionSummary } = await import("./sessions-B6GVXJ2H.js");
10137
10195
  let data;
10138
10196
  if (options.file) {
10139
10197
  const { readFileSync: readFileSync17 } = await import("fs");