@builderpackai/cli 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 ADDED
@@ -0,0 +1,77 @@
1
+ # Builderpack CLI
2
+
3
+ Install and manage Builderpack skills for Claude Code and Codex. Package: `@builderpackai/cli`.
4
+
5
+ ## Install
6
+
7
+ Run without installing globally:
8
+
9
+ ```
10
+ npx --yes --package @builderpackai/cli builderpack login
11
+ ```
12
+
13
+ Or install globally:
14
+
15
+ ```
16
+ npm i -g @builderpackai/cli
17
+ builderpack login
18
+ ```
19
+
20
+ ## Login
21
+
22
+ ```
23
+ builderpack login
24
+ ```
25
+
26
+ Then open the device page and enter the code:
27
+
28
+ ```
29
+ https://builderpack.ai/device
30
+ ```
31
+
32
+ ## List skills
33
+
34
+ ```
35
+ builderpack skills list
36
+ builderpack skills list --theme gamedev
37
+ ```
38
+
39
+ ## Install skills
40
+
41
+ Install all skills in a theme:
42
+
43
+ ```
44
+ builderpack skills add --theme gamedev --tool claude
45
+ builderpack skills add --theme gamedev --tool codex
46
+ ```
47
+
48
+ Install specific skills:
49
+
50
+ ```
51
+ builderpack skills add --skill og-image-creator --skill seo-optimizer --tool claude
52
+ ```
53
+
54
+ Install everything:
55
+
56
+ ```
57
+ builderpack skills add --all --tool claude,codex
58
+ ```
59
+
60
+ ## Global vs project install
61
+
62
+ Default is project-local (puts files in `.claude/skills` or `.codex/skills` in your repo).
63
+
64
+ Use `--global` to install to your home config:
65
+
66
+ ```
67
+ builderpack skills add --theme gamedev --tool claude --global
68
+ ```
69
+
70
+ ## Troubleshooting
71
+
72
+ ```
73
+ builderpack whoami
74
+ builderpack logout
75
+ ```
76
+
77
+ Need help? Contact Builderpack support at builderpack.ai.
package/bin/cli.mjs ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import("../dist/cli.js").catch((err) => {
3
+ // eslint-disable-next-line no-console
4
+ console.error(err)
5
+ process.exitCode = 1
6
+ })
7
+
package/dist/cli.js ADDED
@@ -0,0 +1,512 @@
1
+ // src/config.ts
2
+ import { homedir, tmpdir } from "os";
3
+ import { join } from "path";
4
+ import { mkdirSync, readFileSync, writeFileSync, existsSync, rmSync } from "fs";
5
+ var getApiBase = () => {
6
+ return (process.env.BUILDERPACK_API_BASE?.trim() || "https://builderpack.ai/api/cli/v1").replace(
7
+ /\/$/,
8
+ ""
9
+ );
10
+ };
11
+ var getConfigDir = () => {
12
+ const xdg = process.env.XDG_CONFIG_HOME?.trim();
13
+ if (xdg) return join(xdg, "builderpack");
14
+ if (process.platform === "win32") {
15
+ const appData = process.env.APPDATA?.trim();
16
+ if (appData) return join(appData, "builderpack");
17
+ }
18
+ return join(homedir(), ".config", "builderpack");
19
+ };
20
+ var getAuthPath = () => {
21
+ return join(getConfigDir(), "auth.json");
22
+ };
23
+ var loadAuth = () => {
24
+ const p = getAuthPath();
25
+ if (!existsSync(p)) return null;
26
+ try {
27
+ const parsed = JSON.parse(readFileSync(p, "utf8"));
28
+ if (!parsed?.accessToken || !parsed?.apiBase) return null;
29
+ return { apiBase: parsed.apiBase, accessToken: parsed.accessToken };
30
+ } catch {
31
+ return null;
32
+ }
33
+ };
34
+ var requireAuth = () => {
35
+ const auth = loadAuth();
36
+ if (!auth) {
37
+ throw new Error("Not logged in. Run: builderpack login");
38
+ }
39
+ return auth;
40
+ };
41
+ var saveAuth = (auth) => {
42
+ const dir = getConfigDir();
43
+ mkdirSync(dir, { recursive: true });
44
+ writeFileSync(getAuthPath(), JSON.stringify(auth, null, 2), "utf8");
45
+ };
46
+ var clearAuth = () => {
47
+ const p = getAuthPath();
48
+ try {
49
+ rmSync(p);
50
+ } catch {
51
+ }
52
+ };
53
+
54
+ // src/http.ts
55
+ var httpGetJson = async (url, options) => {
56
+ const res = await fetch(url, {
57
+ method: "GET",
58
+ headers: {
59
+ ...options?.bearer ? { Authorization: `Bearer ${options.bearer}` } : {}
60
+ }
61
+ });
62
+ if (!res.ok) {
63
+ const bodyText = await res.text().catch(() => "");
64
+ throw { status: res.status, bodyText };
65
+ }
66
+ return await res.json();
67
+ };
68
+ var httpPostJson = async (url, body, options) => {
69
+ const res = await fetch(url, {
70
+ method: "POST",
71
+ headers: {
72
+ "Content-Type": "application/json",
73
+ ...options?.bearer ? { Authorization: `Bearer ${options.bearer}` } : {}
74
+ },
75
+ body: JSON.stringify(body)
76
+ });
77
+ if (!res.ok) {
78
+ const bodyText = await res.text().catch(() => "");
79
+ throw { status: res.status, bodyText };
80
+ }
81
+ return await res.json();
82
+ };
83
+
84
+ // src/print.ts
85
+ var die = (message, code = 1) => {
86
+ process.stderr.write(message + "\n");
87
+ process.exit(code);
88
+ };
89
+ var log = (message) => {
90
+ process.stdout.write(message + "\n");
91
+ };
92
+ var warn = (message) => {
93
+ process.stderr.write(message + "\n");
94
+ };
95
+
96
+ // src/open.ts
97
+ import { spawnSync } from "child_process";
98
+ var tryOpenUrl = (url) => {
99
+ try {
100
+ if (process.platform === "darwin") {
101
+ spawnSync("open", [url], { stdio: "ignore" });
102
+ return;
103
+ }
104
+ if (process.platform === "win32") {
105
+ spawnSync("cmd", ["/c", "start", "", url], { stdio: "ignore" });
106
+ return;
107
+ }
108
+ spawnSync("xdg-open", [url], { stdio: "ignore" });
109
+ } catch {
110
+ }
111
+ };
112
+
113
+ // src/auth.ts
114
+ var commandLogin = async () => {
115
+ const apiBase = getApiBase();
116
+ const start = await httpPostJson(`${apiBase}/auth/device/start`, {});
117
+ log("");
118
+ log("Builderpack CLI login");
119
+ log("");
120
+ log(`1) Open: ${start.verification_uri}`);
121
+ log(`2) Enter code: ${start.user_code}`);
122
+ log("");
123
+ if (start.verification_uri_complete) {
124
+ tryOpenUrl(start.verification_uri_complete);
125
+ } else {
126
+ tryOpenUrl(start.verification_uri);
127
+ }
128
+ const deadline = Date.now() + start.expires_in * 1e3;
129
+ while (Date.now() < deadline) {
130
+ try {
131
+ const token = await httpPostJson(`${apiBase}/auth/device/token`, {
132
+ device_code: start.device_code
133
+ });
134
+ saveAuth({ apiBase, accessToken: token.access_token });
135
+ log("Logged in. You can now run: builderpack skills add ...");
136
+ return;
137
+ } catch (e) {
138
+ const status = typeof e?.status === "number" ? e.status : 0;
139
+ if (status === 428) {
140
+ await new Promise((r) => setTimeout(r, Math.max(1, start.interval) * 1e3));
141
+ continue;
142
+ }
143
+ if (status === 410) {
144
+ die("Login expired. Run: builderpack login");
145
+ }
146
+ await new Promise((r) => setTimeout(r, Math.max(1, start.interval) * 1e3));
147
+ continue;
148
+ }
149
+ }
150
+ die("Login expired. Run: builderpack login");
151
+ };
152
+ var commandWhoami = async () => {
153
+ const auth = requireAuth();
154
+ const me = await httpGetJson(`${auth.apiBase}/me`, { bearer: auth.accessToken });
155
+ log(JSON.stringify(me, null, 2));
156
+ };
157
+ var commandLogout = () => {
158
+ clearAuth();
159
+ log("Logged out.");
160
+ };
161
+
162
+ // src/skills.ts
163
+ import { mkdtemp, writeFile, readdir as readdir2 } from "fs/promises";
164
+ import { existsSync as existsSync2, readFileSync as readFileSync3 } from "fs";
165
+ import { join as join4 } from "path";
166
+ import { tmpdir as tmpdir2 } from "os";
167
+ import AdmZip from "adm-zip";
168
+
169
+ // src/catalog.ts
170
+ var fetchCatalog = async () => {
171
+ const auth = requireAuth();
172
+ const res = await httpGetJson(`${auth.apiBase}/catalog`, { bearer: auth.accessToken });
173
+ return res.catalog;
174
+ };
175
+
176
+ // src/fsx.ts
177
+ import { mkdir, rm, readdir, stat, copyFile, symlink, readlink } from "fs/promises";
178
+ import { dirname, join as join2, relative, resolve } from "path";
179
+ var ensureDir = async (path) => {
180
+ await mkdir(path, { recursive: true });
181
+ };
182
+ var removePath = async (path) => {
183
+ await rm(path, { recursive: true, force: true });
184
+ };
185
+ var copyDir = async (src, dest) => {
186
+ await ensureDir(dest);
187
+ const entries = await readdir(src, { withFileTypes: true });
188
+ await Promise.all(
189
+ entries.map(async (entry) => {
190
+ const s = join2(src, entry.name);
191
+ const d = join2(dest, entry.name);
192
+ if (entry.isDirectory()) {
193
+ await copyDir(s, d);
194
+ return;
195
+ }
196
+ if (entry.isFile()) {
197
+ await ensureDir(dirname(d));
198
+ await copyFile(s, d);
199
+ }
200
+ })
201
+ );
202
+ };
203
+ var createSymlink = async (target, linkPath) => {
204
+ try {
205
+ const resolvedTarget = resolve(target);
206
+ const resolvedLinkPath = resolve(linkPath);
207
+ if (resolvedTarget === resolvedLinkPath) return true;
208
+ try {
209
+ const existing = await readlink(linkPath);
210
+ const resolvedExisting = resolve(dirname(linkPath), existing);
211
+ if (resolvedExisting === resolvedTarget) return true;
212
+ } catch {
213
+ }
214
+ await removePath(linkPath);
215
+ await ensureDir(dirname(linkPath));
216
+ const rel = relative(dirname(linkPath), target);
217
+ const type = process.platform === "win32" ? "junction" : void 0;
218
+ await symlink(rel, linkPath, type);
219
+ return true;
220
+ } catch {
221
+ return false;
222
+ }
223
+ };
224
+ var fileExists = async (path) => {
225
+ try {
226
+ const s = await stat(path);
227
+ return s.isFile();
228
+ } catch {
229
+ return false;
230
+ }
231
+ };
232
+
233
+ // src/paths.ts
234
+ import { spawnSync as spawnSync2 } from "child_process";
235
+ import { homedir as homedir2 } from "os";
236
+ import { join as join3, resolve as resolve2 } from "path";
237
+ var getRepoRoot = () => {
238
+ const out = spawnSync2("git", ["rev-parse", "--show-toplevel"], { encoding: "utf8" });
239
+ if (out.status === 0 && out.stdout) {
240
+ return out.stdout.trim();
241
+ }
242
+ return process.cwd();
243
+ };
244
+ var getCanonicalDir = (scope, repoRoot) => {
245
+ if (scope === "global") {
246
+ return join3(homedir2(), ".builderpack", "store", "skills");
247
+ }
248
+ return join3(repoRoot, ".builderpack", "store", "skills");
249
+ };
250
+ var getToolSkillsDir = (tool, scope, repoRoot) => {
251
+ if (scope === "project") {
252
+ if (tool === "claude") return join3(repoRoot, ".claude", "skills");
253
+ return join3(repoRoot, ".codex", "skills");
254
+ }
255
+ if (tool === "claude") {
256
+ const base = process.env.CLAUDE_CONFIG_DIR?.trim() || join3(homedir2(), ".claude");
257
+ return join3(base, "skills");
258
+ }
259
+ const codexHome = process.env.CODEX_HOME?.trim() || join3(homedir2(), ".codex");
260
+ return join3(codexHome, "skills");
261
+ };
262
+ var isSafeChildPath = (baseDir, childPath) => {
263
+ const base = resolve2(baseDir);
264
+ const target = resolve2(childPath);
265
+ return target === base || target.startsWith(base + "/") || target.startsWith(base + "\\");
266
+ };
267
+
268
+ // src/skill-md.ts
269
+ import { readFileSync as readFileSync2 } from "fs";
270
+ var extractSkillName = (skillMdPath) => {
271
+ const content = readFileSync2(skillMdPath, "utf8");
272
+ const match = content.match(/^\s*---\s*\n([\s\S]*?)\n---\s*\n/);
273
+ if (!match) return null;
274
+ const fm = match[1];
275
+ const nameMatch = fm.match(/^\s*name\s*:\s*(.+?)\s*$/m);
276
+ if (!nameMatch) return null;
277
+ return nameMatch[1].trim().replace(/^["']|["']$/g, "");
278
+ };
279
+
280
+ // src/skills.ts
281
+ var commandSkillsList = async (args) => {
282
+ const theme = getFlagValue(args, "--theme");
283
+ const catalog = await fetchCatalog();
284
+ const ids = theme && catalog.themes[theme] ? catalog.themes[theme] : catalog.skills.map((s) => s.id);
285
+ for (const id of ids) {
286
+ const skill = catalog.skills.find((s) => s.id === id);
287
+ const variants = skill?.variants?.join(",") || "";
288
+ log(`${id}${variants ? ` (${variants})` : ""}`);
289
+ }
290
+ };
291
+ var commandSkillsAdd = async (args) => {
292
+ const auth = requireAuth();
293
+ const catalog = await fetchCatalog();
294
+ const scope = hasFlag(args, "--global") ? "global" : "project";
295
+ const mode = getFlagValue(args, "--mode") || "symlink";
296
+ const strict = hasFlag(args, "--strict");
297
+ const dryRun = hasFlag(args, "--dry-run");
298
+ const toolArg = getFlagValue(args, "--tool") || "claude,codex";
299
+ const tools = toolArg.split(",").map((t) => t.trim()).filter(Boolean);
300
+ const invalidTools = tools.filter((t) => t !== "claude" && t !== "codex");
301
+ if (invalidTools.length > 0) {
302
+ die(`Invalid --tool value(s): ${invalidTools.join(", ")} (expected claude,codex)`);
303
+ }
304
+ const normalizedTools = tools;
305
+ const theme = getFlagValue(args, "--theme");
306
+ const skillArgs = getMultiFlagValues(args, "--skill");
307
+ const all = hasFlag(args, "--all");
308
+ const selected = resolveSelectedSkills({ catalog, theme, skillArgs, all });
309
+ if (selected.length === 0) {
310
+ die("No skills selected. Use --theme <name>, --skill <id>, or --all");
311
+ }
312
+ const repoRoot = scope === "project" ? getRepoRoot() : process.cwd();
313
+ const canonicalBase = getCanonicalDir(scope, repoRoot);
314
+ if (scope === "project" && mode === "symlink") {
315
+ const gitignorePath = join4(repoRoot, ".gitignore");
316
+ if (existsSync2(gitignorePath)) {
317
+ try {
318
+ const content = readFileSync3(gitignorePath, "utf8");
319
+ if (!content.includes(".builderpack/")) {
320
+ warn("Note: consider adding `.builderpack/` to your repo .gitignore");
321
+ }
322
+ } catch {
323
+ }
324
+ }
325
+ }
326
+ for (const skillId of selected) {
327
+ const skill = catalog.skills.find((s) => s.id === skillId);
328
+ if (!skill) {
329
+ if (strict) die(`Unknown skill: ${skillId}`);
330
+ warn(`Skipping unknown skill: ${skillId}`);
331
+ continue;
332
+ }
333
+ for (const tool of normalizedTools) {
334
+ if (!skill.variants.includes(tool)) {
335
+ const msg = `Skipping ${skillId} for ${tool}: variant not available`;
336
+ if (strict) die(msg);
337
+ warn(msg);
338
+ continue;
339
+ }
340
+ if (dryRun) {
341
+ log(`[dry-run] would install ${skillId} (${tool})`);
342
+ continue;
343
+ }
344
+ const signed = await httpGetJson(
345
+ `${auth.apiBase}/artifacts/skills/${encodeURIComponent(skillId)}/${encodeURIComponent(tool)}`,
346
+ { bearer: auth.accessToken }
347
+ );
348
+ const extractedDir = await downloadAndExtractZip(signed.signedUrl);
349
+ const resolvedSkillDir = await resolveExtractedSkillRoot(extractedDir);
350
+ const skillMdPath = join4(resolvedSkillDir, "SKILL.md");
351
+ const skillName = await fileExists(skillMdPath) ? extractSkillName(skillMdPath) : null;
352
+ if (skillName !== skillId) {
353
+ die(`Invalid payload for ${skillId}: SKILL.md name is ${skillName ?? "missing"}`);
354
+ }
355
+ const canonicalDir = join4(canonicalBase, skillId);
356
+ const toolBase = getToolSkillsDir(tool, scope, repoRoot);
357
+ const toolDir = join4(toolBase, skillId);
358
+ if (!isSafeChildPath(canonicalBase, canonicalDir) || !isSafeChildPath(toolBase, toolDir)) {
359
+ die(`Unsafe install path for skill: ${skillId}`);
360
+ }
361
+ await ensureDir(canonicalBase);
362
+ await ensureDir(toolBase);
363
+ if (mode === "copy") {
364
+ await removePath(toolDir);
365
+ await copyDir(resolvedSkillDir, toolDir);
366
+ log(`Installed ${skillId} (${tool}) -> ${toolDir}`);
367
+ continue;
368
+ }
369
+ await removePath(canonicalDir);
370
+ await copyDir(resolvedSkillDir, canonicalDir);
371
+ const symlinkOk = await createSymlink(canonicalDir, toolDir);
372
+ if (!symlinkOk) {
373
+ await removePath(toolDir);
374
+ await copyDir(resolvedSkillDir, toolDir);
375
+ warn(`Symlink failed; copied ${skillId} (${tool}) -> ${toolDir}`);
376
+ } else {
377
+ log(`Installed ${skillId} (${tool}) -> ${toolDir}`);
378
+ }
379
+ }
380
+ }
381
+ };
382
+ var hasFlag = (args, flag) => args.includes(flag);
383
+ var getFlagValue = (args, flag) => {
384
+ const idx = args.indexOf(flag);
385
+ if (idx === -1) return null;
386
+ const v = args[idx + 1];
387
+ if (!v || v.startsWith("-")) return null;
388
+ return v;
389
+ };
390
+ var getMultiFlagValues = (args, flag) => {
391
+ const out = [];
392
+ for (let i = 0; i < args.length; i++) {
393
+ if (args[i] === flag) {
394
+ const v = args[i + 1];
395
+ if (v && !v.startsWith("-")) out.push(v);
396
+ }
397
+ }
398
+ return out;
399
+ };
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
+ var downloadAndExtractZip = async (signedUrl) => {
414
+ const res = await fetch(signedUrl);
415
+ if (!res.ok) {
416
+ die(`Failed to download artifact (HTTP ${res.status})`);
417
+ }
418
+ const tmpBase = await mkdtemp(join4(tmpdir2(), "builderpack-"));
419
+ const zipPath = join4(tmpBase, "artifact.zip");
420
+ const buf = Buffer.from(await res.arrayBuffer());
421
+ await writeFile(zipPath, buf);
422
+ const zip = new AdmZip(zipPath);
423
+ const outDir = join4(tmpBase, "out");
424
+ zip.extractAllTo(outDir, true);
425
+ return outDir;
426
+ };
427
+ var resolveExtractedSkillRoot = async (dir) => {
428
+ const direct = join4(dir, "SKILL.md");
429
+ if (await fileExists(direct)) return dir;
430
+ const entries = await readdir2(dir, { withFileTypes: true });
431
+ const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
432
+ if (dirs.length === 1) {
433
+ const nested = join4(dir, dirs[0], "SKILL.md");
434
+ if (await fileExists(nested)) return join4(dir, dirs[0]);
435
+ }
436
+ die("Invalid artifact zip: missing SKILL.md at root");
437
+ throw new Error("unreachable");
438
+ };
439
+
440
+ // src/cli.ts
441
+ import { readFileSync as readFileSync4 } from "fs";
442
+ import { join as join5, dirname as dirname2 } from "path";
443
+ import { fileURLToPath } from "url";
444
+ var showHelp = () => {
445
+ log(`builderpack
446
+
447
+ Usage:
448
+ builderpack login
449
+ builderpack whoami
450
+ builderpack logout
451
+
452
+ builderpack skills list [--theme <name>]
453
+ builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run]
454
+ `);
455
+ };
456
+ var main = async () => {
457
+ const [, , ...argv] = process.argv;
458
+ const [cmd, sub, ...rest] = argv;
459
+ if (!cmd || cmd === "--help" || cmd === "-h") {
460
+ showHelp();
461
+ return;
462
+ }
463
+ if (cmd === "--version" || cmd === "-v") {
464
+ try {
465
+ const here = dirname2(fileURLToPath(import.meta.url));
466
+ const pkgPath = join5(here, "..", "package.json");
467
+ const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
468
+ log(pkg.version || "0.0.0");
469
+ } catch {
470
+ log("0.0.0");
471
+ }
472
+ return;
473
+ }
474
+ if (cmd === "login") {
475
+ await commandLogin();
476
+ return;
477
+ }
478
+ if (cmd === "whoami") {
479
+ await commandWhoami();
480
+ return;
481
+ }
482
+ if (cmd === "logout") {
483
+ commandLogout();
484
+ return;
485
+ }
486
+ if (cmd === "skills") {
487
+ if (!sub || sub === "--help" || sub === "-h") {
488
+ log(`builderpack skills
489
+
490
+ Usage:
491
+ builderpack skills list [--theme <name>]
492
+ builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run]
493
+ `);
494
+ return;
495
+ }
496
+ if (sub === "list") {
497
+ await commandSkillsList(rest);
498
+ return;
499
+ }
500
+ if (sub === "add") {
501
+ await commandSkillsAdd(rest);
502
+ return;
503
+ }
504
+ die(`Unknown skills command: ${sub}`);
505
+ }
506
+ die(`Unknown command: ${cmd}`);
507
+ };
508
+ main().catch((err) => {
509
+ console.error(err);
510
+ process.exitCode = 1;
511
+ });
512
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +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"]}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@builderpackai/cli",
3
+ "version": "0.1.3",
4
+ "description": "Builderpack CLI (skills installer)",
5
+ "type": "module",
6
+ "bin": {
7
+ "builderpack": "./bin/cli.mjs",
8
+ "bp": "./bin/cli.mjs"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "bin",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsup src/cli.ts --format esm --target node18 --sourcemap --out-dir dist",
17
+ "dev": "node --import tsx src/cli.ts",
18
+ "package:skills": "node --import tsx scripts/package-skills.ts",
19
+ "upload:catalog": "supabase --experimental --workdir web storage cp ../catalog/v1.json ss:///builderpack-cli/catalog/v1.json",
20
+ "release": "node scripts/release.js",
21
+ "type-check": "tsc --noEmit"
22
+ },
23
+ "dependencies": {
24
+ "adm-zip": "^0.5.16"
25
+ },
26
+ "devDependencies": {
27
+ "@types/adm-zip": "^0.5.7",
28
+ "@types/node": "^22.13.1",
29
+ "tsup": "^8.0.2",
30
+ "tsx": "^4.19.2",
31
+ "typescript": "^5.5.3"
32
+ },
33
+ "engines": {
34
+ "node": ">=18"
35
+ }
36
+ }