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.
- package/README.md +79 -25
- package/dist/index.js +402 -50
- 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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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/
|
|
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:
|
|
330
|
-
agent:
|
|
331
|
-
command:
|
|
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(
|
|
569
|
+
console.log(chalk3.dim(`No ${options.type}s installed.`));
|
|
341
570
|
} else {
|
|
342
|
-
console.log(
|
|
571
|
+
console.log(chalk3.dim("No artifacts installed."));
|
|
343
572
|
}
|
|
344
573
|
console.log();
|
|
345
574
|
console.log("Install artifacts with:");
|
|
346
|
-
console.log(`${
|
|
575
|
+
console.log(`${chalk3.green(" $ ")}ai-builder add agent anthropic/frontend-tester`);
|
|
347
576
|
return;
|
|
348
577
|
}
|
|
349
578
|
console.log();
|
|
350
|
-
console.log(
|
|
579
|
+
console.log(chalk3.bold("Installed Artifacts"));
|
|
351
580
|
console.log();
|
|
352
581
|
console.log(
|
|
353
|
-
`${
|
|
582
|
+
`${chalk3.dim(" ") + padEnd("TYPE", 10) + padEnd("NAME", 30) + padEnd("AUTHOR", 15)}INSTALLED`
|
|
354
583
|
);
|
|
355
|
-
console.log(
|
|
584
|
+
console.log(chalk3.dim(` ${"-".repeat(70)}`));
|
|
356
585
|
for (const artifact of artifacts) {
|
|
357
|
-
const typeColor = TYPE_COLORS[artifact.type] ||
|
|
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 =
|
|
361
|
-
const date =
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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} ${
|
|
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(
|
|
665
|
+
console.log(chalk4.green(`Removed ${type} ${chalk4.bold(slug)}`));
|
|
437
666
|
} else {
|
|
438
|
-
console.log(
|
|
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} ${
|
|
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
|
|
685
|
+
import chalk5 from "chalk";
|
|
457
686
|
import ora2 from "ora";
|
|
458
687
|
var TYPE_COLORS2 = {
|
|
459
|
-
skill:
|
|
460
|
-
agent:
|
|
461
|
-
command:
|
|
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(
|
|
704
|
+
console.log(chalk5.dim(`No results found for "${query}"`));
|
|
476
705
|
return;
|
|
477
706
|
}
|
|
478
707
|
console.log();
|
|
479
|
-
console.log(
|
|
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] ||
|
|
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} ${
|
|
486
|
-
console.log(` ${
|
|
714
|
+
console.log(` ${typeLabel} ${chalk5.bold(artifact.name)}`);
|
|
715
|
+
console.log(` ${chalk5.cyan(fullSlug)}`);
|
|
487
716
|
if (artifact.summary) {
|
|
488
|
-
console.log(` ${
|
|
717
|
+
console.log(` ${chalk5.dim(truncate(artifact.summary, 60))}`);
|
|
489
718
|
}
|
|
490
|
-
console.log(` ${
|
|
719
|
+
console.log(` ${chalk5.dim(`${formatNumber(artifact.installCount)} installs`)}`);
|
|
491
720
|
console.log();
|
|
492
721
|
}
|
|
493
722
|
if (total > artifacts.length) {
|
|
494
|
-
console.log(
|
|
495
|
-
console.log(
|
|
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
|
-
`${
|
|
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(
|
|
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(
|
|
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(
|
|
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(`${
|
|
542
|
-
console.log(`${
|
|
543
|
-
console.log(`${
|
|
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 ${
|
|
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.
|
|
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"
|