@use-aistack/cli 0.1.0 → 0.2.0

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/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import { Command } from "commander";
5
5
 
6
6
  // src/commands/login.ts
7
- import * as p from "@clack/prompts";
7
+ import * as p2 from "@clack/prompts";
8
8
  import open from "open";
9
9
 
10
10
  // src/api.ts
@@ -54,13 +54,23 @@ async function projectsCollect(token, data) {
54
54
  if (res.status === 401)
55
55
  throw new Error("Authentication expired. Run `aistack login` again.");
56
56
  if (!res.ok) {
57
- const body = await res.json().catch(() => ({}));
58
- throw new Error(
59
- body.error || `Collect failed: ${res.status}`
60
- );
57
+ throw new Error(await formatHttpError(res, "Collect failed"));
61
58
  }
62
59
  return res.json();
63
60
  }
61
+ async function formatHttpError(res, label) {
62
+ const prefix = `${label}: ${res.status} ${res.statusText || ""}`.trim();
63
+ const text2 = await res.text().catch(() => "");
64
+ if (!text2) return prefix;
65
+ try {
66
+ const body = JSON.parse(text2);
67
+ const detail = body.error || body.message;
68
+ if (detail) return `${prefix} \u2014 ${detail}`;
69
+ } catch {
70
+ }
71
+ const snippet = text2.trim().slice(0, 500);
72
+ return snippet ? `${prefix} \u2014 ${snippet}` : prefix;
73
+ }
64
74
  async function projectGet(shortId) {
65
75
  const res = await request(`/api/cli/projects/${encodeURIComponent(shortId)}`);
66
76
  if (res.status === 404) return null;
@@ -127,6 +137,7 @@ function saveProjectSettings(directory, name, excluded) {
127
137
  }
128
138
 
129
139
  // src/theme.ts
140
+ import * as p from "@clack/prompts";
130
141
  var esc = (code) => `\x1B[${code}m`;
131
142
  var reset = esc("0");
132
143
  var LIME = "163;230;53";
@@ -156,11 +167,31 @@ function section(label, count) {
156
167
  function divider() {
157
168
  console.log(`${BAR} ${dim("\u2500".repeat(40))}`);
158
169
  }
170
+ function intro2(cmd) {
171
+ console.log();
172
+ p.intro(banner(cmd));
173
+ }
174
+ function outro2(msg) {
175
+ p.outro(msg);
176
+ console.log();
177
+ }
178
+ function outroError(msg) {
179
+ p.outro(red(msg));
180
+ console.log();
181
+ }
182
+ function outroCancel(msg = "cancelled") {
183
+ p.cancel(dim(msg));
184
+ console.log();
185
+ }
186
+ function outroSkipped(msg) {
187
+ p.outro(dim(msg));
188
+ console.log();
189
+ }
159
190
 
160
191
  // src/commands/login.ts
161
192
  async function loginCommand() {
162
- p.intro(banner("login"));
163
- const s = p.spinner();
193
+ intro2("login");
194
+ const s = p2.spinner();
164
195
  s.start("Starting authentication...");
165
196
  let session;
166
197
  try {
@@ -168,15 +199,16 @@ async function loginCommand() {
168
199
  s.stop("Session created");
169
200
  } catch (err) {
170
201
  s.stop("Failed to start authentication");
171
- p.log.error(err instanceof Error ? err.message : String(err));
202
+ p2.log.error(err instanceof Error ? err.message : String(err));
203
+ outroError("error");
172
204
  process.exit(1);
173
205
  }
174
- p.log.info(`${dim("CODE")} ${limeBold(session.userCode)}`);
175
- p.log.info(`${dim("OPEN")} ${dim(session.authUrl)}`);
206
+ p2.log.info(`${dim("CODE")} ${limeBold(session.userCode)}`);
207
+ p2.log.info(`${dim("OPEN")} ${dim(session.authUrl)}`);
176
208
  try {
177
209
  await open(session.authUrl);
178
210
  } catch {
179
- p.log.warn(
211
+ p2.log.warn(
180
212
  "Could not open browser automatically. Please visit the URL above."
181
213
  );
182
214
  }
@@ -189,30 +221,33 @@ async function loginCommand() {
189
221
  if (result.status === "approved" && result.token) {
190
222
  s.stop(lime("Authenticated"));
191
223
  saveToken(result.token, result.userId);
192
- p.log.success(
224
+ p2.log.success(
193
225
  `Token saved. Run ${limeBold("aistack collect")} to get started.`
194
226
  );
195
- p.outro(lime("done"));
227
+ outro2(lime("done"));
196
228
  return;
197
229
  }
198
230
  if (result.status === "expired") {
199
231
  s.stop("Session expired");
200
- p.log.error("Authentication session expired. Please try again.");
232
+ p2.log.error("Authentication session expired. Please try again.");
233
+ outroError("expired");
201
234
  process.exit(1);
202
235
  }
203
236
  } catch (err) {
204
237
  s.stop("Error polling");
205
- p.log.error(err instanceof Error ? err.message : String(err));
238
+ p2.log.error(err instanceof Error ? err.message : String(err));
239
+ outroError("error");
206
240
  process.exit(1);
207
241
  }
208
242
  }
209
243
  s.stop("Timed out");
210
- p.log.error("Authentication timed out after 3 minutes. Please try again.");
244
+ p2.log.error("Authentication timed out after 3 minutes. Please try again.");
245
+ outroError("timed out");
211
246
  process.exit(1);
212
247
  }
213
248
 
214
249
  // src/commands/collect.ts
215
- import * as p2 from "@clack/prompts";
250
+ import * as p3 from "@clack/prompts";
216
251
  import { basename as basename2 } from "path";
217
252
 
218
253
  // src/scanner.ts
@@ -223,32 +258,39 @@ import ignore from "ignore";
223
258
  var MAX_FILE_SIZE = 100 * 1024;
224
259
  var LOCAL_PATTERNS = [
225
260
  // Rules
226
- { path: "CLAUDE.md", type: "rule" },
227
- { path: "AGENTS.md", type: "rule" },
228
- { path: ".cursorrules", type: "rule" },
229
- { path: ".windsurfrules", type: "rule" },
230
- { path: ".clinerules", type: "rule" },
231
- { path: ".github/copilot-instructions.md", type: "rule" },
261
+ { path: "CLAUDE.md", type: "rule", group: "claude-code" },
262
+ { path: "AGENTS.md", type: "rule", group: "claude-code" },
263
+ { path: ".cursorrules", type: "rule", group: "cursor" },
264
+ { path: ".windsurfrules", type: "rule", group: "windsurf" },
265
+ { path: ".clinerules", type: "rule", group: "cline" },
266
+ { path: ".github/copilot-instructions.md", type: "rule", group: "copilot" },
232
267
  // MCP
233
- { path: "mcp.json", type: "mcp" },
234
- { path: ".cursor/mcp.json", type: "mcp" },
235
- { path: "claude_desktop_config.json", type: "mcp" },
268
+ { path: "mcp.json", type: "mcp", group: "generic" },
269
+ { path: ".cursor/mcp.json", type: "mcp", group: "cursor" },
270
+ {
271
+ path: "claude_desktop_config.json",
272
+ type: "mcp",
273
+ group: "claude-desktop"
274
+ },
236
275
  // Config
237
- { path: ".aider.conf.yml", type: "config" },
238
- { path: ".continue/config.json", type: "config" },
239
- // Config
240
- { path: ".claude/settings.json", type: "config" },
241
- { path: ".claude/settings.local.json", type: "config" },
276
+ { path: ".aider.conf.yml", type: "config", group: "aider" },
277
+ { path: ".continue/config.json", type: "config", group: "continue" },
278
+ { path: ".claude/settings.json", type: "config", group: "claude-code" },
279
+ {
280
+ path: ".claude/settings.local.json",
281
+ type: "config",
282
+ group: "claude-code"
283
+ },
242
284
  // Prompts
243
- { path: "system-prompt.md", type: "prompt" }
285
+ { path: "system-prompt.md", type: "prompt", group: "generic" }
244
286
  ];
245
287
  var LOCAL_DIR_PATTERNS = [
246
- { dir: ".cursor/rules", type: "rule" },
247
- { dir: ".claude/commands", type: "command" },
248
- { dir: ".claude/agents", type: "subagent" },
249
- { dir: ".claude/hooks", type: "hook" },
250
- { dir: "prompts", type: "prompt" },
251
- { dir: ".ai", type: "custom" }
288
+ { dir: ".cursor/rules", type: "rule", group: "cursor" },
289
+ { dir: ".claude/commands", type: "command", group: "claude-code" },
290
+ { dir: ".claude/agents", type: "subagent", group: "claude-code" },
291
+ { dir: ".claude/hooks", type: "hook", group: "claude-code" },
292
+ { dir: "prompts", type: "prompt", group: "generic" },
293
+ { dir: ".ai", type: "custom", group: "generic" }
252
294
  ];
253
295
  function loadGitignore(cwd) {
254
296
  const ig = ignore();
@@ -298,12 +340,13 @@ function scanLocal(cwd) {
298
340
  relativePath: rel,
299
341
  content,
300
342
  type: pattern.type,
301
- source: "local"
343
+ source: "local",
344
+ group: pattern.group
302
345
  });
303
346
  }
304
347
  }
305
348
  }
306
- for (const { dir, type } of LOCAL_DIR_PATTERNS) {
349
+ for (const { dir, type, group } of LOCAL_DIR_PATTERNS) {
307
350
  const dirPath = join2(cwd, dir);
308
351
  const files = walkDir(dirPath);
309
352
  for (const filePath of files) {
@@ -316,7 +359,8 @@ function scanLocal(cwd) {
316
359
  relativePath: rel,
317
360
  content,
318
361
  type,
319
- source: "local"
362
+ source: "local",
363
+ group
320
364
  });
321
365
  }
322
366
  }
@@ -347,7 +391,8 @@ function scanSkillDirs(dir, cwd, ig, results, depth) {
347
391
  relativePath: rel,
348
392
  content,
349
393
  type: "skill",
350
- source: "local"
394
+ source: "local",
395
+ group: "generic"
351
396
  });
352
397
  }
353
398
  }
@@ -369,11 +414,11 @@ function scanGlobal() {
369
414
  const home = homedir2();
370
415
  const results = [];
371
416
  const globalPatterns = [
372
- { path: ".claude/CLAUDE.md", type: "rule" },
373
- { path: ".claude/settings.json", type: "config" },
374
- { path: ".cursor/mcp.json", type: "mcp" },
375
- { path: ".continue/config.json", type: "config" },
376
- { path: ".aider.conf.yml", type: "config" }
417
+ { path: ".claude/CLAUDE.md", type: "rule", group: "claude-code" },
418
+ { path: ".claude/settings.json", type: "config", group: "claude-code" },
419
+ { path: ".cursor/mcp.json", type: "mcp", group: "cursor" },
420
+ { path: ".continue/config.json", type: "config", group: "continue" },
421
+ { path: ".aider.conf.yml", type: "config", group: "aider" }
377
422
  ];
378
423
  for (const pattern of globalPatterns) {
379
424
  const filePath = join2(home, pattern.path);
@@ -384,17 +429,18 @@ function scanGlobal() {
384
429
  relativePath: `~/${pattern.path}`,
385
430
  content,
386
431
  type: pattern.type,
387
- source: "global"
432
+ source: "global",
433
+ group: pattern.group
388
434
  });
389
435
  }
390
436
  }
391
437
  const globalDirs = [
392
- { dir: ".claude/commands", type: "command" },
393
- { dir: ".claude/agents", type: "subagent" },
394
- { dir: ".claude/hooks", type: "hook" },
395
- { dir: ".cursor/rules", type: "rule" }
438
+ { dir: ".claude/commands", type: "command", group: "claude-code" },
439
+ { dir: ".claude/agents", type: "subagent", group: "claude-code" },
440
+ { dir: ".claude/hooks", type: "hook", group: "claude-code" },
441
+ { dir: ".cursor/rules", type: "rule", group: "cursor" }
396
442
  ];
397
- for (const { dir, type } of globalDirs) {
443
+ for (const { dir, type, group } of globalDirs) {
398
444
  const dirPath = join2(home, dir);
399
445
  const files = walkDir(dirPath, 2);
400
446
  for (const filePath of files) {
@@ -405,7 +451,8 @@ function scanGlobal() {
405
451
  relativePath: `~/${relative(home, filePath)}`,
406
452
  content,
407
453
  type,
408
- source: "global"
454
+ source: "global",
455
+ group
409
456
  });
410
457
  }
411
458
  }
@@ -415,45 +462,75 @@ function scanGlobal() {
415
462
 
416
463
  // src/classifier.ts
417
464
  import { basename, dirname } from "path";
465
+
466
+ // src/stableKey.ts
467
+ function computeStableKey(group, type, relPath) {
468
+ return `${group}:${type}:${relPath}`;
469
+ }
470
+
471
+ // src/classifier.ts
418
472
  function classify(files) {
419
- const skillDirs = /* @__PURE__ */ new Map();
420
- const nonSkillFiles = [];
473
+ const groups = /* @__PURE__ */ new Map();
474
+ const singletons = [];
475
+ const singletonRoots = /* @__PURE__ */ new Set([
476
+ ".",
477
+ "~",
478
+ "~/.claude",
479
+ "~/.cursor",
480
+ "~/.continue",
481
+ ".claude",
482
+ ".cursor",
483
+ ".github"
484
+ ]);
421
485
  for (const file of files) {
422
- if (file.type === "skill") {
423
- const dir = dirname(file.relativePath);
424
- const existing = skillDirs.get(dir) ?? [];
425
- existing.push(file);
426
- skillDirs.set(dir, existing);
486
+ const dir = dirname(file.relativePath);
487
+ const isSingleton = singletonRoots.has(dir);
488
+ if (isSingleton) {
489
+ singletons.push(file);
427
490
  } else {
428
- nonSkillFiles.push(file);
491
+ const key = `${file.group}:${file.source}:${file.type}:${dir}`;
492
+ const existing = groups.get(key) ?? [];
493
+ existing.push(file);
494
+ groups.set(key, existing);
429
495
  }
430
496
  }
431
497
  const items = [];
432
- for (const file of nonSkillFiles) {
433
- const tags = file.source === "global" ? ["global"] : void 0;
498
+ const scope = (source) => source === "global" ? "global" : "project";
499
+ for (const file of singletons) {
500
+ const s = scope(file.source);
501
+ const relPath = file.relativePath.replace(/^~\/\.[^/]+\//, "").replace(/^\.[^/]+\//, "");
434
502
  items.push({
435
503
  type: file.type,
436
504
  name: file.relativePath,
505
+ group: file.group,
506
+ scope: s,
507
+ stableKey: computeStableKey(file.group, file.type, relPath),
437
508
  files: [
438
509
  {
439
510
  name: basename(file.relativePath),
440
511
  content: file.content,
441
- path: file.relativePath,
442
- tags
512
+ path: file.relativePath
443
513
  }
444
514
  ]
445
515
  });
446
516
  }
447
- for (const [dir, dirFiles] of skillDirs) {
448
- const isGlobal = dirFiles[0]?.source === "global";
517
+ for (const [, groupFiles] of groups) {
518
+ const first = groupFiles[0];
519
+ const dir = dirname(first.relativePath);
520
+ const s = scope(first.source);
521
+ const relPath = dir.replace(/^~\/\.claude\//, "").replace(/^\.claude\//, "").replace(/^~\/\.cursor\//, "").replace(/^\.cursor\//, "");
522
+ const typeLabel = first.type === "subagent" ? "subagents" : `${first.type}s`;
449
523
  items.push({
450
- type: "skill",
524
+ type: first.type,
451
525
  name: dir,
452
- files: dirFiles.map((f) => ({
526
+ description: `${groupFiles.length} ${typeLabel}`,
527
+ group: first.group,
528
+ scope: s,
529
+ stableKey: computeStableKey(first.group, first.type, relPath),
530
+ files: groupFiles.map((f) => ({
453
531
  name: basename(f.relativePath),
454
532
  content: f.content,
455
- path: f.relativePath,
456
- tags: isGlobal ? ["global"] : void 0
533
+ path: f.relativePath
457
534
  }))
458
535
  });
459
536
  }
@@ -462,38 +539,39 @@ function classify(files) {
462
539
 
463
540
  // src/commands/collect.ts
464
541
  async function collectCommand(options) {
465
- p2.intro(banner("collect"));
542
+ intro2("collect");
466
543
  const token = getToken();
467
544
  if (!token) {
468
- p2.log.error(`Not authenticated. Run ${limeBold("aistack login")} first.`);
545
+ p3.log.error(`Not authenticated. Run ${limeBold("aistack login")} first.`);
546
+ outroError("not authenticated");
469
547
  process.exit(1);
470
548
  }
471
549
  const cwd = process.cwd();
472
550
  const savedName = getProjectName(cwd);
473
551
  const savedExcluded = getExcludedPaths(cwd);
474
- const s = p2.spinner();
552
+ const s = p3.spinner();
475
553
  s.start("Scanning...");
476
554
  const localFiles = scanLocal(cwd);
477
555
  const globalFiles = options.global ? scanGlobal() : [];
478
556
  s.stop("Scan complete");
479
557
  if (localFiles.length === 0 && globalFiles.length === 0) {
480
- p2.log.warn("No AI configuration files found.");
481
- p2.outro(dim("nothing to collect"));
558
+ p3.log.warn("No AI configuration files found.");
559
+ outroSkipped("nothing to collect");
482
560
  return;
483
561
  }
484
562
  let projectName;
485
563
  if (savedName) {
486
- p2.log.info(`${dim("PROJECT")} ${limeBold(savedName)}`);
564
+ p3.log.info(`${dim("PROJECT")} ${limeBold(savedName)}`);
487
565
  projectName = savedName;
488
566
  } else {
489
567
  const defaultName = basename2(cwd);
490
- const name = await p2.text({
568
+ const name = await p3.text({
491
569
  message: "Project name:",
492
570
  defaultValue: defaultName,
493
571
  placeholder: defaultName
494
572
  });
495
- if (p2.isCancel(name)) {
496
- p2.cancel("Cancelled.");
573
+ if (p3.isCancel(name)) {
574
+ outroCancel();
497
575
  process.exit(0);
498
576
  }
499
577
  projectName = name || defaultName;
@@ -503,7 +581,7 @@ async function collectCommand(options) {
503
581
  (f) => !savedExcluded.includes(f.relativePath)
504
582
  );
505
583
  let excluded = allFiles.filter((f) => savedExcluded.includes(f.relativePath));
506
- p2.log.info(
584
+ p3.log.info(
507
585
  `${lime(String(selectedFiles.length))} included${excluded.length > 0 ? ` \xB7 ${dim(String(excluded.length) + " excluded")}` : ""}`
508
586
  );
509
587
  let allInstructions = classify(selectedFiles);
@@ -515,7 +593,8 @@ async function collectCommand(options) {
515
593
  existingProject = await projectGet(shortId);
516
594
  }
517
595
  } catch (err) {
518
- p2.log.error(err instanceof Error ? err.message : String(err));
596
+ p3.log.error(err instanceof Error ? err.message : String(err));
597
+ outroError("error");
519
598
  process.exit(1);
520
599
  }
521
600
  if (existingProject) {
@@ -524,8 +603,8 @@ async function collectCommand(options) {
524
603
  existingProject.instructions
525
604
  );
526
605
  if (diff.changed === 0 && diff.added === 0 && diff.removed === 0) {
527
- p2.log.info("No changes since last collect.");
528
- p2.outro(dim("nothing to upload"));
606
+ p3.log.info("No changes since last collect.");
607
+ outroSkipped("nothing to upload");
529
608
  return;
530
609
  }
531
610
  divider();
@@ -545,7 +624,7 @@ async function collectCommand(options) {
545
624
  const local = selectedFiles.filter((f) => f.source === "local");
546
625
  const global = selectedFiles.filter((f) => f.source === "global");
547
626
  if (local.length > 0) {
548
- p2.log.step(`${bold("LOCAL")} ${dim(String(local.length))}`);
627
+ p3.log.step(`${bold("LOCAL")} ${dim(String(local.length))}`);
549
628
  divider();
550
629
  for (const [type, files] of groupByType(local)) {
551
630
  lines([`${lime(type.toUpperCase())} ${dim(`${files.length}`)}`]);
@@ -554,7 +633,7 @@ async function collectCommand(options) {
554
633
  divider();
555
634
  }
556
635
  if (global.length > 0) {
557
- p2.log.step(`${bold("GLOBAL")} ${dim(String(global.length))}`);
636
+ p3.log.step(`${bold("GLOBAL")} ${dim(String(global.length))}`);
558
637
  divider();
559
638
  for (const [type, files] of groupByType(global)) {
560
639
  lines([`${lime(type.toUpperCase())} ${dim(`${files.length}`)}`]);
@@ -563,7 +642,7 @@ async function collectCommand(options) {
563
642
  divider();
564
643
  }
565
644
  }
566
- const action = await p2.select({
645
+ const action = await p3.select({
567
646
  message: existingProject ? "Upload changes?" : `Upload ${bold(String(selectedFiles.length))} files as ${limeBold(projectName)}?`,
568
647
  options: [
569
648
  { value: "upload", label: "Upload" },
@@ -571,12 +650,12 @@ async function collectCommand(options) {
571
650
  { value: "cancel", label: "Cancel" }
572
651
  ]
573
652
  });
574
- if (p2.isCancel(action) || action === "cancel") {
575
- p2.cancel("Cancelled.");
653
+ if (p3.isCancel(action) || action === "cancel") {
654
+ outroCancel();
576
655
  process.exit(0);
577
656
  }
578
657
  if (action === "customize") {
579
- const selected = await p2.multiselect({
658
+ const selected = await p3.multiselect({
580
659
  message: "Select files to include:",
581
660
  options: allFiles.map((f) => ({
582
661
  value: f.relativePath,
@@ -585,8 +664,8 @@ async function collectCommand(options) {
585
664
  })),
586
665
  initialValues: selectedFiles.map((f) => f.relativePath)
587
666
  });
588
- if (p2.isCancel(selected)) {
589
- p2.cancel("Cancelled.");
667
+ if (p3.isCancel(selected)) {
668
+ outroCancel();
590
669
  process.exit(0);
591
670
  }
592
671
  const selectedSet = new Set(selected);
@@ -594,8 +673,8 @@ async function collectCommand(options) {
594
673
  excluded = allFiles.filter((f) => !selectedSet.has(f.relativePath));
595
674
  allInstructions = classify(selectedFiles);
596
675
  if (selectedFiles.length === 0) {
597
- p2.log.warn("No files selected.");
598
- p2.outro(dim("nothing to collect"));
676
+ p3.log.warn("No files selected.");
677
+ outroSkipped("nothing to collect");
599
678
  process.exit(0);
600
679
  }
601
680
  }
@@ -611,11 +690,12 @@ async function collectCommand(options) {
611
690
  projectName,
612
691
  excluded.map((f) => f.relativePath)
613
692
  );
614
- p2.log.success(dim(result.url));
615
- p2.outro(lime("done"));
693
+ p3.log.success(dim(result.url));
694
+ outro2(lime("done"));
616
695
  } catch (err) {
617
696
  s.stop("Upload failed");
618
- p2.log.error(err instanceof Error ? err.message : String(err));
697
+ p3.log.error(err instanceof Error ? err.message : String(err));
698
+ outroError("upload failed");
619
699
  process.exit(1);
620
700
  }
621
701
  }
@@ -687,12 +767,12 @@ function diffInstructions(current, existing) {
687
767
  }
688
768
 
689
769
  // src/commands/create.ts
690
- import * as p3 from "@clack/prompts";
770
+ import * as p4 from "@clack/prompts";
691
771
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
692
772
  import { dirname as dirname2, join as join3 } from "path";
693
773
  async function createCommand(slugOrShortId) {
694
- p3.intro(banner("create"));
695
- const s = p3.spinner();
774
+ intro2("create");
775
+ const s = p4.spinner();
696
776
  s.start("Fetching project...");
697
777
  const shortId = slugOrShortId.includes("-") ? slugOrShortId.slice(slugOrShortId.lastIndexOf("-") + 1) : slugOrShortId;
698
778
  let project;
@@ -700,21 +780,23 @@ async function createCommand(slugOrShortId) {
700
780
  project = await projectGet(shortId);
701
781
  if (!project) {
702
782
  s.stop("Not found");
703
- p3.log.error(`Project "${slugOrShortId}" not found.`);
783
+ p4.log.error(`Project "${slugOrShortId}" not found.`);
784
+ outroError("not found");
704
785
  process.exit(1);
705
786
  }
706
787
  s.stop(bold(project.name));
707
788
  } catch (err) {
708
789
  s.stop("Failed to fetch project");
709
- p3.log.error(err instanceof Error ? err.message : String(err));
790
+ p4.log.error(err instanceof Error ? err.message : String(err));
791
+ outroError("error");
710
792
  process.exit(1);
711
793
  }
712
794
  const localFiles = [];
713
795
  const globalFiles = [];
714
796
  for (const item of project.instructions) {
797
+ const isGlobal = item.scope === "global";
715
798
  for (const file of item.files) {
716
799
  const writePath = file.path ?? file.name;
717
- const isGlobal = file.tags?.includes("global");
718
800
  if (isGlobal) {
719
801
  globalFiles.push({ path: writePath, content: file.content });
720
802
  } else {
@@ -728,8 +810,8 @@ async function createCommand(slugOrShortId) {
728
810
  lines(globalFiles.map((f) => dim(f.path)));
729
811
  }
730
812
  if (localFiles.length === 0) {
731
- p3.log.warn("No local files to write.");
732
- p3.outro(dim("nothing to create"));
813
+ p4.log.warn("No local files to write.");
814
+ outroSkipped("nothing to create");
733
815
  return;
734
816
  }
735
817
  const cwd = process.cwd();
@@ -753,16 +835,16 @@ async function createCommand(slugOrShortId) {
753
835
  );
754
836
  if (toWrite.length === 0) {
755
837
  divider();
756
- p3.log.info("All local files already exist.");
757
- p3.outro(dim("nothing to write"));
838
+ p4.log.info("All local files already exist.");
839
+ outroSkipped("nothing to write");
758
840
  return;
759
841
  }
760
842
  divider();
761
- const confirm2 = await p3.confirm({
843
+ const confirm2 = await p4.confirm({
762
844
  message: `Write ${lime(String(toWrite.length))} new files? ${dim(`(${skipped.length} skipped)`)}`
763
845
  });
764
- if (p3.isCancel(confirm2) || !confirm2) {
765
- p3.cancel("Cancelled.");
846
+ if (p4.isCancel(confirm2) || !confirm2) {
847
+ outroCancel();
766
848
  process.exit(0);
767
849
  }
768
850
  for (const f of toWrite) {
@@ -771,10 +853,10 @@ async function createCommand(slugOrShortId) {
771
853
  mkdirSync2(dir, { recursive: true });
772
854
  writeFileSync2(fullPath, f.content);
773
855
  }
774
- p3.log.success(
856
+ p4.log.success(
775
857
  `${lime(String(toWrite.length))} written, ${dim(String(skipped.length) + " skipped")}`
776
858
  );
777
- p3.outro(lime("done"));
859
+ outro2(lime("done"));
778
860
  }
779
861
 
780
862
  // src/index.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/api.ts","../src/config.ts","../src/theme.ts","../src/commands/collect.ts","../src/scanner.ts","../src/classifier.ts","../src/commands/create.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { loginCommand } from \"./commands/login.js\";\nimport { collectCommand } from \"./commands/collect.js\";\nimport { createCommand } from \"./commands/create.js\";\n\nconst program = new Command();\n\nprogram\n\t.name(\"aistack\")\n\t.description(\"Share and clone AI development configurations\")\n\t.version(\"0.1.0\");\n\nprogram\n\t.command(\"login\")\n\t.description(\"Authenticate with AI Stack\")\n\t.action(loginCommand);\n\nprogram\n\t.command(\"collect\")\n\t.description(\"Scan and upload AI config files from your project\")\n\t.option(\"--no-global\", \"Exclude global config files (~/.claude, etc.)\")\n\t.action((options) => collectCommand({ global: options.global ?? true }));\n\nprogram\n\t.command(\"create\")\n\t.description(\"Download and write AI config files from a shared project\")\n\t.argument(\"<slug>\", \"Project slug or short ID\")\n\t.action(createCommand);\n\nprogram.parse();\n","import * as p from \"@clack/prompts\";\nimport open from \"open\";\nimport { authStart, authPoll } from \"../api.js\";\nimport { saveToken } from \"../config.js\";\nimport { banner, dim, lime, limeBold } from \"../theme.js\";\n\nexport async function loginCommand() {\n\tp.intro(banner(\"login\"));\n\n\tconst s = p.spinner();\n\ts.start(\"Starting authentication...\");\n\n\tlet session: Awaited<ReturnType<typeof authStart>>;\n\ttry {\n\t\tsession = await authStart();\n\t\ts.stop(\"Session created\");\n\t} catch (err) {\n\t\ts.stop(\"Failed to start authentication\");\n\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\tprocess.exit(1);\n\t}\n\n\tp.log.info(`${dim(\"CODE\")} ${limeBold(session.userCode)}`);\n\tp.log.info(`${dim(\"OPEN\")} ${dim(session.authUrl)}`);\n\n\ttry {\n\t\tawait open(session.authUrl);\n\t} catch {\n\t\tp.log.warn(\n\t\t\t\"Could not open browser automatically. Please visit the URL above.\",\n\t\t);\n\t}\n\n\ts.start(\"Waiting for approval...\");\n\n\tconst maxAttempts = 36;\n\tfor (let i = 0; i < maxAttempts; i++) {\n\t\tawait new Promise((resolve) => setTimeout(resolve, 5000));\n\n\t\ttry {\n\t\t\tconst result = await authPoll(session.secretId);\n\n\t\t\tif (result.status === \"approved\" && result.token) {\n\t\t\t\ts.stop(lime(\"Authenticated\"));\n\t\t\t\tsaveToken(result.token, result.userId);\n\t\t\t\tp.log.success(\n\t\t\t\t\t`Token saved. Run ${limeBold(\"aistack collect\")} to get started.`,\n\t\t\t\t);\n\t\t\t\tp.outro(lime(\"done\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (result.status === \"expired\") {\n\t\t\t\ts.stop(\"Session expired\");\n\t\t\t\tp.log.error(\"Authentication session expired. Please try again.\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\ts.stop(\"Error polling\");\n\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\ts.stop(\"Timed out\");\n\tp.log.error(\"Authentication timed out after 3 minutes. Please try again.\");\n\tprocess.exit(1);\n}\n","const BASE_URL = process.env.AISTACK_URL || \"https://aistack.to\";\n\nasync function request(\n\tpath: string,\n\toptions: RequestInit = {},\n): Promise<Response> {\n\treturn fetch(`${BASE_URL}${path}`, {\n\t\t...options,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t...options.headers,\n\t\t},\n\t});\n}\n\nfunction authHeaders(token: string): HeadersInit {\n\treturn { Authorization: `Bearer ${token}` };\n}\n\nexport async function authStart(): Promise<{\n\tsecretId: string;\n\tuserCode: string;\n\tauthUrl: string;\n}> {\n\tconst res = await request(\"/api/cli/auth/start\", { method: \"POST\" });\n\tif (!res.ok) throw new Error(`Auth start failed: ${res.status}`);\n\treturn res.json();\n}\n\nexport async function authPoll(\n\tsecretId: string,\n): Promise<{ status: string; token?: string; userId?: string }> {\n\tconst res = await request(\n\t\t`/api/cli/auth/poll?secretId=${encodeURIComponent(secretId)}`,\n\t);\n\tif (!res.ok) throw new Error(`Auth poll failed: ${res.status}`);\n\treturn res.json();\n}\n\nexport async function projectsCheck(\n\ttoken: string,\n\tname: string,\n): Promise<{ exists: boolean; slug?: string }> {\n\tconst res = await request(\n\t\t`/api/cli/projects/check?name=${encodeURIComponent(name)}`,\n\t\t{\n\t\t\theaders: authHeaders(token),\n\t\t},\n\t);\n\tif (res.status === 401)\n\t\tthrow new Error(\"Authentication expired. Run `aistack login` again.\");\n\tif (!res.ok) throw new Error(`Project check failed: ${res.status}`);\n\treturn res.json();\n}\n\nexport async function projectsCollect(\n\ttoken: string,\n\tdata: { name: string; instructions: InstructionItem[] },\n): Promise<{ slug: string; shortId: string; url: string }> {\n\tconst res = await request(\"/api/cli/projects/collect\", {\n\t\tmethod: \"POST\",\n\t\theaders: authHeaders(token),\n\t\tbody: JSON.stringify(data),\n\t});\n\tif (res.status === 401)\n\t\tthrow new Error(\"Authentication expired. Run `aistack login` again.\");\n\tif (!res.ok) {\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tthrow new Error(\n\t\t\t(body as { error?: string }).error || `Collect failed: ${res.status}`,\n\t\t);\n\t}\n\treturn res.json();\n}\n\nexport async function projectGet(shortId: string): Promise<ProjectData | null> {\n\tconst res = await request(`/api/cli/projects/${encodeURIComponent(shortId)}`);\n\tif (res.status === 404) return null;\n\tif (!res.ok) throw new Error(`Project fetch failed: ${res.status}`);\n\treturn res.json();\n}\n\n// Types used across the CLI\nexport interface InstructionFile {\n\tname: string;\n\tcontent: string;\n\tpath?: string;\n\ttags?: string[];\n}\n\nexport interface InstructionItem {\n\ttype: string;\n\tname: string;\n\tdescription?: string;\n\tfiles: InstructionFile[];\n}\n\nexport interface ProjectData {\n\tname: string;\n\tslug: string;\n\tshortId: string;\n\tinstructions: InstructionItem[];\n\tcreator?: { name: string };\n\tstack?: { name: string; slug: string };\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nconst CONFIG_DIR = join(homedir(), \".config\", \"aistack\");\nconst CREDENTIALS_FILE = join(CONFIG_DIR, \"credentials.json\");\n\ninterface Credentials {\n\ttoken: string;\n\tuserId?: string;\n}\n\nexport function getToken(): string | null {\n\tif (!existsSync(CREDENTIALS_FILE)) return null;\n\ttry {\n\t\tconst data = JSON.parse(\n\t\t\treadFileSync(CREDENTIALS_FILE, \"utf-8\"),\n\t\t) as Credentials;\n\t\treturn data.token ?? null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function saveToken(token: string, userId?: string): void {\n\tmkdirSync(CONFIG_DIR, { recursive: true });\n\twriteFileSync(CREDENTIALS_FILE, JSON.stringify({ token, userId }, null, 2));\n}\n\nexport function clearToken(): void {\n\tif (existsSync(CREDENTIALS_FILE)) {\n\t\twriteFileSync(CREDENTIALS_FILE, \"{}\");\n\t}\n}\n\nconst PROJECTS_FILE = join(CONFIG_DIR, \"projects.json\");\n\ninterface ProjectEntry {\n\tname: string;\n\texcluded?: string[];\n}\n\ninterface ProjectsData {\n\t[directory: string]: ProjectEntry;\n}\n\nfunction readProjects(): ProjectsData {\n\tif (!existsSync(PROJECTS_FILE)) return {};\n\ttry {\n\t\tconst raw = JSON.parse(readFileSync(PROJECTS_FILE, \"utf-8\"));\n\t\t// Migrate old format (string values) to new format\n\t\tconst data: ProjectsData = {};\n\t\tfor (const [key, value] of Object.entries(raw)) {\n\t\t\tif (typeof value === \"string\") {\n\t\t\t\tdata[key] = { name: value };\n\t\t\t} else {\n\t\t\t\tdata[key] = value as ProjectEntry;\n\t\t\t}\n\t\t}\n\t\treturn data;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction writeProjects(data: ProjectsData): void {\n\tmkdirSync(CONFIG_DIR, { recursive: true });\n\twriteFileSync(PROJECTS_FILE, JSON.stringify(data, null, 2));\n}\n\nexport function getProjectName(directory: string): string | null {\n\treturn readProjects()[directory]?.name ?? null;\n}\n\nexport function getExcludedPaths(directory: string): string[] {\n\treturn readProjects()[directory]?.excluded ?? [];\n}\n\nexport function saveProjectSettings(\n\tdirectory: string,\n\tname: string,\n\texcluded: string[],\n): void {\n\tconst data = readProjects();\n\tdata[directory] = {\n\t\tname,\n\t\texcluded: excluded.length > 0 ? excluded : undefined,\n\t};\n\twriteProjects(data);\n}\n","const esc = (code: string) => `\\x1b[${code}m`;\nconst reset = esc(\"0\");\n\nconst LIME = \"163;230;53\";\nconst BLACK = \"0;0;0\";\nconst YELLOW = \"250;204;21\";\nconst RED = \"248;113;113\";\nconst MUTED = \"120;120;120\";\n\nexport const lime = (s: string) => `${esc(`38;2;${LIME}`)}${s}${reset}`;\nexport const limeBold = (s: string) =>\n\t`${esc(\"1\")}${esc(`38;2;${LIME}`)}${s}${reset}`;\nexport const bgLime = (s: string) =>\n\t`${esc(`48;2;${LIME}`)}${esc(`38;2;${BLACK}`)}${s}${reset}`;\nexport const yellow = (s: string) => `${esc(`38;2;${YELLOW}`)}${s}${reset}`;\nexport const red = (s: string) => `${esc(`38;2;${RED}`)}${s}${reset}`;\nexport const dim = (s: string) => `${esc(`38;2;${MUTED}`)}${s}${reset}`;\nexport const bold = (s: string) => `${esc(\"1\")}${s}${reset}`;\n\n// ■ logo square in lime + AISTACK in bold on lime bg\nexport const banner = (cmd: string) =>\n\t`${lime(\"■\")} ${bgLime(` AISTACK `)} ${bold(cmd.toUpperCase())}`;\n\n// Compact line with clack-style bar\nconst BAR = `${esc(`38;2;${MUTED}`)}│${reset}`;\n\nexport function lines(items: string[]) {\n\tfor (const item of items) {\n\t\tconsole.log(`${BAR} ${item}`);\n\t}\n}\n\nexport function section(label: string, count?: number) {\n\tconsole.log(`${BAR}`);\n\tconst countStr = count !== undefined ? ` ${dim(String(count))}` : \"\";\n\tconsole.log(`${BAR} ${bold(label.toUpperCase())}${countStr}`);\n}\n\nexport function divider() {\n\tconsole.log(`${BAR} ${dim(\"─\".repeat(40))}`);\n}\n","import * as p from \"@clack/prompts\";\nimport { basename } from \"node:path\";\nimport { scanLocal, scanGlobal, type ScannedFile } from \"../scanner.js\";\nimport { classify } from \"../classifier.js\";\nimport {\n\tprojectsCheck,\n\tprojectsCollect,\n\tprojectGet,\n\ttype InstructionItem,\n} from \"../api.js\";\nimport {\n\tgetToken,\n\tgetProjectName,\n\tgetExcludedPaths,\n\tsaveProjectSettings,\n} from \"../config.js\";\nimport {\n\tbanner,\n\tbold,\n\tdim,\n\tdivider,\n\tlime,\n\tlimeBold,\n\tlines,\n\tred,\n\tsection,\n\tyellow,\n} from \"../theme.js\";\n\nexport async function collectCommand(options: { global: boolean }) {\n\tp.intro(banner(\"collect\"));\n\n\tconst token = getToken();\n\tif (!token) {\n\t\tp.log.error(`Not authenticated. Run ${limeBold(\"aistack login\")} first.`);\n\t\tprocess.exit(1);\n\t}\n\n\tconst cwd = process.cwd();\n\tconst savedName = getProjectName(cwd);\n\tconst savedExcluded = getExcludedPaths(cwd);\n\n\tconst s = p.spinner();\n\ts.start(\"Scanning...\");\n\n\tconst localFiles = scanLocal(cwd);\n\tconst globalFiles = options.global ? scanGlobal() : [];\n\ts.stop(\"Scan complete\");\n\n\tif (localFiles.length === 0 && globalFiles.length === 0) {\n\t\tp.log.warn(\"No AI configuration files found.\");\n\t\tp.outro(dim(\"nothing to collect\"));\n\t\treturn;\n\t}\n\n\t// Project name\n\tlet projectName: string;\n\tif (savedName) {\n\t\tp.log.info(`${dim(\"PROJECT\")} ${limeBold(savedName)}`);\n\t\tprojectName = savedName;\n\t} else {\n\t\tconst defaultName = basename(cwd);\n\t\tconst name = await p.text({\n\t\t\tmessage: \"Project name:\",\n\t\t\tdefaultValue: defaultName,\n\t\t\tplaceholder: defaultName,\n\t\t});\n\t\tif (p.isCancel(name)) {\n\t\t\tp.cancel(\"Cancelled.\");\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tprojectName = (name as string) || defaultName;\n\t}\n\n\t// Apply saved exclusions\n\tconst allFiles = [...localFiles, ...globalFiles];\n\tlet selectedFiles = allFiles.filter(\n\t\t(f) => !savedExcluded.includes(f.relativePath),\n\t);\n\tlet excluded = allFiles.filter((f) => savedExcluded.includes(f.relativePath));\n\n\t// Show file counts\n\tp.log.info(\n\t\t`${lime(String(selectedFiles.length))} included${excluded.length > 0 ? ` · ${dim(String(excluded.length) + \" excluded\")}` : \"\"}`,\n\t);\n\n\t// Classify selected files\n\tlet allInstructions = classify(selectedFiles);\n\n\t// Fetch existing project and diff\n\tlet existingProject: Awaited<ReturnType<typeof projectGet>> = null;\n\ttry {\n\t\tconst check = await projectsCheck(token, projectName);\n\t\tif (check.exists && check.slug) {\n\t\t\tconst shortId = check.slug.includes(\"-\")\n\t\t\t\t? check.slug.slice(check.slug.lastIndexOf(\"-\") + 1)\n\t\t\t\t: check.slug;\n\t\t\texistingProject = await projectGet(shortId);\n\t\t}\n\t} catch (err) {\n\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\tprocess.exit(1);\n\t}\n\n\t// Show file list or diff\n\tif (existingProject) {\n\t\tconst diff = diffInstructions(\n\t\t\tallInstructions,\n\t\t\texistingProject.instructions,\n\t\t);\n\n\t\tif (diff.changed === 0 && diff.added === 0 && diff.removed === 0) {\n\t\t\tp.log.info(\"No changes since last collect.\");\n\t\t\tp.outro(dim(\"nothing to upload\"));\n\t\t\treturn;\n\t\t}\n\n\t\tdivider();\n\t\tsection(\"changes\");\n\t\tlines(\n\t\t\tdiff.details.map((f) => {\n\t\t\t\tif (f.status === \"added\") return lime(`+ ${f.name}`);\n\t\t\t\tif (f.status === \"changed\") return yellow(`~ ${f.name}`);\n\t\t\t\treturn red(`- ${f.name}`);\n\t\t\t}),\n\t\t);\n\t\tif (diff.unchanged > 0) {\n\t\t\tlines([dim(`${diff.unchanged} unchanged`)]);\n\t\t}\n\t\tdivider();\n\t} else {\n\t\tconst local = selectedFiles.filter((f) => f.source === \"local\");\n\t\tconst global = selectedFiles.filter((f) => f.source === \"global\");\n\n\t\tif (local.length > 0) {\n\t\t\tp.log.step(`${bold(\"LOCAL\")} ${dim(String(local.length))}`);\n\t\t\tdivider();\n\t\t\tfor (const [type, files] of groupByType(local)) {\n\t\t\t\tlines([`${lime(type.toUpperCase())} ${dim(`${files.length}`)}`]);\n\t\t\t\tlines(files.map((f) => dim(` ${f.relativePath}`)));\n\t\t\t}\n\t\t\tdivider();\n\t\t}\n\t\tif (global.length > 0) {\n\t\t\tp.log.step(`${bold(\"GLOBAL\")} ${dim(String(global.length))}`);\n\t\t\tdivider();\n\t\t\tfor (const [type, files] of groupByType(global)) {\n\t\t\t\tlines([`${lime(type.toUpperCase())} ${dim(`${files.length}`)}`]);\n\t\t\t\tlines(files.map((f) => dim(` ${f.relativePath}`)));\n\t\t\t}\n\t\t\tdivider();\n\t\t}\n\t}\n\n\t// Action: upload, customize, or cancel\n\tconst action = await p.select({\n\t\tmessage: existingProject\n\t\t\t? \"Upload changes?\"\n\t\t\t: `Upload ${bold(String(selectedFiles.length))} files as ${limeBold(projectName)}?`,\n\t\toptions: [\n\t\t\t{ value: \"upload\", label: \"Upload\" },\n\t\t\t{ value: \"customize\", label: \"Select files\" },\n\t\t\t{ value: \"cancel\", label: \"Cancel\" },\n\t\t],\n\t});\n\n\tif (p.isCancel(action) || action === \"cancel\") {\n\t\tp.cancel(\"Cancelled.\");\n\t\tprocess.exit(0);\n\t}\n\n\tif (action === \"customize\") {\n\t\tconst selected = await p.multiselect({\n\t\t\tmessage: \"Select files to include:\",\n\t\t\toptions: allFiles.map((f) => ({\n\t\t\t\tvalue: f.relativePath,\n\t\t\t\tlabel: f.relativePath,\n\t\t\t\thint: `${f.type}${f.source === \"global\" ? \" · global\" : \"\"}`,\n\t\t\t})),\n\t\t\tinitialValues: selectedFiles.map((f) => f.relativePath),\n\t\t});\n\n\t\tif (p.isCancel(selected)) {\n\t\t\tp.cancel(\"Cancelled.\");\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\tconst selectedSet = new Set(selected as string[]);\n\t\tselectedFiles = allFiles.filter((f) => selectedSet.has(f.relativePath));\n\t\texcluded = allFiles.filter((f) => !selectedSet.has(f.relativePath));\n\t\tallInstructions = classify(selectedFiles);\n\n\t\tif (selectedFiles.length === 0) {\n\t\t\tp.log.warn(\"No files selected.\");\n\t\t\tp.outro(dim(\"nothing to collect\"));\n\t\t\tprocess.exit(0);\n\t\t}\n\t}\n\n\ts.start(\"Uploading...\");\n\ttry {\n\t\tconst result = await projectsCollect(token, {\n\t\t\tname: projectName,\n\t\t\tinstructions: allInstructions,\n\t\t});\n\t\ts.stop(lime(\"Uploaded\"));\n\t\tsaveProjectSettings(\n\t\t\tcwd,\n\t\t\tprojectName,\n\t\t\texcluded.map((f) => f.relativePath),\n\t\t);\n\t\tp.log.success(dim(result.url));\n\t\tp.outro(lime(\"done\"));\n\t} catch (err) {\n\t\ts.stop(\"Upload failed\");\n\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\tprocess.exit(1);\n\t}\n}\n\nconst TYPE_ORDER = [\n\t\"config\",\n\t\"prompt\",\n\t\"rule\",\n\t\"command\",\n\t\"skill\",\n\t\"subagent\",\n\t\"mcp\",\n\t\"hook\",\n\t\"custom\",\n];\n\nfunction groupByType(files: ScannedFile[]): Map<string, ScannedFile[]> {\n\tconst map = new Map<string, ScannedFile[]>();\n\tfor (const f of files) {\n\t\tconst existing = map.get(f.type) ?? [];\n\t\texisting.push(f);\n\t\tmap.set(f.type, existing);\n\t}\n\tconst sorted = new Map<string, ScannedFile[]>();\n\tfor (const type of TYPE_ORDER) {\n\t\tconst group = map.get(type);\n\t\tif (group) sorted.set(type, group);\n\t}\n\tfor (const [type, group] of map) {\n\t\tif (!sorted.has(type)) sorted.set(type, group);\n\t}\n\treturn sorted;\n}\n\ninterface DiffResult {\n\tadded: number;\n\tchanged: number;\n\tremoved: number;\n\tunchanged: number;\n\tdetails: Array<{ name: string; status: \"added\" | \"changed\" | \"removed\" }>;\n}\n\nfunction diffInstructions(\n\tcurrent: InstructionItem[],\n\texisting: InstructionItem[],\n): DiffResult {\n\tconst existingMap = new Map<string, string>();\n\tfor (const item of existing) {\n\t\tfor (const file of item.files) {\n\t\t\texistingMap.set(file.path ?? file.name, file.content);\n\t\t}\n\t}\n\n\tconst currentMap = new Map<string, string>();\n\tfor (const item of current) {\n\t\tfor (const file of item.files) {\n\t\t\tcurrentMap.set(file.path ?? file.name, file.content);\n\t\t}\n\t}\n\n\tconst details: DiffResult[\"details\"] = [];\n\tlet added = 0;\n\tlet changed = 0;\n\tlet unchanged = 0;\n\n\tfor (const [key, content] of currentMap) {\n\t\tconst prev = existingMap.get(key);\n\t\tif (prev === undefined) {\n\t\t\tadded++;\n\t\t\tdetails.push({ name: key, status: \"added\" });\n\t\t} else if (prev !== content) {\n\t\t\tchanged++;\n\t\t\tdetails.push({ name: key, status: \"changed\" });\n\t\t} else {\n\t\t\tunchanged++;\n\t\t}\n\t}\n\n\tlet removed = 0;\n\tfor (const key of existingMap.keys()) {\n\t\tif (!currentMap.has(key)) {\n\t\t\tremoved++;\n\t\t\tdetails.push({ name: key, status: \"removed\" });\n\t\t}\n\t}\n\n\treturn { added, changed, removed, unchanged, details };\n}\n","import { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport ignore from \"ignore\";\n\nexport type FileType =\n\t| \"rule\"\n\t| \"mcp\"\n\t| \"skill\"\n\t| \"command\"\n\t| \"prompt\"\n\t| \"hook\"\n\t| \"subagent\"\n\t| \"config\"\n\t| \"custom\";\n\nexport interface ScannedFile {\n\tpath: string;\n\trelativePath: string;\n\tcontent: string;\n\ttype: FileType;\n\tsource: \"local\" | \"global\";\n}\n\nconst MAX_FILE_SIZE = 100 * 1024; // 100KB\n\ninterface FilePattern {\n\tpath: string;\n\ttype: FileType;\n}\n\nconst LOCAL_PATTERNS: FilePattern[] = [\n\t// Rules\n\t{ path: \"CLAUDE.md\", type: \"rule\" },\n\t{ path: \"AGENTS.md\", type: \"rule\" },\n\t{ path: \".cursorrules\", type: \"rule\" },\n\t{ path: \".windsurfrules\", type: \"rule\" },\n\t{ path: \".clinerules\", type: \"rule\" },\n\t{ path: \".github/copilot-instructions.md\", type: \"rule\" },\n\t// MCP\n\t{ path: \"mcp.json\", type: \"mcp\" },\n\t{ path: \".cursor/mcp.json\", type: \"mcp\" },\n\t{ path: \"claude_desktop_config.json\", type: \"mcp\" },\n\t// Config\n\t{ path: \".aider.conf.yml\", type: \"config\" },\n\t{ path: \".continue/config.json\", type: \"config\" },\n\t// Config\n\t{ path: \".claude/settings.json\", type: \"config\" },\n\t{ path: \".claude/settings.local.json\", type: \"config\" },\n\t// Prompts\n\t{ path: \"system-prompt.md\", type: \"prompt\" },\n];\n\nconst LOCAL_DIR_PATTERNS: { dir: string; type: FileType }[] = [\n\t{ dir: \".cursor/rules\", type: \"rule\" },\n\t{ dir: \".claude/commands\", type: \"command\" },\n\t{ dir: \".claude/agents\", type: \"subagent\" },\n\t{ dir: \".claude/hooks\", type: \"hook\" },\n\t{ dir: \"prompts\", type: \"prompt\" },\n\t{ dir: \".ai\", type: \"custom\" },\n];\n\nfunction loadGitignore(cwd: string): ReturnType<typeof ignore> {\n\tconst ig = ignore();\n\tconst gitignorePath = join(cwd, \".gitignore\");\n\tif (existsSync(gitignorePath)) {\n\t\tig.add(readFileSync(gitignorePath, \"utf-8\"));\n\t}\n\tig.add([\"node_modules\", \".git\", \"dist\", \"build\", \".next\", \".output\"]);\n\treturn ig;\n}\n\nfunction readFileSafe(filePath: string): string | null {\n\ttry {\n\t\tconst stat = statSync(filePath);\n\t\tif (stat.size > MAX_FILE_SIZE) return null;\n\t\treturn readFileSync(filePath, \"utf-8\");\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction walkDir(dir: string, maxDepth = 3, currentDepth = 0): string[] {\n\tif (currentDepth >= maxDepth || !existsSync(dir)) return [];\n\tconst results: string[] = [];\n\ttry {\n\t\tfor (const entry of readdirSync(dir, { withFileTypes: true })) {\n\t\t\tconst fullPath = join(dir, entry.name);\n\t\t\tif (entry.isFile()) {\n\t\t\t\tresults.push(fullPath);\n\t\t\t} else if (entry.isDirectory()) {\n\t\t\t\tresults.push(...walkDir(fullPath, maxDepth, currentDepth + 1));\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t/* permission errors, etc */\n\t}\n\treturn results;\n}\n\nexport function scanLocal(cwd: string): ScannedFile[] {\n\tconst ig = loadGitignore(cwd);\n\tconst results: ScannedFile[] = [];\n\n\tfor (const pattern of LOCAL_PATTERNS) {\n\t\tconst filePath = join(cwd, pattern.path);\n\t\tconst content = readFileSafe(filePath);\n\t\tif (content !== null) {\n\t\t\tconst rel = relative(cwd, filePath);\n\t\t\tif (!ig.ignores(rel)) {\n\t\t\t\tresults.push({\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\trelativePath: rel,\n\t\t\t\t\tcontent,\n\t\t\t\t\ttype: pattern.type,\n\t\t\t\t\tsource: \"local\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const { dir, type } of LOCAL_DIR_PATTERNS) {\n\t\tconst dirPath = join(cwd, dir);\n\t\tconst files = walkDir(dirPath);\n\t\tfor (const filePath of files) {\n\t\t\tconst rel = relative(cwd, filePath);\n\t\t\tif (ig.ignores(rel)) continue;\n\t\t\tconst content = readFileSafe(filePath);\n\t\t\tif (content !== null) {\n\t\t\t\tresults.push({\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\trelativePath: rel,\n\t\t\t\t\tcontent,\n\t\t\t\t\ttype,\n\t\t\t\t\tsource: \"local\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// Scan for skill directories (dirs with SKILL.md, 3 levels deep)\n\ttry {\n\t\tfor (const entry of readdirSync(cwd, { withFileTypes: true }).filter((e) =>\n\t\t\te.isDirectory(),\n\t\t)) {\n\t\t\tif (ig.ignores(entry.name + \"/\")) continue;\n\t\t\tscanSkillDirs(join(cwd, entry.name), cwd, ig, results, 1);\n\t\t}\n\t} catch {\n\t\t/* permission errors */\n\t}\n\n\treturn results;\n}\n\nfunction scanSkillDirs(\n\tdir: string,\n\tcwd: string,\n\tig: ReturnType<typeof ignore>,\n\tresults: ScannedFile[],\n\tdepth: number,\n) {\n\tif (depth > 3) return;\n\tconst skillMd = join(dir, \"SKILL.md\");\n\tif (existsSync(skillMd)) {\n\t\tconst files = walkDir(dir, 1);\n\t\tfor (const filePath of files) {\n\t\t\tconst rel = relative(cwd, filePath);\n\t\t\tif (ig.ignores(rel)) continue;\n\t\t\tconst content = readFileSafe(filePath);\n\t\t\tif (content !== null) {\n\t\t\t\tresults.push({\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\trelativePath: rel,\n\t\t\t\t\tcontent,\n\t\t\t\t\ttype: \"skill\",\n\t\t\t\t\tsource: \"local\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\ttry {\n\t\tfor (const entry of readdirSync(dir, { withFileTypes: true })) {\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tconst rel = relative(cwd, join(dir, entry.name));\n\t\t\t\tif (!ig.ignores(rel + \"/\")) {\n\t\t\t\t\tscanSkillDirs(join(dir, entry.name), cwd, ig, results, depth + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t/* permission errors */\n\t}\n}\n\nexport function scanGlobal(): ScannedFile[] {\n\tconst home = homedir();\n\tconst results: ScannedFile[] = [];\n\n\tconst globalPatterns: FilePattern[] = [\n\t\t{ path: \".claude/CLAUDE.md\", type: \"rule\" },\n\t\t{ path: \".claude/settings.json\", type: \"config\" },\n\t\t{ path: \".cursor/mcp.json\", type: \"mcp\" },\n\t\t{ path: \".continue/config.json\", type: \"config\" },\n\t\t{ path: \".aider.conf.yml\", type: \"config\" },\n\t];\n\n\tfor (const pattern of globalPatterns) {\n\t\tconst filePath = join(home, pattern.path);\n\t\tconst content = readFileSafe(filePath);\n\t\tif (content !== null) {\n\t\t\tresults.push({\n\t\t\t\tpath: filePath,\n\t\t\t\trelativePath: `~/${pattern.path}`,\n\t\t\t\tcontent,\n\t\t\t\ttype: pattern.type,\n\t\t\t\tsource: \"global\",\n\t\t\t});\n\t\t}\n\t}\n\n\tconst globalDirs: { dir: string; type: FileType }[] = [\n\t\t{ dir: \".claude/commands\", type: \"command\" },\n\t\t{ dir: \".claude/agents\", type: \"subagent\" },\n\t\t{ dir: \".claude/hooks\", type: \"hook\" },\n\t\t{ dir: \".cursor/rules\", type: \"rule\" },\n\t];\n\n\tfor (const { dir, type } of globalDirs) {\n\t\tconst dirPath = join(home, dir);\n\t\tconst files = walkDir(dirPath, 2);\n\t\tfor (const filePath of files) {\n\t\t\tconst content = readFileSafe(filePath);\n\t\t\tif (content !== null) {\n\t\t\t\tresults.push({\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\trelativePath: `~/${relative(home, filePath)}`,\n\t\t\t\t\tcontent,\n\t\t\t\t\ttype,\n\t\t\t\t\tsource: \"global\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n}\n","import type { ScannedFile } from \"./scanner.js\";\nimport type { InstructionItem } from \"./api.js\";\nimport { basename, dirname } from \"node:path\";\n\nexport function classify(files: ScannedFile[]): InstructionItem[] {\n\tconst skillDirs = new Map<string, ScannedFile[]>();\n\tconst nonSkillFiles: ScannedFile[] = [];\n\n\tfor (const file of files) {\n\t\tif (file.type === \"skill\") {\n\t\t\tconst dir = dirname(file.relativePath);\n\t\t\tconst existing = skillDirs.get(dir) ?? [];\n\t\t\texisting.push(file);\n\t\t\tskillDirs.set(dir, existing);\n\t\t} else {\n\t\t\tnonSkillFiles.push(file);\n\t\t}\n\t}\n\n\tconst items: InstructionItem[] = [];\n\n\tfor (const file of nonSkillFiles) {\n\t\tconst tags = file.source === \"global\" ? [\"global\"] : undefined;\n\t\titems.push({\n\t\t\ttype: file.type,\n\t\t\tname: file.relativePath,\n\t\t\tfiles: [\n\t\t\t\t{\n\t\t\t\t\tname: basename(file.relativePath),\n\t\t\t\t\tcontent: file.content,\n\t\t\t\t\tpath: file.relativePath,\n\t\t\t\t\ttags,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t}\n\n\tfor (const [dir, dirFiles] of skillDirs) {\n\t\tconst isGlobal = dirFiles[0]?.source === \"global\";\n\t\titems.push({\n\t\t\ttype: \"skill\",\n\t\t\tname: dir,\n\t\t\tfiles: dirFiles.map((f) => ({\n\t\t\t\tname: basename(f.relativePath),\n\t\t\t\tcontent: f.content,\n\t\t\t\tpath: f.relativePath,\n\t\t\t\ttags: isGlobal ? [\"global\"] : undefined,\n\t\t\t})),\n\t\t});\n\t}\n\n\treturn items;\n}\n\nexport function isGlobalItem(item: InstructionItem): boolean {\n\treturn item.files.some((f) => f.tags?.includes(\"global\"));\n}\n","import * as p from \"@clack/prompts\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { projectGet } from \"../api.js\";\nimport {\n\tbanner,\n\tbold,\n\tdim,\n\tdivider,\n\tlime,\n\tlines,\n\tsection,\n\tyellow,\n} from \"../theme.js\";\n\nexport async function createCommand(slugOrShortId: string) {\n\tp.intro(banner(\"create\"));\n\n\tconst s = p.spinner();\n\ts.start(\"Fetching project...\");\n\n\tconst shortId = slugOrShortId.includes(\"-\")\n\t\t? slugOrShortId.slice(slugOrShortId.lastIndexOf(\"-\") + 1)\n\t\t: slugOrShortId;\n\n\tlet project: Awaited<ReturnType<typeof projectGet>>;\n\ttry {\n\t\tproject = await projectGet(shortId);\n\t\tif (!project) {\n\t\t\ts.stop(\"Not found\");\n\t\t\tp.log.error(`Project \"${slugOrShortId}\" not found.`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t\ts.stop(bold(project.name));\n\t} catch (err) {\n\t\ts.stop(\"Failed to fetch project\");\n\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\tprocess.exit(1);\n\t}\n\n\tconst localFiles: FileToWrite[] = [];\n\tconst globalFiles: FileToWrite[] = [];\n\n\tfor (const item of project.instructions) {\n\t\tfor (const file of item.files) {\n\t\t\tconst writePath = file.path ?? file.name;\n\t\t\tconst isGlobal = file.tags?.includes(\"global\");\n\t\t\tif (isGlobal) {\n\t\t\t\tglobalFiles.push({ path: writePath, content: file.content });\n\t\t\t} else {\n\t\t\t\tlocalFiles.push({ path: writePath, content: file.content });\n\t\t\t}\n\t\t}\n\t}\n\n\tif (globalFiles.length > 0) {\n\t\tsection(\"global config\", globalFiles.length);\n\t\tlines([dim(\"view only\")]);\n\t\tlines(globalFiles.map((f) => dim(f.path)));\n\t}\n\n\tif (localFiles.length === 0) {\n\t\tp.log.warn(\"No local files to write.\");\n\t\tp.outro(dim(\"nothing to create\"));\n\t\treturn;\n\t}\n\n\tconst cwd = process.cwd();\n\tconst toWrite: FileToWrite[] = [];\n\tconst skipped: { path: string; differs: boolean }[] = [];\n\n\tfor (const f of localFiles) {\n\t\tconst fullPath = join(cwd, f.path);\n\t\tif (existsSync(fullPath)) {\n\t\t\tconst existing = readFileSync(fullPath, \"utf-8\");\n\t\t\tskipped.push({ path: f.path, differs: existing !== f.content });\n\t\t} else {\n\t\t\ttoWrite.push(f);\n\t\t}\n\t}\n\n\tsection(\"local files\", localFiles.length);\n\tlines(toWrite.map((f) => lime(`+ ${f.path}`)));\n\tlines(\n\t\tskipped.map((f) =>\n\t\t\tf.differs\n\t\t\t\t? `${yellow(`= ${f.path}`)} ${dim(\"(differs)\")}`\n\t\t\t\t: dim(`= ${f.path} (identical)`),\n\t\t),\n\t);\n\n\tif (toWrite.length === 0) {\n\t\tdivider();\n\t\tp.log.info(\"All local files already exist.\");\n\t\tp.outro(dim(\"nothing to write\"));\n\t\treturn;\n\t}\n\n\tdivider();\n\n\tconst confirm = await p.confirm({\n\t\tmessage: `Write ${lime(String(toWrite.length))} new files? ${dim(`(${skipped.length} skipped)`)}`,\n\t});\n\n\tif (p.isCancel(confirm) || !confirm) {\n\t\tp.cancel(\"Cancelled.\");\n\t\tprocess.exit(0);\n\t}\n\n\tfor (const f of toWrite) {\n\t\tconst fullPath = join(cwd, f.path);\n\t\tconst dir = dirname(fullPath);\n\t\tmkdirSync(dir, { recursive: true });\n\t\twriteFileSync(fullPath, f.content);\n\t}\n\n\tp.log.success(\n\t\t`${lime(String(toWrite.length))} written, ${dim(String(skipped.length) + \" skipped\")}`,\n\t);\n\tp.outro(lime(\"done\"));\n}\n\ninterface FileToWrite {\n\tpath: string;\n\tcontent: string;\n}\n"],"mappings":"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","names":["p","basename","existsSync","readFileSync","join","homedir","basename","p","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","join","existsSync","readFileSync","confirm","dirname","mkdirSync","writeFileSync"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/api.ts","../src/config.ts","../src/theme.ts","../src/commands/collect.ts","../src/scanner.ts","../src/classifier.ts","../src/stableKey.ts","../src/commands/create.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { loginCommand } from \"./commands/login.js\";\nimport { collectCommand } from \"./commands/collect.js\";\nimport { createCommand } from \"./commands/create.js\";\n\nconst program = new Command();\n\nprogram\n\t.name(\"aistack\")\n\t.description(\"Share and clone AI development configurations\")\n\t.version(\"0.1.0\");\n\nprogram\n\t.command(\"login\")\n\t.description(\"Authenticate with AI Stack\")\n\t.action(loginCommand);\n\nprogram\n\t.command(\"collect\")\n\t.description(\"Scan and upload AI config files from your project\")\n\t.option(\"--no-global\", \"Exclude global config files (~/.claude, etc.)\")\n\t.action((options) => collectCommand({ global: options.global ?? true }));\n\nprogram\n\t.command(\"create\")\n\t.description(\"Download and write AI config files from a shared project\")\n\t.argument(\"<slug>\", \"Project slug or short ID\")\n\t.action(createCommand);\n\nprogram.parse();\n","import * as p from \"@clack/prompts\";\nimport open from \"open\";\nimport { authStart, authPoll } from \"../api.js\";\nimport { saveToken } from \"../config.js\";\nimport { dim, intro, lime, limeBold, outro, outroError } from \"../theme.js\";\n\nexport async function loginCommand() {\n\tintro(\"login\");\n\n\tconst s = p.spinner();\n\ts.start(\"Starting authentication...\");\n\n\tlet session: Awaited<ReturnType<typeof authStart>>;\n\ttry {\n\t\tsession = await authStart();\n\t\ts.stop(\"Session created\");\n\t} catch (err) {\n\t\ts.stop(\"Failed to start authentication\");\n\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\toutroError(\"error\");\n\t\tprocess.exit(1);\n\t}\n\n\tp.log.info(`${dim(\"CODE\")} ${limeBold(session.userCode)}`);\n\tp.log.info(`${dim(\"OPEN\")} ${dim(session.authUrl)}`);\n\n\ttry {\n\t\tawait open(session.authUrl);\n\t} catch {\n\t\tp.log.warn(\n\t\t\t\"Could not open browser automatically. Please visit the URL above.\",\n\t\t);\n\t}\n\n\ts.start(\"Waiting for approval...\");\n\n\tconst maxAttempts = 36;\n\tfor (let i = 0; i < maxAttempts; i++) {\n\t\tawait new Promise((resolve) => setTimeout(resolve, 5000));\n\n\t\ttry {\n\t\t\tconst result = await authPoll(session.secretId);\n\n\t\t\tif (result.status === \"approved\" && result.token) {\n\t\t\t\ts.stop(lime(\"Authenticated\"));\n\t\t\t\tsaveToken(result.token, result.userId);\n\t\t\t\tp.log.success(\n\t\t\t\t\t`Token saved. Run ${limeBold(\"aistack collect\")} to get started.`,\n\t\t\t\t);\n\t\t\t\toutro(lime(\"done\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (result.status === \"expired\") {\n\t\t\t\ts.stop(\"Session expired\");\n\t\t\t\tp.log.error(\"Authentication session expired. Please try again.\");\n\t\t\t\toutroError(\"expired\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\ts.stop(\"Error polling\");\n\t\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\t\toutroError(\"error\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\ts.stop(\"Timed out\");\n\tp.log.error(\"Authentication timed out after 3 minutes. Please try again.\");\n\toutroError(\"timed out\");\n\tprocess.exit(1);\n}\n","const BASE_URL = process.env.AISTACK_URL || \"https://aistack.to\";\n\nasync function request(\n\tpath: string,\n\toptions: RequestInit = {},\n): Promise<Response> {\n\treturn fetch(`${BASE_URL}${path}`, {\n\t\t...options,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t...options.headers,\n\t\t},\n\t});\n}\n\nfunction authHeaders(token: string): HeadersInit {\n\treturn { Authorization: `Bearer ${token}` };\n}\n\nexport async function authStart(): Promise<{\n\tsecretId: string;\n\tuserCode: string;\n\tauthUrl: string;\n}> {\n\tconst res = await request(\"/api/cli/auth/start\", { method: \"POST\" });\n\tif (!res.ok) throw new Error(`Auth start failed: ${res.status}`);\n\treturn res.json();\n}\n\nexport async function authPoll(\n\tsecretId: string,\n): Promise<{ status: string; token?: string; userId?: string }> {\n\tconst res = await request(\n\t\t`/api/cli/auth/poll?secretId=${encodeURIComponent(secretId)}`,\n\t);\n\tif (!res.ok) throw new Error(`Auth poll failed: ${res.status}`);\n\treturn res.json();\n}\n\nexport async function projectsCheck(\n\ttoken: string,\n\tname: string,\n): Promise<{ exists: boolean; slug?: string }> {\n\tconst res = await request(\n\t\t`/api/cli/projects/check?name=${encodeURIComponent(name)}`,\n\t\t{\n\t\t\theaders: authHeaders(token),\n\t\t},\n\t);\n\tif (res.status === 401)\n\t\tthrow new Error(\"Authentication expired. Run `aistack login` again.\");\n\tif (!res.ok) throw new Error(`Project check failed: ${res.status}`);\n\treturn res.json();\n}\n\nexport async function projectsCollect(\n\ttoken: string,\n\tdata: { name: string; instructions: InstructionItem[] },\n): Promise<{ slug: string; shortId: string; url: string }> {\n\tconst res = await request(\"/api/cli/projects/collect\", {\n\t\tmethod: \"POST\",\n\t\theaders: authHeaders(token),\n\t\tbody: JSON.stringify(data),\n\t});\n\tif (res.status === 401)\n\t\tthrow new Error(\"Authentication expired. Run `aistack login` again.\");\n\tif (!res.ok) {\n\t\tthrow new Error(await formatHttpError(res, \"Collect failed\"));\n\t}\n\treturn res.json();\n}\n\nasync function formatHttpError(res: Response, label: string): Promise<string> {\n\tconst prefix = `${label}: ${res.status} ${res.statusText || \"\"}`.trim();\n\tconst text = await res.text().catch(() => \"\");\n\tif (!text) return prefix;\n\ttry {\n\t\tconst body = JSON.parse(text) as { error?: string; message?: string };\n\t\tconst detail = body.error || body.message;\n\t\tif (detail) return `${prefix} — ${detail}`;\n\t} catch {}\n\tconst snippet = text.trim().slice(0, 500);\n\treturn snippet ? `${prefix} — ${snippet}` : prefix;\n}\n\nexport async function projectGet(shortId: string): Promise<ProjectData | null> {\n\tconst res = await request(`/api/cli/projects/${encodeURIComponent(shortId)}`);\n\tif (res.status === 404) return null;\n\tif (!res.ok) throw new Error(`Project fetch failed: ${res.status}`);\n\treturn res.json();\n}\n\n// Types used across the CLI\nexport interface InstructionFile {\n\tname: string;\n\tcontent: string;\n\tpath?: string;\n\ttags?: string[];\n}\n\nexport interface InstructionItem {\n\ttype: string;\n\tname: string;\n\tdescription?: string;\n\tgroup: string;\n\tscope?: \"global\" | \"project\";\n\tstableKey: string;\n\tfiles: InstructionFile[];\n}\n\nexport interface ProjectData {\n\tname: string;\n\tslug: string;\n\tshortId: string;\n\tinstructions: InstructionItem[];\n\tcreator?: { name: string };\n\tstack?: { name: string; slug: string };\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nconst CONFIG_DIR = join(homedir(), \".config\", \"aistack\");\nconst CREDENTIALS_FILE = join(CONFIG_DIR, \"credentials.json\");\n\ninterface Credentials {\n\ttoken: string;\n\tuserId?: string;\n}\n\nexport function getToken(): string | null {\n\tif (!existsSync(CREDENTIALS_FILE)) return null;\n\ttry {\n\t\tconst data = JSON.parse(\n\t\t\treadFileSync(CREDENTIALS_FILE, \"utf-8\"),\n\t\t) as Credentials;\n\t\treturn data.token ?? null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function saveToken(token: string, userId?: string): void {\n\tmkdirSync(CONFIG_DIR, { recursive: true });\n\twriteFileSync(CREDENTIALS_FILE, JSON.stringify({ token, userId }, null, 2));\n}\n\nexport function clearToken(): void {\n\tif (existsSync(CREDENTIALS_FILE)) {\n\t\twriteFileSync(CREDENTIALS_FILE, \"{}\");\n\t}\n}\n\nconst PROJECTS_FILE = join(CONFIG_DIR, \"projects.json\");\n\ninterface ProjectEntry {\n\tname: string;\n\texcluded?: string[];\n}\n\ninterface ProjectsData {\n\t[directory: string]: ProjectEntry;\n}\n\nfunction readProjects(): ProjectsData {\n\tif (!existsSync(PROJECTS_FILE)) return {};\n\ttry {\n\t\tconst raw = JSON.parse(readFileSync(PROJECTS_FILE, \"utf-8\"));\n\t\t// Migrate old format (string values) to new format\n\t\tconst data: ProjectsData = {};\n\t\tfor (const [key, value] of Object.entries(raw)) {\n\t\t\tif (typeof value === \"string\") {\n\t\t\t\tdata[key] = { name: value };\n\t\t\t} else {\n\t\t\t\tdata[key] = value as ProjectEntry;\n\t\t\t}\n\t\t}\n\t\treturn data;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction writeProjects(data: ProjectsData): void {\n\tmkdirSync(CONFIG_DIR, { recursive: true });\n\twriteFileSync(PROJECTS_FILE, JSON.stringify(data, null, 2));\n}\n\nexport function getProjectName(directory: string): string | null {\n\treturn readProjects()[directory]?.name ?? null;\n}\n\nexport function getExcludedPaths(directory: string): string[] {\n\treturn readProjects()[directory]?.excluded ?? [];\n}\n\nexport function saveProjectSettings(\n\tdirectory: string,\n\tname: string,\n\texcluded: string[],\n): void {\n\tconst data = readProjects();\n\tdata[directory] = {\n\t\tname,\n\t\texcluded: excluded.length > 0 ? excluded : undefined,\n\t};\n\twriteProjects(data);\n}\n","import * as p from \"@clack/prompts\";\n\nconst esc = (code: string) => `\\x1b[${code}m`;\nconst reset = esc(\"0\");\n\nconst LIME = \"163;230;53\";\nconst BLACK = \"0;0;0\";\nconst YELLOW = \"250;204;21\";\nconst RED = \"248;113;113\";\nconst MUTED = \"120;120;120\";\n\nexport const lime = (s: string) => `${esc(`38;2;${LIME}`)}${s}${reset}`;\nexport const limeBold = (s: string) =>\n\t`${esc(\"1\")}${esc(`38;2;${LIME}`)}${s}${reset}`;\nexport const bgLime = (s: string) =>\n\t`${esc(`48;2;${LIME}`)}${esc(`38;2;${BLACK}`)}${s}${reset}`;\nexport const yellow = (s: string) => `${esc(`38;2;${YELLOW}`)}${s}${reset}`;\nexport const red = (s: string) => `${esc(`38;2;${RED}`)}${s}${reset}`;\nexport const dim = (s: string) => `${esc(`38;2;${MUTED}`)}${s}${reset}`;\nexport const bold = (s: string) => `${esc(\"1\")}${s}${reset}`;\n\n// ■ logo square in lime + AISTACK in bold on lime bg\nexport const banner = (cmd: string) =>\n\t`${lime(\"■\")} ${bgLime(` AISTACK `)} ${bold(cmd.toUpperCase())}`;\n\n// Compact line with clack-style bar\nconst BAR = `${esc(`38;2;${MUTED}`)}│${reset}`;\n\nexport function lines(items: string[]) {\n\tfor (const item of items) {\n\t\tconsole.log(`${BAR} ${item}`);\n\t}\n}\n\nexport function section(label: string, count?: number) {\n\tconsole.log(`${BAR}`);\n\tconst countStr = count !== undefined ? ` ${dim(String(count))}` : \"\";\n\tconsole.log(`${BAR} ${bold(label.toUpperCase())}${countStr}`);\n}\n\nexport function divider() {\n\tconsole.log(`${BAR} ${dim(\"─\".repeat(40))}`);\n}\n\nexport function intro(cmd: string) {\n\tconsole.log();\n\tp.intro(banner(cmd));\n}\n\nexport function outro(msg: string) {\n\tp.outro(msg);\n\tconsole.log();\n}\n\nexport function outroError(msg: string) {\n\tp.outro(red(msg));\n\tconsole.log();\n}\n\nexport function outroCancel(msg = \"cancelled\") {\n\tp.cancel(dim(msg));\n\tconsole.log();\n}\n\nexport function outroSkipped(msg: string) {\n\tp.outro(dim(msg));\n\tconsole.log();\n}\n","import * as p from \"@clack/prompts\";\nimport { basename } from \"node:path\";\nimport { scanLocal, scanGlobal, type ScannedFile } from \"../scanner.js\";\nimport { classify } from \"../classifier.js\";\nimport {\n\tprojectsCheck,\n\tprojectsCollect,\n\tprojectGet,\n\ttype InstructionItem,\n} from \"../api.js\";\nimport {\n\tgetToken,\n\tgetProjectName,\n\tgetExcludedPaths,\n\tsaveProjectSettings,\n} from \"../config.js\";\nimport {\n\tbold,\n\tdim,\n\tdivider,\n\tintro,\n\tlime,\n\tlimeBold,\n\tlines,\n\toutro,\n\toutroCancel,\n\toutroError,\n\toutroSkipped,\n\tred,\n\tsection,\n\tyellow,\n} from \"../theme.js\";\n\nexport async function collectCommand(options: { global: boolean }) {\n\tintro(\"collect\");\n\n\tconst token = getToken();\n\tif (!token) {\n\t\tp.log.error(`Not authenticated. Run ${limeBold(\"aistack login\")} first.`);\n\t\toutroError(\"not authenticated\");\n\t\tprocess.exit(1);\n\t}\n\n\tconst cwd = process.cwd();\n\tconst savedName = getProjectName(cwd);\n\tconst savedExcluded = getExcludedPaths(cwd);\n\n\tconst s = p.spinner();\n\ts.start(\"Scanning...\");\n\n\tconst localFiles = scanLocal(cwd);\n\tconst globalFiles = options.global ? scanGlobal() : [];\n\ts.stop(\"Scan complete\");\n\n\tif (localFiles.length === 0 && globalFiles.length === 0) {\n\t\tp.log.warn(\"No AI configuration files found.\");\n\t\toutroSkipped(\"nothing to collect\");\n\t\treturn;\n\t}\n\n\t// Project name\n\tlet projectName: string;\n\tif (savedName) {\n\t\tp.log.info(`${dim(\"PROJECT\")} ${limeBold(savedName)}`);\n\t\tprojectName = savedName;\n\t} else {\n\t\tconst defaultName = basename(cwd);\n\t\tconst name = await p.text({\n\t\t\tmessage: \"Project name:\",\n\t\t\tdefaultValue: defaultName,\n\t\t\tplaceholder: defaultName,\n\t\t});\n\t\tif (p.isCancel(name)) {\n\t\t\toutroCancel();\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tprojectName = (name as string) || defaultName;\n\t}\n\n\t// Apply saved exclusions\n\tconst allFiles = [...localFiles, ...globalFiles];\n\tlet selectedFiles = allFiles.filter(\n\t\t(f) => !savedExcluded.includes(f.relativePath),\n\t);\n\tlet excluded = allFiles.filter((f) => savedExcluded.includes(f.relativePath));\n\n\t// Show file counts\n\tp.log.info(\n\t\t`${lime(String(selectedFiles.length))} included${excluded.length > 0 ? ` · ${dim(String(excluded.length) + \" excluded\")}` : \"\"}`,\n\t);\n\n\t// Classify selected files\n\tlet allInstructions = classify(selectedFiles);\n\n\t// Fetch existing project and diff\n\tlet existingProject: Awaited<ReturnType<typeof projectGet>> = null;\n\ttry {\n\t\tconst check = await projectsCheck(token, projectName);\n\t\tif (check.exists && check.slug) {\n\t\t\tconst shortId = check.slug.includes(\"-\")\n\t\t\t\t? check.slug.slice(check.slug.lastIndexOf(\"-\") + 1)\n\t\t\t\t: check.slug;\n\t\t\texistingProject = await projectGet(shortId);\n\t\t}\n\t} catch (err) {\n\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\toutroError(\"error\");\n\t\tprocess.exit(1);\n\t}\n\n\t// Show file list or diff\n\tif (existingProject) {\n\t\tconst diff = diffInstructions(\n\t\t\tallInstructions,\n\t\t\texistingProject.instructions,\n\t\t);\n\n\t\tif (diff.changed === 0 && diff.added === 0 && diff.removed === 0) {\n\t\t\tp.log.info(\"No changes since last collect.\");\n\t\t\toutroSkipped(\"nothing to upload\");\n\t\t\treturn;\n\t\t}\n\n\t\tdivider();\n\t\tsection(\"changes\");\n\t\tlines(\n\t\t\tdiff.details.map((f) => {\n\t\t\t\tif (f.status === \"added\") return lime(`+ ${f.name}`);\n\t\t\t\tif (f.status === \"changed\") return yellow(`~ ${f.name}`);\n\t\t\t\treturn red(`- ${f.name}`);\n\t\t\t}),\n\t\t);\n\t\tif (diff.unchanged > 0) {\n\t\t\tlines([dim(`${diff.unchanged} unchanged`)]);\n\t\t}\n\t\tdivider();\n\t} else {\n\t\tconst local = selectedFiles.filter((f) => f.source === \"local\");\n\t\tconst global = selectedFiles.filter((f) => f.source === \"global\");\n\n\t\tif (local.length > 0) {\n\t\t\tp.log.step(`${bold(\"LOCAL\")} ${dim(String(local.length))}`);\n\t\t\tdivider();\n\t\t\tfor (const [type, files] of groupByType(local)) {\n\t\t\t\tlines([`${lime(type.toUpperCase())} ${dim(`${files.length}`)}`]);\n\t\t\t\tlines(files.map((f) => dim(` ${f.relativePath}`)));\n\t\t\t}\n\t\t\tdivider();\n\t\t}\n\t\tif (global.length > 0) {\n\t\t\tp.log.step(`${bold(\"GLOBAL\")} ${dim(String(global.length))}`);\n\t\t\tdivider();\n\t\t\tfor (const [type, files] of groupByType(global)) {\n\t\t\t\tlines([`${lime(type.toUpperCase())} ${dim(`${files.length}`)}`]);\n\t\t\t\tlines(files.map((f) => dim(` ${f.relativePath}`)));\n\t\t\t}\n\t\t\tdivider();\n\t\t}\n\t}\n\n\t// Action: upload, customize, or cancel\n\tconst action = await p.select({\n\t\tmessage: existingProject\n\t\t\t? \"Upload changes?\"\n\t\t\t: `Upload ${bold(String(selectedFiles.length))} files as ${limeBold(projectName)}?`,\n\t\toptions: [\n\t\t\t{ value: \"upload\", label: \"Upload\" },\n\t\t\t{ value: \"customize\", label: \"Select files\" },\n\t\t\t{ value: \"cancel\", label: \"Cancel\" },\n\t\t],\n\t});\n\n\tif (p.isCancel(action) || action === \"cancel\") {\n\t\toutroCancel();\n\t\tprocess.exit(0);\n\t}\n\n\tif (action === \"customize\") {\n\t\tconst selected = await p.multiselect({\n\t\t\tmessage: \"Select files to include:\",\n\t\t\toptions: allFiles.map((f) => ({\n\t\t\t\tvalue: f.relativePath,\n\t\t\t\tlabel: f.relativePath,\n\t\t\t\thint: `${f.type}${f.source === \"global\" ? \" · global\" : \"\"}`,\n\t\t\t})),\n\t\t\tinitialValues: selectedFiles.map((f) => f.relativePath),\n\t\t});\n\n\t\tif (p.isCancel(selected)) {\n\t\t\toutroCancel();\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\tconst selectedSet = new Set(selected as string[]);\n\t\tselectedFiles = allFiles.filter((f) => selectedSet.has(f.relativePath));\n\t\texcluded = allFiles.filter((f) => !selectedSet.has(f.relativePath));\n\t\tallInstructions = classify(selectedFiles);\n\n\t\tif (selectedFiles.length === 0) {\n\t\t\tp.log.warn(\"No files selected.\");\n\t\t\toutroSkipped(\"nothing to collect\");\n\t\t\tprocess.exit(0);\n\t\t}\n\t}\n\n\ts.start(\"Uploading...\");\n\ttry {\n\t\tconst result = await projectsCollect(token, {\n\t\t\tname: projectName,\n\t\t\tinstructions: allInstructions,\n\t\t});\n\t\ts.stop(lime(\"Uploaded\"));\n\t\tsaveProjectSettings(\n\t\t\tcwd,\n\t\t\tprojectName,\n\t\t\texcluded.map((f) => f.relativePath),\n\t\t);\n\t\tp.log.success(dim(result.url));\n\t\toutro(lime(\"done\"));\n\t} catch (err) {\n\t\ts.stop(\"Upload failed\");\n\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\toutroError(\"upload failed\");\n\t\tprocess.exit(1);\n\t}\n}\n\nconst TYPE_ORDER = [\n\t\"config\",\n\t\"prompt\",\n\t\"rule\",\n\t\"command\",\n\t\"skill\",\n\t\"subagent\",\n\t\"mcp\",\n\t\"hook\",\n\t\"custom\",\n];\n\nfunction groupByType(files: ScannedFile[]): Map<string, ScannedFile[]> {\n\tconst map = new Map<string, ScannedFile[]>();\n\tfor (const f of files) {\n\t\tconst existing = map.get(f.type) ?? [];\n\t\texisting.push(f);\n\t\tmap.set(f.type, existing);\n\t}\n\tconst sorted = new Map<string, ScannedFile[]>();\n\tfor (const type of TYPE_ORDER) {\n\t\tconst group = map.get(type);\n\t\tif (group) sorted.set(type, group);\n\t}\n\tfor (const [type, group] of map) {\n\t\tif (!sorted.has(type)) sorted.set(type, group);\n\t}\n\treturn sorted;\n}\n\ninterface DiffResult {\n\tadded: number;\n\tchanged: number;\n\tremoved: number;\n\tunchanged: number;\n\tdetails: Array<{ name: string; status: \"added\" | \"changed\" | \"removed\" }>;\n}\n\nfunction diffInstructions(\n\tcurrent: InstructionItem[],\n\texisting: InstructionItem[],\n): DiffResult {\n\tconst existingMap = new Map<string, string>();\n\tfor (const item of existing) {\n\t\tfor (const file of item.files) {\n\t\t\texistingMap.set(file.path ?? file.name, file.content);\n\t\t}\n\t}\n\n\tconst currentMap = new Map<string, string>();\n\tfor (const item of current) {\n\t\tfor (const file of item.files) {\n\t\t\tcurrentMap.set(file.path ?? file.name, file.content);\n\t\t}\n\t}\n\n\tconst details: DiffResult[\"details\"] = [];\n\tlet added = 0;\n\tlet changed = 0;\n\tlet unchanged = 0;\n\n\tfor (const [key, content] of currentMap) {\n\t\tconst prev = existingMap.get(key);\n\t\tif (prev === undefined) {\n\t\t\tadded++;\n\t\t\tdetails.push({ name: key, status: \"added\" });\n\t\t} else if (prev !== content) {\n\t\t\tchanged++;\n\t\t\tdetails.push({ name: key, status: \"changed\" });\n\t\t} else {\n\t\t\tunchanged++;\n\t\t}\n\t}\n\n\tlet removed = 0;\n\tfor (const key of existingMap.keys()) {\n\t\tif (!currentMap.has(key)) {\n\t\t\tremoved++;\n\t\t\tdetails.push({ name: key, status: \"removed\" });\n\t\t}\n\t}\n\n\treturn { added, changed, removed, unchanged, details };\n}\n","import { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport ignore from \"ignore\";\n\nexport type FileType =\n\t| \"rule\"\n\t| \"mcp\"\n\t| \"skill\"\n\t| \"command\"\n\t| \"prompt\"\n\t| \"hook\"\n\t| \"subagent\"\n\t| \"config\"\n\t| \"custom\";\n\nexport interface ScannedFile {\n\tpath: string;\n\trelativePath: string;\n\tcontent: string;\n\ttype: FileType;\n\tsource: \"local\" | \"global\";\n\tgroup: string;\n}\n\nconst MAX_FILE_SIZE = 100 * 1024; // 100KB\n\ninterface FilePattern {\n\tpath: string;\n\ttype: FileType;\n\tgroup: string;\n}\n\nconst LOCAL_PATTERNS: FilePattern[] = [\n\t// Rules\n\t{ path: \"CLAUDE.md\", type: \"rule\", group: \"claude-code\" },\n\t{ path: \"AGENTS.md\", type: \"rule\", group: \"claude-code\" },\n\t{ path: \".cursorrules\", type: \"rule\", group: \"cursor\" },\n\t{ path: \".windsurfrules\", type: \"rule\", group: \"windsurf\" },\n\t{ path: \".clinerules\", type: \"rule\", group: \"cline\" },\n\t{ path: \".github/copilot-instructions.md\", type: \"rule\", group: \"copilot\" },\n\t// MCP\n\t{ path: \"mcp.json\", type: \"mcp\", group: \"generic\" },\n\t{ path: \".cursor/mcp.json\", type: \"mcp\", group: \"cursor\" },\n\t{\n\t\tpath: \"claude_desktop_config.json\",\n\t\ttype: \"mcp\",\n\t\tgroup: \"claude-desktop\",\n\t},\n\t// Config\n\t{ path: \".aider.conf.yml\", type: \"config\", group: \"aider\" },\n\t{ path: \".continue/config.json\", type: \"config\", group: \"continue\" },\n\t{ path: \".claude/settings.json\", type: \"config\", group: \"claude-code\" },\n\t{\n\t\tpath: \".claude/settings.local.json\",\n\t\ttype: \"config\",\n\t\tgroup: \"claude-code\",\n\t},\n\t// Prompts\n\t{ path: \"system-prompt.md\", type: \"prompt\", group: \"generic\" },\n];\n\nconst LOCAL_DIR_PATTERNS: { dir: string; type: FileType; group: string }[] = [\n\t{ dir: \".cursor/rules\", type: \"rule\", group: \"cursor\" },\n\t{ dir: \".claude/commands\", type: \"command\", group: \"claude-code\" },\n\t{ dir: \".claude/agents\", type: \"subagent\", group: \"claude-code\" },\n\t{ dir: \".claude/hooks\", type: \"hook\", group: \"claude-code\" },\n\t{ dir: \"prompts\", type: \"prompt\", group: \"generic\" },\n\t{ dir: \".ai\", type: \"custom\", group: \"generic\" },\n];\n\nfunction loadGitignore(cwd: string): ReturnType<typeof ignore> {\n\tconst ig = ignore();\n\tconst gitignorePath = join(cwd, \".gitignore\");\n\tif (existsSync(gitignorePath)) {\n\t\tig.add(readFileSync(gitignorePath, \"utf-8\"));\n\t}\n\tig.add([\"node_modules\", \".git\", \"dist\", \"build\", \".next\", \".output\"]);\n\treturn ig;\n}\n\nfunction readFileSafe(filePath: string): string | null {\n\ttry {\n\t\tconst stat = statSync(filePath);\n\t\tif (stat.size > MAX_FILE_SIZE) return null;\n\t\treturn readFileSync(filePath, \"utf-8\");\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction walkDir(dir: string, maxDepth = 3, currentDepth = 0): string[] {\n\tif (currentDepth >= maxDepth || !existsSync(dir)) return [];\n\tconst results: string[] = [];\n\ttry {\n\t\tfor (const entry of readdirSync(dir, { withFileTypes: true })) {\n\t\t\tconst fullPath = join(dir, entry.name);\n\t\t\tif (entry.isFile()) {\n\t\t\t\tresults.push(fullPath);\n\t\t\t} else if (entry.isDirectory()) {\n\t\t\t\tresults.push(...walkDir(fullPath, maxDepth, currentDepth + 1));\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t/* permission errors, etc */\n\t}\n\treturn results;\n}\n\nexport function scanLocal(cwd: string): ScannedFile[] {\n\tconst ig = loadGitignore(cwd);\n\tconst results: ScannedFile[] = [];\n\n\tfor (const pattern of LOCAL_PATTERNS) {\n\t\tconst filePath = join(cwd, pattern.path);\n\t\tconst content = readFileSafe(filePath);\n\t\tif (content !== null) {\n\t\t\tconst rel = relative(cwd, filePath);\n\t\t\tif (!ig.ignores(rel)) {\n\t\t\t\tresults.push({\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\trelativePath: rel,\n\t\t\t\t\tcontent,\n\t\t\t\t\ttype: pattern.type,\n\t\t\t\t\tsource: \"local\",\n\t\t\t\t\tgroup: pattern.group,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const { dir, type, group } of LOCAL_DIR_PATTERNS) {\n\t\tconst dirPath = join(cwd, dir);\n\t\tconst files = walkDir(dirPath);\n\t\tfor (const filePath of files) {\n\t\t\tconst rel = relative(cwd, filePath);\n\t\t\tif (ig.ignores(rel)) continue;\n\t\t\tconst content = readFileSafe(filePath);\n\t\t\tif (content !== null) {\n\t\t\t\tresults.push({\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\trelativePath: rel,\n\t\t\t\t\tcontent,\n\t\t\t\t\ttype,\n\t\t\t\t\tsource: \"local\",\n\t\t\t\t\tgroup,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// Scan for skill directories (dirs with SKILL.md, 3 levels deep)\n\ttry {\n\t\tfor (const entry of readdirSync(cwd, { withFileTypes: true }).filter((e) =>\n\t\t\te.isDirectory(),\n\t\t)) {\n\t\t\tif (ig.ignores(entry.name + \"/\")) continue;\n\t\t\tscanSkillDirs(join(cwd, entry.name), cwd, ig, results, 1);\n\t\t}\n\t} catch {\n\t\t/* permission errors */\n\t}\n\n\treturn results;\n}\n\nfunction scanSkillDirs(\n\tdir: string,\n\tcwd: string,\n\tig: ReturnType<typeof ignore>,\n\tresults: ScannedFile[],\n\tdepth: number,\n) {\n\tif (depth > 3) return;\n\tconst skillMd = join(dir, \"SKILL.md\");\n\tif (existsSync(skillMd)) {\n\t\tconst files = walkDir(dir, 1);\n\t\tfor (const filePath of files) {\n\t\t\tconst rel = relative(cwd, filePath);\n\t\t\tif (ig.ignores(rel)) continue;\n\t\t\tconst content = readFileSafe(filePath);\n\t\t\tif (content !== null) {\n\t\t\t\tresults.push({\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\trelativePath: rel,\n\t\t\t\t\tcontent,\n\t\t\t\t\ttype: \"skill\",\n\t\t\t\t\tsource: \"local\",\n\t\t\t\t\tgroup: \"generic\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\ttry {\n\t\tfor (const entry of readdirSync(dir, { withFileTypes: true })) {\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tconst rel = relative(cwd, join(dir, entry.name));\n\t\t\t\tif (!ig.ignores(rel + \"/\")) {\n\t\t\t\t\tscanSkillDirs(join(dir, entry.name), cwd, ig, results, depth + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t/* permission errors */\n\t}\n}\n\nexport function scanGlobal(): ScannedFile[] {\n\tconst home = homedir();\n\tconst results: ScannedFile[] = [];\n\n\tconst globalPatterns: FilePattern[] = [\n\t\t{ path: \".claude/CLAUDE.md\", type: \"rule\", group: \"claude-code\" },\n\t\t{ path: \".claude/settings.json\", type: \"config\", group: \"claude-code\" },\n\t\t{ path: \".cursor/mcp.json\", type: \"mcp\", group: \"cursor\" },\n\t\t{ path: \".continue/config.json\", type: \"config\", group: \"continue\" },\n\t\t{ path: \".aider.conf.yml\", type: \"config\", group: \"aider\" },\n\t];\n\n\tfor (const pattern of globalPatterns) {\n\t\tconst filePath = join(home, pattern.path);\n\t\tconst content = readFileSafe(filePath);\n\t\tif (content !== null) {\n\t\t\tresults.push({\n\t\t\t\tpath: filePath,\n\t\t\t\trelativePath: `~/${pattern.path}`,\n\t\t\t\tcontent,\n\t\t\t\ttype: pattern.type,\n\t\t\t\tsource: \"global\",\n\t\t\t\tgroup: pattern.group,\n\t\t\t});\n\t\t}\n\t}\n\n\tconst globalDirs: { dir: string; type: FileType; group: string }[] = [\n\t\t{ dir: \".claude/commands\", type: \"command\", group: \"claude-code\" },\n\t\t{ dir: \".claude/agents\", type: \"subagent\", group: \"claude-code\" },\n\t\t{ dir: \".claude/hooks\", type: \"hook\", group: \"claude-code\" },\n\t\t{ dir: \".cursor/rules\", type: \"rule\", group: \"cursor\" },\n\t];\n\n\tfor (const { dir, type, group } of globalDirs) {\n\t\tconst dirPath = join(home, dir);\n\t\tconst files = walkDir(dirPath, 2);\n\t\tfor (const filePath of files) {\n\t\t\tconst content = readFileSafe(filePath);\n\t\t\tif (content !== null) {\n\t\t\t\tresults.push({\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\trelativePath: `~/${relative(home, filePath)}`,\n\t\t\t\t\tcontent,\n\t\t\t\t\ttype,\n\t\t\t\t\tsource: \"global\",\n\t\t\t\t\tgroup,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n}\n","import type { ScannedFile } from \"./scanner.js\";\nimport type { InstructionItem } from \"./api.js\";\nimport { basename, dirname } from \"node:path\";\nimport { computeStableKey } from \"./stableKey.js\";\n\nexport function classify(files: ScannedFile[]): InstructionItem[] {\n\t// Group by {group, scope, type, containing directory}\n\tconst groups = new Map<string, ScannedFile[]>();\n\tconst singletons: ScannedFile[] = [];\n\n\tconst singletonRoots = new Set([\n\t\t\".\",\n\t\t\"~\",\n\t\t\"~/.claude\",\n\t\t\"~/.cursor\",\n\t\t\"~/.continue\",\n\t\t\".claude\",\n\t\t\".cursor\",\n\t\t\".github\",\n\t]);\n\n\tfor (const file of files) {\n\t\tconst dir = dirname(file.relativePath);\n\t\tconst isSingleton = singletonRoots.has(dir);\n\n\t\tif (isSingleton) {\n\t\t\tsingletons.push(file);\n\t\t} else {\n\t\t\tconst key = `${file.group}:${file.source}:${file.type}:${dir}`;\n\t\t\tconst existing = groups.get(key) ?? [];\n\t\t\texisting.push(file);\n\t\t\tgroups.set(key, existing);\n\t\t}\n\t}\n\n\tconst items: InstructionItem[] = [];\n\tconst scope = (source: string) =>\n\t\tsource === \"global\" ? (\"global\" as const) : (\"project\" as const);\n\n\t// Singletons: one InstructionItem per file\n\tfor (const file of singletons) {\n\t\tconst s = scope(file.source);\n\t\tconst relPath = file.relativePath\n\t\t\t.replace(/^~\\/\\.[^/]+\\//, \"\")\n\t\t\t.replace(/^\\.[^/]+\\//, \"\");\n\t\titems.push({\n\t\t\ttype: file.type,\n\t\t\tname: file.relativePath,\n\t\t\tgroup: file.group,\n\t\t\tscope: s,\n\t\t\tstableKey: computeStableKey(file.group, file.type, relPath),\n\t\t\tfiles: [\n\t\t\t\t{\n\t\t\t\t\tname: basename(file.relativePath),\n\t\t\t\t\tcontent: file.content,\n\t\t\t\t\tpath: file.relativePath,\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\t}\n\n\t// Groups: one InstructionItem per directory group\n\tfor (const [, groupFiles] of groups) {\n\t\tconst first = groupFiles[0];\n\t\tconst dir = dirname(first.relativePath);\n\t\tconst s = scope(first.source);\n\t\tconst relPath = dir\n\t\t\t.replace(/^~\\/\\.claude\\//, \"\")\n\t\t\t.replace(/^\\.claude\\//, \"\")\n\t\t\t.replace(/^~\\/\\.cursor\\//, \"\")\n\t\t\t.replace(/^\\.cursor\\//, \"\");\n\t\tconst typeLabel =\n\t\t\tfirst.type === \"subagent\" ? \"subagents\" : `${first.type}s`;\n\n\t\titems.push({\n\t\t\ttype: first.type,\n\t\t\tname: dir,\n\t\t\tdescription: `${groupFiles.length} ${typeLabel}`,\n\t\t\tgroup: first.group,\n\t\t\tscope: s,\n\t\t\tstableKey: computeStableKey(first.group, first.type, relPath),\n\t\t\tfiles: groupFiles.map((f) => ({\n\t\t\t\tname: basename(f.relativePath),\n\t\t\t\tcontent: f.content,\n\t\t\t\tpath: f.relativePath,\n\t\t\t})),\n\t\t});\n\t}\n\n\treturn items;\n}\n","export function computeStableKey(\n\tgroup: string,\n\ttype: string,\n\trelPath: string,\n): string {\n\treturn `${group}:${type}:${relPath}`;\n}\n","import * as p from \"@clack/prompts\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { projectGet } from \"../api.js\";\nimport {\n\tbold,\n\tdim,\n\tdivider,\n\tintro,\n\tlime,\n\tlines,\n\toutro,\n\toutroCancel,\n\toutroError,\n\toutroSkipped,\n\tsection,\n\tyellow,\n} from \"../theme.js\";\n\nexport async function createCommand(slugOrShortId: string) {\n\tintro(\"create\");\n\n\tconst s = p.spinner();\n\ts.start(\"Fetching project...\");\n\n\tconst shortId = slugOrShortId.includes(\"-\")\n\t\t? slugOrShortId.slice(slugOrShortId.lastIndexOf(\"-\") + 1)\n\t\t: slugOrShortId;\n\n\tlet project: Awaited<ReturnType<typeof projectGet>>;\n\ttry {\n\t\tproject = await projectGet(shortId);\n\t\tif (!project) {\n\t\t\ts.stop(\"Not found\");\n\t\t\tp.log.error(`Project \"${slugOrShortId}\" not found.`);\n\t\t\toutroError(\"not found\");\n\t\t\tprocess.exit(1);\n\t\t}\n\t\ts.stop(bold(project.name));\n\t} catch (err) {\n\t\ts.stop(\"Failed to fetch project\");\n\t\tp.log.error(err instanceof Error ? err.message : String(err));\n\t\toutroError(\"error\");\n\t\tprocess.exit(1);\n\t}\n\n\tconst localFiles: FileToWrite[] = [];\n\tconst globalFiles: FileToWrite[] = [];\n\n\tfor (const item of project.instructions) {\n\t\tconst isGlobal = item.scope === \"global\";\n\t\tfor (const file of item.files) {\n\t\t\tconst writePath = file.path ?? file.name;\n\t\t\tif (isGlobal) {\n\t\t\t\tglobalFiles.push({ path: writePath, content: file.content });\n\t\t\t} else {\n\t\t\t\tlocalFiles.push({ path: writePath, content: file.content });\n\t\t\t}\n\t\t}\n\t}\n\n\tif (globalFiles.length > 0) {\n\t\tsection(\"global config\", globalFiles.length);\n\t\tlines([dim(\"view only\")]);\n\t\tlines(globalFiles.map((f) => dim(f.path)));\n\t}\n\n\tif (localFiles.length === 0) {\n\t\tp.log.warn(\"No local files to write.\");\n\t\toutroSkipped(\"nothing to create\");\n\t\treturn;\n\t}\n\n\tconst cwd = process.cwd();\n\tconst toWrite: FileToWrite[] = [];\n\tconst skipped: { path: string; differs: boolean }[] = [];\n\n\tfor (const f of localFiles) {\n\t\tconst fullPath = join(cwd, f.path);\n\t\tif (existsSync(fullPath)) {\n\t\t\tconst existing = readFileSync(fullPath, \"utf-8\");\n\t\t\tskipped.push({ path: f.path, differs: existing !== f.content });\n\t\t} else {\n\t\t\ttoWrite.push(f);\n\t\t}\n\t}\n\n\tsection(\"local files\", localFiles.length);\n\tlines(toWrite.map((f) => lime(`+ ${f.path}`)));\n\tlines(\n\t\tskipped.map((f) =>\n\t\t\tf.differs\n\t\t\t\t? `${yellow(`= ${f.path}`)} ${dim(\"(differs)\")}`\n\t\t\t\t: dim(`= ${f.path} (identical)`),\n\t\t),\n\t);\n\n\tif (toWrite.length === 0) {\n\t\tdivider();\n\t\tp.log.info(\"All local files already exist.\");\n\t\toutroSkipped(\"nothing to write\");\n\t\treturn;\n\t}\n\n\tdivider();\n\n\tconst confirm = await p.confirm({\n\t\tmessage: `Write ${lime(String(toWrite.length))} new files? ${dim(`(${skipped.length} skipped)`)}`,\n\t});\n\n\tif (p.isCancel(confirm) || !confirm) {\n\t\toutroCancel();\n\t\tprocess.exit(0);\n\t}\n\n\tfor (const f of toWrite) {\n\t\tconst fullPath = join(cwd, f.path);\n\t\tconst dir = dirname(fullPath);\n\t\tmkdirSync(dir, { recursive: true });\n\t\twriteFileSync(fullPath, f.content);\n\t}\n\n\tp.log.success(\n\t\t`${lime(String(toWrite.length))} written, ${dim(String(skipped.length) + \" skipped\")}`,\n\t);\n\toutro(lime(\"done\"));\n}\n\ninterface FileToWrite {\n\tpath: string;\n\tcontent: string;\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;;;ACAxB,YAAYA,QAAO;AACnB,OAAO,UAAU;;;ACDjB,IAAM,WAAW,QAAQ,IAAI,eAAe;AAE5C,eAAe,QACd,MACA,UAAuB,CAAC,GACJ;AACpB,SAAO,MAAM,GAAG,QAAQ,GAAG,IAAI,IAAI;AAAA,IAClC,GAAG;AAAA,IACH,SAAS;AAAA,MACR,gBAAgB;AAAA,MAChB,GAAG,QAAQ;AAAA,IACZ;AAAA,EACD,CAAC;AACF;AAEA,SAAS,YAAY,OAA4B;AAChD,SAAO,EAAE,eAAe,UAAU,KAAK,GAAG;AAC3C;AAEA,eAAsB,YAInB;AACF,QAAM,MAAM,MAAM,QAAQ,uBAAuB,EAAE,QAAQ,OAAO,CAAC;AACnE,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,sBAAsB,IAAI,MAAM,EAAE;AAC/D,SAAO,IAAI,KAAK;AACjB;AAEA,eAAsB,SACrB,UAC+D;AAC/D,QAAM,MAAM,MAAM;AAAA,IACjB,+BAA+B,mBAAmB,QAAQ,CAAC;AAAA,EAC5D;AACA,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,qBAAqB,IAAI,MAAM,EAAE;AAC9D,SAAO,IAAI,KAAK;AACjB;AAEA,eAAsB,cACrB,OACA,MAC8C;AAC9C,QAAM,MAAM,MAAM;AAAA,IACjB,gCAAgC,mBAAmB,IAAI,CAAC;AAAA,IACxD;AAAA,MACC,SAAS,YAAY,KAAK;AAAA,IAC3B;AAAA,EACD;AACA,MAAI,IAAI,WAAW;AAClB,UAAM,IAAI,MAAM,oDAAoD;AACrE,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,yBAAyB,IAAI,MAAM,EAAE;AAClE,SAAO,IAAI,KAAK;AACjB;AAEA,eAAsB,gBACrB,OACA,MAC0D;AAC1D,QAAM,MAAM,MAAM,QAAQ,6BAA6B;AAAA,IACtD,QAAQ;AAAA,IACR,SAAS,YAAY,KAAK;AAAA,IAC1B,MAAM,KAAK,UAAU,IAAI;AAAA,EAC1B,CAAC;AACD,MAAI,IAAI,WAAW;AAClB,UAAM,IAAI,MAAM,oDAAoD;AACrE,MAAI,CAAC,IAAI,IAAI;AACZ,UAAM,IAAI,MAAM,MAAM,gBAAgB,KAAK,gBAAgB,CAAC;AAAA,EAC7D;AACA,SAAO,IAAI,KAAK;AACjB;AAEA,eAAe,gBAAgB,KAAe,OAAgC;AAC7E,QAAM,SAAS,GAAG,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI,cAAc,EAAE,GAAG,KAAK;AACtE,QAAMC,QAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,MAAI,CAACA,MAAM,QAAO;AAClB,MAAI;AACH,UAAM,OAAO,KAAK,MAAMA,KAAI;AAC5B,UAAM,SAAS,KAAK,SAAS,KAAK;AAClC,QAAI,OAAQ,QAAO,GAAG,MAAM,WAAM,MAAM;AAAA,EACzC,QAAQ;AAAA,EAAC;AACT,QAAM,UAAUA,MAAK,KAAK,EAAE,MAAM,GAAG,GAAG;AACxC,SAAO,UAAU,GAAG,MAAM,WAAM,OAAO,KAAK;AAC7C;AAEA,eAAsB,WAAW,SAA8C;AAC9E,QAAM,MAAM,MAAM,QAAQ,qBAAqB,mBAAmB,OAAO,CAAC,EAAE;AAC5E,MAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,yBAAyB,IAAI,MAAM,EAAE;AAClE,SAAO,IAAI,KAAK;AACjB;;;AC1FA,SAAS,YAAY,WAAW,cAAc,qBAAqB;AACnE,SAAS,eAAe;AACxB,SAAS,YAAY;AAErB,IAAM,aAAa,KAAK,QAAQ,GAAG,WAAW,SAAS;AACvD,IAAM,mBAAmB,KAAK,YAAY,kBAAkB;AAOrD,SAAS,WAA0B;AACzC,MAAI,CAAC,WAAW,gBAAgB,EAAG,QAAO;AAC1C,MAAI;AACH,UAAM,OAAO,KAAK;AAAA,MACjB,aAAa,kBAAkB,OAAO;AAAA,IACvC;AACA,WAAO,KAAK,SAAS;AAAA,EACtB,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAEO,SAAS,UAAU,OAAe,QAAuB;AAC/D,YAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,gBAAc,kBAAkB,KAAK,UAAU,EAAE,OAAO,OAAO,GAAG,MAAM,CAAC,CAAC;AAC3E;AAQA,IAAM,gBAAgB,KAAK,YAAY,eAAe;AAWtD,SAAS,eAA6B;AACrC,MAAI,CAAC,WAAW,aAAa,EAAG,QAAO,CAAC;AACxC,MAAI;AACH,UAAM,MAAM,KAAK,MAAM,aAAa,eAAe,OAAO,CAAC;AAE3D,UAAM,OAAqB,CAAC;AAC5B,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC/C,UAAI,OAAO,UAAU,UAAU;AAC9B,aAAK,GAAG,IAAI,EAAE,MAAM,MAAM;AAAA,MAC3B,OAAO;AACN,aAAK,GAAG,IAAI;AAAA,MACb;AAAA,IACD;AACA,WAAO;AAAA,EACR,QAAQ;AACP,WAAO,CAAC;AAAA,EACT;AACD;AAEA,SAAS,cAAc,MAA0B;AAChD,YAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,gBAAc,eAAe,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAC3D;AAEO,SAAS,eAAe,WAAkC;AAChE,SAAO,aAAa,EAAE,SAAS,GAAG,QAAQ;AAC3C;AAEO,SAAS,iBAAiB,WAA6B;AAC7D,SAAO,aAAa,EAAE,SAAS,GAAG,YAAY,CAAC;AAChD;AAEO,SAAS,oBACf,WACA,MACA,UACO;AACP,QAAM,OAAO,aAAa;AAC1B,OAAK,SAAS,IAAI;AAAA,IACjB;AAAA,IACA,UAAU,SAAS,SAAS,IAAI,WAAW;AAAA,EAC5C;AACA,gBAAc,IAAI;AACnB;;;ACzFA,YAAY,OAAO;AAEnB,IAAM,MAAM,CAAC,SAAiB,QAAQ,IAAI;AAC1C,IAAM,QAAQ,IAAI,GAAG;AAErB,IAAM,OAAO;AACb,IAAM,QAAQ;AACd,IAAM,SAAS;AACf,IAAM,MAAM;AACZ,IAAM,QAAQ;AAEP,IAAM,OAAO,CAAC,MAAc,GAAG,IAAI,QAAQ,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK;AAC9D,IAAM,WAAW,CAAC,MACxB,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,QAAQ,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK;AACvC,IAAM,SAAS,CAAC,MACtB,GAAG,IAAI,QAAQ,IAAI,EAAE,CAAC,GAAG,IAAI,QAAQ,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK;AACnD,IAAM,SAAS,CAAC,MAAc,GAAG,IAAI,QAAQ,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK;AAClE,IAAM,MAAM,CAAC,MAAc,GAAG,IAAI,QAAQ,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK;AAC5D,IAAM,MAAM,CAAC,MAAc,GAAG,IAAI,QAAQ,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK;AAC9D,IAAM,OAAO,CAAC,MAAc,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK;AAGnD,IAAM,SAAS,CAAC,QACtB,GAAG,KAAK,QAAG,CAAC,IAAI,OAAO,WAAW,CAAC,IAAI,KAAK,IAAI,YAAY,CAAC,CAAC;AAG/D,IAAM,MAAM,GAAG,IAAI,QAAQ,KAAK,EAAE,CAAC,SAAI,KAAK;AAErC,SAAS,MAAM,OAAiB;AACtC,aAAW,QAAQ,OAAO;AACzB,YAAQ,IAAI,GAAG,GAAG,KAAK,IAAI,EAAE;AAAA,EAC9B;AACD;AAEO,SAAS,QAAQ,OAAe,OAAgB;AACtD,UAAQ,IAAI,GAAG,GAAG,EAAE;AACpB,QAAM,WAAW,UAAU,SAAY,IAAI,IAAI,OAAO,KAAK,CAAC,CAAC,KAAK;AAClE,UAAQ,IAAI,GAAG,GAAG,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC,GAAG,QAAQ,EAAE;AAC9D;AAEO,SAAS,UAAU;AACzB,UAAQ,IAAI,GAAG,GAAG,KAAK,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC,EAAE;AAC7C;AAEO,SAASC,OAAM,KAAa;AAClC,UAAQ,IAAI;AACZ,EAAE,QAAM,OAAO,GAAG,CAAC;AACpB;AAEO,SAASC,OAAM,KAAa;AAClC,EAAE,QAAM,GAAG;AACX,UAAQ,IAAI;AACb;AAEO,SAAS,WAAW,KAAa;AACvC,EAAE,QAAM,IAAI,GAAG,CAAC;AAChB,UAAQ,IAAI;AACb;AAEO,SAAS,YAAY,MAAM,aAAa;AAC9C,EAAE,SAAO,IAAI,GAAG,CAAC;AACjB,UAAQ,IAAI;AACb;AAEO,SAAS,aAAa,KAAa;AACzC,EAAE,QAAM,IAAI,GAAG,CAAC;AAChB,UAAQ,IAAI;AACb;;;AH7DA,eAAsB,eAAe;AACpC,EAAAC,OAAM,OAAO;AAEb,QAAM,IAAM,WAAQ;AACpB,IAAE,MAAM,4BAA4B;AAEpC,MAAI;AACJ,MAAI;AACH,cAAU,MAAM,UAAU;AAC1B,MAAE,KAAK,iBAAiB;AAAA,EACzB,SAAS,KAAK;AACb,MAAE,KAAK,gCAAgC;AACvC,IAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,eAAW,OAAO;AAClB,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,EAAE,OAAI,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,SAAS,QAAQ,QAAQ,CAAC,EAAE;AACzD,EAAE,OAAI,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,QAAQ,OAAO,CAAC,EAAE;AAEnD,MAAI;AACH,UAAM,KAAK,QAAQ,OAAO;AAAA,EAC3B,QAAQ;AACP,IAAE,OAAI;AAAA,MACL;AAAA,IACD;AAAA,EACD;AAEA,IAAE,MAAM,yBAAyB;AAEjC,QAAM,cAAc;AACpB,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACrC,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAI,CAAC;AAExD,QAAI;AACH,YAAM,SAAS,MAAM,SAAS,QAAQ,QAAQ;AAE9C,UAAI,OAAO,WAAW,cAAc,OAAO,OAAO;AACjD,UAAE,KAAK,KAAK,eAAe,CAAC;AAC5B,kBAAU,OAAO,OAAO,OAAO,MAAM;AACrC,QAAE,OAAI;AAAA,UACL,oBAAoB,SAAS,iBAAiB,CAAC;AAAA,QAChD;AACA,QAAAC,OAAM,KAAK,MAAM,CAAC;AAClB;AAAA,MACD;AAEA,UAAI,OAAO,WAAW,WAAW;AAChC,UAAE,KAAK,iBAAiB;AACxB,QAAE,OAAI,MAAM,mDAAmD;AAC/D,mBAAW,SAAS;AACpB,gBAAQ,KAAK,CAAC;AAAA,MACf;AAAA,IACD,SAAS,KAAK;AACb,QAAE,KAAK,eAAe;AACtB,MAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,iBAAW,OAAO;AAClB,cAAQ,KAAK,CAAC;AAAA,IACf;AAAA,EACD;AAEA,IAAE,KAAK,WAAW;AAClB,EAAE,OAAI,MAAM,6DAA6D;AACzE,aAAW,WAAW;AACtB,UAAQ,KAAK,CAAC;AACf;;;AIvEA,YAAYC,QAAO;AACnB,SAAS,YAAAC,iBAAgB;;;ACDzB,SAAS,cAAAC,aAAY,aAAa,gBAAAC,eAAc,gBAAgB;AAChE,SAAS,QAAAC,OAAM,gBAAgB;AAC/B,SAAS,WAAAC,gBAAe;AACxB,OAAO,YAAY;AAsBnB,IAAM,gBAAgB,MAAM;AAQ5B,IAAM,iBAAgC;AAAA;AAAA,EAErC,EAAE,MAAM,aAAa,MAAM,QAAQ,OAAO,cAAc;AAAA,EACxD,EAAE,MAAM,aAAa,MAAM,QAAQ,OAAO,cAAc;AAAA,EACxD,EAAE,MAAM,gBAAgB,MAAM,QAAQ,OAAO,SAAS;AAAA,EACtD,EAAE,MAAM,kBAAkB,MAAM,QAAQ,OAAO,WAAW;AAAA,EAC1D,EAAE,MAAM,eAAe,MAAM,QAAQ,OAAO,QAAQ;AAAA,EACpD,EAAE,MAAM,mCAAmC,MAAM,QAAQ,OAAO,UAAU;AAAA;AAAA,EAE1E,EAAE,MAAM,YAAY,MAAM,OAAO,OAAO,UAAU;AAAA,EAClD,EAAE,MAAM,oBAAoB,MAAM,OAAO,OAAO,SAAS;AAAA,EACzD;AAAA,IACC,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,EACR;AAAA;AAAA,EAEA,EAAE,MAAM,mBAAmB,MAAM,UAAU,OAAO,QAAQ;AAAA,EAC1D,EAAE,MAAM,yBAAyB,MAAM,UAAU,OAAO,WAAW;AAAA,EACnE,EAAE,MAAM,yBAAyB,MAAM,UAAU,OAAO,cAAc;AAAA,EACtE;AAAA,IACC,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,EACR;AAAA;AAAA,EAEA,EAAE,MAAM,oBAAoB,MAAM,UAAU,OAAO,UAAU;AAC9D;AAEA,IAAM,qBAAuE;AAAA,EAC5E,EAAE,KAAK,iBAAiB,MAAM,QAAQ,OAAO,SAAS;AAAA,EACtD,EAAE,KAAK,oBAAoB,MAAM,WAAW,OAAO,cAAc;AAAA,EACjE,EAAE,KAAK,kBAAkB,MAAM,YAAY,OAAO,cAAc;AAAA,EAChE,EAAE,KAAK,iBAAiB,MAAM,QAAQ,OAAO,cAAc;AAAA,EAC3D,EAAE,KAAK,WAAW,MAAM,UAAU,OAAO,UAAU;AAAA,EACnD,EAAE,KAAK,OAAO,MAAM,UAAU,OAAO,UAAU;AAChD;AAEA,SAAS,cAAc,KAAwC;AAC9D,QAAM,KAAK,OAAO;AAClB,QAAM,gBAAgBD,MAAK,KAAK,YAAY;AAC5C,MAAIF,YAAW,aAAa,GAAG;AAC9B,OAAG,IAAIC,cAAa,eAAe,OAAO,CAAC;AAAA,EAC5C;AACA,KAAG,IAAI,CAAC,gBAAgB,QAAQ,QAAQ,SAAS,SAAS,SAAS,CAAC;AACpE,SAAO;AACR;AAEA,SAAS,aAAa,UAAiC;AACtD,MAAI;AACH,UAAM,OAAO,SAAS,QAAQ;AAC9B,QAAI,KAAK,OAAO,cAAe,QAAO;AACtC,WAAOA,cAAa,UAAU,OAAO;AAAA,EACtC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAEA,SAAS,QAAQ,KAAa,WAAW,GAAG,eAAe,GAAa;AACvE,MAAI,gBAAgB,YAAY,CAACD,YAAW,GAAG,EAAG,QAAO,CAAC;AAC1D,QAAM,UAAoB,CAAC;AAC3B,MAAI;AACH,eAAW,SAAS,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC9D,YAAM,WAAWE,MAAK,KAAK,MAAM,IAAI;AACrC,UAAI,MAAM,OAAO,GAAG;AACnB,gBAAQ,KAAK,QAAQ;AAAA,MACtB,WAAW,MAAM,YAAY,GAAG;AAC/B,gBAAQ,KAAK,GAAG,QAAQ,UAAU,UAAU,eAAe,CAAC,CAAC;AAAA,MAC9D;AAAA,IACD;AAAA,EACD,QAAQ;AAAA,EAER;AACA,SAAO;AACR;AAEO,SAAS,UAAU,KAA4B;AACrD,QAAM,KAAK,cAAc,GAAG;AAC5B,QAAM,UAAyB,CAAC;AAEhC,aAAW,WAAW,gBAAgB;AACrC,UAAM,WAAWA,MAAK,KAAK,QAAQ,IAAI;AACvC,UAAM,UAAU,aAAa,QAAQ;AACrC,QAAI,YAAY,MAAM;AACrB,YAAM,MAAM,SAAS,KAAK,QAAQ;AAClC,UAAI,CAAC,GAAG,QAAQ,GAAG,GAAG;AACrB,gBAAQ,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,cAAc;AAAA,UACd;AAAA,UACA,MAAM,QAAQ;AAAA,UACd,QAAQ;AAAA,UACR,OAAO,QAAQ;AAAA,QAChB,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,aAAW,EAAE,KAAK,MAAM,MAAM,KAAK,oBAAoB;AACtD,UAAM,UAAUA,MAAK,KAAK,GAAG;AAC7B,UAAM,QAAQ,QAAQ,OAAO;AAC7B,eAAW,YAAY,OAAO;AAC7B,YAAM,MAAM,SAAS,KAAK,QAAQ;AAClC,UAAI,GAAG,QAAQ,GAAG,EAAG;AACrB,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,YAAY,MAAM;AACrB,gBAAQ,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,cAAc;AAAA,UACd;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,UACR;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAGA,MAAI;AACH,eAAW,SAAS,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,EAAE;AAAA,MAAO,CAAC,MACrE,EAAE,YAAY;AAAA,IACf,GAAG;AACF,UAAI,GAAG,QAAQ,MAAM,OAAO,GAAG,EAAG;AAClC,oBAAcA,MAAK,KAAK,MAAM,IAAI,GAAG,KAAK,IAAI,SAAS,CAAC;AAAA,IACzD;AAAA,EACD,QAAQ;AAAA,EAER;AAEA,SAAO;AACR;AAEA,SAAS,cACR,KACA,KACA,IACA,SACA,OACC;AACD,MAAI,QAAQ,EAAG;AACf,QAAM,UAAUA,MAAK,KAAK,UAAU;AACpC,MAAIF,YAAW,OAAO,GAAG;AACxB,UAAM,QAAQ,QAAQ,KAAK,CAAC;AAC5B,eAAW,YAAY,OAAO;AAC7B,YAAM,MAAM,SAAS,KAAK,QAAQ;AAClC,UAAI,GAAG,QAAQ,GAAG,EAAG;AACrB,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,YAAY,MAAM;AACrB,gBAAQ,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,cAAc;AAAA,UACd;AAAA,UACA,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,OAAO;AAAA,QACR,CAAC;AAAA,MACF;AAAA,IACD;AACA;AAAA,EACD;AACA,MAAI;AACH,eAAW,SAAS,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC9D,UAAI,MAAM,YAAY,GAAG;AACxB,cAAM,MAAM,SAAS,KAAKE,MAAK,KAAK,MAAM,IAAI,CAAC;AAC/C,YAAI,CAAC,GAAG,QAAQ,MAAM,GAAG,GAAG;AAC3B,wBAAcA,MAAK,KAAK,MAAM,IAAI,GAAG,KAAK,IAAI,SAAS,QAAQ,CAAC;AAAA,QACjE;AAAA,MACD;AAAA,IACD;AAAA,EACD,QAAQ;AAAA,EAER;AACD;AAEO,SAAS,aAA4B;AAC3C,QAAM,OAAOC,SAAQ;AACrB,QAAM,UAAyB,CAAC;AAEhC,QAAM,iBAAgC;AAAA,IACrC,EAAE,MAAM,qBAAqB,MAAM,QAAQ,OAAO,cAAc;AAAA,IAChE,EAAE,MAAM,yBAAyB,MAAM,UAAU,OAAO,cAAc;AAAA,IACtE,EAAE,MAAM,oBAAoB,MAAM,OAAO,OAAO,SAAS;AAAA,IACzD,EAAE,MAAM,yBAAyB,MAAM,UAAU,OAAO,WAAW;AAAA,IACnE,EAAE,MAAM,mBAAmB,MAAM,UAAU,OAAO,QAAQ;AAAA,EAC3D;AAEA,aAAW,WAAW,gBAAgB;AACrC,UAAM,WAAWD,MAAK,MAAM,QAAQ,IAAI;AACxC,UAAM,UAAU,aAAa,QAAQ;AACrC,QAAI,YAAY,MAAM;AACrB,cAAQ,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,cAAc,KAAK,QAAQ,IAAI;AAAA,QAC/B;AAAA,QACA,MAAM,QAAQ;AAAA,QACd,QAAQ;AAAA,QACR,OAAO,QAAQ;AAAA,MAChB,CAAC;AAAA,IACF;AAAA,EACD;AAEA,QAAM,aAA+D;AAAA,IACpE,EAAE,KAAK,oBAAoB,MAAM,WAAW,OAAO,cAAc;AAAA,IACjE,EAAE,KAAK,kBAAkB,MAAM,YAAY,OAAO,cAAc;AAAA,IAChE,EAAE,KAAK,iBAAiB,MAAM,QAAQ,OAAO,cAAc;AAAA,IAC3D,EAAE,KAAK,iBAAiB,MAAM,QAAQ,OAAO,SAAS;AAAA,EACvD;AAEA,aAAW,EAAE,KAAK,MAAM,MAAM,KAAK,YAAY;AAC9C,UAAM,UAAUA,MAAK,MAAM,GAAG;AAC9B,UAAM,QAAQ,QAAQ,SAAS,CAAC;AAChC,eAAW,YAAY,OAAO;AAC7B,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,YAAY,MAAM;AACrB,gBAAQ,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,cAAc,KAAK,SAAS,MAAM,QAAQ,CAAC;AAAA,UAC3C;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,UACR;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;;;ACnQA,SAAS,UAAU,eAAe;;;ACF3B,SAAS,iBACf,OACA,MACA,SACS;AACT,SAAO,GAAG,KAAK,IAAI,IAAI,IAAI,OAAO;AACnC;;;ADDO,SAAS,SAAS,OAAyC;AAEjE,QAAM,SAAS,oBAAI,IAA2B;AAC9C,QAAM,aAA4B,CAAC;AAEnC,QAAM,iBAAiB,oBAAI,IAAI;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,aAAW,QAAQ,OAAO;AACzB,UAAM,MAAM,QAAQ,KAAK,YAAY;AACrC,UAAM,cAAc,eAAe,IAAI,GAAG;AAE1C,QAAI,aAAa;AAChB,iBAAW,KAAK,IAAI;AAAA,IACrB,OAAO;AACN,YAAM,MAAM,GAAG,KAAK,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK,IAAI,IAAI,GAAG;AAC5D,YAAM,WAAW,OAAO,IAAI,GAAG,KAAK,CAAC;AACrC,eAAS,KAAK,IAAI;AAClB,aAAO,IAAI,KAAK,QAAQ;AAAA,IACzB;AAAA,EACD;AAEA,QAAM,QAA2B,CAAC;AAClC,QAAM,QAAQ,CAAC,WACd,WAAW,WAAY,WAAsB;AAG9C,aAAW,QAAQ,YAAY;AAC9B,UAAM,IAAI,MAAM,KAAK,MAAM;AAC3B,UAAM,UAAU,KAAK,aACnB,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,cAAc,EAAE;AAC1B,UAAM,KAAK;AAAA,MACV,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,WAAW,iBAAiB,KAAK,OAAO,KAAK,MAAM,OAAO;AAAA,MAC1D,OAAO;AAAA,QACN;AAAA,UACC,MAAM,SAAS,KAAK,YAAY;AAAA,UAChC,SAAS,KAAK;AAAA,UACd,MAAM,KAAK;AAAA,QACZ;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAGA,aAAW,CAAC,EAAE,UAAU,KAAK,QAAQ;AACpC,UAAM,QAAQ,WAAW,CAAC;AAC1B,UAAM,MAAM,QAAQ,MAAM,YAAY;AACtC,UAAM,IAAI,MAAM,MAAM,MAAM;AAC5B,UAAM,UAAU,IACd,QAAQ,kBAAkB,EAAE,EAC5B,QAAQ,eAAe,EAAE,EACzB,QAAQ,kBAAkB,EAAE,EAC5B,QAAQ,eAAe,EAAE;AAC3B,UAAM,YACL,MAAM,SAAS,aAAa,cAAc,GAAG,MAAM,IAAI;AAExD,UAAM,KAAK;AAAA,MACV,MAAM,MAAM;AAAA,MACZ,MAAM;AAAA,MACN,aAAa,GAAG,WAAW,MAAM,IAAI,SAAS;AAAA,MAC9C,OAAO,MAAM;AAAA,MACb,OAAO;AAAA,MACP,WAAW,iBAAiB,MAAM,OAAO,MAAM,MAAM,OAAO;AAAA,MAC5D,OAAO,WAAW,IAAI,CAAC,OAAO;AAAA,QAC7B,MAAM,SAAS,EAAE,YAAY;AAAA,QAC7B,SAAS,EAAE;AAAA,QACX,MAAM,EAAE;AAAA,MACT,EAAE;AAAA,IACH,CAAC;AAAA,EACF;AAEA,SAAO;AACR;;;AFzDA,eAAsB,eAAe,SAA8B;AAClE,EAAAE,OAAM,SAAS;AAEf,QAAM,QAAQ,SAAS;AACvB,MAAI,CAAC,OAAO;AACX,IAAE,OAAI,MAAM,0BAA0B,SAAS,eAAe,CAAC,SAAS;AACxE,eAAW,mBAAmB;AAC9B,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,YAAY,eAAe,GAAG;AACpC,QAAM,gBAAgB,iBAAiB,GAAG;AAE1C,QAAM,IAAM,WAAQ;AACpB,IAAE,MAAM,aAAa;AAErB,QAAM,aAAa,UAAU,GAAG;AAChC,QAAM,cAAc,QAAQ,SAAS,WAAW,IAAI,CAAC;AACrD,IAAE,KAAK,eAAe;AAEtB,MAAI,WAAW,WAAW,KAAK,YAAY,WAAW,GAAG;AACxD,IAAE,OAAI,KAAK,kCAAkC;AAC7C,iBAAa,oBAAoB;AACjC;AAAA,EACD;AAGA,MAAI;AACJ,MAAI,WAAW;AACd,IAAE,OAAI,KAAK,GAAG,IAAI,SAAS,CAAC,IAAI,SAAS,SAAS,CAAC,EAAE;AACrD,kBAAc;AAAA,EACf,OAAO;AACN,UAAM,cAAcC,UAAS,GAAG;AAChC,UAAM,OAAO,MAAQ,QAAK;AAAA,MACzB,SAAS;AAAA,MACT,cAAc;AAAA,MACd,aAAa;AAAA,IACd,CAAC;AACD,QAAM,YAAS,IAAI,GAAG;AACrB,kBAAY;AACZ,cAAQ,KAAK,CAAC;AAAA,IACf;AACA,kBAAe,QAAmB;AAAA,EACnC;AAGA,QAAM,WAAW,CAAC,GAAG,YAAY,GAAG,WAAW;AAC/C,MAAI,gBAAgB,SAAS;AAAA,IAC5B,CAAC,MAAM,CAAC,cAAc,SAAS,EAAE,YAAY;AAAA,EAC9C;AACA,MAAI,WAAW,SAAS,OAAO,CAAC,MAAM,cAAc,SAAS,EAAE,YAAY,CAAC;AAG5E,EAAE,OAAI;AAAA,IACL,GAAG,KAAK,OAAO,cAAc,MAAM,CAAC,CAAC,YAAY,SAAS,SAAS,IAAI,SAAM,IAAI,OAAO,SAAS,MAAM,IAAI,WAAW,CAAC,KAAK,EAAE;AAAA,EAC/H;AAGA,MAAI,kBAAkB,SAAS,aAAa;AAG5C,MAAI,kBAA0D;AAC9D,MAAI;AACH,UAAM,QAAQ,MAAM,cAAc,OAAO,WAAW;AACpD,QAAI,MAAM,UAAU,MAAM,MAAM;AAC/B,YAAM,UAAU,MAAM,KAAK,SAAS,GAAG,IACpC,MAAM,KAAK,MAAM,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC,IAChD,MAAM;AACT,wBAAkB,MAAM,WAAW,OAAO;AAAA,IAC3C;AAAA,EACD,SAAS,KAAK;AACb,IAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,eAAW,OAAO;AAClB,YAAQ,KAAK,CAAC;AAAA,EACf;AAGA,MAAI,iBAAiB;AACpB,UAAM,OAAO;AAAA,MACZ;AAAA,MACA,gBAAgB;AAAA,IACjB;AAEA,QAAI,KAAK,YAAY,KAAK,KAAK,UAAU,KAAK,KAAK,YAAY,GAAG;AACjE,MAAE,OAAI,KAAK,gCAAgC;AAC3C,mBAAa,mBAAmB;AAChC;AAAA,IACD;AAEA,YAAQ;AACR,YAAQ,SAAS;AACjB;AAAA,MACC,KAAK,QAAQ,IAAI,CAAC,MAAM;AACvB,YAAI,EAAE,WAAW,QAAS,QAAO,KAAK,KAAK,EAAE,IAAI,EAAE;AACnD,YAAI,EAAE,WAAW,UAAW,QAAO,OAAO,KAAK,EAAE,IAAI,EAAE;AACvD,eAAO,IAAI,KAAK,EAAE,IAAI,EAAE;AAAA,MACzB,CAAC;AAAA,IACF;AACA,QAAI,KAAK,YAAY,GAAG;AACvB,YAAM,CAAC,IAAI,GAAG,KAAK,SAAS,YAAY,CAAC,CAAC;AAAA,IAC3C;AACA,YAAQ;AAAA,EACT,OAAO;AACN,UAAM,QAAQ,cAAc,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO;AAC9D,UAAM,SAAS,cAAc,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ;AAEhE,QAAI,MAAM,SAAS,GAAG;AACrB,MAAE,OAAI,KAAK,GAAG,KAAK,OAAO,CAAC,IAAI,IAAI,OAAO,MAAM,MAAM,CAAC,CAAC,EAAE;AAC1D,cAAQ;AACR,iBAAW,CAAC,MAAM,KAAK,KAAK,YAAY,KAAK,GAAG;AAC/C,cAAM,CAAC,GAAG,KAAK,KAAK,YAAY,CAAC,CAAC,IAAI,IAAI,GAAG,MAAM,MAAM,EAAE,CAAC,EAAE,CAAC;AAC/D,cAAM,MAAM,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;AAAA,MACnD;AACA,cAAQ;AAAA,IACT;AACA,QAAI,OAAO,SAAS,GAAG;AACtB,MAAE,OAAI,KAAK,GAAG,KAAK,QAAQ,CAAC,IAAI,IAAI,OAAO,OAAO,MAAM,CAAC,CAAC,EAAE;AAC5D,cAAQ;AACR,iBAAW,CAAC,MAAM,KAAK,KAAK,YAAY,MAAM,GAAG;AAChD,cAAM,CAAC,GAAG,KAAK,KAAK,YAAY,CAAC,CAAC,IAAI,IAAI,GAAG,MAAM,MAAM,EAAE,CAAC,EAAE,CAAC;AAC/D,cAAM,MAAM,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;AAAA,MACnD;AACA,cAAQ;AAAA,IACT;AAAA,EACD;AAGA,QAAM,SAAS,MAAQ,UAAO;AAAA,IAC7B,SAAS,kBACN,oBACA,UAAU,KAAK,OAAO,cAAc,MAAM,CAAC,CAAC,aAAa,SAAS,WAAW,CAAC;AAAA,IACjF,SAAS;AAAA,MACR,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,MACnC,EAAE,OAAO,aAAa,OAAO,eAAe;AAAA,MAC5C,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,IACpC;AAAA,EACD,CAAC;AAED,MAAM,YAAS,MAAM,KAAK,WAAW,UAAU;AAC9C,gBAAY;AACZ,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,MAAI,WAAW,aAAa;AAC3B,UAAM,WAAW,MAAQ,eAAY;AAAA,MACpC,SAAS;AAAA,MACT,SAAS,SAAS,IAAI,CAAC,OAAO;AAAA,QAC7B,OAAO,EAAE;AAAA,QACT,OAAO,EAAE;AAAA,QACT,MAAM,GAAG,EAAE,IAAI,GAAG,EAAE,WAAW,WAAW,iBAAc,EAAE;AAAA,MAC3D,EAAE;AAAA,MACF,eAAe,cAAc,IAAI,CAAC,MAAM,EAAE,YAAY;AAAA,IACvD,CAAC;AAED,QAAM,YAAS,QAAQ,GAAG;AACzB,kBAAY;AACZ,cAAQ,KAAK,CAAC;AAAA,IACf;AAEA,UAAM,cAAc,IAAI,IAAI,QAAoB;AAChD,oBAAgB,SAAS,OAAO,CAAC,MAAM,YAAY,IAAI,EAAE,YAAY,CAAC;AACtE,eAAW,SAAS,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,YAAY,CAAC;AAClE,sBAAkB,SAAS,aAAa;AAExC,QAAI,cAAc,WAAW,GAAG;AAC/B,MAAE,OAAI,KAAK,oBAAoB;AAC/B,mBAAa,oBAAoB;AACjC,cAAQ,KAAK,CAAC;AAAA,IACf;AAAA,EACD;AAEA,IAAE,MAAM,cAAc;AACtB,MAAI;AACH,UAAM,SAAS,MAAM,gBAAgB,OAAO;AAAA,MAC3C,MAAM;AAAA,MACN,cAAc;AAAA,IACf,CAAC;AACD,MAAE,KAAK,KAAK,UAAU,CAAC;AACvB;AAAA,MACC;AAAA,MACA;AAAA,MACA,SAAS,IAAI,CAAC,MAAM,EAAE,YAAY;AAAA,IACnC;AACA,IAAE,OAAI,QAAQ,IAAI,OAAO,GAAG,CAAC;AAC7B,IAAAC,OAAM,KAAK,MAAM,CAAC;AAAA,EACnB,SAAS,KAAK;AACb,MAAE,KAAK,eAAe;AACtB,IAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,eAAW,eAAe;AAC1B,YAAQ,KAAK,CAAC;AAAA,EACf;AACD;AAEA,IAAM,aAAa;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEA,SAAS,YAAY,OAAkD;AACtE,QAAM,MAAM,oBAAI,IAA2B;AAC3C,aAAW,KAAK,OAAO;AACtB,UAAM,WAAW,IAAI,IAAI,EAAE,IAAI,KAAK,CAAC;AACrC,aAAS,KAAK,CAAC;AACf,QAAI,IAAI,EAAE,MAAM,QAAQ;AAAA,EACzB;AACA,QAAM,SAAS,oBAAI,IAA2B;AAC9C,aAAW,QAAQ,YAAY;AAC9B,UAAM,QAAQ,IAAI,IAAI,IAAI;AAC1B,QAAI,MAAO,QAAO,IAAI,MAAM,KAAK;AAAA,EAClC;AACA,aAAW,CAAC,MAAM,KAAK,KAAK,KAAK;AAChC,QAAI,CAAC,OAAO,IAAI,IAAI,EAAG,QAAO,IAAI,MAAM,KAAK;AAAA,EAC9C;AACA,SAAO;AACR;AAUA,SAAS,iBACR,SACA,UACa;AACb,QAAM,cAAc,oBAAI,IAAoB;AAC5C,aAAW,QAAQ,UAAU;AAC5B,eAAW,QAAQ,KAAK,OAAO;AAC9B,kBAAY,IAAI,KAAK,QAAQ,KAAK,MAAM,KAAK,OAAO;AAAA,IACrD;AAAA,EACD;AAEA,QAAM,aAAa,oBAAI,IAAoB;AAC3C,aAAW,QAAQ,SAAS;AAC3B,eAAW,QAAQ,KAAK,OAAO;AAC9B,iBAAW,IAAI,KAAK,QAAQ,KAAK,MAAM,KAAK,OAAO;AAAA,IACpD;AAAA,EACD;AAEA,QAAM,UAAiC,CAAC;AACxC,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,MAAI,YAAY;AAEhB,aAAW,CAAC,KAAK,OAAO,KAAK,YAAY;AACxC,UAAM,OAAO,YAAY,IAAI,GAAG;AAChC,QAAI,SAAS,QAAW;AACvB;AACA,cAAQ,KAAK,EAAE,MAAM,KAAK,QAAQ,QAAQ,CAAC;AAAA,IAC5C,WAAW,SAAS,SAAS;AAC5B;AACA,cAAQ,KAAK,EAAE,MAAM,KAAK,QAAQ,UAAU,CAAC;AAAA,IAC9C,OAAO;AACN;AAAA,IACD;AAAA,EACD;AAEA,MAAI,UAAU;AACd,aAAW,OAAO,YAAY,KAAK,GAAG;AACrC,QAAI,CAAC,WAAW,IAAI,GAAG,GAAG;AACzB;AACA,cAAQ,KAAK,EAAE,MAAM,KAAK,QAAQ,UAAU,CAAC;AAAA,IAC9C;AAAA,EACD;AAEA,SAAO,EAAE,OAAO,SAAS,SAAS,WAAW,QAAQ;AACtD;;;AItTA,YAAYC,QAAO;AACnB,SAAS,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,eAAc,iBAAAC,sBAAqB;AACnE,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAiB9B,eAAsB,cAAc,eAAuB;AAC1D,EAAAC,OAAM,QAAQ;AAEd,QAAM,IAAM,WAAQ;AACpB,IAAE,MAAM,qBAAqB;AAE7B,QAAM,UAAU,cAAc,SAAS,GAAG,IACvC,cAAc,MAAM,cAAc,YAAY,GAAG,IAAI,CAAC,IACtD;AAEH,MAAI;AACJ,MAAI;AACH,cAAU,MAAM,WAAW,OAAO;AAClC,QAAI,CAAC,SAAS;AACb,QAAE,KAAK,WAAW;AAClB,MAAE,OAAI,MAAM,YAAY,aAAa,cAAc;AACnD,iBAAW,WAAW;AACtB,cAAQ,KAAK,CAAC;AAAA,IACf;AACA,MAAE,KAAK,KAAK,QAAQ,IAAI,CAAC;AAAA,EAC1B,SAAS,KAAK;AACb,MAAE,KAAK,yBAAyB;AAChC,IAAE,OAAI,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC5D,eAAW,OAAO;AAClB,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,aAA4B,CAAC;AACnC,QAAM,cAA6B,CAAC;AAEpC,aAAW,QAAQ,QAAQ,cAAc;AACxC,UAAM,WAAW,KAAK,UAAU;AAChC,eAAW,QAAQ,KAAK,OAAO;AAC9B,YAAM,YAAY,KAAK,QAAQ,KAAK;AACpC,UAAI,UAAU;AACb,oBAAY,KAAK,EAAE,MAAM,WAAW,SAAS,KAAK,QAAQ,CAAC;AAAA,MAC5D,OAAO;AACN,mBAAW,KAAK,EAAE,MAAM,WAAW,SAAS,KAAK,QAAQ,CAAC;AAAA,MAC3D;AAAA,IACD;AAAA,EACD;AAEA,MAAI,YAAY,SAAS,GAAG;AAC3B,YAAQ,iBAAiB,YAAY,MAAM;AAC3C,UAAM,CAAC,IAAI,WAAW,CAAC,CAAC;AACxB,UAAM,YAAY,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,CAAC,CAAC;AAAA,EAC1C;AAEA,MAAI,WAAW,WAAW,GAAG;AAC5B,IAAE,OAAI,KAAK,0BAA0B;AACrC,iBAAa,mBAAmB;AAChC;AAAA,EACD;AAEA,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,UAAyB,CAAC;AAChC,QAAM,UAAgD,CAAC;AAEvD,aAAW,KAAK,YAAY;AAC3B,UAAM,WAAWC,MAAK,KAAK,EAAE,IAAI;AACjC,QAAIC,YAAW,QAAQ,GAAG;AACzB,YAAM,WAAWC,cAAa,UAAU,OAAO;AAC/C,cAAQ,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,aAAa,EAAE,QAAQ,CAAC;AAAA,IAC/D,OAAO;AACN,cAAQ,KAAK,CAAC;AAAA,IACf;AAAA,EACD;AAEA,UAAQ,eAAe,WAAW,MAAM;AACxC,QAAM,QAAQ,IAAI,CAAC,MAAM,KAAK,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C;AAAA,IACC,QAAQ;AAAA,MAAI,CAAC,MACZ,EAAE,UACC,GAAG,OAAO,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,WAAW,CAAC,KAC5C,IAAI,KAAK,EAAE,IAAI,cAAc;AAAA,IACjC;AAAA,EACD;AAEA,MAAI,QAAQ,WAAW,GAAG;AACzB,YAAQ;AACR,IAAE,OAAI,KAAK,gCAAgC;AAC3C,iBAAa,kBAAkB;AAC/B;AAAA,EACD;AAEA,UAAQ;AAER,QAAMC,WAAU,MAAQ,WAAQ;AAAA,IAC/B,SAAS,SAAS,KAAK,OAAO,QAAQ,MAAM,CAAC,CAAC,eAAe,IAAI,IAAI,QAAQ,MAAM,WAAW,CAAC;AAAA,EAChG,CAAC;AAED,MAAM,YAASA,QAAO,KAAK,CAACA,UAAS;AACpC,gBAAY;AACZ,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,aAAW,KAAK,SAAS;AACxB,UAAM,WAAWH,MAAK,KAAK,EAAE,IAAI;AACjC,UAAM,MAAMI,SAAQ,QAAQ;AAC5B,IAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,IAAAC,eAAc,UAAU,EAAE,OAAO;AAAA,EAClC;AAEA,EAAE,OAAI;AAAA,IACL,GAAG,KAAK,OAAO,QAAQ,MAAM,CAAC,CAAC,aAAa,IAAI,OAAO,QAAQ,MAAM,IAAI,UAAU,CAAC;AAAA,EACrF;AACA,EAAAC,OAAM,KAAK,MAAM,CAAC;AACnB;;;ATzHA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACE,KAAK,SAAS,EACd,YAAY,+CAA+C,EAC3D,QAAQ,OAAO;AAEjB,QACE,QAAQ,OAAO,EACf,YAAY,4BAA4B,EACxC,OAAO,YAAY;AAErB,QACE,QAAQ,SAAS,EACjB,YAAY,mDAAmD,EAC/D,OAAO,eAAe,+CAA+C,EACrE,OAAO,CAAC,YAAY,eAAe,EAAE,QAAQ,QAAQ,UAAU,KAAK,CAAC,CAAC;AAExE,QACE,QAAQ,QAAQ,EAChB,YAAY,0DAA0D,EACtE,SAAS,UAAU,0BAA0B,EAC7C,OAAO,aAAa;AAEtB,QAAQ,MAAM;","names":["p","text","intro","outro","intro","outro","p","basename","existsSync","readFileSync","join","homedir","intro","basename","outro","p","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","intro","join","existsSync","readFileSync","confirm","dirname","mkdirSync","writeFileSync","outro"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@use-aistack/cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Share and clone AI development configurations",
5
5
  "type": "module",
6
6
  "license": "MIT",