ai-builder 0.1.1 → 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 +79 -25
  2. package/dist/index.js +402 -50
  3. package/package.json +2 -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
 
@@ -43,19 +45,19 @@ npx ai-builder add agent git-town/code_reviewer
43
45
 
44
46
  ```bash
45
47
  # Install an agent
46
- ai-builder add agent git-town/code_reviewer
48
+ npx ai-builder add agent git-town/code_reviewer
47
49
 
48
50
  # Install a command
49
- ai-builder add command truffle-ai/quality-checks
51
+ npx ai-builder add command truffle-ai/quality-checks
50
52
 
51
53
  # Install a skill
52
- ai-builder add skill anthropic/pdf
54
+ npx ai-builder add skill anthropic/pdf
53
55
 
54
56
  # Search for artifacts
55
- ai-builder search "test"
57
+ npx ai-builder search "test"
56
58
 
57
59
  # List installed artifacts
58
- ai-builder list
60
+ npx ai-builder list
59
61
  ```
60
62
 
61
63
  ---
@@ -67,7 +69,7 @@ ai-builder list
67
69
  Install an artifact from the registry:
68
70
 
69
71
  ```bash
70
- ai-builder add <type> <author/slug>
72
+ npx ai-builder add <type> <author/slug>
71
73
  ```
72
74
 
73
75
  **Types:** `skill`, `agent`, `command`, `stack`
@@ -76,26 +78,26 @@ ai-builder add <type> <author/slug>
76
78
 
77
79
  ```bash
78
80
  # Install an agent
79
- ai-builder add agent git-town/code_reviewer
81
+ npx ai-builder add agent git-town/code_reviewer
80
82
 
81
83
  # Install a command
82
- ai-builder add command truffle-ai/quality-checks
84
+ npx ai-builder add command truffle-ai/quality-checks
83
85
 
84
86
  # Install a skill
85
- ai-builder add skill anthropic/mcp-builder
87
+ npx ai-builder add skill anthropic/mcp-builder
86
88
 
87
89
  # Force reinstall (overwrite existing)
88
- ai-builder add agent git-town/code_reviewer --force
90
+ npx ai-builder add agent git-town/code_reviewer --force
89
91
  ```
90
92
 
91
93
  **Stacks** bundle multiple artifacts together:
92
94
 
93
95
  ```bash
94
96
  # Install a stack (prompts for confirmation)
95
- ai-builder add stack my-stack
97
+ npx ai-builder add stack my-stack
96
98
 
97
99
  # Skip confirmation
98
- ai-builder add stack my-stack --yes
100
+ npx ai-builder add stack my-stack --yes
99
101
  ```
100
102
 
101
103
  ### Remove
@@ -103,18 +105,18 @@ ai-builder add stack my-stack --yes
103
105
  Remove an installed artifact:
104
106
 
105
107
  ```bash
106
- ai-builder remove <type> <author/slug>
107
- ai-builder rm <type> <author/slug> # alias
108
+ npx ai-builder remove <type> <author/slug>
109
+ npx ai-builder rm <type> <author/slug> # alias
108
110
  ```
109
111
 
110
112
  **Examples:**
111
113
 
112
114
  ```bash
113
115
  # Remove an agent
114
- ai-builder remove agent git-town/code_reviewer
116
+ npx ai-builder remove agent git-town/code_reviewer
115
117
 
116
118
  # Skip confirmation
117
- ai-builder rm agent git-town/code_reviewer --yes
119
+ npx ai-builder rm agent git-town/code_reviewer --yes
118
120
  ```
119
121
 
120
122
  ### List
@@ -122,17 +124,17 @@ ai-builder rm agent git-town/code_reviewer --yes
122
124
  List all installed artifacts:
123
125
 
124
126
  ```bash
125
- ai-builder list
126
- ai-builder ls # alias
127
+ npx ai-builder list
128
+ npx ai-builder ls # alias
127
129
  ```
128
130
 
129
131
  **Options:**
130
132
 
131
133
  ```bash
132
134
  # Filter by type
133
- ai-builder list --type agent
134
- ai-builder list --type skill
135
- ai-builder list --type command
135
+ npx ai-builder list --type agent
136
+ npx ai-builder list --type skill
137
+ npx ai-builder list --type command
136
138
  ```
137
139
 
138
140
  ### Search
@@ -140,20 +142,72 @@ ai-builder list --type command
140
142
  Search the registry for artifacts:
141
143
 
142
144
  ```bash
143
- ai-builder search <query>
145
+ npx ai-builder search <query>
144
146
  ```
145
147
 
146
148
  **Options:**
147
149
 
148
150
  ```bash
149
151
  # Filter by type
150
- ai-builder search "review" --type agent
152
+ npx ai-builder search "review" --type agent
151
153
 
152
154
  # Filter by task category
153
- ai-builder search "nextjs" --task frontend
155
+ npx ai-builder search "nextjs" --task frontend
154
156
 
155
157
  # Limit results
156
- ai-builder search "database" --limit 5
158
+ npx ai-builder search "database" --limit 5
159
+ ```
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
157
211
  ```
158
212
 
159
213
  ---
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
@@ -10,14 +10,22 @@ import chalk from "chalk";
10
10
  import ora from "ora";
11
11
 
12
12
  // src/services/api.ts
13
+ import { createCliLogger } from "@aibuilder/logger/adapters/cli";
13
14
  var API_BASE = process.env.AI_BUILDER_API_URL || "https://aibuilder.sh/api";
15
+ var logger = createCliLogger({
16
+ verbose: process.env.DEBUG?.includes("ai-builder"),
17
+ base: { module: "cli:api" }
18
+ });
14
19
  async function resolveArtifact(type, slug) {
15
20
  const url = `${API_BASE}/resolve?type=${encodeURIComponent(type)}&slug=${encodeURIComponent(slug)}`;
21
+ const timer = logger.startTimer("api-resolve");
16
22
  const response = await fetch(url);
17
23
  if (!response.ok) {
18
24
  const errorBody = await response.json().catch(() => ({ error: "Unknown error" }));
25
+ timer.done({ type, slug, status: response.status, success: false });
19
26
  throw new Error(errorBody.error || `Failed to resolve artifact: ${response.status}`);
20
27
  }
28
+ timer.done({ type, slug, status: response.status, success: true });
21
29
  return response.json();
22
30
  }
23
31
  async function searchArtifacts(options) {
@@ -30,30 +38,45 @@ async function searchArtifacts(options) {
30
38
  if (options.task) params.set("task", options.task);
31
39
  if (options.limit) params.set("limit", options.limit.toString());
32
40
  const url = `${API_BASE}/artifacts?${params.toString()}`;
41
+ const timer = logger.startTimer("api-search");
33
42
  const response = await fetch(url);
34
43
  if (!response.ok) {
44
+ timer.done({ query: options.query, status: response.status, success: false });
35
45
  throw new Error(`Failed to search artifacts: ${response.status}`);
36
46
  }
37
- return response.json();
47
+ const result = await response.json();
48
+ timer.done({
49
+ query: options.query,
50
+ resultCount: result.artifacts.length,
51
+ total: result.total,
52
+ success: true
53
+ });
54
+ return result;
38
55
  }
39
56
  async function trackInstall(type, slug, cliVersion) {
40
57
  try {
41
- await fetch(`${API_BASE}/install-events`, {
58
+ const response = await fetch(`${API_BASE}/install-events`, {
42
59
  method: "POST",
43
60
  headers: { "Content-Type": "application/json" },
44
61
  body: JSON.stringify({ type, slug, cliVersion })
45
62
  });
46
- } catch {
63
+ logger.debug({ type, slug, cliVersion, status: response.status }, "Install tracked");
64
+ } catch (error) {
65
+ logger.debug({ err: error, type, slug }, "Install tracking failed (non-critical)");
47
66
  }
48
67
  }
49
68
  async function resolveStack(slug) {
50
69
  const url = `${API_BASE}/stacks/${encodeURIComponent(slug)}`;
70
+ const timer = logger.startTimer("api-resolve-stack");
51
71
  const response = await fetch(url);
52
72
  if (!response.ok) {
53
73
  const errorBody = await response.json().catch(() => ({ error: "Unknown error" }));
74
+ timer.done({ slug, status: response.status, success: false });
54
75
  throw new Error(errorBody.error || `Failed to resolve stack: ${response.status}`);
55
76
  }
56
- return response.json();
77
+ const result = await response.json();
78
+ timer.done({ slug, artifactCount: result.artifactCount, status: response.status, success: true });
79
+ return result;
57
80
  }
58
81
 
59
82
  // src/services/installer.ts
@@ -323,12 +346,218 @@ async function confirm(question) {
323
346
  });
324
347
  }
325
348
 
326
- // 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";
327
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";
328
557
  var TYPE_COLORS = {
329
- skill: chalk2.blue,
330
- agent: chalk2.magenta,
331
- command: chalk2.green
558
+ skill: chalk3.blue,
559
+ agent: chalk3.magenta,
560
+ command: chalk3.green
332
561
  };
333
562
  async function listCommand(options) {
334
563
  let artifacts = getInstalledArtifacts();
@@ -337,33 +566,33 @@ async function listCommand(options) {
337
566
  }
338
567
  if (artifacts.length === 0) {
339
568
  if (options.type) {
340
- console.log(chalk2.dim(`No ${options.type}s installed.`));
569
+ console.log(chalk3.dim(`No ${options.type}s installed.`));
341
570
  } else {
342
- console.log(chalk2.dim("No artifacts installed."));
571
+ console.log(chalk3.dim("No artifacts installed."));
343
572
  }
344
573
  console.log();
345
574
  console.log("Install artifacts with:");
346
- console.log(`${chalk2.green(" $ ")}ai-builder add agent anthropic/frontend-tester`);
575
+ console.log(`${chalk3.green(" $ ")}ai-builder add agent anthropic/frontend-tester`);
347
576
  return;
348
577
  }
349
578
  console.log();
350
- console.log(chalk2.bold("Installed Artifacts"));
579
+ console.log(chalk3.bold("Installed Artifacts"));
351
580
  console.log();
352
581
  console.log(
353
- `${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`
354
583
  );
355
- console.log(chalk2.dim(` ${"-".repeat(70)}`));
584
+ console.log(chalk3.dim(` ${"-".repeat(70)}`));
356
585
  for (const artifact of artifacts) {
357
- const typeColor = TYPE_COLORS[artifact.type] || chalk2.white;
586
+ const typeColor = TYPE_COLORS[artifact.type] || chalk3.white;
358
587
  const typeLabel = typeColor(padEnd(artifact.type, 10));
359
588
  const name = padEnd(artifact.name, 30);
360
- const author = chalk2.dim(padEnd(artifact.author, 15));
361
- const date = chalk2.dim(formatDate(artifact.installedAt));
589
+ const author = chalk3.dim(padEnd(artifact.author, 15));
590
+ const date = chalk3.dim(formatDate(artifact.installedAt));
362
591
  console.log(` ${typeLabel}${name}${author}${date}`);
363
592
  }
364
593
  console.log();
365
594
  console.log(
366
- chalk2.dim(` ${artifacts.length} artifact${artifacts.length === 1 ? "" : "s"} installed`)
595
+ chalk3.dim(` ${artifacts.length} artifact${artifacts.length === 1 ? "" : "s"} installed`)
367
596
  );
368
597
  console.log();
369
598
  }
@@ -393,39 +622,39 @@ function formatDate(isoDate) {
393
622
 
394
623
  // src/commands/remove.ts
395
624
  import * as readline2 from "readline";
396
- import chalk3 from "chalk";
625
+ import chalk4 from "chalk";
397
626
  var VALID_TYPES2 = ["skill", "agent", "command"];
398
627
  async function removeCommand(type, slug, options) {
399
628
  if (!type) {
400
- console.log(chalk3.red("Error: Missing artifact type."));
629
+ console.log(chalk4.red("Error: Missing artifact type."));
401
630
  console.log("Usage: ai-builder remove <type> <author/slug>");
402
631
  console.log("Types: skill, agent, command");
403
632
  process.exit(1);
404
633
  }
405
634
  if (!VALID_TYPES2.includes(type)) {
406
- console.log(chalk3.red(`Error: Invalid type "${type}".`));
635
+ console.log(chalk4.red(`Error: Invalid type "${type}".`));
407
636
  console.log("Valid types: skill, agent, command");
408
637
  process.exit(1);
409
638
  }
410
639
  if (!slug) {
411
- console.log(chalk3.red("Error: Missing artifact slug."));
640
+ console.log(chalk4.red("Error: Missing artifact slug."));
412
641
  console.log("Usage: ai-builder remove <type> <author/slug>");
413
642
  console.log("Example: ai-builder remove agent anthropic/frontend-tester");
414
643
  process.exit(1);
415
644
  }
416
645
  if (!slug.includes("/")) {
417
- console.log(chalk3.red("Error: Invalid slug format."));
646
+ console.log(chalk4.red("Error: Invalid slug format."));
418
647
  console.log("Expected format: author/artifact-name");
419
648
  console.log("Example: anthropic/frontend-tester");
420
649
  process.exit(1);
421
650
  }
422
651
  const [author, artifactSlug] = slug.split("/");
423
652
  if (!isInstalled(type, author, artifactSlug)) {
424
- console.log(chalk3.yellow(`${type} ${chalk3.bold(slug)} is not installed.`));
653
+ console.log(chalk4.yellow(`${type} ${chalk4.bold(slug)} is not installed.`));
425
654
  return;
426
655
  }
427
656
  if (!options.yes) {
428
- const confirmed = await confirm2(`Remove ${type} ${chalk3.cyan(slug)}?`);
657
+ const confirmed = await confirm2(`Remove ${type} ${chalk4.cyan(slug)}?`);
429
658
  if (!confirmed) {
430
659
  console.log("Cancelled.");
431
660
  return;
@@ -433,9 +662,9 @@ async function removeCommand(type, slug, options) {
433
662
  }
434
663
  const removed = uninstallArtifact(type, author, artifactSlug);
435
664
  if (removed) {
436
- console.log(chalk3.green(`Removed ${type} ${chalk3.bold(slug)}`));
665
+ console.log(chalk4.green(`Removed ${type} ${chalk4.bold(slug)}`));
437
666
  } else {
438
- console.log(chalk3.red(`Failed to remove ${type} ${slug}`));
667
+ console.log(chalk4.red(`Failed to remove ${type} ${slug}`));
439
668
  process.exit(1);
440
669
  }
441
670
  }
@@ -445,7 +674,7 @@ async function confirm2(question) {
445
674
  output: process.stdout
446
675
  });
447
676
  return new Promise((resolve) => {
448
- rl.question(`${question} ${chalk3.dim("[y/N]")} `, (answer) => {
677
+ rl.question(`${question} ${chalk4.dim("[y/N]")} `, (answer) => {
449
678
  rl.close();
450
679
  resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
451
680
  });
@@ -453,12 +682,12 @@ async function confirm2(question) {
453
682
  }
454
683
 
455
684
  // src/commands/search.ts
456
- import chalk4 from "chalk";
685
+ import chalk5 from "chalk";
457
686
  import ora2 from "ora";
458
687
  var TYPE_COLORS2 = {
459
- skill: chalk4.blue,
460
- agent: chalk4.magenta,
461
- command: chalk4.green
688
+ skill: chalk5.blue,
689
+ agent: chalk5.magenta,
690
+ command: chalk5.green
462
691
  };
463
692
  async function searchCommand(query, options) {
464
693
  const limit = Number.parseInt(options.limit || "10", 10);
@@ -472,40 +701,40 @@ async function searchCommand(query, options) {
472
701
  });
473
702
  spinner.stop();
474
703
  if (artifacts.length === 0) {
475
- console.log(chalk4.dim(`No results found for "${query}"`));
704
+ console.log(chalk5.dim(`No results found for "${query}"`));
476
705
  return;
477
706
  }
478
707
  console.log();
479
- console.log(chalk4.bold(`Found ${total} result${total === 1 ? "" : "s"}`));
708
+ console.log(chalk5.bold(`Found ${total} result${total === 1 ? "" : "s"}`));
480
709
  console.log();
481
710
  for (const artifact of artifacts) {
482
- const typeColor = TYPE_COLORS2[artifact.type] || chalk4.white;
711
+ const typeColor = TYPE_COLORS2[artifact.type] || chalk5.white;
483
712
  const typeLabel = typeColor(`[${artifact.type}]`);
484
713
  const fullSlug = `${artifact.author}/${artifact.slug}`;
485
- console.log(` ${typeLabel} ${chalk4.bold(artifact.name)}`);
486
- console.log(` ${chalk4.cyan(fullSlug)}`);
714
+ console.log(` ${typeLabel} ${chalk5.bold(artifact.name)}`);
715
+ console.log(` ${chalk5.cyan(fullSlug)}`);
487
716
  if (artifact.summary) {
488
- console.log(` ${chalk4.dim(truncate(artifact.summary, 60))}`);
717
+ console.log(` ${chalk5.dim(truncate(artifact.summary, 60))}`);
489
718
  }
490
- console.log(` ${chalk4.dim(`${formatNumber(artifact.installCount)} installs`)}`);
719
+ console.log(` ${chalk5.dim(`${formatNumber(artifact.installCount)} installs`)}`);
491
720
  console.log();
492
721
  }
493
722
  if (total > artifacts.length) {
494
- console.log(chalk4.dim(` ... and ${total - artifacts.length} more results`));
495
- 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"));
496
725
  console.log();
497
726
  }
498
727
  console.log("Install with:");
499
728
  if (artifacts.length > 0) {
500
729
  const first = artifacts[0];
501
730
  console.log(
502
- `${chalk4.green(" $ ")}ai-builder add ${first.type} ${first.author}/${first.slug}`
731
+ `${chalk5.green(" $ ")}ai-builder add ${first.type} ${first.author}/${first.slug}`
503
732
  );
504
733
  }
505
734
  console.log();
506
735
  } catch (error) {
507
736
  const message = error instanceof Error ? error.message : "Unknown error";
508
- spinner.fail(chalk4.red(`Search failed: ${message}`));
737
+ spinner.fail(chalk5.red(`Search failed: ${message}`));
509
738
  process.exit(1);
510
739
  }
511
740
  }
@@ -523,26 +752,149 @@ function formatNumber(num) {
523
752
  return num.toString();
524
753
  }
525
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
+
526
870
  // src/index.ts
527
871
  var program = new Command();
528
- 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);
529
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);
530
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);
531
875
  program.command("list").alias("ls").description("List installed artifacts").option("-t, --type <type>", "Filter by type: skill, agent, or command").action(listCommand);
532
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);
533
880
  program.action(() => {
534
- 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
+ );
535
885
  console.log(" Usage:");
536
886
  console.log(" ai-builder add <type> <author/slug> Install an artifact");
537
887
  console.log(" ai-builder remove <type> <slug> Remove an artifact");
538
888
  console.log(" ai-builder list List installed");
539
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");
540
892
  console.log("\n Examples:");
541
- console.log(`${chalk5.green(" $ ")}ai-builder add agent anthropic/frontend-tester`);
542
- console.log(`${chalk5.green(" $ ")}ai-builder add stack nextjs-fullstack`);
543
- 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"`);
544
896
  console.log(`
545
- Learn more at ${chalk5.cyan("https://aibuilder.sh")}
897
+ Learn more at ${chalk8.cyan("https://aibuilder.sh")}
546
898
  `);
547
899
  });
548
900
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-builder",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "CLI for installing Claude Code artifacts from aibuilder.sh",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,6 +22,7 @@
22
22
  "access": "public"
23
23
  },
24
24
  "dependencies": {
25
+ "@aibuilder/logger": "workspace:*",
25
26
  "chalk": "^5.3.0",
26
27
  "commander": "^12.1.0",
27
28
  "ora": "^8.1.0"