ai-builder 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +54 -0
  2. package/dist/index.js +395 -58
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -22,6 +22,8 @@
22
22
  - **Install stacks** - Bundle multiple artifacts together for specific workflows
23
23
  - **Search the registry** - Find artifacts by name, description, or task category
24
24
  - **Manage installed artifacts** - List and remove artifacts from your project
25
+ - **Self-update** - Keep the CLI up to date with a single command
26
+ - **Shell completions** - Tab completion for bash and zsh
25
27
 
26
28
  ---
27
29
 
@@ -156,6 +158,58 @@ npx ai-builder search "nextjs" --task frontend
156
158
  npx ai-builder search "database" --limit 5
157
159
  ```
158
160
 
161
+ ### Status
162
+
163
+ Show CLI status and installed artifacts:
164
+
165
+ ```bash
166
+ npx ai-builder status
167
+ ```
168
+
169
+ **Output includes:**
170
+ - CLI version
171
+ - Claude directory detection
172
+ - Installed artifact counts by type
173
+ - Registry connectivity check
174
+
175
+ ### Update
176
+
177
+ Update the CLI to the latest version:
178
+
179
+ ```bash
180
+ npx ai-builder update
181
+ ```
182
+
183
+ **Options:**
184
+
185
+ ```bash
186
+ # Check for updates without installing
187
+ npx ai-builder update --check
188
+ ```
189
+
190
+ ### Completion
191
+
192
+ Generate shell completions for bash or zsh:
193
+
194
+ ```bash
195
+ # Output completion script
196
+ npx ai-builder completion bash
197
+ npx ai-builder completion zsh
198
+
199
+ # Auto-install for current shell
200
+ npx ai-builder completion --setup
201
+ ```
202
+
203
+ **Manual installation:**
204
+
205
+ ```bash
206
+ # Bash
207
+ ai-builder completion bash >> ~/.bashrc
208
+
209
+ # Zsh
210
+ ai-builder completion zsh >> ~/.zshrc
211
+ ```
212
+
159
213
  ---
160
214
 
161
215
  ## Artifact Types
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import chalk5 from "chalk";
4
+ import chalk8 from "chalk";
5
5
  import { Command } from "commander";
6
6
 
7
7
  // src/commands/add.ts
@@ -12,17 +12,20 @@ import ora from "ora";
12
12
  // src/services/api.ts
13
13
  import { createCliLogger } from "@aibuilder/logger/adapters/cli";
14
14
  var API_BASE = process.env.AI_BUILDER_API_URL || "https://aibuilder.sh/api";
15
- var logger = createCliLogger({ base: { module: "cli:api" } });
15
+ var logger = createCliLogger({
16
+ verbose: process.env.DEBUG?.includes("ai-builder"),
17
+ base: { module: "cli:api" }
18
+ });
16
19
  async function resolveArtifact(type, slug) {
17
20
  const url = `${API_BASE}/resolve?type=${encodeURIComponent(type)}&slug=${encodeURIComponent(slug)}`;
18
- logger.debug({ type, slug, url }, "Resolving artifact");
21
+ const timer = logger.startTimer("api-resolve");
19
22
  const response = await fetch(url);
20
23
  if (!response.ok) {
21
24
  const errorBody = await response.json().catch(() => ({ error: "Unknown error" }));
22
- logger.error({ type, slug, status: response.status }, "Failed to resolve artifact");
25
+ timer.done({ type, slug, status: response.status, success: false });
23
26
  throw new Error(errorBody.error || `Failed to resolve artifact: ${response.status}`);
24
27
  }
25
- logger.debug({ type, slug }, "Artifact resolved successfully");
28
+ timer.done({ type, slug, status: response.status, success: true });
26
29
  return response.json();
27
30
  }
28
31
  async function searchArtifacts(options) {
@@ -35,39 +38,44 @@ async function searchArtifacts(options) {
35
38
  if (options.task) params.set("task", options.task);
36
39
  if (options.limit) params.set("limit", options.limit.toString());
37
40
  const url = `${API_BASE}/artifacts?${params.toString()}`;
38
- logger.debug({ options, url }, "Searching artifacts");
41
+ const timer = logger.startTimer("api-search");
39
42
  const response = await fetch(url);
40
43
  if (!response.ok) {
41
- logger.error({ status: response.status, options }, "Search failed");
44
+ timer.done({ query: options.query, status: response.status, success: false });
42
45
  throw new Error(`Failed to search artifacts: ${response.status}`);
43
46
  }
44
47
  const result = await response.json();
45
- logger.debug({ resultCount: result.artifacts.length, total: result.total }, "Search completed");
48
+ timer.done({
49
+ query: options.query,
50
+ resultCount: result.artifacts.length,
51
+ total: result.total,
52
+ success: true
53
+ });
46
54
  return result;
47
55
  }
48
56
  async function trackInstall(type, slug, cliVersion) {
49
57
  try {
50
- await fetch(`${API_BASE}/install-events`, {
58
+ const response = await fetch(`${API_BASE}/install-events`, {
51
59
  method: "POST",
52
60
  headers: { "Content-Type": "application/json" },
53
61
  body: JSON.stringify({ type, slug, cliVersion })
54
62
  });
55
- logger.debug({ type, slug, cliVersion }, "Install tracked");
63
+ logger.debug({ type, slug, cliVersion, status: response.status }, "Install tracked");
56
64
  } catch (error) {
57
65
  logger.debug({ err: error, type, slug }, "Install tracking failed (non-critical)");
58
66
  }
59
67
  }
60
68
  async function resolveStack(slug) {
61
69
  const url = `${API_BASE}/stacks/${encodeURIComponent(slug)}`;
62
- logger.debug({ slug, url }, "Resolving stack");
70
+ const timer = logger.startTimer("api-resolve-stack");
63
71
  const response = await fetch(url);
64
72
  if (!response.ok) {
65
73
  const errorBody = await response.json().catch(() => ({ error: "Unknown error" }));
66
- logger.error({ slug, status: response.status }, "Failed to resolve stack");
74
+ timer.done({ slug, status: response.status, success: false });
67
75
  throw new Error(errorBody.error || `Failed to resolve stack: ${response.status}`);
68
76
  }
69
77
  const result = await response.json();
70
- logger.debug({ slug, artifactCount: result.artifactCount }, "Stack resolved successfully");
78
+ timer.done({ slug, artifactCount: result.artifactCount, status: response.status, success: true });
71
79
  return result;
72
80
  }
73
81
 
@@ -338,12 +346,218 @@ async function confirm(question) {
338
346
  });
339
347
  }
340
348
 
341
- // src/commands/list.ts
349
+ // src/commands/completion.ts
350
+ import * as fs3 from "fs";
351
+ import * as os from "os";
352
+ import * as path3 from "path";
342
353
  import chalk2 from "chalk";
354
+ var BASH_COMPLETION = `
355
+ # ai-builder bash completion
356
+ _ai_builder_completions() {
357
+ local cur prev words cword
358
+ _get_comp_words_by_ref -n : cur prev words cword
359
+
360
+ local commands="add remove rm list ls search status update completion"
361
+ local types="skill agent command stack"
362
+
363
+ case "\${prev}" in
364
+ ai-builder)
365
+ COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
366
+ return 0
367
+ ;;
368
+ add|remove|rm)
369
+ COMPREPLY=( $(compgen -W "\${types}" -- "\${cur}") )
370
+ return 0
371
+ ;;
372
+ -t|--type)
373
+ COMPREPLY=( $(compgen -W "skill agent command" -- "\${cur}") )
374
+ return 0
375
+ ;;
376
+ completion)
377
+ COMPREPLY=( $(compgen -W "bash zsh --setup" -- "\${cur}") )
378
+ return 0
379
+ ;;
380
+ esac
381
+
382
+ if [[ "\${cur}" == -* ]]; then
383
+ local opts="--help --version"
384
+ case "\${words[1]}" in
385
+ add)
386
+ opts="--force --yes --help"
387
+ ;;
388
+ remove|rm)
389
+ opts="--yes --help"
390
+ ;;
391
+ list|ls)
392
+ opts="--type --help"
393
+ ;;
394
+ search)
395
+ opts="--type --task --limit --help"
396
+ ;;
397
+ update)
398
+ opts="--check --help"
399
+ ;;
400
+ esac
401
+ COMPREPLY=( $(compgen -W "\${opts}" -- "\${cur}") )
402
+ return 0
403
+ fi
404
+ }
405
+
406
+ complete -F _ai_builder_completions ai-builder
407
+ `.trim();
408
+ var ZSH_COMPLETION = `
409
+ #compdef ai-builder
410
+
411
+ _ai_builder() {
412
+ local -a commands types
413
+
414
+ commands=(
415
+ 'add:Install an artifact or stack'
416
+ 'remove:Remove an installed artifact'
417
+ 'rm:Remove an installed artifact'
418
+ 'list:List installed artifacts'
419
+ 'ls:List installed artifacts'
420
+ 'search:Search the registry for artifacts'
421
+ 'status:Show CLI status'
422
+ 'update:Update the CLI'
423
+ 'completion:Generate shell completions'
424
+ )
425
+
426
+ types=(skill agent command stack)
427
+
428
+ _arguments -C \\
429
+ '1:command:->command' \\
430
+ '*::arg:->args'
431
+
432
+ case "$state" in
433
+ command)
434
+ _describe -t commands 'ai-builder command' commands
435
+ ;;
436
+ args)
437
+ case "$words[1]" in
438
+ add|remove|rm)
439
+ _arguments \\
440
+ '1:type:(skill agent command stack)' \\
441
+ '2:slug:' \\
442
+ '--force[Overwrite existing artifacts]' \\
443
+ '--yes[Skip confirmation]' \\
444
+ '--help[Show help]'
445
+ ;;
446
+ list|ls)
447
+ _arguments \\
448
+ '--type[Filter by type]:type:(skill agent command)' \\
449
+ '--help[Show help]'
450
+ ;;
451
+ search)
452
+ _arguments \\
453
+ '1:query:' \\
454
+ '--type[Filter by type]:type:(skill agent command)' \\
455
+ '--task[Filter by task category]:task:' \\
456
+ '--limit[Number of results]:limit:' \\
457
+ '--help[Show help]'
458
+ ;;
459
+ update)
460
+ _arguments \\
461
+ '--check[Check for updates without installing]' \\
462
+ '--help[Show help]'
463
+ ;;
464
+ completion)
465
+ _arguments \\
466
+ '1:shell:(bash zsh)' \\
467
+ '--setup[Auto-install to shell config]' \\
468
+ '--help[Show help]'
469
+ ;;
470
+ esac
471
+ ;;
472
+ esac
473
+ }
474
+
475
+ _ai_builder "$@"
476
+ `.trim();
477
+ function getShellConfigPath(shell) {
478
+ const home = os.homedir();
479
+ if (shell === "bash") {
480
+ const bashrc = path3.join(home, ".bashrc");
481
+ const bashProfile = path3.join(home, ".bash_profile");
482
+ return fs3.existsSync(bashrc) ? bashrc : bashProfile;
483
+ }
484
+ if (shell === "zsh") {
485
+ return path3.join(home, ".zshrc");
486
+ }
487
+ return null;
488
+ }
489
+ function detectShell() {
490
+ const shell = process.env.SHELL || "";
491
+ if (shell.includes("zsh")) return "zsh";
492
+ if (shell.includes("bash")) return "bash";
493
+ return null;
494
+ }
495
+ function completionCommand(shell, options) {
496
+ if (options?.setup) {
497
+ const detectedShell = detectShell();
498
+ if (!detectedShell) {
499
+ console.error(chalk2.red("\n Could not detect shell. Use:"));
500
+ console.error(chalk2.dim(" ai-builder completion bash >> ~/.bashrc"));
501
+ console.error(chalk2.dim(" ai-builder completion zsh >> ~/.zshrc\n"));
502
+ process.exit(1);
503
+ }
504
+ const configPath = getShellConfigPath(detectedShell);
505
+ if (!configPath) {
506
+ console.error(chalk2.red(`
507
+ Could not find config for ${detectedShell}
508
+ `));
509
+ process.exit(1);
510
+ }
511
+ const completion = detectedShell === "zsh" ? ZSH_COMPLETION : BASH_COMPLETION;
512
+ const marker = "# ai-builder completion";
513
+ const existingContent = fs3.existsSync(configPath) ? fs3.readFileSync(configPath, "utf-8") : "";
514
+ if (existingContent.includes(marker)) {
515
+ console.log(chalk2.yellow(`
516
+ Completion already installed in ${configPath}`));
517
+ console.log(chalk2.dim(" Restart your terminal to apply changes\n"));
518
+ return;
519
+ }
520
+ fs3.appendFileSync(configPath, `
521
+ ${completion}
522
+ `);
523
+ console.log(chalk2.green(`
524
+ Completion installed to ${configPath}`));
525
+ console.log(chalk2.dim(` Restart your terminal or run: source ${configPath}
526
+ `));
527
+ return;
528
+ }
529
+ if (!shell) {
530
+ console.log(chalk2.cyan.bold("\n ai-builder completion\n"));
531
+ console.log(" Generate shell completions for ai-builder.\n");
532
+ console.log(" Usage:");
533
+ console.log(" ai-builder completion bash Output bash completion");
534
+ console.log(" ai-builder completion zsh Output zsh completion");
535
+ console.log(" ai-builder completion --setup Auto-install for current shell\n");
536
+ console.log(" Manual installation:");
537
+ console.log(chalk2.dim(" ai-builder completion bash >> ~/.bashrc"));
538
+ console.log(chalk2.dim(" ai-builder completion zsh >> ~/.zshrc\n"));
539
+ return;
540
+ }
541
+ if (shell === "bash") {
542
+ console.log(BASH_COMPLETION);
543
+ return;
544
+ }
545
+ if (shell === "zsh") {
546
+ console.log(ZSH_COMPLETION);
547
+ return;
548
+ }
549
+ console.error(chalk2.red(`
550
+ Unsupported shell: ${shell}`));
551
+ console.error(chalk2.dim(" Supported: bash, zsh\n"));
552
+ process.exit(1);
553
+ }
554
+
555
+ // src/commands/list.ts
556
+ import chalk3 from "chalk";
343
557
  var TYPE_COLORS = {
344
- skill: chalk2.blue,
345
- agent: chalk2.magenta,
346
- command: chalk2.green
558
+ skill: chalk3.blue,
559
+ agent: chalk3.magenta,
560
+ command: chalk3.green
347
561
  };
348
562
  async function listCommand(options) {
349
563
  let artifacts = getInstalledArtifacts();
@@ -352,33 +566,33 @@ async function listCommand(options) {
352
566
  }
353
567
  if (artifacts.length === 0) {
354
568
  if (options.type) {
355
- console.log(chalk2.dim(`No ${options.type}s installed.`));
569
+ console.log(chalk3.dim(`No ${options.type}s installed.`));
356
570
  } else {
357
- console.log(chalk2.dim("No artifacts installed."));
571
+ console.log(chalk3.dim("No artifacts installed."));
358
572
  }
359
573
  console.log();
360
574
  console.log("Install artifacts with:");
361
- console.log(`${chalk2.green(" $ ")}ai-builder add agent anthropic/frontend-tester`);
575
+ console.log(`${chalk3.green(" $ ")}ai-builder add agent anthropic/frontend-tester`);
362
576
  return;
363
577
  }
364
578
  console.log();
365
- console.log(chalk2.bold("Installed Artifacts"));
579
+ console.log(chalk3.bold("Installed Artifacts"));
366
580
  console.log();
367
581
  console.log(
368
- `${chalk2.dim(" ") + padEnd("TYPE", 10) + padEnd("NAME", 30) + padEnd("AUTHOR", 15)}INSTALLED`
582
+ `${chalk3.dim(" ") + padEnd("TYPE", 10) + padEnd("NAME", 30) + padEnd("AUTHOR", 15)}INSTALLED`
369
583
  );
370
- console.log(chalk2.dim(` ${"-".repeat(70)}`));
584
+ console.log(chalk3.dim(` ${"-".repeat(70)}`));
371
585
  for (const artifact of artifacts) {
372
- const typeColor = TYPE_COLORS[artifact.type] || chalk2.white;
586
+ const typeColor = TYPE_COLORS[artifact.type] || chalk3.white;
373
587
  const typeLabel = typeColor(padEnd(artifact.type, 10));
374
588
  const name = padEnd(artifact.name, 30);
375
- const author = chalk2.dim(padEnd(artifact.author, 15));
376
- const date = chalk2.dim(formatDate(artifact.installedAt));
589
+ const author = chalk3.dim(padEnd(artifact.author, 15));
590
+ const date = chalk3.dim(formatDate(artifact.installedAt));
377
591
  console.log(` ${typeLabel}${name}${author}${date}`);
378
592
  }
379
593
  console.log();
380
594
  console.log(
381
- chalk2.dim(` ${artifacts.length} artifact${artifacts.length === 1 ? "" : "s"} installed`)
595
+ chalk3.dim(` ${artifacts.length} artifact${artifacts.length === 1 ? "" : "s"} installed`)
382
596
  );
383
597
  console.log();
384
598
  }
@@ -408,39 +622,39 @@ function formatDate(isoDate) {
408
622
 
409
623
  // src/commands/remove.ts
410
624
  import * as readline2 from "readline";
411
- import chalk3 from "chalk";
625
+ import chalk4 from "chalk";
412
626
  var VALID_TYPES2 = ["skill", "agent", "command"];
413
627
  async function removeCommand(type, slug, options) {
414
628
  if (!type) {
415
- console.log(chalk3.red("Error: Missing artifact type."));
629
+ console.log(chalk4.red("Error: Missing artifact type."));
416
630
  console.log("Usage: ai-builder remove <type> <author/slug>");
417
631
  console.log("Types: skill, agent, command");
418
632
  process.exit(1);
419
633
  }
420
634
  if (!VALID_TYPES2.includes(type)) {
421
- console.log(chalk3.red(`Error: Invalid type "${type}".`));
635
+ console.log(chalk4.red(`Error: Invalid type "${type}".`));
422
636
  console.log("Valid types: skill, agent, command");
423
637
  process.exit(1);
424
638
  }
425
639
  if (!slug) {
426
- console.log(chalk3.red("Error: Missing artifact slug."));
640
+ console.log(chalk4.red("Error: Missing artifact slug."));
427
641
  console.log("Usage: ai-builder remove <type> <author/slug>");
428
642
  console.log("Example: ai-builder remove agent anthropic/frontend-tester");
429
643
  process.exit(1);
430
644
  }
431
645
  if (!slug.includes("/")) {
432
- console.log(chalk3.red("Error: Invalid slug format."));
646
+ console.log(chalk4.red("Error: Invalid slug format."));
433
647
  console.log("Expected format: author/artifact-name");
434
648
  console.log("Example: anthropic/frontend-tester");
435
649
  process.exit(1);
436
650
  }
437
651
  const [author, artifactSlug] = slug.split("/");
438
652
  if (!isInstalled(type, author, artifactSlug)) {
439
- console.log(chalk3.yellow(`${type} ${chalk3.bold(slug)} is not installed.`));
653
+ console.log(chalk4.yellow(`${type} ${chalk4.bold(slug)} is not installed.`));
440
654
  return;
441
655
  }
442
656
  if (!options.yes) {
443
- const confirmed = await confirm2(`Remove ${type} ${chalk3.cyan(slug)}?`);
657
+ const confirmed = await confirm2(`Remove ${type} ${chalk4.cyan(slug)}?`);
444
658
  if (!confirmed) {
445
659
  console.log("Cancelled.");
446
660
  return;
@@ -448,9 +662,9 @@ async function removeCommand(type, slug, options) {
448
662
  }
449
663
  const removed = uninstallArtifact(type, author, artifactSlug);
450
664
  if (removed) {
451
- console.log(chalk3.green(`Removed ${type} ${chalk3.bold(slug)}`));
665
+ console.log(chalk4.green(`Removed ${type} ${chalk4.bold(slug)}`));
452
666
  } else {
453
- console.log(chalk3.red(`Failed to remove ${type} ${slug}`));
667
+ console.log(chalk4.red(`Failed to remove ${type} ${slug}`));
454
668
  process.exit(1);
455
669
  }
456
670
  }
@@ -460,7 +674,7 @@ async function confirm2(question) {
460
674
  output: process.stdout
461
675
  });
462
676
  return new Promise((resolve) => {
463
- rl.question(`${question} ${chalk3.dim("[y/N]")} `, (answer) => {
677
+ rl.question(`${question} ${chalk4.dim("[y/N]")} `, (answer) => {
464
678
  rl.close();
465
679
  resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
466
680
  });
@@ -468,12 +682,12 @@ async function confirm2(question) {
468
682
  }
469
683
 
470
684
  // src/commands/search.ts
471
- import chalk4 from "chalk";
685
+ import chalk5 from "chalk";
472
686
  import ora2 from "ora";
473
687
  var TYPE_COLORS2 = {
474
- skill: chalk4.blue,
475
- agent: chalk4.magenta,
476
- command: chalk4.green
688
+ skill: chalk5.blue,
689
+ agent: chalk5.magenta,
690
+ command: chalk5.green
477
691
  };
478
692
  async function searchCommand(query, options) {
479
693
  const limit = Number.parseInt(options.limit || "10", 10);
@@ -487,40 +701,40 @@ async function searchCommand(query, options) {
487
701
  });
488
702
  spinner.stop();
489
703
  if (artifacts.length === 0) {
490
- console.log(chalk4.dim(`No results found for "${query}"`));
704
+ console.log(chalk5.dim(`No results found for "${query}"`));
491
705
  return;
492
706
  }
493
707
  console.log();
494
- console.log(chalk4.bold(`Found ${total} result${total === 1 ? "" : "s"}`));
708
+ console.log(chalk5.bold(`Found ${total} result${total === 1 ? "" : "s"}`));
495
709
  console.log();
496
710
  for (const artifact of artifacts) {
497
- const typeColor = TYPE_COLORS2[artifact.type] || chalk4.white;
711
+ const typeColor = TYPE_COLORS2[artifact.type] || chalk5.white;
498
712
  const typeLabel = typeColor(`[${artifact.type}]`);
499
713
  const fullSlug = `${artifact.author}/${artifact.slug}`;
500
- console.log(` ${typeLabel} ${chalk4.bold(artifact.name)}`);
501
- console.log(` ${chalk4.cyan(fullSlug)}`);
714
+ console.log(` ${typeLabel} ${chalk5.bold(artifact.name)}`);
715
+ console.log(` ${chalk5.cyan(fullSlug)}`);
502
716
  if (artifact.summary) {
503
- console.log(` ${chalk4.dim(truncate(artifact.summary, 60))}`);
717
+ console.log(` ${chalk5.dim(truncate(artifact.summary, 60))}`);
504
718
  }
505
- console.log(` ${chalk4.dim(`${formatNumber(artifact.installCount)} installs`)}`);
719
+ console.log(` ${chalk5.dim(`${formatNumber(artifact.installCount)} installs`)}`);
506
720
  console.log();
507
721
  }
508
722
  if (total > artifacts.length) {
509
- console.log(chalk4.dim(` ... and ${total - artifacts.length} more results`));
510
- console.log(chalk4.dim(" Use --limit to see more results"));
723
+ console.log(chalk5.dim(` ... and ${total - artifacts.length} more results`));
724
+ console.log(chalk5.dim(" Use --limit to see more results"));
511
725
  console.log();
512
726
  }
513
727
  console.log("Install with:");
514
728
  if (artifacts.length > 0) {
515
729
  const first = artifacts[0];
516
730
  console.log(
517
- `${chalk4.green(" $ ")}ai-builder add ${first.type} ${first.author}/${first.slug}`
731
+ `${chalk5.green(" $ ")}ai-builder add ${first.type} ${first.author}/${first.slug}`
518
732
  );
519
733
  }
520
734
  console.log();
521
735
  } catch (error) {
522
736
  const message = error instanceof Error ? error.message : "Unknown error";
523
- spinner.fail(chalk4.red(`Search failed: ${message}`));
737
+ spinner.fail(chalk5.red(`Search failed: ${message}`));
524
738
  process.exit(1);
525
739
  }
526
740
  }
@@ -538,26 +752,149 @@ function formatNumber(num) {
538
752
  return num.toString();
539
753
  }
540
754
 
755
+ // src/commands/status.ts
756
+ import * as fs4 from "fs";
757
+ import * as path4 from "path";
758
+ import chalk6 from "chalk";
759
+
760
+ // src/version.ts
761
+ import { createRequire } from "module";
762
+ var require2 = createRequire(import.meta.url);
763
+ var pkg = require2("../package.json");
764
+ var version = pkg.version;
765
+
766
+ // src/commands/status.ts
767
+ var API_BASE2 = process.env.AI_BUILDER_API_URL || "https://aibuilder.sh/api";
768
+ async function statusCommand() {
769
+ console.log(chalk6.cyan.bold("\n ai-builder status\n"));
770
+ console.log(` ${chalk6.dim("Version:")} ${chalk6.white(version)}`);
771
+ const claudeDir = path4.join(process.cwd(), ".claude");
772
+ const claudeDirExists = fs4.existsSync(claudeDir);
773
+ console.log(
774
+ ` ${chalk6.dim("Claude dir:")} ${claudeDirExists ? chalk6.green(".claude/ found") : chalk6.yellow(".claude/ not found")}`
775
+ );
776
+ const installed = getInstalledArtifacts();
777
+ const byType = installed.reduce(
778
+ (acc, artifact) => {
779
+ acc[artifact.type] = (acc[artifact.type] || 0) + 1;
780
+ return acc;
781
+ },
782
+ {}
783
+ );
784
+ if (installed.length === 0) {
785
+ console.log(` ${chalk6.dim("Installed:")} ${chalk6.dim("none")}`);
786
+ } else {
787
+ const summary = Object.entries(byType).map(([type, count]) => `${count} ${type}${count > 1 ? "s" : ""}`).join(", ");
788
+ console.log(` ${chalk6.dim("Installed:")} ${chalk6.white(summary)}`);
789
+ }
790
+ process.stdout.write(` ${chalk6.dim("Registry:")} `);
791
+ try {
792
+ const start = Date.now();
793
+ const response = await fetch(`${API_BASE2}/artifacts?limit=1`);
794
+ const latency = Date.now() - start;
795
+ if (response.ok) {
796
+ console.log(chalk6.green("connected") + chalk6.dim(` (${latency}ms)`));
797
+ } else {
798
+ console.log(chalk6.red(`error ${response.status}`));
799
+ }
800
+ } catch {
801
+ console.log(chalk6.red("unreachable"));
802
+ }
803
+ console.log();
804
+ }
805
+
806
+ // src/commands/update.ts
807
+ import { execFileSync } from "child_process";
808
+ import chalk7 from "chalk";
809
+ var NPM_REGISTRY = "https://registry.npmjs.org/ai-builder";
810
+ async function getLatestVersion() {
811
+ const response = await fetch(NPM_REGISTRY);
812
+ if (!response.ok) {
813
+ throw new Error(`Failed to fetch package info: ${response.status}`);
814
+ }
815
+ const data = await response.json();
816
+ return data["dist-tags"].latest;
817
+ }
818
+ function compareVersions(current, latest) {
819
+ const currentParts = current.split(".").map(Number);
820
+ const latestParts = latest.split(".").map(Number);
821
+ for (let i = 0; i < 3; i++) {
822
+ if (latestParts[i] > currentParts[i]) return 1;
823
+ if (latestParts[i] < currentParts[i]) return -1;
824
+ }
825
+ return 0;
826
+ }
827
+ async function updateCommand(options) {
828
+ console.log(chalk7.cyan.bold("\n ai-builder update\n"));
829
+ console.log(` ${chalk7.dim("Current version:")} ${chalk7.white(version)}`);
830
+ process.stdout.write(` ${chalk7.dim("Latest version:")} `);
831
+ let latestVersion;
832
+ try {
833
+ latestVersion = await getLatestVersion();
834
+ console.log(chalk7.white(latestVersion));
835
+ } catch {
836
+ console.log(chalk7.red("failed to fetch"));
837
+ console.log(chalk7.dim("\n Could not reach npm registry\n"));
838
+ process.exit(1);
839
+ }
840
+ const comparison = compareVersions(version, latestVersion);
841
+ if (comparison === 0) {
842
+ console.log(chalk7.green("\n You are on the latest version!\n"));
843
+ return;
844
+ }
845
+ if (comparison < 0) {
846
+ console.log(chalk7.yellow("\n Your version is newer than published\n"));
847
+ return;
848
+ }
849
+ if (options.check) {
850
+ console.log(chalk7.yellow(`
851
+ Update available: ${version} \u2192 ${latestVersion}`));
852
+ console.log(chalk7.dim(` Run 'ai-builder update' to install
853
+ `));
854
+ return;
855
+ }
856
+ console.log(chalk7.dim(`
857
+ Updating to ${latestVersion}...`));
858
+ try {
859
+ execFileSync("npm", ["install", "-g", "ai-builder@latest"], { stdio: "inherit" });
860
+ console.log(chalk7.green(`
861
+ Updated to ${latestVersion}!
862
+ `));
863
+ } catch {
864
+ console.log(chalk7.red("\n Update failed. Try running:"));
865
+ console.log(chalk7.dim(" npm install -g ai-builder@latest\n"));
866
+ process.exit(1);
867
+ }
868
+ }
869
+
541
870
  // src/index.ts
542
871
  var program = new Command();
543
- program.name("ai-builder").description("CLI for installing Claude Code artifacts from aibuilder.sh").version("0.1.0");
872
+ program.name("ai-builder").description("CLI for installing Claude Code artifacts from aibuilder.sh").version(version);
544
873
  program.command("add").description("Install an artifact or stack").argument("[type]", "Artifact type: skill, agent, command, or stack").argument("[slug]", "Artifact slug in author/name format").option("-f, --force", "Overwrite existing artifacts").option("-y, --yes", "Skip confirmation for stacks").action(addCommand);
545
874
  program.command("remove").alias("rm").description("Remove an installed artifact").argument("[type]", "Artifact type: skill, agent, or command").argument("[slug]", "Artifact slug in author/name format").option("-y, --yes", "Skip confirmation").action(removeCommand);
546
875
  program.command("list").alias("ls").description("List installed artifacts").option("-t, --type <type>", "Filter by type: skill, agent, or command").action(listCommand);
547
876
  program.command("search").description("Search the registry for artifacts").argument("<query>", "Search query").option("-t, --type <type>", "Filter by type: skill, agent, or command").option("--task <task>", "Filter by task category").option("-l, --limit <number>", "Number of results", "10").action(searchCommand);
877
+ program.command("status").description("Show CLI status and installed artifacts").action(statusCommand);
878
+ program.command("update").description("Update the CLI to the latest version").option("-c, --check", "Check for updates without installing").action(updateCommand);
879
+ program.command("completion").description("Generate shell completions").argument("[shell]", "Shell type: bash or zsh").option("-s, --setup", "Auto-install completion for current shell").action(completionCommand);
548
880
  program.action(() => {
549
- console.log(chalk5.cyan.bold("\n ai-builder") + chalk5.dim(" - Claude Code artifact registry\n"));
881
+ console.log(
882
+ chalk8.cyan.bold("\n ai-builder") + chalk8.dim(` v${version} - Claude Code artifact registry
883
+ `)
884
+ );
550
885
  console.log(" Usage:");
551
886
  console.log(" ai-builder add <type> <author/slug> Install an artifact");
552
887
  console.log(" ai-builder remove <type> <slug> Remove an artifact");
553
888
  console.log(" ai-builder list List installed");
554
889
  console.log(" ai-builder search <query> Search registry");
890
+ console.log(" ai-builder status Show CLI status");
891
+ console.log(" ai-builder update Update CLI");
555
892
  console.log("\n Examples:");
556
- console.log(`${chalk5.green(" $ ")}ai-builder add agent anthropic/frontend-tester`);
557
- console.log(`${chalk5.green(" $ ")}ai-builder add stack nextjs-fullstack`);
558
- console.log(`${chalk5.green(" $ ")}ai-builder search "test generator"`);
893
+ console.log(`${chalk8.green(" $ ")}ai-builder add agent anthropic/frontend-tester`);
894
+ console.log(`${chalk8.green(" $ ")}ai-builder add stack nextjs-fullstack`);
895
+ console.log(`${chalk8.green(" $ ")}ai-builder search "test generator"`);
559
896
  console.log(`
560
- Learn more at ${chalk5.cyan("https://aibuilder.sh")}
897
+ Learn more at ${chalk8.cyan("https://aibuilder.sh")}
561
898
  `);
562
899
  });
563
900
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-builder",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "CLI for installing Claude Code artifacts from aibuilder.sh",
5
5
  "type": "module",
6
6
  "bin": {