@builderpackai/cli 0.1.5 → 0.1.11

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/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
- const res = await fetch(url, {
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
- const res = await fetch(url, {
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) Open: ${start.verification_uri}`);
152
+ log(`1) You will open: ${start.verification_uri}`);
121
153
  log(`2) Enter code: ${start.user_code}`);
122
154
  log("");
123
- if (start.verification_uri_complete) {
124
- tryOpenUrl(start.verification_uri_complete);
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
- tryOpenUrl(start.verification_uri);
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) {
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/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"]}
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.5",
3
+ "version": "0.1.11",
4
4
  "description": "Builderpack CLI (skills installer)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,6 +22,7 @@
22
22
  "test": "node --import tsx --test tests/**/*.test.ts"
23
23
  },
24
24
  "dependencies": {
25
+ "@builderpackai/cli": "^0.1.6",
25
26
  "adm-zip": "^0.5.16"
26
27
  },
27
28
  "devDependencies": {