@builderpackai/cli 0.1.4 → 0.1.6
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 +50 -0
- package/dist/cli.js +100 -32
- package/dist/cli.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -57,6 +57,56 @@ Install everything:
|
|
|
57
57
|
builderpack skills add --all --tool claude,codex
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
## Common queries
|
|
61
|
+
|
|
62
|
+
List everything:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
builderpack skills list
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
List by theme:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
builderpack skills list --theme gamedev
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Install by theme:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
builderpack skills add --theme saas --tool claude
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Install by skill id:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
builderpack skills add --skill og-image-creator --tool codex
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Install multiple skills:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
builderpack skills add --skill og-image-creator --skill seo-optimizer --tool claude
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Dry run (no changes):
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
builderpack skills add --theme gamedev --tool claude --dry-run
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Verbose (see exactly what’s selected and installed):
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
builderpack skills add --theme gamedev --tool claude --verbose
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Selection rules:
|
|
105
|
+
|
|
106
|
+
- `--all` overrides everything.
|
|
107
|
+
- If `--theme` is set, it’s used and `--skill` is ignored.
|
|
108
|
+
- If only `--skill` is set, those ids are used.
|
|
109
|
+
|
|
60
110
|
## Global vs project install
|
|
61
111
|
|
|
62
112
|
Default is project-local (puts files in `.claude/skills` or `.codex/skills` in your repo).
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { homedir, tmpdir } from "os";
|
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import { mkdirSync, readFileSync, writeFileSync, existsSync, rmSync } from "fs";
|
|
5
5
|
var getApiBase = () => {
|
|
6
|
-
return (process.env.BUILDERPACK_API_BASE?.trim() || "https://builderpack.ai/api/cli/v1").replace(
|
|
6
|
+
return (process.env.BUILDERPACK_API_BASE?.trim() || "https://www.builderpack.ai/api/cli/v1").replace(
|
|
7
7
|
/\/$/,
|
|
8
8
|
""
|
|
9
9
|
);
|
|
@@ -52,33 +52,52 @@ var clearAuth = () => {
|
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
// src/http.ts
|
|
55
|
+
var requestJson = async (opts, maxRedirects = 3) => {
|
|
56
|
+
let current = opts;
|
|
57
|
+
for (let i = 0; i <= maxRedirects; i++) {
|
|
58
|
+
const res = await fetch(current.url, {
|
|
59
|
+
method: current.method,
|
|
60
|
+
headers: current.headers,
|
|
61
|
+
body: current.body,
|
|
62
|
+
redirect: "manual"
|
|
63
|
+
});
|
|
64
|
+
if (res.status >= 300 && res.status < 400) {
|
|
65
|
+
const location = res.headers.get("location");
|
|
66
|
+
if (!location) {
|
|
67
|
+
const bodyText = await res.text().catch(() => "");
|
|
68
|
+
throw { status: res.status, bodyText };
|
|
69
|
+
}
|
|
70
|
+
const nextUrl = new URL(location, current.url).toString();
|
|
71
|
+
current = { ...current, url: nextUrl };
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (!res.ok) {
|
|
75
|
+
const bodyText = await res.text().catch(() => "");
|
|
76
|
+
throw { status: res.status, bodyText };
|
|
77
|
+
}
|
|
78
|
+
return await res.json();
|
|
79
|
+
}
|
|
80
|
+
throw { status: 310, bodyText: "Too many redirects" };
|
|
81
|
+
};
|
|
55
82
|
var httpGetJson = async (url, options) => {
|
|
56
|
-
|
|
83
|
+
return requestJson({
|
|
57
84
|
method: "GET",
|
|
85
|
+
url,
|
|
58
86
|
headers: {
|
|
59
87
|
...options?.bearer ? { Authorization: `Bearer ${options.bearer}` } : {}
|
|
60
88
|
}
|
|
61
89
|
});
|
|
62
|
-
if (!res.ok) {
|
|
63
|
-
const bodyText = await res.text().catch(() => "");
|
|
64
|
-
throw { status: res.status, bodyText };
|
|
65
|
-
}
|
|
66
|
-
return await res.json();
|
|
67
90
|
};
|
|
68
91
|
var httpPostJson = async (url, body, options) => {
|
|
69
|
-
|
|
92
|
+
return requestJson({
|
|
70
93
|
method: "POST",
|
|
94
|
+
url,
|
|
71
95
|
headers: {
|
|
72
96
|
"Content-Type": "application/json",
|
|
73
97
|
...options?.bearer ? { Authorization: `Bearer ${options.bearer}` } : {}
|
|
74
98
|
},
|
|
75
99
|
body: JSON.stringify(body)
|
|
76
100
|
});
|
|
77
|
-
if (!res.ok) {
|
|
78
|
-
const bodyText = await res.text().catch(() => "");
|
|
79
|
-
throw { status: res.status, bodyText };
|
|
80
|
-
}
|
|
81
|
-
return await res.json();
|
|
82
101
|
};
|
|
83
102
|
|
|
84
103
|
// src/print.ts
|
|
@@ -111,19 +130,37 @@ var tryOpenUrl = (url) => {
|
|
|
111
130
|
};
|
|
112
131
|
|
|
113
132
|
// src/auth.ts
|
|
133
|
+
import { createInterface } from "readline";
|
|
134
|
+
var waitForEnter = async () => {
|
|
135
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
await new Promise((resolve3) => {
|
|
139
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
140
|
+
rl.question("Press Enter to launch the browser...", () => {
|
|
141
|
+
rl.close();
|
|
142
|
+
resolve3();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
};
|
|
114
146
|
var commandLogin = async () => {
|
|
115
147
|
const apiBase = getApiBase();
|
|
116
148
|
const start = await httpPostJson(`${apiBase}/auth/device/start`, {});
|
|
117
149
|
log("");
|
|
118
150
|
log("Builderpack CLI login");
|
|
119
151
|
log("");
|
|
120
|
-
log(`1)
|
|
152
|
+
log(`1) You will open: ${start.verification_uri}`);
|
|
121
153
|
log(`2) Enter code: ${start.user_code}`);
|
|
122
154
|
log("");
|
|
123
|
-
|
|
124
|
-
|
|
155
|
+
const urlToOpen = start.verification_uri_complete || start.verification_uri;
|
|
156
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
157
|
+
log("Press Enter to open the browser automatically.");
|
|
158
|
+
log("Then enter the code above and confirm it matches.");
|
|
159
|
+
await waitForEnter();
|
|
160
|
+
tryOpenUrl(urlToOpen);
|
|
125
161
|
} else {
|
|
126
|
-
|
|
162
|
+
log(`Open this URL in a browser when ready: ${urlToOpen}`);
|
|
163
|
+
log("Enter the code above and confirm it matches.");
|
|
127
164
|
}
|
|
128
165
|
const deadline = Date.now() + start.expires_in * 1e3;
|
|
129
166
|
while (Date.now() < deadline) {
|
|
@@ -277,11 +314,33 @@ var extractSkillName = (skillMdPath) => {
|
|
|
277
314
|
return nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
278
315
|
};
|
|
279
316
|
|
|
317
|
+
// src/skills-select.ts
|
|
318
|
+
var resolveSelectedSkills = (opts) => {
|
|
319
|
+
const { catalog, theme, skillArgs, all } = opts;
|
|
320
|
+
if (all) return catalog.skills.map((s) => s.id);
|
|
321
|
+
if (theme) {
|
|
322
|
+
const ids = catalog.themes[theme];
|
|
323
|
+
if (!ids) die(`Unknown theme: ${theme}`);
|
|
324
|
+
return ids;
|
|
325
|
+
}
|
|
326
|
+
if (skillArgs.length > 0) {
|
|
327
|
+
return skillArgs;
|
|
328
|
+
}
|
|
329
|
+
return [];
|
|
330
|
+
};
|
|
331
|
+
|
|
280
332
|
// src/skills.ts
|
|
281
333
|
var commandSkillsList = async (args) => {
|
|
282
334
|
const theme = getFlagValue(args, "--theme");
|
|
335
|
+
const verbose = hasFlag(args, "--verbose");
|
|
283
336
|
const catalog = await fetchCatalog();
|
|
284
337
|
const ids = theme && catalog.themes[theme] ? catalog.themes[theme] : catalog.skills.map((s) => s.id);
|
|
338
|
+
if (verbose) {
|
|
339
|
+
const themeInfo = theme ? theme : "all";
|
|
340
|
+
log(`[verbose] theme: ${themeInfo}`);
|
|
341
|
+
log(`[verbose] total skills: ${catalog.skills.length}`);
|
|
342
|
+
log(`[verbose] selected count: ${ids.length}`);
|
|
343
|
+
}
|
|
285
344
|
for (const id of ids) {
|
|
286
345
|
const skill = catalog.skills.find((s) => s.id === id);
|
|
287
346
|
const variants = skill?.variants?.join(",") || "";
|
|
@@ -295,6 +354,7 @@ var commandSkillsAdd = async (args) => {
|
|
|
295
354
|
const mode = getFlagValue(args, "--mode") || "symlink";
|
|
296
355
|
const strict = hasFlag(args, "--strict");
|
|
297
356
|
const dryRun = hasFlag(args, "--dry-run");
|
|
357
|
+
const verbose = hasFlag(args, "--verbose");
|
|
298
358
|
const toolArg = getFlagValue(args, "--tool") || "claude,codex";
|
|
299
359
|
const tools = toolArg.split(",").map((t) => t.trim()).filter(Boolean);
|
|
300
360
|
const invalidTools = tools.filter((t) => t !== "claude" && t !== "codex");
|
|
@@ -311,6 +371,16 @@ var commandSkillsAdd = async (args) => {
|
|
|
311
371
|
}
|
|
312
372
|
const repoRoot = scope === "project" ? getRepoRoot() : process.cwd();
|
|
313
373
|
const canonicalBase = getCanonicalDir(scope, repoRoot);
|
|
374
|
+
if (verbose) {
|
|
375
|
+
log(`[verbose] api base: ${auth.apiBase}`);
|
|
376
|
+
log(`[verbose] scope: ${scope}`);
|
|
377
|
+
log(`[verbose] mode: ${mode}`);
|
|
378
|
+
log(`[verbose] strict: ${strict}`);
|
|
379
|
+
log(`[verbose] dry-run: ${dryRun}`);
|
|
380
|
+
log(`[verbose] tools: ${normalizedTools.join(",")}`);
|
|
381
|
+
log(`[verbose] theme: ${theme ?? "none"}`);
|
|
382
|
+
log(`[verbose] skills: ${selected.join(",")}`);
|
|
383
|
+
}
|
|
314
384
|
if (scope === "project" && mode === "symlink") {
|
|
315
385
|
const gitignorePath = join4(repoRoot, ".gitignore");
|
|
316
386
|
if (existsSync2(gitignorePath)) {
|
|
@@ -341,10 +411,17 @@ var commandSkillsAdd = async (args) => {
|
|
|
341
411
|
log(`[dry-run] would install ${skillId} (${tool})`);
|
|
342
412
|
continue;
|
|
343
413
|
}
|
|
414
|
+
if (verbose) {
|
|
415
|
+
log(`[verbose] request artifact: ${skillId} (${tool})`);
|
|
416
|
+
}
|
|
344
417
|
const signed = await httpGetJson(
|
|
345
418
|
`${auth.apiBase}/artifacts/skills/${encodeURIComponent(skillId)}/${encodeURIComponent(tool)}`,
|
|
346
419
|
{ bearer: auth.accessToken }
|
|
347
420
|
);
|
|
421
|
+
if (verbose) {
|
|
422
|
+
log(`[verbose] signed url expires in: ${signed.expiresIn}s`);
|
|
423
|
+
log(`[verbose] object path: ${signed.objectPath}`);
|
|
424
|
+
}
|
|
348
425
|
const extractedDir = await downloadAndExtractZip(signed.signedUrl);
|
|
349
426
|
const resolvedSkillDir = await resolveExtractedSkillRoot(extractedDir);
|
|
350
427
|
const skillMdPath = join4(resolvedSkillDir, "SKILL.md");
|
|
@@ -358,6 +435,10 @@ var commandSkillsAdd = async (args) => {
|
|
|
358
435
|
if (!isSafeChildPath(canonicalBase, canonicalDir) || !isSafeChildPath(toolBase, toolDir)) {
|
|
359
436
|
die(`Unsafe install path for skill: ${skillId}`);
|
|
360
437
|
}
|
|
438
|
+
if (verbose) {
|
|
439
|
+
log(`[verbose] canonical dir: ${canonicalDir}`);
|
|
440
|
+
log(`[verbose] tool dir: ${toolDir}`);
|
|
441
|
+
}
|
|
361
442
|
await ensureDir(canonicalBase);
|
|
362
443
|
await ensureDir(toolBase);
|
|
363
444
|
if (mode === "copy") {
|
|
@@ -397,19 +478,6 @@ var getMultiFlagValues = (args, flag) => {
|
|
|
397
478
|
}
|
|
398
479
|
return out;
|
|
399
480
|
};
|
|
400
|
-
var resolveSelectedSkills = (opts) => {
|
|
401
|
-
const { catalog, theme, skillArgs, all } = opts;
|
|
402
|
-
if (all) return catalog.skills.map((s) => s.id);
|
|
403
|
-
if (theme) {
|
|
404
|
-
const ids = catalog.themes[theme];
|
|
405
|
-
if (!ids) die(`Unknown theme: ${theme}`);
|
|
406
|
-
return ids;
|
|
407
|
-
}
|
|
408
|
-
if (skillArgs.length > 0) {
|
|
409
|
-
return skillArgs;
|
|
410
|
-
}
|
|
411
|
-
return [];
|
|
412
|
-
};
|
|
413
481
|
var downloadAndExtractZip = async (signedUrl) => {
|
|
414
482
|
const res = await fetch(signedUrl);
|
|
415
483
|
if (!res.ok) {
|
|
@@ -450,7 +518,7 @@ Usage:
|
|
|
450
518
|
builderpack logout
|
|
451
519
|
|
|
452
520
|
builderpack skills list [--theme <name>]
|
|
453
|
-
builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run]
|
|
521
|
+
builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run] [--verbose]
|
|
454
522
|
`);
|
|
455
523
|
};
|
|
456
524
|
var main = async () => {
|
|
@@ -489,7 +557,7 @@ var main = async () => {
|
|
|
489
557
|
|
|
490
558
|
Usage:
|
|
491
559
|
builderpack skills list [--theme <name>]
|
|
492
|
-
builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run]
|
|
560
|
+
builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run] [--verbose]
|
|
493
561
|
`);
|
|
494
562
|
return;
|
|
495
563
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/http.ts","../src/print.ts","../src/open.ts","../src/auth.ts","../src/skills.ts","../src/catalog.ts","../src/fsx.ts","../src/paths.ts","../src/skill-md.ts","../src/cli.ts"],"sourcesContent":["import { homedir, tmpdir } from \"os\"\nimport { join } from \"path\"\nimport { mkdirSync, readFileSync, writeFileSync, existsSync, rmSync } from \"fs\"\n\nexport type BuilderpackAuth = {\n apiBase: string\n accessToken: string\n}\n\nexport const getApiBase = (): string => {\n return (process.env.BUILDERPACK_API_BASE?.trim() || \"https://builderpack.ai/api/cli/v1\").replace(\n /\\/$/,\n \"\"\n )\n}\n\nexport const getConfigDir = (): string => {\n const xdg = process.env.XDG_CONFIG_HOME?.trim()\n if (xdg) return join(xdg, \"builderpack\")\n\n if (process.platform === \"win32\") {\n const appData = process.env.APPDATA?.trim()\n if (appData) return join(appData, \"builderpack\")\n }\n\n return join(homedir(), \".config\", \"builderpack\")\n}\n\nexport const getAuthPath = (): string => {\n return join(getConfigDir(), \"auth.json\")\n}\n\nexport const loadAuth = (): BuilderpackAuth | null => {\n const p = getAuthPath()\n if (!existsSync(p)) return null\n try {\n const parsed = JSON.parse(readFileSync(p, \"utf8\")) as Partial<BuilderpackAuth>\n if (!parsed?.accessToken || !parsed?.apiBase) return null\n return { apiBase: parsed.apiBase, accessToken: parsed.accessToken }\n } catch {\n return null\n }\n}\n\nexport const requireAuth = (): BuilderpackAuth => {\n const auth = loadAuth()\n if (!auth) {\n throw new Error(\"Not logged in. Run: builderpack login\")\n }\n return auth\n}\n\nexport const saveAuth = (auth: BuilderpackAuth): void => {\n const dir = getConfigDir()\n mkdirSync(dir, { recursive: true })\n writeFileSync(getAuthPath(), JSON.stringify(auth, null, 2), \"utf8\")\n}\n\nexport const clearAuth = (): void => {\n const p = getAuthPath()\n try {\n rmSync(p)\n } catch {\n // ignore\n }\n}\n\nexport const getTempDir = (): string => {\n return join(tmpdir(), \"builderpack\")\n}\n","export type HttpError = {\n status: number\n bodyText: string\n}\n\nexport const httpGetJson = async <T>(\n url: string,\n options?: { bearer?: string }\n): Promise<T> => {\n const res = await fetch(url, {\n method: \"GET\",\n headers: {\n ...(options?.bearer ? { Authorization: `Bearer ${options.bearer}` } : {}),\n },\n })\n\n if (!res.ok) {\n const bodyText = await res.text().catch(() => \"\")\n throw { status: res.status, bodyText } satisfies HttpError\n }\n\n return (await res.json()) as T\n}\n\nexport const httpPostJson = async <T>(\n url: string,\n body: unknown,\n options?: { bearer?: string }\n): Promise<T> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(options?.bearer ? { Authorization: `Bearer ${options.bearer}` } : {}),\n },\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const bodyText = await res.text().catch(() => \"\")\n throw { status: res.status, bodyText } satisfies HttpError\n }\n\n return (await res.json()) as T\n}\n\n","export const die = (message: string, code: number = 1): never => {\n process.stderr.write(message + \"\\n\")\n process.exit(code)\n}\n\nexport const log = (message: string): void => {\n process.stdout.write(message + \"\\n\")\n}\n\nexport const warn = (message: string): void => {\n process.stderr.write(message + \"\\n\")\n}\n\n","import { spawnSync } from \"child_process\"\n\nexport const tryOpenUrl = (url: string): void => {\n try {\n if (process.platform === \"darwin\") {\n spawnSync(\"open\", [url], { stdio: \"ignore\" })\n return\n }\n\n if (process.platform === \"win32\") {\n spawnSync(\"cmd\", [\"/c\", \"start\", \"\", url], { stdio: \"ignore\" })\n return\n }\n\n spawnSync(\"xdg-open\", [url], { stdio: \"ignore\" })\n } catch {\n // ignore\n }\n}\n\n","import { getApiBase, requireAuth, saveAuth, clearAuth } from \"./config\"\nimport { httpGetJson, httpPostJson } from \"./http\"\nimport { die, log } from \"./print\"\nimport { tryOpenUrl } from \"./open\"\n\ntype DeviceStartResponse = {\n device_code: string\n user_code: string\n verification_uri: string\n verification_uri_complete?: string\n expires_in: number\n interval: number\n}\n\ntype DeviceTokenResponse = {\n access_token: string\n expires_in: number\n}\n\ntype MeResponse = {\n email: string\n entitlements: { claude: boolean; codex: boolean; adk: boolean; allInOne: boolean }\n}\n\nexport const commandLogin = async (): Promise<void> => {\n const apiBase = getApiBase()\n const start = await httpPostJson<DeviceStartResponse>(`${apiBase}/auth/device/start`, {})\n\n log(\"\")\n log(\"Builderpack CLI login\")\n log(\"\")\n log(`1) Open: ${start.verification_uri}`)\n log(`2) Enter code: ${start.user_code}`)\n log(\"\")\n\n if (start.verification_uri_complete) {\n tryOpenUrl(start.verification_uri_complete)\n } else {\n tryOpenUrl(start.verification_uri)\n }\n\n const deadline = Date.now() + start.expires_in * 1000\n while (Date.now() < deadline) {\n try {\n const token = await httpPostJson<DeviceTokenResponse>(`${apiBase}/auth/device/token`, {\n device_code: start.device_code,\n })\n\n saveAuth({ apiBase, accessToken: token.access_token })\n log(\"Logged in. You can now run: builderpack skills add ...\")\n return\n } catch (e: any) {\n const status = typeof e?.status === \"number\" ? e.status : 0\n if (status === 428) {\n await new Promise((r) => setTimeout(r, Math.max(1, start.interval) * 1000))\n continue\n }\n if (status === 410) {\n die(\"Login expired. Run: builderpack login\")\n }\n // Other error; keep retrying a couple times then bail\n await new Promise((r) => setTimeout(r, Math.max(1, start.interval) * 1000))\n continue\n }\n }\n\n die(\"Login expired. Run: builderpack login\")\n}\n\nexport const commandWhoami = async (): Promise<void> => {\n const auth = requireAuth()\n const me = await httpGetJson<MeResponse>(`${auth.apiBase}/me`, { bearer: auth.accessToken })\n log(JSON.stringify(me, null, 2))\n}\n\nexport const commandLogout = (): void => {\n clearAuth()\n log(\"Logged out.\")\n}\n","import { mkdtemp, writeFile, readdir } from \"fs/promises\"\nimport { existsSync, readFileSync } from \"fs\"\nimport { join } from \"path\"\nimport { tmpdir } from \"os\"\nimport AdmZip from \"adm-zip\"\nimport { requireAuth } from \"./config\"\nimport { fetchCatalog, type CatalogV1 } from \"./catalog\"\nimport { httpGetJson } from \"./http\"\nimport { die, log, warn } from \"./print\"\nimport { copyDir, createSymlink, ensureDir, fileExists, removePath } from \"./fsx\"\nimport { getCanonicalDir, getRepoRoot, getToolSkillsDir, isSafeChildPath } from \"./paths\"\nimport { extractSkillName } from \"./skill-md\"\n\ntype Variant = \"claude\" | \"codex\"\n\ntype SignedUrlResponse = {\n signedUrl: string\n expiresIn: number\n objectPath: string\n}\n\nexport const commandSkillsList = async (args: string[]): Promise<void> => {\n const theme = getFlagValue(args, \"--theme\")\n const catalog = await fetchCatalog()\n\n const ids =\n theme && catalog.themes[theme]\n ? catalog.themes[theme]\n : catalog.skills.map((s) => s.id)\n\n for (const id of ids) {\n const skill = catalog.skills.find((s) => s.id === id)\n const variants = skill?.variants?.join(\",\") || \"\"\n log(`${id}${variants ? ` (${variants})` : \"\"}`)\n }\n}\n\nexport const commandSkillsAdd = async (args: string[]): Promise<void> => {\n const auth = requireAuth()\n\n const catalog = await fetchCatalog()\n\n const scope = hasFlag(args, \"--global\") ? \"global\" : \"project\"\n const mode = (getFlagValue(args, \"--mode\") || \"symlink\") as \"symlink\" | \"copy\"\n const strict = hasFlag(args, \"--strict\")\n const dryRun = hasFlag(args, \"--dry-run\")\n\n const toolArg = getFlagValue(args, \"--tool\") || \"claude,codex\"\n const tools = toolArg\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean)\n\n const invalidTools = tools.filter((t) => t !== \"claude\" && t !== \"codex\")\n if (invalidTools.length > 0) {\n die(`Invalid --tool value(s): ${invalidTools.join(\", \")} (expected claude,codex)`)\n }\n\n const normalizedTools = tools as Variant[]\n\n const theme = getFlagValue(args, \"--theme\")\n const skillArgs = getMultiFlagValues(args, \"--skill\")\n const all = hasFlag(args, \"--all\")\n\n const selected = resolveSelectedSkills({ catalog, theme, skillArgs, all })\n if (selected.length === 0) {\n die(\"No skills selected. Use --theme <name>, --skill <id>, or --all\")\n }\n\n const repoRoot = scope === \"project\" ? getRepoRoot() : process.cwd()\n const canonicalBase = getCanonicalDir(scope, repoRoot)\n\n if (scope === \"project\" && mode === \"symlink\") {\n const gitignorePath = join(repoRoot, \".gitignore\")\n if (existsSync(gitignorePath)) {\n try {\n const content = readFileSync(gitignorePath, \"utf8\")\n if (!content.includes(\".builderpack/\")) {\n warn(\"Note: consider adding `.builderpack/` to your repo .gitignore\")\n }\n } catch {\n // ignore\n }\n }\n }\n\n for (const skillId of selected) {\n const skill = catalog.skills.find((s) => s.id === skillId)\n if (!skill) {\n if (strict) die(`Unknown skill: ${skillId}`)\n warn(`Skipping unknown skill: ${skillId}`)\n continue\n }\n\n for (const tool of normalizedTools) {\n if (!skill.variants.includes(tool)) {\n const msg = `Skipping ${skillId} for ${tool}: variant not available`\n if (strict) die(msg)\n warn(msg)\n continue\n }\n\n if (dryRun) {\n log(`[dry-run] would install ${skillId} (${tool})`)\n continue\n }\n\n const signed = await httpGetJson<SignedUrlResponse>(\n `${auth.apiBase}/artifacts/skills/${encodeURIComponent(skillId)}/${encodeURIComponent(tool)}`,\n { bearer: auth.accessToken }\n )\n\n const extractedDir = await downloadAndExtractZip(signed.signedUrl)\n const resolvedSkillDir = await resolveExtractedSkillRoot(extractedDir)\n\n const skillMdPath = join(resolvedSkillDir, \"SKILL.md\")\n const skillName = (await fileExists(skillMdPath)) ? extractSkillName(skillMdPath) : null\n if (skillName !== skillId) {\n die(`Invalid payload for ${skillId}: SKILL.md name is ${skillName ?? \"missing\"}`)\n }\n\n const canonicalDir = join(canonicalBase, skillId)\n const toolBase = getToolSkillsDir(tool, scope, repoRoot)\n const toolDir = join(toolBase, skillId)\n\n if (!isSafeChildPath(canonicalBase, canonicalDir) || !isSafeChildPath(toolBase, toolDir)) {\n die(`Unsafe install path for skill: ${skillId}`)\n }\n\n await ensureDir(canonicalBase)\n await ensureDir(toolBase)\n\n if (mode === \"copy\") {\n await removePath(toolDir)\n await copyDir(resolvedSkillDir, toolDir)\n log(`Installed ${skillId} (${tool}) -> ${toolDir}`)\n continue\n }\n\n await removePath(canonicalDir)\n await copyDir(resolvedSkillDir, canonicalDir)\n\n const symlinkOk = await createSymlink(canonicalDir, toolDir)\n if (!symlinkOk) {\n await removePath(toolDir)\n await copyDir(resolvedSkillDir, toolDir)\n warn(`Symlink failed; copied ${skillId} (${tool}) -> ${toolDir}`)\n } else {\n log(`Installed ${skillId} (${tool}) -> ${toolDir}`)\n }\n }\n }\n}\n\nconst hasFlag = (args: string[], flag: string): boolean => args.includes(flag)\n\nconst getFlagValue = (args: string[], flag: string): string | null => {\n const idx = args.indexOf(flag)\n if (idx === -1) return null\n const v = args[idx + 1]\n if (!v || v.startsWith(\"-\")) return null\n return v\n}\n\nconst getMultiFlagValues = (args: string[], flag: string): string[] => {\n const out: string[] = []\n for (let i = 0; i < args.length; i++) {\n if (args[i] === flag) {\n const v = args[i + 1]\n if (v && !v.startsWith(\"-\")) out.push(v)\n }\n }\n return out\n}\n\nconst resolveSelectedSkills = (opts: {\n catalog: CatalogV1\n theme: string | null\n skillArgs: string[]\n all: boolean\n}): string[] => {\n const { catalog, theme, skillArgs, all } = opts\n\n if (all) return catalog.skills.map((s) => s.id)\n\n if (theme) {\n const ids = catalog.themes[theme]\n if (!ids) die(`Unknown theme: ${theme}`)\n return ids\n }\n\n if (skillArgs.length > 0) {\n return skillArgs\n }\n\n return []\n}\n\nconst downloadAndExtractZip = async (signedUrl: string): Promise<string> => {\n const res = await fetch(signedUrl)\n if (!res.ok) {\n die(`Failed to download artifact (HTTP ${res.status})`)\n }\n\n const tmpBase = await mkdtemp(join(tmpdir(), \"builderpack-\"))\n const zipPath = join(tmpBase, \"artifact.zip\")\n\n const buf = Buffer.from(await res.arrayBuffer())\n await writeFile(zipPath, buf)\n\n const zip = new AdmZip(zipPath)\n const outDir = join(tmpBase, \"out\")\n zip.extractAllTo(outDir, true)\n return outDir\n}\n\nconst resolveExtractedSkillRoot = async (dir: string): Promise<string> => {\n const direct = join(dir, \"SKILL.md\")\n if (await fileExists(direct)) return dir\n\n // Heuristic: if there is exactly one top-level directory and it contains SKILL.md, use it\n const entries = await readdir(dir, { withFileTypes: true })\n const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name)\n if (dirs.length === 1) {\n const nested = join(dir, dirs[0], \"SKILL.md\")\n if (await fileExists(nested)) return join(dir, dirs[0])\n }\n\n die(\"Invalid artifact zip: missing SKILL.md at root\")\n throw new Error(\"unreachable\")\n}\n","import { requireAuth } from \"./config\"\nimport { httpGetJson } from \"./http\"\n\nexport type CatalogV1 = {\n version: 1\n themes: Record<string, string[]>\n skills: Array<{ id: string; variants: Array<\"claude\" | \"codex\">; themes: string[] }>\n}\n\ntype CatalogResponse = { catalog: CatalogV1; entitlements: unknown }\n\nexport const fetchCatalog = async (): Promise<CatalogV1> => {\n const auth = requireAuth()\n\n const res = await httpGetJson<CatalogResponse>(`${auth.apiBase}/catalog`, { bearer: auth.accessToken })\n return res.catalog\n}\n","import { mkdir, rm, readdir, stat, copyFile, symlink, readlink } from \"fs/promises\"\nimport { dirname, join, relative, resolve } from \"path\"\n\nexport const ensureDir = async (path: string): Promise<void> => {\n await mkdir(path, { recursive: true })\n}\n\nexport const removePath = async (path: string): Promise<void> => {\n await rm(path, { recursive: true, force: true })\n}\n\nexport const copyDir = async (src: string, dest: string): Promise<void> => {\n await ensureDir(dest)\n const entries = await readdir(src, { withFileTypes: true })\n await Promise.all(\n entries.map(async (entry) => {\n const s = join(src, entry.name)\n const d = join(dest, entry.name)\n if (entry.isDirectory()) {\n await copyDir(s, d)\n return\n }\n if (entry.isFile()) {\n await ensureDir(dirname(d))\n await copyFile(s, d)\n }\n })\n )\n}\n\nexport const createSymlink = async (target: string, linkPath: string): Promise<boolean> => {\n try {\n const resolvedTarget = resolve(target)\n const resolvedLinkPath = resolve(linkPath)\n if (resolvedTarget === resolvedLinkPath) return true\n\n // if existing link already points correctly, keep it\n try {\n const existing = await readlink(linkPath)\n const resolvedExisting = resolve(dirname(linkPath), existing)\n if (resolvedExisting === resolvedTarget) return true\n } catch {\n // ignore\n }\n\n await removePath(linkPath)\n await ensureDir(dirname(linkPath))\n\n const rel = relative(dirname(linkPath), target)\n const type = process.platform === \"win32\" ? \"junction\" : undefined\n await symlink(rel, linkPath, type as any)\n return true\n } catch {\n return false\n }\n}\n\nexport const fileExists = async (path: string): Promise<boolean> => {\n try {\n const s = await stat(path)\n return s.isFile()\n } catch {\n return false\n }\n}\n\n","import { spawnSync } from \"child_process\"\nimport { homedir } from \"os\"\nimport { join, resolve } from \"path\"\n\nexport type InstallScope = \"project\" | \"global\"\nexport type ToolVariant = \"claude\" | \"codex\"\n\nexport const getRepoRoot = (): string => {\n const out = spawnSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], { encoding: \"utf8\" })\n if (out.status === 0 && out.stdout) {\n return out.stdout.trim()\n }\n return process.cwd()\n}\n\nexport const getCanonicalDir = (scope: InstallScope, repoRoot: string): string => {\n if (scope === \"global\") {\n return join(homedir(), \".builderpack\", \"store\", \"skills\")\n }\n return join(repoRoot, \".builderpack\", \"store\", \"skills\")\n}\n\nexport const getToolSkillsDir = (\n tool: ToolVariant,\n scope: InstallScope,\n repoRoot: string\n): string => {\n if (scope === \"project\") {\n if (tool === \"claude\") return join(repoRoot, \".claude\", \"skills\")\n return join(repoRoot, \".codex\", \"skills\")\n }\n\n if (tool === \"claude\") {\n const base = process.env.CLAUDE_CONFIG_DIR?.trim() || join(homedir(), \".claude\")\n return join(base, \"skills\")\n }\n\n const codexHome = process.env.CODEX_HOME?.trim() || join(homedir(), \".codex\")\n return join(codexHome, \"skills\")\n}\n\nexport const isSafeChildPath = (baseDir: string, childPath: string): boolean => {\n const base = resolve(baseDir)\n const target = resolve(childPath)\n return target === base || target.startsWith(base + \"/\") || target.startsWith(base + \"\\\\\")\n}\n\n","import { readFileSync } from \"fs\"\n\nexport const extractSkillName = (skillMdPath: string): string | null => {\n const content = readFileSync(skillMdPath, \"utf8\")\n const match = content.match(/^\\s*---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n/)\n if (!match) return null\n const fm = match[1]\n const nameMatch = fm.match(/^\\s*name\\s*:\\s*(.+?)\\s*$/m)\n if (!nameMatch) return null\n return nameMatch[1].trim().replace(/^[\"']|[\"']$/g, \"\")\n}\n\n","import { commandLogin, commandLogout, commandWhoami } from \"./auth\"\nimport { commandSkillsAdd, commandSkillsList } from \"./skills\"\nimport { die, log } from \"./print\"\nimport { readFileSync } from \"fs\"\nimport { join, dirname } from \"path\"\nimport { fileURLToPath } from \"url\"\n\nconst showHelp = (): void => {\n log(`builderpack\n\nUsage:\n builderpack login\n builderpack whoami\n builderpack logout\n\n builderpack skills list [--theme <name>]\n builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run]\n`)\n}\n\nconst main = async (): Promise<void> => {\n const [, , ...argv] = process.argv\n const [cmd, sub, ...rest] = argv\n\n if (!cmd || cmd === \"--help\" || cmd === \"-h\") {\n showHelp()\n return\n }\n\n if (cmd === \"--version\" || cmd === \"-v\") {\n try {\n const here = dirname(fileURLToPath(import.meta.url))\n const pkgPath = join(here, \"..\", \"package.json\")\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { version?: string }\n log(pkg.version || \"0.0.0\")\n } catch {\n log(\"0.0.0\")\n }\n return\n }\n\n if (cmd === \"login\") {\n await commandLogin()\n return\n }\n if (cmd === \"whoami\") {\n await commandWhoami()\n return\n }\n if (cmd === \"logout\") {\n commandLogout()\n return\n }\n\n if (cmd === \"skills\") {\n if (!sub || sub === \"--help\" || sub === \"-h\") {\n log(`builderpack skills\n\nUsage:\n builderpack skills list [--theme <name>]\n builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run]\n`)\n return\n }\n\n if (sub === \"list\") {\n await commandSkillsList(rest)\n return\n }\n\n if (sub === \"add\") {\n await commandSkillsAdd(rest)\n return\n }\n\n die(`Unknown skills command: ${sub}`)\n }\n\n die(`Unknown command: ${cmd}`)\n}\n\nmain().catch((err) => {\n // eslint-disable-next-line no-console\n console.error(err)\n process.exitCode = 1\n})\n"],"mappings":"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","names":["readdir","existsSync","readFileSync","join","tmpdir","join","spawnSync","homedir","join","resolve","readFileSync","join","existsSync","readFileSync","tmpdir","readdir","readFileSync","join","dirname"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/http.ts","../src/print.ts","../src/open.ts","../src/auth.ts","../src/skills.ts","../src/catalog.ts","../src/fsx.ts","../src/paths.ts","../src/skill-md.ts","../src/skills-select.ts","../src/cli.ts"],"sourcesContent":["import { homedir, tmpdir } from \"os\"\nimport { join } from \"path\"\nimport { mkdirSync, readFileSync, writeFileSync, existsSync, rmSync } from \"fs\"\n\nexport type BuilderpackAuth = {\n apiBase: string\n accessToken: string\n}\n\nexport const getApiBase = (): string => {\n return (process.env.BUILDERPACK_API_BASE?.trim() || \"https://www.builderpack.ai/api/cli/v1\").replace(\n /\\/$/,\n \"\"\n )\n}\n\nexport const getConfigDir = (): string => {\n const xdg = process.env.XDG_CONFIG_HOME?.trim()\n if (xdg) return join(xdg, \"builderpack\")\n\n if (process.platform === \"win32\") {\n const appData = process.env.APPDATA?.trim()\n if (appData) return join(appData, \"builderpack\")\n }\n\n return join(homedir(), \".config\", \"builderpack\")\n}\n\nexport const getAuthPath = (): string => {\n return join(getConfigDir(), \"auth.json\")\n}\n\nexport const loadAuth = (): BuilderpackAuth | null => {\n const p = getAuthPath()\n if (!existsSync(p)) return null\n try {\n const parsed = JSON.parse(readFileSync(p, \"utf8\")) as Partial<BuilderpackAuth>\n if (!parsed?.accessToken || !parsed?.apiBase) return null\n return { apiBase: parsed.apiBase, accessToken: parsed.accessToken }\n } catch {\n return null\n }\n}\n\nexport const requireAuth = (): BuilderpackAuth => {\n const auth = loadAuth()\n if (!auth) {\n throw new Error(\"Not logged in. Run: builderpack login\")\n }\n return auth\n}\n\nexport const saveAuth = (auth: BuilderpackAuth): void => {\n const dir = getConfigDir()\n mkdirSync(dir, { recursive: true })\n writeFileSync(getAuthPath(), JSON.stringify(auth, null, 2), \"utf8\")\n}\n\nexport const clearAuth = (): void => {\n const p = getAuthPath()\n try {\n rmSync(p)\n } catch {\n // ignore\n }\n}\n\nexport const getTempDir = (): string => {\n return join(tmpdir(), \"builderpack\")\n}\n","export type HttpError = {\n status: number\n bodyText: string\n}\n\ntype RequestOptions = {\n method: \"GET\" | \"POST\"\n url: string\n headers: Record<string, string>\n body?: string\n}\n\nconst requestJson = async <T>(\n opts: RequestOptions,\n maxRedirects: number = 3\n): Promise<T> => {\n let current = opts\n for (let i = 0; i <= maxRedirects; i++) {\n const res = await fetch(current.url, {\n method: current.method,\n headers: current.headers,\n body: current.body,\n redirect: \"manual\",\n })\n\n if (res.status >= 300 && res.status < 400) {\n const location = res.headers.get(\"location\")\n if (!location) {\n const bodyText = await res.text().catch(() => \"\")\n throw { status: res.status, bodyText } satisfies HttpError\n }\n const nextUrl = new URL(location, current.url).toString()\n current = { ...current, url: nextUrl }\n continue\n }\n\n if (!res.ok) {\n const bodyText = await res.text().catch(() => \"\")\n throw { status: res.status, bodyText } satisfies HttpError\n }\n\n return (await res.json()) as T\n }\n\n throw { status: 310, bodyText: \"Too many redirects\" } satisfies HttpError\n}\n\nexport const httpGetJson = async <T>(\n url: string,\n options?: { bearer?: string }\n): Promise<T> => {\n return requestJson<T>({\n method: \"GET\",\n url,\n headers: {\n ...(options?.bearer ? { Authorization: `Bearer ${options.bearer}` } : {}),\n },\n })\n}\n\nexport const httpPostJson = async <T>(\n url: string,\n body: unknown,\n options?: { bearer?: string }\n): Promise<T> => {\n return requestJson<T>({\n method: \"POST\",\n url,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(options?.bearer ? { Authorization: `Bearer ${options.bearer}` } : {}),\n },\n body: JSON.stringify(body),\n })\n}\n","export const die = (message: string, code: number = 1): never => {\n process.stderr.write(message + \"\\n\")\n process.exit(code)\n}\n\nexport const log = (message: string): void => {\n process.stdout.write(message + \"\\n\")\n}\n\nexport const warn = (message: string): void => {\n process.stderr.write(message + \"\\n\")\n}\n\n","import { spawnSync } from \"child_process\"\n\nexport const tryOpenUrl = (url: string): void => {\n try {\n if (process.platform === \"darwin\") {\n spawnSync(\"open\", [url], { stdio: \"ignore\" })\n return\n }\n\n if (process.platform === \"win32\") {\n spawnSync(\"cmd\", [\"/c\", \"start\", \"\", url], { stdio: \"ignore\" })\n return\n }\n\n spawnSync(\"xdg-open\", [url], { stdio: \"ignore\" })\n } catch {\n // ignore\n }\n}\n\n","import { getApiBase, requireAuth, saveAuth, clearAuth } from \"./config\"\nimport { httpGetJson, httpPostJson } from \"./http\"\nimport { die, log } from \"./print\"\nimport { tryOpenUrl } from \"./open\"\nimport { createInterface } from \"readline\"\n\nconst waitForEnter = async (): Promise<void> => {\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n return\n }\n\n await new Promise<void>((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout })\n rl.question(\"Press Enter to launch the browser...\", () => {\n rl.close()\n resolve()\n })\n })\n}\n\ntype DeviceStartResponse = {\n device_code: string\n user_code: string\n verification_uri: string\n verification_uri_complete?: string\n expires_in: number\n interval: number\n}\n\ntype DeviceTokenResponse = {\n access_token: string\n expires_in: number\n}\n\ntype MeResponse = {\n email: string\n entitlements: { claude: boolean; codex: boolean; adk: boolean; allInOne: boolean }\n}\n\nexport const commandLogin = async (): Promise<void> => {\n const apiBase = getApiBase()\n const start = await httpPostJson<DeviceStartResponse>(`${apiBase}/auth/device/start`, {})\n\n log(\"\")\n log(\"Builderpack CLI login\")\n log(\"\")\n log(`1) You will open: ${start.verification_uri}`)\n log(`2) Enter code: ${start.user_code}`)\n log(\"\")\n\n const urlToOpen = start.verification_uri_complete || start.verification_uri\n if (process.stdin.isTTY && process.stdout.isTTY) {\n log(\"Press Enter to open the browser automatically.\")\n log(\"Then enter the code above and confirm it matches.\")\n await waitForEnter()\n tryOpenUrl(urlToOpen)\n } else {\n // Non-interactive environment; don't auto-launch a browser.\n log(`Open this URL in a browser when ready: ${urlToOpen}`)\n log(\"Enter the code above and confirm it matches.\")\n }\n\n const deadline = Date.now() + start.expires_in * 1000\n while (Date.now() < deadline) {\n try {\n const token = await httpPostJson<DeviceTokenResponse>(`${apiBase}/auth/device/token`, {\n device_code: start.device_code,\n })\n\n saveAuth({ apiBase, accessToken: token.access_token })\n log(\"Logged in. You can now run: builderpack skills add ...\")\n return\n } catch (e: any) {\n const status = typeof e?.status === \"number\" ? e.status : 0\n if (status === 428) {\n await new Promise((r) => setTimeout(r, Math.max(1, start.interval) * 1000))\n continue\n }\n if (status === 410) {\n die(\"Login expired. Run: builderpack login\")\n }\n // Other error; keep retrying a couple times then bail\n await new Promise((r) => setTimeout(r, Math.max(1, start.interval) * 1000))\n continue\n }\n }\n\n die(\"Login expired. Run: builderpack login\")\n}\n\nexport const commandWhoami = async (): Promise<void> => {\n const auth = requireAuth()\n const me = await httpGetJson<MeResponse>(`${auth.apiBase}/me`, { bearer: auth.accessToken })\n log(JSON.stringify(me, null, 2))\n}\n\nexport const commandLogout = (): void => {\n clearAuth()\n log(\"Logged out.\")\n}\n","import { mkdtemp, writeFile, readdir } from \"fs/promises\"\nimport { existsSync, readFileSync } from \"fs\"\nimport { join } from \"path\"\nimport { tmpdir } from \"os\"\nimport AdmZip from \"adm-zip\"\nimport { requireAuth } from \"./config\"\nimport { fetchCatalog, type CatalogV1 } from \"./catalog\"\nimport { httpGetJson } from \"./http\"\nimport { die, log, warn } from \"./print\"\nimport { copyDir, createSymlink, ensureDir, fileExists, removePath } from \"./fsx\"\nimport { getCanonicalDir, getRepoRoot, getToolSkillsDir, isSafeChildPath } from \"./paths\"\nimport { extractSkillName } from \"./skill-md\"\nimport { resolveSelectedSkills } from \"./skills-select\"\n\ntype Variant = \"claude\" | \"codex\"\n\ntype SignedUrlResponse = {\n signedUrl: string\n expiresIn: number\n objectPath: string\n}\n\nexport const commandSkillsList = async (args: string[]): Promise<void> => {\n const theme = getFlagValue(args, \"--theme\")\n const verbose = hasFlag(args, \"--verbose\")\n const catalog = await fetchCatalog()\n\n const ids =\n theme && catalog.themes[theme]\n ? catalog.themes[theme]\n : catalog.skills.map((s) => s.id)\n\n if (verbose) {\n const themeInfo = theme ? theme : \"all\"\n log(`[verbose] theme: ${themeInfo}`)\n log(`[verbose] total skills: ${catalog.skills.length}`)\n log(`[verbose] selected count: ${ids.length}`)\n }\n\n for (const id of ids) {\n const skill = catalog.skills.find((s) => s.id === id)\n const variants = skill?.variants?.join(\",\") || \"\"\n log(`${id}${variants ? ` (${variants})` : \"\"}`)\n }\n}\n\nexport const commandSkillsAdd = async (args: string[]): Promise<void> => {\n const auth = requireAuth()\n\n const catalog = await fetchCatalog()\n\n const scope = hasFlag(args, \"--global\") ? \"global\" : \"project\"\n const mode = (getFlagValue(args, \"--mode\") || \"symlink\") as \"symlink\" | \"copy\"\n const strict = hasFlag(args, \"--strict\")\n const dryRun = hasFlag(args, \"--dry-run\")\n const verbose = hasFlag(args, \"--verbose\")\n\n const toolArg = getFlagValue(args, \"--tool\") || \"claude,codex\"\n const tools = toolArg\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean)\n\n const invalidTools = tools.filter((t) => t !== \"claude\" && t !== \"codex\")\n if (invalidTools.length > 0) {\n die(`Invalid --tool value(s): ${invalidTools.join(\", \")} (expected claude,codex)`)\n }\n\n const normalizedTools = tools as Variant[]\n\n const theme = getFlagValue(args, \"--theme\")\n const skillArgs = getMultiFlagValues(args, \"--skill\")\n const all = hasFlag(args, \"--all\")\n\n const selected = resolveSelectedSkills({ catalog, theme, skillArgs, all })\n if (selected.length === 0) {\n die(\"No skills selected. Use --theme <name>, --skill <id>, or --all\")\n }\n\n const repoRoot = scope === \"project\" ? getRepoRoot() : process.cwd()\n const canonicalBase = getCanonicalDir(scope, repoRoot)\n\n if (verbose) {\n log(`[verbose] api base: ${auth.apiBase}`)\n log(`[verbose] scope: ${scope}`)\n log(`[verbose] mode: ${mode}`)\n log(`[verbose] strict: ${strict}`)\n log(`[verbose] dry-run: ${dryRun}`)\n log(`[verbose] tools: ${normalizedTools.join(\",\")}`)\n log(`[verbose] theme: ${theme ?? \"none\"}`)\n log(`[verbose] skills: ${selected.join(\",\")}`)\n }\n\n if (scope === \"project\" && mode === \"symlink\") {\n const gitignorePath = join(repoRoot, \".gitignore\")\n if (existsSync(gitignorePath)) {\n try {\n const content = readFileSync(gitignorePath, \"utf8\")\n if (!content.includes(\".builderpack/\")) {\n warn(\"Note: consider adding `.builderpack/` to your repo .gitignore\")\n }\n } catch {\n // ignore\n }\n }\n }\n\n for (const skillId of selected) {\n const skill = catalog.skills.find((s) => s.id === skillId)\n if (!skill) {\n if (strict) die(`Unknown skill: ${skillId}`)\n warn(`Skipping unknown skill: ${skillId}`)\n continue\n }\n\n for (const tool of normalizedTools) {\n if (!skill.variants.includes(tool)) {\n const msg = `Skipping ${skillId} for ${tool}: variant not available`\n if (strict) die(msg)\n warn(msg)\n continue\n }\n\n if (dryRun) {\n log(`[dry-run] would install ${skillId} (${tool})`)\n continue\n }\n\n if (verbose) {\n log(`[verbose] request artifact: ${skillId} (${tool})`)\n }\n const signed = await httpGetJson<SignedUrlResponse>(\n `${auth.apiBase}/artifacts/skills/${encodeURIComponent(skillId)}/${encodeURIComponent(tool)}`,\n { bearer: auth.accessToken }\n )\n\n if (verbose) {\n log(`[verbose] signed url expires in: ${signed.expiresIn}s`)\n log(`[verbose] object path: ${signed.objectPath}`)\n }\n const extractedDir = await downloadAndExtractZip(signed.signedUrl)\n const resolvedSkillDir = await resolveExtractedSkillRoot(extractedDir)\n\n const skillMdPath = join(resolvedSkillDir, \"SKILL.md\")\n const skillName = (await fileExists(skillMdPath)) ? extractSkillName(skillMdPath) : null\n if (skillName !== skillId) {\n die(`Invalid payload for ${skillId}: SKILL.md name is ${skillName ?? \"missing\"}`)\n }\n\n const canonicalDir = join(canonicalBase, skillId)\n const toolBase = getToolSkillsDir(tool, scope, repoRoot)\n const toolDir = join(toolBase, skillId)\n\n if (!isSafeChildPath(canonicalBase, canonicalDir) || !isSafeChildPath(toolBase, toolDir)) {\n die(`Unsafe install path for skill: ${skillId}`)\n }\n\n if (verbose) {\n log(`[verbose] canonical dir: ${canonicalDir}`)\n log(`[verbose] tool dir: ${toolDir}`)\n }\n\n await ensureDir(canonicalBase)\n await ensureDir(toolBase)\n\n if (mode === \"copy\") {\n await removePath(toolDir)\n await copyDir(resolvedSkillDir, toolDir)\n log(`Installed ${skillId} (${tool}) -> ${toolDir}`)\n continue\n }\n\n await removePath(canonicalDir)\n await copyDir(resolvedSkillDir, canonicalDir)\n\n const symlinkOk = await createSymlink(canonicalDir, toolDir)\n if (!symlinkOk) {\n await removePath(toolDir)\n await copyDir(resolvedSkillDir, toolDir)\n warn(`Symlink failed; copied ${skillId} (${tool}) -> ${toolDir}`)\n } else {\n log(`Installed ${skillId} (${tool}) -> ${toolDir}`)\n }\n }\n }\n}\n\nconst hasFlag = (args: string[], flag: string): boolean => args.includes(flag)\n\nconst getFlagValue = (args: string[], flag: string): string | null => {\n const idx = args.indexOf(flag)\n if (idx === -1) return null\n const v = args[idx + 1]\n if (!v || v.startsWith(\"-\")) return null\n return v\n}\n\nconst getMultiFlagValues = (args: string[], flag: string): string[] => {\n const out: string[] = []\n for (let i = 0; i < args.length; i++) {\n if (args[i] === flag) {\n const v = args[i + 1]\n if (v && !v.startsWith(\"-\")) out.push(v)\n }\n }\n return out\n}\n\nconst downloadAndExtractZip = async (signedUrl: string): Promise<string> => {\n const res = await fetch(signedUrl)\n if (!res.ok) {\n die(`Failed to download artifact (HTTP ${res.status})`)\n }\n\n const tmpBase = await mkdtemp(join(tmpdir(), \"builderpack-\"))\n const zipPath = join(tmpBase, \"artifact.zip\")\n\n const buf = Buffer.from(await res.arrayBuffer())\n await writeFile(zipPath, buf)\n\n const zip = new AdmZip(zipPath)\n const outDir = join(tmpBase, \"out\")\n zip.extractAllTo(outDir, true)\n return outDir\n}\n\nconst resolveExtractedSkillRoot = async (dir: string): Promise<string> => {\n const direct = join(dir, \"SKILL.md\")\n if (await fileExists(direct)) return dir\n\n // Heuristic: if there is exactly one top-level directory and it contains SKILL.md, use it\n const entries = await readdir(dir, { withFileTypes: true })\n const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name)\n if (dirs.length === 1) {\n const nested = join(dir, dirs[0], \"SKILL.md\")\n if (await fileExists(nested)) return join(dir, dirs[0])\n }\n\n die(\"Invalid artifact zip: missing SKILL.md at root\")\n throw new Error(\"unreachable\")\n}\n","import { requireAuth } from \"./config\"\nimport { httpGetJson } from \"./http\"\n\nexport type CatalogV1 = {\n version: 1\n themes: Record<string, string[]>\n skills: Array<{ id: string; variants: Array<\"claude\" | \"codex\">; themes: string[] }>\n}\n\ntype CatalogResponse = { catalog: CatalogV1; entitlements: unknown }\n\nexport const fetchCatalog = async (): Promise<CatalogV1> => {\n const auth = requireAuth()\n\n const res = await httpGetJson<CatalogResponse>(`${auth.apiBase}/catalog`, { bearer: auth.accessToken })\n return res.catalog\n}\n","import { mkdir, rm, readdir, stat, copyFile, symlink, readlink } from \"fs/promises\"\nimport { dirname, join, relative, resolve } from \"path\"\n\nexport const ensureDir = async (path: string): Promise<void> => {\n await mkdir(path, { recursive: true })\n}\n\nexport const removePath = async (path: string): Promise<void> => {\n await rm(path, { recursive: true, force: true })\n}\n\nexport const copyDir = async (src: string, dest: string): Promise<void> => {\n await ensureDir(dest)\n const entries = await readdir(src, { withFileTypes: true })\n await Promise.all(\n entries.map(async (entry) => {\n const s = join(src, entry.name)\n const d = join(dest, entry.name)\n if (entry.isDirectory()) {\n await copyDir(s, d)\n return\n }\n if (entry.isFile()) {\n await ensureDir(dirname(d))\n await copyFile(s, d)\n }\n })\n )\n}\n\nexport const createSymlink = async (target: string, linkPath: string): Promise<boolean> => {\n try {\n const resolvedTarget = resolve(target)\n const resolvedLinkPath = resolve(linkPath)\n if (resolvedTarget === resolvedLinkPath) return true\n\n // if existing link already points correctly, keep it\n try {\n const existing = await readlink(linkPath)\n const resolvedExisting = resolve(dirname(linkPath), existing)\n if (resolvedExisting === resolvedTarget) return true\n } catch {\n // ignore\n }\n\n await removePath(linkPath)\n await ensureDir(dirname(linkPath))\n\n const rel = relative(dirname(linkPath), target)\n const type = process.platform === \"win32\" ? \"junction\" : undefined\n await symlink(rel, linkPath, type as any)\n return true\n } catch {\n return false\n }\n}\n\nexport const fileExists = async (path: string): Promise<boolean> => {\n try {\n const s = await stat(path)\n return s.isFile()\n } catch {\n return false\n }\n}\n\n","import { spawnSync } from \"child_process\"\nimport { homedir } from \"os\"\nimport { join, resolve } from \"path\"\n\nexport type InstallScope = \"project\" | \"global\"\nexport type ToolVariant = \"claude\" | \"codex\"\n\nexport const getRepoRoot = (): string => {\n const out = spawnSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], { encoding: \"utf8\" })\n if (out.status === 0 && out.stdout) {\n return out.stdout.trim()\n }\n return process.cwd()\n}\n\nexport const getCanonicalDir = (scope: InstallScope, repoRoot: string): string => {\n if (scope === \"global\") {\n return join(homedir(), \".builderpack\", \"store\", \"skills\")\n }\n return join(repoRoot, \".builderpack\", \"store\", \"skills\")\n}\n\nexport const getToolSkillsDir = (\n tool: ToolVariant,\n scope: InstallScope,\n repoRoot: string\n): string => {\n if (scope === \"project\") {\n if (tool === \"claude\") return join(repoRoot, \".claude\", \"skills\")\n return join(repoRoot, \".codex\", \"skills\")\n }\n\n if (tool === \"claude\") {\n const base = process.env.CLAUDE_CONFIG_DIR?.trim() || join(homedir(), \".claude\")\n return join(base, \"skills\")\n }\n\n const codexHome = process.env.CODEX_HOME?.trim() || join(homedir(), \".codex\")\n return join(codexHome, \"skills\")\n}\n\nexport const isSafeChildPath = (baseDir: string, childPath: string): boolean => {\n const base = resolve(baseDir)\n const target = resolve(childPath)\n return target === base || target.startsWith(base + \"/\") || target.startsWith(base + \"\\\\\")\n}\n\n","import { readFileSync } from \"fs\"\n\nexport const extractSkillName = (skillMdPath: string): string | null => {\n const content = readFileSync(skillMdPath, \"utf8\")\n const match = content.match(/^\\s*---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n/)\n if (!match) return null\n const fm = match[1]\n const nameMatch = fm.match(/^\\s*name\\s*:\\s*(.+?)\\s*$/m)\n if (!nameMatch) return null\n return nameMatch[1].trim().replace(/^[\"']|[\"']$/g, \"\")\n}\n\n","import { type CatalogV1 } from \"./catalog\"\nimport { die } from \"./print\"\n\nexport const resolveSelectedSkills = (opts: {\n catalog: CatalogV1\n theme: string | null\n skillArgs: string[]\n all: boolean\n}): string[] => {\n const { catalog, theme, skillArgs, all } = opts\n\n if (all) return catalog.skills.map((s) => s.id)\n\n if (theme) {\n const ids = catalog.themes[theme]\n if (!ids) die(`Unknown theme: ${theme}`)\n return ids\n }\n\n if (skillArgs.length > 0) {\n return skillArgs\n }\n\n return []\n}\n","import { commandLogin, commandLogout, commandWhoami } from \"./auth\"\nimport { commandSkillsAdd, commandSkillsList } from \"./skills\"\nimport { die, log } from \"./print\"\nimport { readFileSync } from \"fs\"\nimport { join, dirname } from \"path\"\nimport { fileURLToPath } from \"url\"\n\nconst showHelp = (): void => {\n log(`builderpack\n\nUsage:\n builderpack login\n builderpack whoami\n builderpack logout\n\n builderpack skills list [--theme <name>]\n builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run] [--verbose]\n`)\n}\n\nconst main = async (): Promise<void> => {\n const [, , ...argv] = process.argv\n const [cmd, sub, ...rest] = argv\n\n if (!cmd || cmd === \"--help\" || cmd === \"-h\") {\n showHelp()\n return\n }\n\n if (cmd === \"--version\" || cmd === \"-v\") {\n try {\n const here = dirname(fileURLToPath(import.meta.url))\n const pkgPath = join(here, \"..\", \"package.json\")\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { version?: string }\n log(pkg.version || \"0.0.0\")\n } catch {\n log(\"0.0.0\")\n }\n return\n }\n\n if (cmd === \"login\") {\n await commandLogin()\n return\n }\n if (cmd === \"whoami\") {\n await commandWhoami()\n return\n }\n if (cmd === \"logout\") {\n commandLogout()\n return\n }\n\n if (cmd === \"skills\") {\n if (!sub || sub === \"--help\" || sub === \"-h\") {\n log(`builderpack skills\n\nUsage:\n builderpack skills list [--theme <name>]\n builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run] [--verbose]\n`)\n return\n }\n\n if (sub === \"list\") {\n await commandSkillsList(rest)\n return\n }\n\n if (sub === \"add\") {\n await commandSkillsAdd(rest)\n return\n }\n\n die(`Unknown skills command: ${sub}`)\n }\n\n die(`Unknown command: ${cmd}`)\n}\n\nmain().catch((err) => {\n // eslint-disable-next-line no-console\n console.error(err)\n process.exitCode = 1\n})\n"],"mappings":"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","names":["resolve","readdir","existsSync","readFileSync","join","tmpdir","join","spawnSync","homedir","join","resolve","readFileSync","join","existsSync","readFileSync","tmpdir","readdir","readFileSync","join","dirname"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builderpackai/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Builderpack CLI (skills installer)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"package:skills": "node --import tsx scripts/package-skills.ts",
|
|
19
19
|
"upload:catalog": "supabase --experimental --workdir web storage cp ../catalog/v1.json ss:///builderpack-cli/catalog/v1.json",
|
|
20
20
|
"release": "node scripts/release.js",
|
|
21
|
-
"type-check": "tsc --noEmit"
|
|
21
|
+
"type-check": "tsc --noEmit",
|
|
22
|
+
"test": "node --import tsx --test tests/**/*.test.ts"
|
|
22
23
|
},
|
|
23
24
|
"dependencies": {
|
|
24
25
|
"adm-zip": "^0.5.16"
|