@builderpackai/cli 0.1.3 → 0.1.5
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 +46 -15
- 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
|
@@ -277,11 +277,33 @@ var extractSkillName = (skillMdPath) => {
|
|
|
277
277
|
return nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
278
278
|
};
|
|
279
279
|
|
|
280
|
+
// src/skills-select.ts
|
|
281
|
+
var resolveSelectedSkills = (opts) => {
|
|
282
|
+
const { catalog, theme, skillArgs, all } = opts;
|
|
283
|
+
if (all) return catalog.skills.map((s) => s.id);
|
|
284
|
+
if (theme) {
|
|
285
|
+
const ids = catalog.themes[theme];
|
|
286
|
+
if (!ids) die(`Unknown theme: ${theme}`);
|
|
287
|
+
return ids;
|
|
288
|
+
}
|
|
289
|
+
if (skillArgs.length > 0) {
|
|
290
|
+
return skillArgs;
|
|
291
|
+
}
|
|
292
|
+
return [];
|
|
293
|
+
};
|
|
294
|
+
|
|
280
295
|
// src/skills.ts
|
|
281
296
|
var commandSkillsList = async (args) => {
|
|
282
297
|
const theme = getFlagValue(args, "--theme");
|
|
298
|
+
const verbose = hasFlag(args, "--verbose");
|
|
283
299
|
const catalog = await fetchCatalog();
|
|
284
300
|
const ids = theme && catalog.themes[theme] ? catalog.themes[theme] : catalog.skills.map((s) => s.id);
|
|
301
|
+
if (verbose) {
|
|
302
|
+
const themeInfo = theme ? theme : "all";
|
|
303
|
+
log(`[verbose] theme: ${themeInfo}`);
|
|
304
|
+
log(`[verbose] total skills: ${catalog.skills.length}`);
|
|
305
|
+
log(`[verbose] selected count: ${ids.length}`);
|
|
306
|
+
}
|
|
285
307
|
for (const id of ids) {
|
|
286
308
|
const skill = catalog.skills.find((s) => s.id === id);
|
|
287
309
|
const variants = skill?.variants?.join(",") || "";
|
|
@@ -295,6 +317,7 @@ var commandSkillsAdd = async (args) => {
|
|
|
295
317
|
const mode = getFlagValue(args, "--mode") || "symlink";
|
|
296
318
|
const strict = hasFlag(args, "--strict");
|
|
297
319
|
const dryRun = hasFlag(args, "--dry-run");
|
|
320
|
+
const verbose = hasFlag(args, "--verbose");
|
|
298
321
|
const toolArg = getFlagValue(args, "--tool") || "claude,codex";
|
|
299
322
|
const tools = toolArg.split(",").map((t) => t.trim()).filter(Boolean);
|
|
300
323
|
const invalidTools = tools.filter((t) => t !== "claude" && t !== "codex");
|
|
@@ -311,6 +334,16 @@ var commandSkillsAdd = async (args) => {
|
|
|
311
334
|
}
|
|
312
335
|
const repoRoot = scope === "project" ? getRepoRoot() : process.cwd();
|
|
313
336
|
const canonicalBase = getCanonicalDir(scope, repoRoot);
|
|
337
|
+
if (verbose) {
|
|
338
|
+
log(`[verbose] api base: ${auth.apiBase}`);
|
|
339
|
+
log(`[verbose] scope: ${scope}`);
|
|
340
|
+
log(`[verbose] mode: ${mode}`);
|
|
341
|
+
log(`[verbose] strict: ${strict}`);
|
|
342
|
+
log(`[verbose] dry-run: ${dryRun}`);
|
|
343
|
+
log(`[verbose] tools: ${normalizedTools.join(",")}`);
|
|
344
|
+
log(`[verbose] theme: ${theme ?? "none"}`);
|
|
345
|
+
log(`[verbose] skills: ${selected.join(",")}`);
|
|
346
|
+
}
|
|
314
347
|
if (scope === "project" && mode === "symlink") {
|
|
315
348
|
const gitignorePath = join4(repoRoot, ".gitignore");
|
|
316
349
|
if (existsSync2(gitignorePath)) {
|
|
@@ -341,10 +374,17 @@ var commandSkillsAdd = async (args) => {
|
|
|
341
374
|
log(`[dry-run] would install ${skillId} (${tool})`);
|
|
342
375
|
continue;
|
|
343
376
|
}
|
|
377
|
+
if (verbose) {
|
|
378
|
+
log(`[verbose] request artifact: ${skillId} (${tool})`);
|
|
379
|
+
}
|
|
344
380
|
const signed = await httpGetJson(
|
|
345
381
|
`${auth.apiBase}/artifacts/skills/${encodeURIComponent(skillId)}/${encodeURIComponent(tool)}`,
|
|
346
382
|
{ bearer: auth.accessToken }
|
|
347
383
|
);
|
|
384
|
+
if (verbose) {
|
|
385
|
+
log(`[verbose] signed url expires in: ${signed.expiresIn}s`);
|
|
386
|
+
log(`[verbose] object path: ${signed.objectPath}`);
|
|
387
|
+
}
|
|
348
388
|
const extractedDir = await downloadAndExtractZip(signed.signedUrl);
|
|
349
389
|
const resolvedSkillDir = await resolveExtractedSkillRoot(extractedDir);
|
|
350
390
|
const skillMdPath = join4(resolvedSkillDir, "SKILL.md");
|
|
@@ -358,6 +398,10 @@ var commandSkillsAdd = async (args) => {
|
|
|
358
398
|
if (!isSafeChildPath(canonicalBase, canonicalDir) || !isSafeChildPath(toolBase, toolDir)) {
|
|
359
399
|
die(`Unsafe install path for skill: ${skillId}`);
|
|
360
400
|
}
|
|
401
|
+
if (verbose) {
|
|
402
|
+
log(`[verbose] canonical dir: ${canonicalDir}`);
|
|
403
|
+
log(`[verbose] tool dir: ${toolDir}`);
|
|
404
|
+
}
|
|
361
405
|
await ensureDir(canonicalBase);
|
|
362
406
|
await ensureDir(toolBase);
|
|
363
407
|
if (mode === "copy") {
|
|
@@ -397,19 +441,6 @@ var getMultiFlagValues = (args, flag) => {
|
|
|
397
441
|
}
|
|
398
442
|
return out;
|
|
399
443
|
};
|
|
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
444
|
var downloadAndExtractZip = async (signedUrl) => {
|
|
414
445
|
const res = await fetch(signedUrl);
|
|
415
446
|
if (!res.ok) {
|
|
@@ -450,7 +481,7 @@ Usage:
|
|
|
450
481
|
builderpack logout
|
|
451
482
|
|
|
452
483
|
builderpack skills list [--theme <name>]
|
|
453
|
-
builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run]
|
|
484
|
+
builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run] [--verbose]
|
|
454
485
|
`);
|
|
455
486
|
};
|
|
456
487
|
var main = async () => {
|
|
@@ -489,7 +520,7 @@ var main = async () => {
|
|
|
489
520
|
|
|
490
521
|
Usage:
|
|
491
522
|
builderpack skills list [--theme <name>]
|
|
492
|
-
builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run]
|
|
523
|
+
builderpack skills add (--theme <name> | --skill <id>... | --all) [--tool claude,codex] [--global] [--mode symlink|copy] [--strict] [--dry-run] [--verbose]
|
|
493
524
|
`);
|
|
494
525
|
return;
|
|
495
526
|
}
|
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://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\"\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":["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.5",
|
|
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"
|