squads-cli 0.2.0 → 0.2.1

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.
Files changed (223) hide show
  1. package/README.md +521 -288
  2. package/dist/auth-YW3UPFSB.js +23 -0
  3. package/dist/auth-YW3UPFSB.js.map +1 -0
  4. package/dist/autonomy-PSVZVX7A.js +105 -0
  5. package/dist/autonomy-PSVZVX7A.js.map +1 -0
  6. package/dist/chunk-67RO2HKR.js +174 -0
  7. package/dist/chunk-67RO2HKR.js.map +1 -0
  8. package/dist/chunk-7OCVIDC7.js +12 -0
  9. package/dist/chunk-7OCVIDC7.js.map +1 -0
  10. package/dist/chunk-BODLDQY7.js +452 -0
  11. package/dist/chunk-BODLDQY7.js.map +1 -0
  12. package/dist/chunk-EHQJHRIW.js +103 -0
  13. package/dist/chunk-EHQJHRIW.js.map +1 -0
  14. package/dist/chunk-FFFCFZ6A.js +121 -0
  15. package/dist/chunk-FFFCFZ6A.js.map +1 -0
  16. package/dist/chunk-FIWT2NMM.js +165 -0
  17. package/dist/chunk-FIWT2NMM.js.map +1 -0
  18. package/dist/chunk-HF4WR7RA.js +154 -0
  19. package/dist/chunk-HF4WR7RA.js.map +1 -0
  20. package/dist/chunk-J6QF4ZQX.js +230 -0
  21. package/dist/chunk-J6QF4ZQX.js.map +1 -0
  22. package/dist/chunk-LOA3KWYJ.js +294 -0
  23. package/dist/chunk-LOA3KWYJ.js.map +1 -0
  24. package/dist/chunk-M5FXNY6Y.js +384 -0
  25. package/dist/chunk-M5FXNY6Y.js.map +1 -0
  26. package/dist/chunk-QHNUMM4V.js +87 -0
  27. package/dist/chunk-QHNUMM4V.js.map +1 -0
  28. package/dist/chunk-QJ7C7CMB.js +223 -0
  29. package/dist/chunk-QJ7C7CMB.js.map +1 -0
  30. package/dist/chunk-RM6BWILN.js +74 -0
  31. package/dist/chunk-RM6BWILN.js.map +1 -0
  32. package/dist/chunk-TYFTF53O.js +613 -0
  33. package/dist/chunk-TYFTF53O.js.map +1 -0
  34. package/dist/chunk-TZXD6WFN.js +420 -0
  35. package/dist/chunk-TZXD6WFN.js.map +1 -0
  36. package/dist/chunk-WVOIY5GW.js +621 -0
  37. package/dist/chunk-WVOIY5GW.js.map +1 -0
  38. package/dist/chunk-Z2UKDBNL.js +162 -0
  39. package/dist/chunk-Z2UKDBNL.js.map +1 -0
  40. package/dist/chunk-ZTQ7ISUR.js +338 -0
  41. package/dist/chunk-ZTQ7ISUR.js.map +1 -0
  42. package/dist/cli.js +2483 -5902
  43. package/dist/cli.js.map +1 -1
  44. package/dist/context-GWPF4SEY.js +291 -0
  45. package/dist/context-GWPF4SEY.js.map +1 -0
  46. package/dist/context-feed-AJGVAR6H.js +394 -0
  47. package/dist/context-feed-AJGVAR6H.js.map +1 -0
  48. package/dist/cost-XBCDJ7XC.js +275 -0
  49. package/dist/cost-XBCDJ7XC.js.map +1 -0
  50. package/dist/create-BLFGG6PF.js +286 -0
  51. package/dist/create-BLFGG6PF.js.map +1 -0
  52. package/dist/dashboard-LGT2B2BL.js +951 -0
  53. package/dist/dashboard-LGT2B2BL.js.map +1 -0
  54. package/dist/dashboard-RMK2BOD2.js +794 -0
  55. package/dist/dashboard-RMK2BOD2.js.map +1 -0
  56. package/dist/doctor-XPUIIBHJ.js +374 -0
  57. package/dist/doctor-XPUIIBHJ.js.map +1 -0
  58. package/dist/env-config-SQEI3Y7Y.js +21 -0
  59. package/dist/env-config-SQEI3Y7Y.js.map +1 -0
  60. package/dist/exec-OUXM7JBF.js +223 -0
  61. package/dist/exec-OUXM7JBF.js.map +1 -0
  62. package/dist/feedback-KNAOG5QK.js +229 -0
  63. package/dist/feedback-KNAOG5QK.js.map +1 -0
  64. package/dist/github-UQTM5KMS.js +23 -0
  65. package/dist/github-UQTM5KMS.js.map +1 -0
  66. package/dist/goal-BVHV5573.js +168 -0
  67. package/dist/goal-BVHV5573.js.map +1 -0
  68. package/dist/health-4UXN44PF.js +218 -0
  69. package/dist/health-4UXN44PF.js.map +1 -0
  70. package/dist/history-ILH3SWHB.js +232 -0
  71. package/dist/history-ILH3SWHB.js.map +1 -0
  72. package/dist/index.d.ts +736 -8
  73. package/dist/index.js +1312 -6
  74. package/dist/index.js.map +1 -1
  75. package/dist/init-XQZ7BOGT.js +812 -0
  76. package/dist/init-XQZ7BOGT.js.map +1 -0
  77. package/dist/kpi-RQIU7WGK.js +413 -0
  78. package/dist/kpi-RQIU7WGK.js.map +1 -0
  79. package/dist/learn-OIFUVZAS.js +269 -0
  80. package/dist/learn-OIFUVZAS.js.map +1 -0
  81. package/dist/login-DXZANWZY.js +155 -0
  82. package/dist/login-DXZANWZY.js.map +1 -0
  83. package/dist/memory-T3ACCS7E.js +560 -0
  84. package/dist/memory-T3ACCS7E.js.map +1 -0
  85. package/dist/memory-VNF2VFRB.js +23 -0
  86. package/dist/memory-VNF2VFRB.js.map +1 -0
  87. package/dist/progress-DAUZMT3N.js +202 -0
  88. package/dist/progress-DAUZMT3N.js.map +1 -0
  89. package/dist/providers-3P5D2XL5.js +65 -0
  90. package/dist/providers-3P5D2XL5.js.map +1 -0
  91. package/dist/results-UECWGLTB.js +224 -0
  92. package/dist/results-UECWGLTB.js.map +1 -0
  93. package/dist/run-I6KAXU6U.js +4049 -0
  94. package/dist/run-I6KAXU6U.js.map +1 -0
  95. package/dist/session-HBU6KZOD.js +64 -0
  96. package/dist/session-HBU6KZOD.js.map +1 -0
  97. package/dist/sessions-CK25VGPL.js +333 -0
  98. package/dist/sessions-CK25VGPL.js.map +1 -0
  99. package/dist/squad-parser-DCG65BJS.js +35 -0
  100. package/dist/squad-parser-DCG65BJS.js.map +1 -0
  101. package/dist/stats-G6NAU5BD.js +334 -0
  102. package/dist/stats-G6NAU5BD.js.map +1 -0
  103. package/dist/status-AQNLDZVN.js +352 -0
  104. package/dist/status-AQNLDZVN.js.map +1 -0
  105. package/dist/sync-ZI3MHA4G.js +836 -0
  106. package/dist/sync-ZI3MHA4G.js.map +1 -0
  107. package/dist/templates/core/AGENTS.md.template +51 -0
  108. package/dist/templates/core/BUSINESS_BRIEF.md.template +29 -0
  109. package/dist/templates/core/CLAUDE.md.template +48 -0
  110. package/dist/templates/core/provider.yaml.template +5 -0
  111. package/dist/templates/first-squad/SQUAD.md.template +23 -0
  112. package/dist/templates/first-squad/lead.md.template +44 -0
  113. package/dist/templates/memory/getting-started/state.md.template +19 -0
  114. package/dist/templates/seed/BUSINESS_BRIEF.md.template +27 -0
  115. package/dist/templates/seed/CLAUDE.md.template +119 -0
  116. package/dist/templates/seed/README.md.template +42 -0
  117. package/dist/templates/seed/config/SYSTEM.md +52 -0
  118. package/dist/templates/seed/config/provider.yaml +4 -0
  119. package/dist/templates/seed/hooks/settings.json.template +31 -0
  120. package/dist/templates/seed/memory/company/directives.md +37 -0
  121. package/dist/templates/seed/memory/company/manager/state.md +16 -0
  122. package/dist/templates/seed/memory/engineering/issue-solver/state.md +12 -0
  123. package/dist/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
  124. package/dist/templates/seed/memory/marketing/content-drafter/state.md +12 -0
  125. package/dist/templates/seed/memory/operations/ops-lead/state.md +12 -0
  126. package/dist/templates/seed/memory/product/lead/state.md +14 -0
  127. package/dist/templates/seed/memory/research/lead/state.md +14 -0
  128. package/dist/templates/seed/skills/gh/SKILL.md +57 -0
  129. package/dist/templates/seed/skills/squads-cli/SKILL.md +84 -0
  130. package/dist/templates/seed/squads/company/SQUAD.md +51 -0
  131. package/dist/templates/seed/squads/company/company-critic.md +49 -0
  132. package/dist/templates/seed/squads/company/company-eval.md +49 -0
  133. package/dist/templates/seed/squads/company/event-dispatcher.md +43 -0
  134. package/dist/templates/seed/squads/company/goal-tracker.md +43 -0
  135. package/dist/templates/seed/squads/company/manager.md +54 -0
  136. package/dist/templates/seed/squads/engineering/SQUAD.md +48 -0
  137. package/dist/templates/seed/squads/engineering/code-reviewer.md +57 -0
  138. package/dist/templates/seed/squads/engineering/issue-solver.md +58 -0
  139. package/dist/templates/seed/squads/engineering/test-writer.md +50 -0
  140. package/dist/templates/seed/squads/intelligence/SQUAD.md +38 -0
  141. package/dist/templates/seed/squads/intelligence/intel-critic.md +36 -0
  142. package/dist/templates/seed/squads/intelligence/intel-eval.md +31 -0
  143. package/dist/templates/seed/squads/intelligence/intel-lead.md +71 -0
  144. package/dist/templates/seed/squads/marketing/SQUAD.md +47 -0
  145. package/dist/templates/seed/squads/marketing/content-drafter.md +71 -0
  146. package/dist/templates/seed/squads/marketing/growth-analyst.md +49 -0
  147. package/dist/templates/seed/squads/marketing/social-poster.md +44 -0
  148. package/dist/templates/seed/squads/operations/SQUAD.md +45 -0
  149. package/dist/templates/seed/squads/operations/finance-tracker.md +47 -0
  150. package/dist/templates/seed/squads/operations/goal-tracker.md +48 -0
  151. package/dist/templates/seed/squads/operations/ops-lead.md +58 -0
  152. package/dist/templates/seed/squads/product/SQUAD.md +41 -0
  153. package/dist/templates/seed/squads/product/lead.md +56 -0
  154. package/dist/templates/seed/squads/product/scanner.md +50 -0
  155. package/dist/templates/seed/squads/product/worker.md +55 -0
  156. package/dist/templates/seed/squads/research/SQUAD.md +38 -0
  157. package/dist/templates/seed/squads/research/analyst.md +50 -0
  158. package/dist/templates/seed/squads/research/lead.md +52 -0
  159. package/dist/templates/seed/squads/research/synthesizer.md +59 -0
  160. package/dist/templates/skills/squads-learn/SKILL.md +86 -0
  161. package/dist/templates/skills/squads-workflow/instruction.md +70 -0
  162. package/dist/terminal-FBQFQTKZ.js +55 -0
  163. package/dist/terminal-FBQFQTKZ.js.map +1 -0
  164. package/dist/update-D7CGIZ3M.js +18 -0
  165. package/dist/update-D7CGIZ3M.js.map +1 -0
  166. package/dist/update-STU276HR.js +83 -0
  167. package/dist/update-STU276HR.js.map +1 -0
  168. package/package.json +31 -13
  169. package/templates/core/AGENTS.md.template +51 -0
  170. package/templates/core/BUSINESS_BRIEF.md.template +29 -0
  171. package/templates/core/CLAUDE.md.template +48 -0
  172. package/templates/core/provider.yaml.template +5 -0
  173. package/templates/first-squad/SQUAD.md.template +23 -0
  174. package/templates/first-squad/lead.md.template +44 -0
  175. package/templates/memory/getting-started/state.md.template +19 -0
  176. package/templates/seed/BUSINESS_BRIEF.md.template +27 -0
  177. package/templates/seed/CLAUDE.md.template +119 -0
  178. package/templates/seed/README.md.template +42 -0
  179. package/templates/seed/config/SYSTEM.md +52 -0
  180. package/templates/seed/config/provider.yaml +4 -0
  181. package/templates/seed/hooks/settings.json.template +31 -0
  182. package/templates/seed/memory/company/directives.md +37 -0
  183. package/templates/seed/memory/company/manager/state.md +16 -0
  184. package/templates/seed/memory/engineering/issue-solver/state.md +12 -0
  185. package/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
  186. package/templates/seed/memory/marketing/content-drafter/state.md +12 -0
  187. package/templates/seed/memory/operations/ops-lead/state.md +12 -0
  188. package/templates/seed/memory/product/lead/state.md +14 -0
  189. package/templates/seed/memory/research/lead/state.md +14 -0
  190. package/templates/seed/skills/gh/SKILL.md +57 -0
  191. package/templates/seed/skills/squads-cli/SKILL.md +84 -0
  192. package/templates/seed/squads/company/SQUAD.md +51 -0
  193. package/templates/seed/squads/company/company-critic.md +49 -0
  194. package/templates/seed/squads/company/company-eval.md +49 -0
  195. package/templates/seed/squads/company/event-dispatcher.md +43 -0
  196. package/templates/seed/squads/company/goal-tracker.md +43 -0
  197. package/templates/seed/squads/company/manager.md +54 -0
  198. package/templates/seed/squads/engineering/SQUAD.md +48 -0
  199. package/templates/seed/squads/engineering/code-reviewer.md +57 -0
  200. package/templates/seed/squads/engineering/issue-solver.md +58 -0
  201. package/templates/seed/squads/engineering/test-writer.md +50 -0
  202. package/templates/seed/squads/intelligence/SQUAD.md +38 -0
  203. package/templates/seed/squads/intelligence/intel-critic.md +36 -0
  204. package/templates/seed/squads/intelligence/intel-eval.md +31 -0
  205. package/templates/seed/squads/intelligence/intel-lead.md +71 -0
  206. package/templates/seed/squads/marketing/SQUAD.md +47 -0
  207. package/templates/seed/squads/marketing/content-drafter.md +71 -0
  208. package/templates/seed/squads/marketing/growth-analyst.md +49 -0
  209. package/templates/seed/squads/marketing/social-poster.md +44 -0
  210. package/templates/seed/squads/operations/SQUAD.md +45 -0
  211. package/templates/seed/squads/operations/finance-tracker.md +47 -0
  212. package/templates/seed/squads/operations/goal-tracker.md +48 -0
  213. package/templates/seed/squads/operations/ops-lead.md +58 -0
  214. package/templates/seed/squads/product/SQUAD.md +41 -0
  215. package/templates/seed/squads/product/lead.md +56 -0
  216. package/templates/seed/squads/product/scanner.md +50 -0
  217. package/templates/seed/squads/product/worker.md +55 -0
  218. package/templates/seed/squads/research/SQUAD.md +38 -0
  219. package/templates/seed/squads/research/analyst.md +50 -0
  220. package/templates/seed/squads/research/lead.md +52 -0
  221. package/templates/seed/squads/research/synthesizer.md +59 -0
  222. package/templates/skills/squads-learn/SKILL.md +86 -0
  223. package/templates/skills/squads-workflow/instruction.md +70 -0
@@ -0,0 +1,269 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ Events,
4
+ track
5
+ } from "./chunk-QJ7C7CMB.js";
6
+ import {
7
+ findSquadsDir,
8
+ listSquads
9
+ } from "./chunk-TYFTF53O.js";
10
+ import {
11
+ findMemoryDir
12
+ } from "./chunk-ZTQ7ISUR.js";
13
+ import {
14
+ RESET,
15
+ colors,
16
+ gradient,
17
+ icons,
18
+ writeLine
19
+ } from "./chunk-M5FXNY6Y.js";
20
+ import "./chunk-7OCVIDC7.js";
21
+
22
+ // src/commands/learn.ts
23
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
24
+ import { join, dirname } from "path";
25
+ function parseLearnings(content) {
26
+ const learnings = [];
27
+ const sections = content.split(/\n---\n/).filter((s) => s.trim());
28
+ for (const section of sections) {
29
+ if (section.startsWith("#")) continue;
30
+ const dateMatch = section.match(/_(\d{4}-\d{2}-\d{2})_/);
31
+ const categoryMatch = section.match(/\*\*(\w+)\*\*:/);
32
+ const tagsMatch = section.match(/Tags: `([^`]+)`/);
33
+ const lines = section.split("\n").filter((l) => l.trim() && !l.startsWith("_") && !l.includes("Tags:"));
34
+ const insight = lines.map((l) => l.replace(/^\*\*\w+\*\*:\s*/, "")).join(" ").trim();
35
+ if (dateMatch && insight) {
36
+ learnings.push({
37
+ date: dateMatch[1],
38
+ insight,
39
+ category: categoryMatch?.[1]?.toLowerCase() || "tip",
40
+ tags: tagsMatch?.[1]?.split(",").map((t) => t.trim()) || []
41
+ });
42
+ }
43
+ }
44
+ return learnings;
45
+ }
46
+ function formatLearning(learning) {
47
+ const categoryEmoji = {
48
+ success: "\u25CF",
49
+ failure: "\u2717",
50
+ pattern: "\u25C6",
51
+ tip: "\u2192"
52
+ };
53
+ let entry = `
54
+ ---
55
+ _${learning.date}_
56
+
57
+ `;
58
+ entry += `${categoryEmoji[learning.category]} **${learning.category.charAt(0).toUpperCase() + learning.category.slice(1)}**: ${learning.insight}
59
+ `;
60
+ if (learning.tags.length > 0) {
61
+ entry += `Tags: \`${learning.tags.join(", ")}\`
62
+ `;
63
+ }
64
+ if (learning.context) {
65
+ entry += `
66
+ _Context: ${learning.context}_
67
+ `;
68
+ }
69
+ return entry;
70
+ }
71
+ async function learnCommand(insight, options) {
72
+ let squadName = options.squad || "general";
73
+ if (options.squad) {
74
+ const squadsDir = findSquadsDir();
75
+ if (squadsDir) {
76
+ const squads = listSquads(squadsDir);
77
+ if (!squads.includes(options.squad)) {
78
+ writeLine();
79
+ writeLine(` ${colors.yellow}${icons.warning} Squad '${options.squad}' not found${RESET}`);
80
+ writeLine(` ${colors.dim}Available: ${squads.join(", ")}${RESET}`);
81
+ writeLine(` ${colors.dim}Using 'general' instead${RESET}`);
82
+ squadName = "general";
83
+ }
84
+ }
85
+ }
86
+ const tags = options.tags ? options.tags.split(",").map((t) => t.trim().toLowerCase()) : [];
87
+ if (tags.length === 0) {
88
+ const autoTags = extractTags(insight);
89
+ tags.push(...autoTags);
90
+ }
91
+ const category = options.category || inferCategory(insight);
92
+ const learning = {
93
+ date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
94
+ insight,
95
+ category,
96
+ tags,
97
+ squad: squadName,
98
+ context: options.context
99
+ };
100
+ const memoryDir = findMemoryDir();
101
+ if (!memoryDir) {
102
+ writeLine(` ${colors.red}No .agents/memory directory found${RESET}`);
103
+ writeLine(` ${colors.dim}Run 'squads init' first${RESET}`);
104
+ return;
105
+ }
106
+ const learningsPath = join(memoryDir, squadName, "shared", "learnings.md");
107
+ const dir = dirname(learningsPath);
108
+ if (!existsSync(dir)) {
109
+ mkdirSync(dir, { recursive: true });
110
+ }
111
+ let content = "";
112
+ if (existsSync(learningsPath)) {
113
+ content = readFileSync(learningsPath, "utf-8");
114
+ } else {
115
+ content = `# ${squadName} - Learnings
116
+
117
+ > Accumulated knowledge from sessions
118
+ `;
119
+ }
120
+ content += formatLearning(learning);
121
+ writeFileSync(learningsPath, content);
122
+ await track(Events.CLI_LEARN, {
123
+ squad: squadName,
124
+ category,
125
+ tagCount: tags.length
126
+ });
127
+ writeLine();
128
+ writeLine(` ${icons.success} Learning captured for ${colors.cyan}${squadName}${RESET}`);
129
+ writeLine();
130
+ writeLine(` ${colors.dim}Category:${RESET} ${category}`);
131
+ if (tags.length > 0) {
132
+ writeLine(` ${colors.dim}Tags:${RESET} ${tags.map((t) => `#${t}`).join(" ")}`);
133
+ }
134
+ writeLine();
135
+ writeLine(` ${colors.green}${insight}${RESET}`);
136
+ writeLine();
137
+ }
138
+ async function learnShowCommand(squadName, options) {
139
+ const memoryDir = findMemoryDir();
140
+ if (!memoryDir) {
141
+ writeLine(` ${colors.red}No memory directory found${RESET}`);
142
+ return;
143
+ }
144
+ const learningsPath = join(memoryDir, squadName, "shared", "learnings.md");
145
+ if (!existsSync(learningsPath)) {
146
+ writeLine(` ${colors.yellow}No learnings recorded for ${squadName}${RESET}`);
147
+ writeLine(` ${colors.dim}Add one: squads learn "insight" --squad ${squadName}${RESET}`);
148
+ return;
149
+ }
150
+ const content = readFileSync(learningsPath, "utf-8");
151
+ const learnings = parseLearnings(content);
152
+ let filtered = learnings;
153
+ if (options.category) {
154
+ filtered = filtered.filter((l) => l.category === options.category);
155
+ }
156
+ if (options.tag) {
157
+ const tag = options.tag.toLowerCase();
158
+ filtered = filtered.filter((l) => l.tags.includes(tag));
159
+ }
160
+ const limit = options.limit ? parseInt(options.limit) : 10;
161
+ const recent = filtered.slice(-limit).reverse();
162
+ await track(Events.CLI_LEARN_SHOW, { squad: squadName });
163
+ writeLine();
164
+ writeLine(` ${gradient("squads")} ${colors.dim}learnings${RESET} ${colors.cyan}${squadName}${RESET}`);
165
+ writeLine();
166
+ if (recent.length === 0) {
167
+ writeLine(` ${colors.dim}No learnings found${RESET}`);
168
+ return;
169
+ }
170
+ writeLine(` ${colors.dim}Showing ${recent.length} of ${filtered.length} learnings${RESET}`);
171
+ writeLine();
172
+ const categoryIcon = {
173
+ success: `${colors.green}${icons.success}${RESET}`,
174
+ failure: `${colors.red}\u2717${RESET}`,
175
+ pattern: `${colors.purple}\u25C6${RESET}`,
176
+ tip: `${colors.cyan}\u2192${RESET}`
177
+ };
178
+ for (const learning of recent) {
179
+ writeLine(` ${colors.dim}${learning.date}${RESET} ${categoryIcon[learning.category]} ${learning.insight}`);
180
+ if (learning.tags.length > 0) {
181
+ writeLine(` ${colors.dim}${learning.tags.map((t) => `#${t}`).join(" ")}${RESET}`);
182
+ }
183
+ }
184
+ writeLine();
185
+ }
186
+ async function learnSearchCommand(query, options) {
187
+ const memoryDir = findMemoryDir();
188
+ if (!memoryDir) {
189
+ writeLine(` ${colors.red}No memory directory found${RESET}`);
190
+ return;
191
+ }
192
+ const squadsDir = findSquadsDir();
193
+ const squads = squadsDir ? listSquads(squadsDir) : [];
194
+ squads.push("general");
195
+ const allLearnings = [];
196
+ for (const squad of squads) {
197
+ const learningsPath = join(memoryDir, squad, "shared", "learnings.md");
198
+ if (existsSync(learningsPath)) {
199
+ const content = readFileSync(learningsPath, "utf-8");
200
+ const learnings = parseLearnings(content);
201
+ allLearnings.push(...learnings.map((l) => ({ ...l, squad })));
202
+ }
203
+ }
204
+ const queryLower = query.toLowerCase();
205
+ const matches = allLearnings.filter(
206
+ (l) => l.insight.toLowerCase().includes(queryLower) || l.tags.some((t) => t.includes(queryLower))
207
+ );
208
+ await track(Events.CLI_LEARN_SEARCH, { query, matches: matches.length });
209
+ writeLine();
210
+ writeLine(` ${gradient("squads")} ${colors.dim}search learnings${RESET} "${query}"`);
211
+ writeLine();
212
+ const limit = options.limit ? parseInt(options.limit) : 10;
213
+ const limited = matches.slice(0, limit);
214
+ if (limited.length === 0) {
215
+ writeLine(` ${colors.dim}No learnings found matching "${query}"${RESET}`);
216
+ return;
217
+ }
218
+ writeLine(` ${colors.dim}Found ${matches.length} matches${RESET}`);
219
+ writeLine();
220
+ const categoryIcon = {
221
+ success: `${colors.green}${icons.success}${RESET}`,
222
+ failure: `${colors.red}\u2717${RESET}`,
223
+ pattern: `${colors.purple}\u25C6${RESET}`,
224
+ tip: `${colors.cyan}\u2192${RESET}`
225
+ };
226
+ for (const learning of limited) {
227
+ writeLine(` ${colors.cyan}${learning.squad}${RESET} ${categoryIcon[learning.category]} ${learning.insight}`);
228
+ }
229
+ writeLine();
230
+ }
231
+ function extractTags(insight) {
232
+ const tags = [];
233
+ const lowerInsight = insight.toLowerCase();
234
+ const patterns = {
235
+ "auth": ["auth", "login", "token", "session", "password"],
236
+ "api": ["api", "endpoint", "request", "response", "rest"],
237
+ "bug": ["bug", "fix", "error", "issue", "crash"],
238
+ "perf": ["performance", "slow", "fast", "optimize", "cache"],
239
+ "ux": ["user", "ui", "interface", "design", "experience"],
240
+ "test": ["test", "spec", "coverage", "assert"],
241
+ "db": ["database", "query", "sql", "postgres", "redis"],
242
+ "deploy": ["deploy", "release", "production", "staging"]
243
+ };
244
+ for (const [tag, keywords] of Object.entries(patterns)) {
245
+ if (keywords.some((kw) => lowerInsight.includes(kw))) {
246
+ tags.push(tag);
247
+ }
248
+ }
249
+ return tags.slice(0, 3);
250
+ }
251
+ function inferCategory(insight) {
252
+ const lower = insight.toLowerCase();
253
+ if (lower.includes("worked") || lower.includes("success") || lower.includes("fixed")) {
254
+ return "success";
255
+ }
256
+ if (lower.includes("failed") || lower.includes("error") || lower.includes("didn't work")) {
257
+ return "failure";
258
+ }
259
+ if (lower.includes("pattern") || lower.includes("always") || lower.includes("whenever")) {
260
+ return "pattern";
261
+ }
262
+ return "tip";
263
+ }
264
+ export {
265
+ learnCommand,
266
+ learnSearchCommand,
267
+ learnShowCommand
268
+ };
269
+ //# sourceMappingURL=learn-OIFUVZAS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/learn.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { findMemoryDir } from '../lib/memory.js';\nimport { findSquadsDir, listSquads } from '../lib/squad-parser.js';\nimport {\n colors,\n RESET,\n gradient,\n icons,\n writeLine,\n} from '../lib/terminal.js';\nimport { track, Events } from '../lib/telemetry.js';\n\nexport interface Learning {\n date: string;\n insight: string;\n category: 'success' | 'failure' | 'pattern' | 'tip';\n tags: string[];\n squad?: string;\n context?: string;\n}\n\n/**\n * Parse existing learnings from a file\n */\nfunction parseLearnings(content: string): Learning[] {\n const learnings: Learning[] = [];\n const sections = content.split(/\\n---\\n/).filter(s => s.trim());\n\n for (const section of sections) {\n if (section.startsWith('#')) continue; // Skip header\n\n const dateMatch = section.match(/_(\\d{4}-\\d{2}-\\d{2})_/);\n const categoryMatch = section.match(/\\*\\*(\\w+)\\*\\*:/);\n const tagsMatch = section.match(/Tags: `([^`]+)`/);\n\n // Extract the insight (the main content)\n const lines = section.split('\\n').filter(l => l.trim() && !l.startsWith('_') && !l.includes('Tags:'));\n const insight = lines\n .map(l => l.replace(/^\\*\\*\\w+\\*\\*:\\s*/, ''))\n .join(' ')\n .trim();\n\n if (dateMatch && insight) {\n learnings.push({\n date: dateMatch[1],\n insight,\n category: (categoryMatch?.[1]?.toLowerCase() as Learning['category']) || 'tip',\n tags: tagsMatch?.[1]?.split(',').map(t => t.trim()) || [],\n });\n }\n }\n\n return learnings;\n}\n\n/**\n * Format a learning entry for storage\n */\nfunction formatLearning(learning: Learning): string {\n // Plain unicode for file storage (no ANSI codes)\n const categoryEmoji = {\n success: '●',\n failure: '✗',\n pattern: '◆',\n tip: '→',\n };\n\n let entry = `\\n---\\n_${learning.date}_\\n\\n`;\n entry += `${categoryEmoji[learning.category]} **${learning.category.charAt(0).toUpperCase() + learning.category.slice(1)}**: ${learning.insight}\\n`;\n\n if (learning.tags.length > 0) {\n entry += `Tags: \\`${learning.tags.join(', ')}\\`\\n`;\n }\n\n if (learning.context) {\n entry += `\\n_Context: ${learning.context}_\\n`;\n }\n\n return entry;\n}\n\n/**\n * Add a learning\n */\nexport async function learnCommand(\n insight: string,\n options: {\n squad?: string;\n category?: string;\n tags?: string;\n context?: string;\n }\n): Promise<void> {\n // Determine squad - use provided or default to 'general'\n let squadName = options.squad || 'general';\n\n // Validate squad exists if specified\n if (options.squad) {\n const squadsDir = findSquadsDir();\n if (squadsDir) {\n const squads = listSquads(squadsDir);\n if (!squads.includes(options.squad)) {\n writeLine();\n writeLine(` ${colors.yellow}${icons.warning} Squad '${options.squad}' not found${RESET}`);\n writeLine(` ${colors.dim}Available: ${squads.join(', ')}${RESET}`);\n writeLine(` ${colors.dim}Using 'general' instead${RESET}`);\n squadName = 'general';\n }\n }\n }\n\n // Parse tags\n const tags = options.tags\n ? options.tags.split(',').map(t => t.trim().toLowerCase())\n : [];\n\n // Auto-extract tags from insight if none provided\n if (tags.length === 0) {\n const autoTags = extractTags(insight);\n tags.push(...autoTags);\n }\n\n // Determine category\n const category = (options.category as Learning['category']) || inferCategory(insight);\n\n // Create learning entry\n const learning: Learning = {\n date: new Date().toISOString().split('T')[0],\n insight,\n category,\n tags,\n squad: squadName,\n context: options.context,\n };\n\n // Get or create learnings file\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n writeLine(` ${colors.red}No .agents/memory directory found${RESET}`);\n writeLine(` ${colors.dim}Run 'squads init' first${RESET}`);\n return;\n }\n\n const learningsPath = join(memoryDir, squadName, 'shared', 'learnings.md');\n const dir = dirname(learningsPath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Read existing or create header\n let content = '';\n if (existsSync(learningsPath)) {\n content = readFileSync(learningsPath, 'utf-8');\n } else {\n content = `# ${squadName} - Learnings\\n\\n> Accumulated knowledge from sessions\\n`;\n }\n\n // Append learning\n content += formatLearning(learning);\n writeFileSync(learningsPath, content);\n\n // Track telemetry\n await track(Events.CLI_LEARN, {\n squad: squadName,\n category,\n tagCount: tags.length,\n });\n\n // Display\n writeLine();\n writeLine(` ${icons.success} Learning captured for ${colors.cyan}${squadName}${RESET}`);\n writeLine();\n writeLine(` ${colors.dim}Category:${RESET} ${category}`);\n if (tags.length > 0) {\n writeLine(` ${colors.dim}Tags:${RESET} ${tags.map(t => `#${t}`).join(' ')}`);\n }\n writeLine();\n writeLine(` ${colors.green}${insight}${RESET}`);\n writeLine();\n}\n\n/**\n * Show learnings for a squad\n */\nexport async function learnShowCommand(\n squadName: string,\n options: { limit?: string; category?: string; tag?: string }\n): Promise<void> {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n writeLine(` ${colors.red}No memory directory found${RESET}`);\n return;\n }\n\n const learningsPath = join(memoryDir, squadName, 'shared', 'learnings.md');\n if (!existsSync(learningsPath)) {\n writeLine(` ${colors.yellow}No learnings recorded for ${squadName}${RESET}`);\n writeLine(` ${colors.dim}Add one: squads learn \"insight\" --squad ${squadName}${RESET}`);\n return;\n }\n\n const content = readFileSync(learningsPath, 'utf-8');\n const learnings = parseLearnings(content);\n\n // Filter\n let filtered = learnings;\n if (options.category) {\n filtered = filtered.filter(l => l.category === options.category);\n }\n if (options.tag) {\n const tag = options.tag.toLowerCase();\n filtered = filtered.filter(l => l.tags.includes(tag));\n }\n\n // Limit and reverse (most recent first)\n const limit = options.limit ? parseInt(options.limit) : 10;\n const recent = filtered.slice(-limit).reverse();\n\n // Track\n await track(Events.CLI_LEARN_SHOW, { squad: squadName });\n\n // Display\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}learnings${RESET} ${colors.cyan}${squadName}${RESET}`);\n writeLine();\n\n if (recent.length === 0) {\n writeLine(` ${colors.dim}No learnings found${RESET}`);\n return;\n }\n\n writeLine(` ${colors.dim}Showing ${recent.length} of ${filtered.length} learnings${RESET}`);\n writeLine();\n\n const categoryIcon = {\n success: `${colors.green}${icons.success}${RESET}`,\n failure: `${colors.red}✗${RESET}`,\n pattern: `${colors.purple}◆${RESET}`,\n tip: `${colors.cyan}→${RESET}`,\n };\n\n for (const learning of recent) {\n writeLine(` ${colors.dim}${learning.date}${RESET} ${categoryIcon[learning.category]} ${learning.insight}`);\n if (learning.tags.length > 0) {\n writeLine(` ${colors.dim}${learning.tags.map(t => `#${t}`).join(' ')}${RESET}`);\n }\n }\n writeLine();\n}\n\n/**\n * Search learnings across all squads\n */\nexport async function learnSearchCommand(\n query: string,\n options: { limit?: string }\n): Promise<void> {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n writeLine(` ${colors.red}No memory directory found${RESET}`);\n return;\n }\n\n const squadsDir = findSquadsDir();\n const squads = squadsDir ? listSquads(squadsDir) : [];\n squads.push('general'); // Always check general\n\n const allLearnings: (Learning & { squad: string })[] = [];\n\n for (const squad of squads) {\n const learningsPath = join(memoryDir, squad, 'shared', 'learnings.md');\n if (existsSync(learningsPath)) {\n const content = readFileSync(learningsPath, 'utf-8');\n const learnings = parseLearnings(content);\n allLearnings.push(...learnings.map(l => ({ ...l, squad })));\n }\n }\n\n // Search\n const queryLower = query.toLowerCase();\n const matches = allLearnings.filter(l =>\n l.insight.toLowerCase().includes(queryLower) ||\n l.tags.some(t => t.includes(queryLower))\n );\n\n // Track\n await track(Events.CLI_LEARN_SEARCH, { query, matches: matches.length });\n\n // Display\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}search learnings${RESET} \"${query}\"`);\n writeLine();\n\n const limit = options.limit ? parseInt(options.limit) : 10;\n const limited = matches.slice(0, limit);\n\n if (limited.length === 0) {\n writeLine(` ${colors.dim}No learnings found matching \"${query}\"${RESET}`);\n return;\n }\n\n writeLine(` ${colors.dim}Found ${matches.length} matches${RESET}`);\n writeLine();\n\n const categoryIcon = {\n success: `${colors.green}${icons.success}${RESET}`,\n failure: `${colors.red}✗${RESET}`,\n pattern: `${colors.purple}◆${RESET}`,\n tip: `${colors.cyan}→${RESET}`,\n };\n\n for (const learning of limited) {\n writeLine(` ${colors.cyan}${learning.squad}${RESET} ${categoryIcon[learning.category]} ${learning.insight}`);\n }\n writeLine();\n}\n\n/**\n * Auto-extract tags from insight text\n */\nfunction extractTags(insight: string): string[] {\n const tags: string[] = [];\n const lowerInsight = insight.toLowerCase();\n\n // Common patterns\n const patterns: Record<string, string[]> = {\n 'auth': ['auth', 'login', 'token', 'session', 'password'],\n 'api': ['api', 'endpoint', 'request', 'response', 'rest'],\n 'bug': ['bug', 'fix', 'error', 'issue', 'crash'],\n 'perf': ['performance', 'slow', 'fast', 'optimize', 'cache'],\n 'ux': ['user', 'ui', 'interface', 'design', 'experience'],\n 'test': ['test', 'spec', 'coverage', 'assert'],\n 'db': ['database', 'query', 'sql', 'postgres', 'redis'],\n 'deploy': ['deploy', 'release', 'production', 'staging'],\n };\n\n for (const [tag, keywords] of Object.entries(patterns)) {\n if (keywords.some(kw => lowerInsight.includes(kw))) {\n tags.push(tag);\n }\n }\n\n return tags.slice(0, 3); // Max 3 auto-tags\n}\n\n/**\n * Infer category from insight text\n */\nfunction inferCategory(insight: string): Learning['category'] {\n const lower = insight.toLowerCase();\n\n if (lower.includes('worked') || lower.includes('success') || lower.includes('fixed')) {\n return 'success';\n }\n if (lower.includes('failed') || lower.includes('error') || lower.includes(\"didn't work\")) {\n return 'failure';\n }\n if (lower.includes('pattern') || lower.includes('always') || lower.includes('whenever')) {\n return 'pattern';\n }\n\n return 'tip';\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ clearSession,
4
+ getEmailDomain,
5
+ isPersonalEmail,
6
+ loadSession,
7
+ saveSession,
8
+ startAuthCallbackServer
9
+ } from "./chunk-Z2UKDBNL.js";
10
+ import {
11
+ track
12
+ } from "./chunk-QJ7C7CMB.js";
13
+ import {
14
+ writeLine
15
+ } from "./chunk-M5FXNY6Y.js";
16
+ import "./chunk-7OCVIDC7.js";
17
+
18
+ // src/commands/login.ts
19
+ import chalk from "chalk";
20
+ import ora from "ora";
21
+ import open from "open";
22
+ var AUTH_URL = process.env.SQUADS_AUTH_URL || "";
23
+ var CALLBACK_PORT = 54321;
24
+ async function isAuthEndpointAvailable() {
25
+ try {
26
+ const controller = new AbortController();
27
+ const timeout = setTimeout(() => controller.abort(), 3e3);
28
+ const response = await fetch(AUTH_URL, {
29
+ method: "HEAD",
30
+ signal: controller.signal
31
+ });
32
+ clearTimeout(timeout);
33
+ return response.ok || response.status < 500;
34
+ } catch {
35
+ return false;
36
+ }
37
+ }
38
+ async function loginCommand() {
39
+ const existingSession = loadSession();
40
+ if (existingSession && existingSession.status === "active") {
41
+ writeLine(chalk.green(`\u2713 Already logged in as ${existingSession.email}`));
42
+ writeLine(chalk.dim(` Domain: ${existingSession.domain}`));
43
+ writeLine(chalk.dim(` Run 'squads logout' to sign out.`));
44
+ return;
45
+ }
46
+ const spinner = ora("Checking authentication service...").start();
47
+ const isAvailable = await isAuthEndpointAvailable();
48
+ if (!isAvailable) {
49
+ spinner.stop();
50
+ spinner.clear();
51
+ writeLine(`
52
+ ${chalk.bold.cyan("Pro & Enterprise Login")} ${chalk.yellow("(Coming Soon)")}
53
+ ${chalk.dim("\u2500".repeat(40))}
54
+
55
+ Authentication is coming soon for Pro & Enterprise teams.
56
+
57
+ ${chalk.bold("In the meantime:")}
58
+ ${chalk.dim("\u2192")} Explore the CLI: ${chalk.cyan("squads status")}
59
+ ${chalk.dim("\u2192")} Run agents: ${chalk.cyan("squads run <squad>")}
60
+ ${chalk.dim("\u2192")} Join waitlist: ${chalk.cyan("https://agents-squads.com/waitlist")}
61
+
62
+ ${chalk.dim("Questions?")} ${chalk.cyan("hello@agents-squads.com")}
63
+ `);
64
+ await track("cli.login.unavailable");
65
+ return;
66
+ }
67
+ spinner.text = "Opening browser to authenticate...";
68
+ spinner.succeed();
69
+ writeLine(`
70
+ ${chalk.bold.magenta("Squads CLI Login")}
71
+ ${chalk.dim("\u2500".repeat(40))}
72
+ `);
73
+ const authSpinner = ora("Waiting for authentication...").start();
74
+ try {
75
+ const callbackPromise = startAuthCallbackServer(CALLBACK_PORT);
76
+ const authUrl = `${AUTH_URL}?callback=http://localhost:${CALLBACK_PORT}/callback`;
77
+ await open(authUrl);
78
+ const { email, token } = await callbackPromise;
79
+ if (isPersonalEmail(email)) {
80
+ authSpinner.fail("Personal emails not supported");
81
+ writeLine(`
82
+ ${chalk.yellow("\u26A0 Squads CLI is for Pro & Enterprise teams only.")}
83
+
84
+ Personal email domains (Gmail, Yahoo, etc.) are not supported.
85
+
86
+ ${chalk.dim("Want to stay updated?")}
87
+ \u2192 Get our free research report: ${chalk.cyan("https://agents-squads.com/research")}
88
+ \u2192 Follow us: ${chalk.cyan("https://x.com/agents_squads")}
89
+ `);
90
+ await track("cli.login.personal_email", { domain: getEmailDomain(email) });
91
+ return;
92
+ }
93
+ const session = {
94
+ email,
95
+ domain: getEmailDomain(email),
96
+ status: "pending",
97
+ // Will be 'active' after sales contact
98
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
99
+ accessToken: token
100
+ };
101
+ saveSession(session);
102
+ authSpinner.succeed(`Logged in as ${chalk.cyan(email)}`);
103
+ await track("cli.login.success", { domain: session.domain });
104
+ writeLine(`
105
+ ${chalk.green("\u2713 Thanks for signing up!")}
106
+
107
+ ${chalk.bold("What happens next:")}
108
+ 1. Our team will reach out within 24 hours
109
+ 2. We'll discuss your AI agent needs
110
+ 3. You'll get access to Pro features
111
+
112
+ ${chalk.dim("In the meantime:")}
113
+ \u2192 Explore squads: ${chalk.cyan("squads status")}
114
+ \u2192 Set goals: ${chalk.cyan('squads goal set <squad> "<goal>"')}
115
+ \u2192 Read our research: ${chalk.cyan("https://agents-squads.com/research")}
116
+
117
+ ${chalk.dim("Questions? Email us at")} ${chalk.cyan("hello@agents-squads.com")}
118
+ `);
119
+ } catch (error) {
120
+ authSpinner.fail("Login failed");
121
+ console.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
122
+ }
123
+ }
124
+ async function logoutCommand() {
125
+ const session = loadSession();
126
+ if (!session) {
127
+ writeLine(chalk.yellow("Not logged in."));
128
+ return;
129
+ }
130
+ clearSession();
131
+ writeLine(chalk.green(`\u2713 Logged out from ${session.email}`));
132
+ await track("cli.logout");
133
+ }
134
+ async function whoamiCommand() {
135
+ const session = loadSession();
136
+ if (!session) {
137
+ writeLine(chalk.yellow("Not logged in."));
138
+ writeLine(chalk.dim("Run: squads login"));
139
+ return;
140
+ }
141
+ writeLine(`
142
+ ${chalk.bold("Current Session")}
143
+ ${chalk.dim("\u2500".repeat(30))}
144
+ Email: ${chalk.cyan(session.email)}
145
+ Domain: ${session.domain}
146
+ Status: ${session.status === "active" ? chalk.green("Active") : chalk.yellow("Pending")}
147
+ Since: ${new Date(session.createdAt).toLocaleDateString()}
148
+ `);
149
+ }
150
+ export {
151
+ loginCommand,
152
+ logoutCommand,
153
+ whoamiCommand
154
+ };
155
+ //# sourceMappingURL=login-DXZANWZY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/login.ts"],"sourcesContent":["import chalk from 'chalk';\nimport ora from 'ora';\nimport open from 'open';\nimport {\n isPersonalEmail,\n getEmailDomain,\n saveSession,\n loadSession,\n clearSession,\n startAuthCallbackServer,\n AuthSession\n} from '../lib/auth.js';\nimport { track } from '../lib/telemetry.js';\nimport { writeLine } from '../lib/terminal.js';\n\nconst AUTH_URL = process.env.SQUADS_AUTH_URL || '';\nconst CALLBACK_PORT = 54321;\n\nasync function isAuthEndpointAvailable(): Promise<boolean> {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 3000);\n const response = await fetch(AUTH_URL, {\n method: 'HEAD',\n signal: controller.signal,\n });\n clearTimeout(timeout);\n return response.ok || response.status < 500;\n } catch {\n return false;\n }\n}\n\nexport async function loginCommand(): Promise<void> {\n const existingSession = loadSession();\n\n if (existingSession && existingSession.status === 'active') {\n writeLine(chalk.green(`✓ Already logged in as ${existingSession.email}`));\n writeLine(chalk.dim(` Domain: ${existingSession.domain}`));\n writeLine(chalk.dim(` Run 'squads logout' to sign out.`));\n return;\n }\n\n // Check if auth endpoint is available\n const spinner = ora('Checking authentication service...').start();\n const isAvailable = await isAuthEndpointAvailable();\n\n if (!isAvailable) {\n spinner.stop();\n spinner.clear();\n writeLine(`\n${chalk.bold.cyan('Pro & Enterprise Login')} ${chalk.yellow('(Coming Soon)')}\n${chalk.dim('─'.repeat(40))}\n\nAuthentication is coming soon for Pro & Enterprise teams.\n\n${chalk.bold('In the meantime:')}\n ${chalk.dim('→')} Explore the CLI: ${chalk.cyan('squads status')}\n ${chalk.dim('→')} Run agents: ${chalk.cyan('squads run <squad>')}\n ${chalk.dim('→')} Join waitlist: ${chalk.cyan('https://agents-squads.com/waitlist')}\n\n${chalk.dim('Questions?')} ${chalk.cyan('hello@agents-squads.com')}\n`);\n await track('cli.login.unavailable');\n return;\n }\n\n spinner.text = 'Opening browser to authenticate...';\n spinner.succeed();\n\n writeLine(`\n${chalk.bold.magenta('Squads CLI Login')}\n${chalk.dim('─'.repeat(40))}\n`);\n\n const authSpinner = ora('Waiting for authentication...').start();\n\n try {\n // Start local callback server\n const callbackPromise = startAuthCallbackServer(CALLBACK_PORT);\n\n // Open browser to auth page\n const authUrl = `${AUTH_URL}?callback=http://localhost:${CALLBACK_PORT}/callback`;\n await open(authUrl);\n\n // Wait for callback\n const { email, token } = await callbackPromise;\n\n // Check if personal email\n if (isPersonalEmail(email)) {\n authSpinner.fail('Personal emails not supported');\n writeLine(`\n${chalk.yellow('⚠ Squads CLI is for Pro & Enterprise teams only.')}\n\nPersonal email domains (Gmail, Yahoo, etc.) are not supported.\n\n${chalk.dim('Want to stay updated?')}\n → Get our free research report: ${chalk.cyan('https://agents-squads.com/research')}\n → Follow us: ${chalk.cyan('https://x.com/agents_squads')}\n`);\n\n await track('cli.login.personal_email', { domain: getEmailDomain(email) });\n return;\n }\n\n // Save session\n const session: AuthSession = {\n email,\n domain: getEmailDomain(email),\n status: 'pending', // Will be 'active' after sales contact\n createdAt: new Date().toISOString(),\n accessToken: token,\n };\n\n saveSession(session);\n authSpinner.succeed(`Logged in as ${chalk.cyan(email)}`);\n\n await track('cli.login.success', { domain: session.domain });\n\n writeLine(`\n${chalk.green('✓ Thanks for signing up!')}\n\n${chalk.bold('What happens next:')}\n 1. Our team will reach out within 24 hours\n 2. We'll discuss your AI agent needs\n 3. You'll get access to Pro features\n\n${chalk.dim('In the meantime:')}\n → Explore squads: ${chalk.cyan('squads status')}\n → Set goals: ${chalk.cyan('squads goal set <squad> \"<goal>\"')}\n → Read our research: ${chalk.cyan('https://agents-squads.com/research')}\n\n${chalk.dim('Questions? Email us at')} ${chalk.cyan('hello@agents-squads.com')}\n`);\n\n } catch (error) {\n authSpinner.fail('Login failed');\n console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));\n }\n}\n\nexport async function logoutCommand(): Promise<void> {\n const session = loadSession();\n\n if (!session) {\n writeLine(chalk.yellow('Not logged in.'));\n return;\n }\n\n clearSession();\n writeLine(chalk.green(`✓ Logged out from ${session.email}`));\n await track('cli.logout');\n}\n\nexport async function whoamiCommand(): Promise<void> {\n const session = loadSession();\n\n if (!session) {\n writeLine(chalk.yellow('Not logged in.'));\n writeLine(chalk.dim('Run: squads login'));\n return;\n }\n\n writeLine(`\n${chalk.bold('Current Session')}\n${chalk.dim('─'.repeat(30))}\nEmail: ${chalk.cyan(session.email)}\nDomain: ${session.domain}\nStatus: ${session.status === 'active' ? chalk.green('Active') : chalk.yellow('Pending')}\nSince: ${new Date(session.createdAt).toLocaleDateString()}\n`);\n}\n"],"mappings":"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","names":[]}