clabox 0.2.1 → 0.3.0

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.
Files changed (54) hide show
  1. package/README.md +0 -1
  2. package/clabox.config.example.mjs +10 -4
  3. package/docs/guideline.md +25 -16
  4. package/lib/{app-ChnKbgkD.js → app-CuEM7S0i.js} +18 -8
  5. package/lib/app-CuEM7S0i.js.map +1 -0
  6. package/lib/{app-B1djcEnN.d.ts → app-MIaByu-I.d.ts} +2 -2
  7. package/lib/cli.js +17 -5
  8. package/lib/cli.js.map +1 -1
  9. package/lib/{config-jZAB2Zg8.d.ts → config-1vfbPBRi.d.ts} +46 -7
  10. package/lib/{config-BQ44iVWT.js → config-CY_Cf87P.js} +21 -4
  11. package/lib/config-CY_Cf87P.js.map +1 -0
  12. package/lib/extras-Bp4DpyZP.js +87 -0
  13. package/lib/extras-Bp4DpyZP.js.map +1 -0
  14. package/lib/{extras-B_dzBrCF.d.ts → extras-CITv2nRg.d.ts} +15 -6
  15. package/lib/{ghostty-DFwFh4aL.d.ts → ghostty-D8KUXOw7.d.ts} +2 -2
  16. package/lib/index.d.ts +10 -9
  17. package/lib/index.js +8 -7
  18. package/lib/info/info.d.ts +2 -0
  19. package/lib/info/info.js +2 -0
  20. package/lib/info-BRlaIckk.js +176 -0
  21. package/lib/info-BRlaIckk.js.map +1 -0
  22. package/lib/info-C0WvNVNS.d.ts +98 -0
  23. package/lib/init/app.d.ts +1 -1
  24. package/lib/init/app.js +1 -1
  25. package/lib/init/ghostty.d.ts +1 -1
  26. package/lib/init/raycast.d.ts +1 -1
  27. package/lib/init/scaffold.d.ts +2 -2
  28. package/lib/init/scaffold.js +2 -2
  29. package/lib/{profile-DM6NAgb-.js → profile-1oytMVlE.js} +25 -5
  30. package/lib/profile-1oytMVlE.js.map +1 -0
  31. package/lib/{profile-7CiMUPu9.d.ts → profile-Bzq0Y4PI.d.ts} +13 -3
  32. package/lib/{raycast-fc5U1x7E.d.ts → raycast-DuHEu0Vz.d.ts} +2 -2
  33. package/lib/{run-yUsOaKFx.js → run-9vQC2fCs.js} +10 -8
  34. package/lib/run-9vQC2fCs.js.map +1 -0
  35. package/lib/{run-BWGDNJiY.d.ts → run-gag6YjI9.d.ts} +10 -7
  36. package/lib/sandbox/extras.d.ts +1 -1
  37. package/lib/sandbox/extras.js +1 -1
  38. package/lib/sandbox/profile.d.ts +2 -2
  39. package/lib/sandbox/profile.js +2 -2
  40. package/lib/sandbox/run.d.ts +2 -2
  41. package/lib/sandbox/run.js +2 -2
  42. package/lib/{scaffold-CbsKxlL0.d.ts → scaffold-BiCJzELQ.d.ts} +10 -3
  43. package/lib/{scaffold-C1tqCL_8.js → scaffold-DiG5q28w.js} +18 -9
  44. package/lib/scaffold-DiG5q28w.js.map +1 -0
  45. package/lib/utils/config.d.ts +2 -2
  46. package/lib/utils/config.js +2 -2
  47. package/package.json +2 -1
  48. package/lib/app-ChnKbgkD.js.map +0 -1
  49. package/lib/config-BQ44iVWT.js.map +0 -1
  50. package/lib/extras-B2ss2Cgh.js +0 -46
  51. package/lib/extras-B2ss2Cgh.js.map +0 -1
  52. package/lib/profile-DM6NAgb-.js.map +0 -1
  53. package/lib/run-yUsOaKFx.js.map +0 -1
  54. package/lib/scaffold-C1tqCL_8.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"profile-DM6NAgb-.js","names":[],"sources":["../src/sandbox/profile.ts"],"sourcesContent":["// Seatbelt (SBPL) profile generator.\n//\n// The old bash version baked the profile into a heredoc and patched it with\n// sed. Here the profile is assembled from small typed helpers, so the parts\n// you actually want to tweak live in config.ts as plain data.\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { type Config, expandHome, HOME } from '../utils/config.js';\n\n// ---- SBPL helpers ----------------------------------------------------------\n\n// Quote a literal string for SBPL. Only `\"` needs escaping; backslashes are\n// left as-is so regex patterns survive verbatim.\nconst q = (s: string): string => `\"${String(s).replace(/\"/g, '\\\\\"')}\"`;\n\nexport const subpath = (p: string): string => `(subpath ${q(p)})`;\nexport const literal = (p: string): string => `(literal ${q(p)})`;\nexport const regex = (p: string): string => `(regex ${q(p)})`;\nexport const globalName = (n: string): string => `(global-name ${q(n)})`;\nexport const ipcName = (n: string): string => `(ipc-posix-name ${q(n)})`;\n\n/** Escape a path for safe embedding inside an SBPL regex. */\nexport const reEscape = (s: string): string => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nfunction block(op: string, rules: string[]): string {\n return [`(${op}`, ...rules.map((r) => ` ${r}`), ')'].join('\\n');\n}\nconst allow = (op: string, ...rules: string[]): string => block(`allow ${op}`, rules);\nconst deny = (op: string, ...rules: string[]): string => block(`deny ${op}`, rules);\n\n// ---- package-manager autodetection ----------------------------------------\n\n/** Detect installed package managers whose paths must be readable/executable. */\nexport function detectPackagePaths(): string[] {\n const paths: string[] = [];\n if (fs.existsSync('/opt/homebrew')) paths.push('/opt/homebrew');\n else if (fs.existsSync('/usr/local/Homebrew')) paths.push('/usr/local/Homebrew');\n const local = path.join(HOME, '.local');\n if (fs.existsSync(local)) paths.push(local);\n if (fs.existsSync('/nix/store')) paths.push('/nix/store');\n return paths;\n}\n\n/** Context needed to assemble a profile for a specific project. */\nexport interface ProfileContext {\n projectDir: string;\n detectedPaths?: string[];\n}\n\n/**\n * Build the full SBPL profile text.\n * @param config effective config (see config.ts)\n * @param ctx { projectDir, detectedPaths }\n */\nexport function buildProfile(\n config: Config,\n { projectDir, detectedPaths = detectPackagePaths() }: ProfileContext,\n): string {\n const configDir = expandHome(config.configDir);\n const sshDir = expandHome(config.bot.sshDir);\n const hooksDir = config.hooksDir ? expandHome(config.hooksDir) : null;\n const homeRe = reEscape(HOME);\n\n const sections: string[] = [];\n const add = (comment: string, body: string) => sections.push(`;; ---------- ${comment}\\n${body}`);\n\n sections.push(\n [\n ';; ------------------------------------------------------------------',\n ';; Claude Code macOS sandbox profile (autogenerated)',\n ';; ------------------------------------------------------------------',\n '(version 1)',\n '(deny default)',\n ].join('\\n'),\n );\n\n add('introspection & sysctl', '(allow file-read-metadata)\\n(allow sysctl-read)');\n\n add(\n 'basic dir traversal',\n [\n allow('file-read*', literal('/')),\n allow('file-read*', literal('/private')),\n allow('file-read-data', literal('/Users')),\n allow('file-read-data', literal(HOME)),\n ].join('\\n'),\n );\n\n add(\n 'system runtime (read-only)',\n allow(\n 'file-read* file-map-executable',\n subpath('/System'),\n subpath('/usr'),\n subpath('/bin'),\n subpath('/sbin'),\n subpath('/Library/Frameworks'),\n subpath('/private/etc'),\n subpath('/var/db/dyld'),\n ...detectedPaths.map(subpath),\n ),\n );\n\n add(\n 'Xcode / Command Line Tools (xcrun, git, etc.)',\n [\n allow(\n 'file-read* file-map-executable',\n subpath('/Library/Developer/CommandLineTools'),\n subpath('/Applications/Xcode.app'),\n ),\n allow(\n 'process-exec',\n subpath('/Library/Developer/CommandLineTools'),\n subpath('/Applications/Xcode.app'),\n ),\n ].join('\\n'),\n );\n\n // global npm/pipx/cargo bins (user-installed)\n const userPaths = detectedPaths.filter((p) => p.endsWith('/.local'));\n add(\n 'global npm/pipx/cargo bins',\n userPaths.length\n ? userPaths.map((p) => allow('file-read*', subpath(p))).join('\\n')\n : ';; No user package paths detected',\n );\n\n add(\n 'executable paths',\n allow(\n 'process-exec',\n subpath('/usr'),\n subpath('/System'),\n subpath('/bin'),\n subpath('/sbin'),\n literal('/usr/bin/env'),\n ...detectedPaths.map(subpath),\n ),\n );\n\n add(\n 'temp dirs',\n allow(\n 'file-read* file-write*',\n subpath('/tmp'),\n subpath('/private/tmp'),\n regex('^/private/var/folders/'),\n ),\n );\n\n add('Claude config & token files', allow('file-read* file-write*', subpath(configDir)));\n\n add(\n 'Claude auto-update (RO) -- suppress warnings',\n allow(\n 'file-read*',\n subpath(path.join(HOME, '.local/state/claude')),\n subpath(path.join(HOME, '.cache/claude')),\n ),\n );\n\n add(\n 'time-zone & prefs (RO)',\n allow('file-read*', subpath('/private/var/db/timezone'), subpath('/Library/Preferences')),\n );\n\n add(\n '/dev access (RO) + ioctl',\n [\n allow('file-read*', literal('/dev')),\n allow('file-read* file-write*', regex('^/dev/(tty.*|null|zero|dtracehelper)')),\n allow('file-ioctl', literal('/dev/dtracehelper'), regex('^/dev/tty.*')),\n ].join('\\n'),\n );\n\n add(\n 'mach-lookup services',\n allow(\n 'mach-lookup',\n globalName('com.apple.system.opendirectoryd.libinfo'),\n globalName('com.apple.SystemConfiguration.DNSConfiguration'),\n globalName('com.apple.coreservices.launchservicesd'),\n globalName('com.apple.CoreServices.coreservicesd'),\n globalName('com.apple.system.notification_center'),\n globalName('com.apple.logd'),\n globalName('com.apple.diagnosticd'),\n globalName('com.apple.lsd.mapdb'),\n globalName('com.apple.lsd.modifydb'),\n globalName('com.apple.coreservices.quarantine-resolver'),\n globalName('com.apple.pasteboard.pboard'),\n globalName('com.apple.pasteboard.1'),\n ),\n );\n\n add(\n 'Launch Services needed by /usr/bin/open',\n allow('mach-lookup', regex('^com\\\\.apple\\\\.lsd(\\\\..*)?$')),\n );\n\n add(\n 'Developer Tools (xcrun / libxcrun)',\n allow('mach-lookup', globalName('com.apple.dt.xcsecurity'), regex('^com\\\\.apple\\\\.dt\\\\..*$')),\n );\n\n add(\n 'Audio (afplay)',\n allow(\n 'mach-lookup',\n globalName('com.apple.audio.audiohald'),\n globalName('com.apple.audio.AudioComponentRegistrar'),\n ),\n );\n\n add(\n 'Notification Center shared-memory (RO)',\n allow('ipc-posix-shm-read-data', ipcName('apple.shm.notification_center')),\n );\n\n add(\n 'User-level preference reads (RO)',\n allow('file-read*', subpath(path.join(HOME, 'Library/Preferences'))),\n );\n\n // Keychain RW so Claude can persist refreshed OAuth tokens (else ~24h → 401).\n add(\n 'Keychain access (for OAuth)',\n [\n allow('file-read* file-write*', subpath(path.join(HOME, 'Library/Keychains'))),\n allow(\n 'mach-lookup',\n globalName('com.apple.SecurityServer'),\n globalName('com.apple.security.agent'),\n globalName('com.apple.securityd'),\n globalName('com.apple.secd'),\n globalName('com.apple.trustd'),\n globalName('com.apple.trustd.agent'),\n globalName('com.apple.CoreAuthentication.daemon'),\n ),\n ].join('\\n'),\n );\n\n add(\n 'git config (RO)',\n allow(\n 'file-read*',\n literal(path.join(HOME, '.gitconfig')),\n literal(path.join(HOME, '.gitignore_global')),\n subpath(path.join(HOME, '.config/git')),\n ),\n );\n\n // Soft privacy DENY list — placed BEFORE the extra readOnly/readWrite and the\n // project dir, so an explicit grant may override it (e.g. running on a project\n // that lives under ~/Documents). The hard secret deny below is what's binding.\n const softDeny = [\n ...config.denyHome.map((d) => subpath(path.join(HOME, d))),\n ...config.paths.deny.map((p) => subpath(expandHome(p))),\n ];\n add(\n 'soft privacy DENY list (overridable by explicit grants)',\n deny('file-read* file-write*', ...softDeny),\n );\n\n add(\n 'SSH: bot key + known_hosts (personal keys hard-denied at the very end)',\n [\n allow(\n 'file-read*',\n literal(path.join(HOME, '.ssh')),\n literal(path.join(HOME, '.ssh/known_hosts')),\n literal(path.join(HOME, '.ssh/known_hosts2')),\n literal(path.join(HOME, '.ssh/config')),\n subpath(sshDir),\n ),\n allow(\n 'file-write*',\n literal(path.join(HOME, '.ssh/known_hosts')),\n literal(path.join(HOME, '.ssh/known_hosts2')),\n ),\n ].join('\\n'),\n );\n\n add(\n 'claude hooks (RO + exec)',\n hooksDir && fs.existsSync(hooksDir)\n ? [\n allow('file-read* file-map-executable', subpath(hooksDir)),\n allow('process-exec', subpath(hooksDir)),\n ].join('\\n')\n : ';; (no hooks dir; set config.hooksDir / CLABOX_HOOKS_DIR to enable)',\n );\n\n // Extra user-supplied RO / RW / exec rules.\n if (config.paths.readOnly.length)\n add(\n 'extra read-only paths',\n allow('file-read*', ...config.paths.readOnly.map((p) => subpath(expandHome(p)))),\n );\n if (config.paths.readWrite.length)\n add(\n 'extra read-write paths',\n allow('file-read* file-write*', ...config.paths.readWrite.map((p) => subpath(expandHome(p)))),\n );\n if (config.paths.exec.length)\n add(\n 'extra exec paths',\n allow('process-exec', ...config.paths.exec.map((p) => subpath(expandHome(p)))),\n );\n\n add(\n 'project workspace (RW)',\n [\n allow('file-read* file-write* file-map-executable', subpath(projectDir)),\n allow('process-exec', subpath(projectDir)),\n ].join('\\n'),\n );\n\n // Hard secret DENY — emitted LAST of all file rules so it wins even over a\n // broad readOnly/readWrite or the project dir (SBPL = last matching rule\n // wins). This is the binding invariant: personal credentials and private keys\n // are never readable, however wide the grants above. Only the bot key subdir\n // (allowed earlier, and not matched by these patterns) stays readable.\n const hardDeny: string[] = [];\n if (config.denyDotConfigs.length) {\n hardDeny.push(regex(`^${homeRe}/\\\\.(${config.denyDotConfigs.join('|')})($|/)`));\n }\n hardDeny.push(\n regex(`^${homeRe}/\\\\.ssh/id_`),\n regex(`^${homeRe}/\\\\.ssh/.*\\\\.pem$`),\n regex(`^${homeRe}/\\\\.ssh/.*\\\\.key$`),\n );\n add(\n 'hard secret DENY (always wins — credentials & private keys)',\n deny('file-read* file-write*', ...hardDeny),\n );\n\n if (config.network) add('networking', '(allow network*)');\n\n sections.push('(allow process-fork)\\n(allow lsopen)');\n\n const text = `${sections.join('\\n\\n')}\\n`;\n\n // Sanity-check before anyone feeds it to sandbox-exec.\n if (!/^\\(version 1\\)/m.test(text)) {\n throw new Error('generated sandbox profile is missing \"(version 1)\"');\n }\n return text;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-yUsOaKFx.js","names":[],"sources":["../src/sandbox/run.ts"],"sourcesContent":["// Profile materialization + launching `claude` under sandbox-exec.\n\nimport { execFileSync, spawnSync } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { type Config, expandHome, HOME } from '../utils/config.js';\nimport { boxSlug, buildBoxExtras, type ExtraFile } from './extras.js';\nimport { buildProfile, detectPackagePaths } from './profile.js';\n\nconst TMPDIR = (process.env.TMPDIR || '/tmp').replace(/\\/$/, '');\n\n/** Deterministic per-project profile path under TMPDIR. */\nexport function profilePath(projectDir: string = process.cwd()): string {\n const hash = crypto.createHash('sha256').update(projectDir).digest('hex').slice(0, 8);\n return path.join(TMPDIR, `clabox-${path.basename(projectDir)}-${hash}.sb`);\n}\n\n/**\n * Effective project dir: `config.cwd` (with `~` expanded, resolved to an\n * absolute path so SBPL `subpath` rules stay valid) if set, else the shell CWD.\n */\nexport function resolveProjectDir(config: Config): string {\n return config.cwd ? path.resolve(expandHome(config.cwd)) : process.cwd();\n}\n\nfunction which(bin: string): string | null {\n try {\n return (\n execFileSync('command', ['-v', bin], { shell: '/bin/sh', encoding: 'utf8' }).trim() || null\n );\n } catch {\n return null;\n }\n}\n\nfunction requireSandboxExec(): void {\n if (!which('sandbox-exec')) {\n throw new Error('sandbox-exec not found. This tool requires macOS with sandbox-exec.');\n }\n}\n\nfunction resolveClaudeBin(config: Config): string {\n const candidate = config.claudeBin || which('claude') || path.join(HOME, '.local/bin/claude');\n if (!candidate || !fs.existsSync(candidate)) {\n throw new Error(`claude not found at '${candidate}'`);\n }\n return candidate;\n}\n\n/** Generate the profile file for the current project, return its path. */\nexport function generateProfile(\n config: Config,\n projectDir: string = resolveProjectDir(config),\n): string {\n requireSandboxExec();\n const file = profilePath(projectDir);\n const text = buildProfile(config, { projectDir, detectedPaths: detectPackagePaths() });\n fs.writeFileSync(file, text);\n return file;\n}\n\n/** Build the `env KEY=VALUE …` argument list forced onto the sandboxed claude. */\nexport function buildEnvArgs(config: Config): string[] {\n const sshDir = expandHome(config.bot.sshDir);\n const botKey = path.join(sshDir, 'id_ed25519');\n const botCfg = path.join(sshDir, 'config');\n const args = [\n `PATH=${path.join(HOME, '.local/bin')}:${process.env.PATH || ''}`,\n `CLAUDE_CONFIG_DIR=${expandHome(config.configDir)}`,\n `GIT_AUTHOR_NAME=${config.bot.name}`,\n `GIT_AUTHOR_EMAIL=${config.bot.email}`,\n `GIT_COMMITTER_NAME=${config.bot.name}`,\n `GIT_COMMITTER_EMAIL=${config.bot.email}`,\n 'GIT_CONFIG_COUNT=2',\n 'GIT_CONFIG_KEY_0=commit.gpgsign',\n 'GIT_CONFIG_VALUE_0=false',\n 'GIT_CONFIG_KEY_1=tag.gpgsign',\n 'GIT_CONFIG_VALUE_1=false',\n ];\n // Pin git ssh to the bot key only when it actually exists, so the sandbox\n // stays usable without a dedicated bot key configured.\n if (fs.existsSync(botKey)) {\n args.push(\n `GIT_SSH_COMMAND=ssh -F ${botCfg} -i ${botKey} -o IdentitiesOnly=yes -o IdentityAgent=none`,\n );\n }\n // User-declared extras go last so they win over the built-in vars above\n // (duplicate keys: `env` keeps the last assignment).\n for (const [key, value] of Object.entries(config.env ?? {})) {\n args.push(`${key}=${value}`);\n }\n return args;\n}\n\n/**\n * Write the per-box extra files (mkdir -p their dirs) `0600`. They live under\n * configDir and can carry secrets (e.g. an MCP auth token in a URL/header), so\n * they're kept out of argv (vs. an inline `--mcp-config '<json>'`) AND off the\n * world-readable bit on disk. Returns the paths.\n */\nexport function writeExtraFiles(files: ExtraFile[]): string[] {\n for (const f of files) {\n fs.mkdirSync(path.dirname(f.path), { recursive: true });\n fs.writeFileSync(f.path, f.content, { mode: 0o600 });\n fs.chmodSync(f.path, 0o600); // enforce even if the file pre-existed\n }\n return files.map((f) => f.path);\n}\n\n/** Options accepted by {@link runClaude}. */\nexport interface RunOptions {\n configFile?: string | null;\n}\n\n/** Generate the profile and exec claude under sandbox-exec. Returns exit code. */\nexport function runClaude(\n config: Config,\n claudeArgs: string[],\n { configFile }: RunOptions = {},\n): number {\n const projectDir = resolveProjectDir(config);\n const claudeBin = resolveClaudeBin(config);\n const profileFile = generateProfile(config, projectDir);\n\n // Compile the box's declarative mcp / systemPrompt into claude args, and\n // materialize the files they reference (under configDir, which is sandbox-RW).\n const extras = buildBoxExtras(config, boxSlug(configFile, projectDir));\n const extraFiles = writeExtraFiles(extras.files);\n\n if (process.env.CLABOX_DEBUG) {\n console.error(`→ Running Claude Code sandboxed in: ${projectDir}`);\n console.error(`→ Profile: ${profileFile}`);\n console.error(`→ Config: ${expandHome(config.configDir)}`);\n if (configFile) console.error(`→ Config file: ${configFile}`);\n for (const f of extraFiles) console.error(`→ MCP: ${f}`);\n }\n\n // Terminal title = cwd (with ~ for $HOME), matching the bash version.\n const title = projectDir.startsWith(HOME) ? `~${projectDir.slice(HOME.length)}` : projectDir;\n process.stdout.write(`\\x1b]0;${title}\\x07`);\n\n const envArgs = buildEnvArgs(config);\n const defaultArgs = Array.isArray(config.claudeArgs) ? config.claudeArgs : [];\n const inner = [\n 'sandbox-exec',\n '-f',\n profileFile,\n 'env',\n ...envArgs,\n claudeBin,\n ...defaultArgs,\n ...extras.claudeArgs,\n ...claudeArgs,\n ];\n\n // `ulimit` is a shell builtin; run the whole thing under sh so we can set it.\n // `exec \"$@\"` keeps argv intact without re-quoting (args start after $0=sh).\n const ulimit = config.ulimitProcs > 0 ? `ulimit -u ${config.ulimitProcs} 2>/dev/null; ` : '';\n const res = spawnSync('/bin/sh', ['-c', `${ulimit}exec \"$@\"`, 'sh', ...inner], {\n cwd: projectDir,\n stdio: 'inherit',\n });\n if (res.error) throw res.error;\n if (res.signal) return 1;\n return res.status ?? 0;\n}\n"],"mappings":";;;;;;;;AAUA,MAAM,UAAU,QAAQ,IAAI,UAAU,OAAA,CAAQ,QAAQ,OAAO,EAAE;;AAG/D,SAAgB,YAAY,aAAqB,QAAQ,IAAI,GAAW;CACtE,MAAM,OAAO,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,UAAU,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;CACpF,OAAO,KAAK,KAAK,QAAQ,UAAU,KAAK,SAAS,UAAU,EAAE,GAAG,KAAK,IAAI;AAC3E;;;;;AAMA,SAAgB,kBAAkB,QAAwB;CACxD,OAAO,OAAO,MAAM,KAAK,QAAQ,WAAW,OAAO,GAAG,CAAC,IAAI,QAAQ,IAAI;AACzE;AAEA,SAAS,MAAM,KAA4B;CACzC,IAAI;EACF,OACE,aAAa,WAAW,CAAC,MAAM,GAAG,GAAG;GAAE,OAAO;GAAW,UAAU;EAAO,CAAC,CAAC,CAAC,KAAK,KAAK;CAE3F,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,qBAA2B;CAClC,IAAI,CAAC,MAAM,cAAc,GACvB,MAAM,IAAI,MAAM,qEAAqE;AAEzF;AAEA,SAAS,iBAAiB,QAAwB;CAChD,MAAM,YAAY,OAAO,aAAa,MAAM,QAAQ,KAAK,KAAK,KAAK,MAAM,mBAAmB;CAC5F,IAAI,CAAC,aAAa,CAAC,GAAG,WAAW,SAAS,GACxC,MAAM,IAAI,MAAM,wBAAwB,UAAU,EAAE;CAEtD,OAAO;AACT;;AAGA,SAAgB,gBACd,QACA,aAAqB,kBAAkB,MAAM,GACrC;CACR,mBAAmB;CACnB,MAAM,OAAO,YAAY,UAAU;CACnC,MAAM,OAAO,aAAa,QAAQ;EAAE;EAAY,eAAe,mBAAmB;CAAE,CAAC;CACrF,GAAG,cAAc,MAAM,IAAI;CAC3B,OAAO;AACT;;AAGA,SAAgB,aAAa,QAA0B;CACrD,MAAM,SAAS,WAAW,OAAO,IAAI,MAAM;CAC3C,MAAM,SAAS,KAAK,KAAK,QAAQ,YAAY;CAC7C,MAAM,SAAS,KAAK,KAAK,QAAQ,QAAQ;CACzC,MAAM,OAAO;EACX,QAAQ,KAAK,KAAK,MAAM,YAAY,EAAE,GAAG,QAAQ,IAAI,QAAQ;EAC7D,qBAAqB,WAAW,OAAO,SAAS;EAChD,mBAAmB,OAAO,IAAI;EAC9B,oBAAoB,OAAO,IAAI;EAC/B,sBAAsB,OAAO,IAAI;EACjC,uBAAuB,OAAO,IAAI;EAClC;EACA;EACA;EACA;EACA;CACF;CAGA,IAAI,GAAG,WAAW,MAAM,GACtB,KAAK,KACH,0BAA0B,OAAO,MAAM,OAAO,6CAChD;CAIF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,OAAO,CAAC,CAAC,GACxD,KAAK,KAAK,GAAG,IAAI,GAAG,OAAO;CAE7B,OAAO;AACT;;;;;;;AAQA,SAAgB,gBAAgB,OAA8B;CAC5D,KAAK,MAAM,KAAK,OAAO;EACrB,GAAG,UAAU,KAAK,QAAQ,EAAE,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;EACtD,GAAG,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,IAAM,CAAC;EACnD,GAAG,UAAU,EAAE,MAAM,GAAK;CAC5B;CACA,OAAO,MAAM,KAAK,MAAM,EAAE,IAAI;AAChC;;AAQA,SAAgB,UACd,QACA,YACA,EAAE,eAA2B,CAAC,GACtB;CACR,MAAM,aAAa,kBAAkB,MAAM;CAC3C,MAAM,YAAY,iBAAiB,MAAM;CACzC,MAAM,cAAc,gBAAgB,QAAQ,UAAU;CAItD,MAAM,SAAS,eAAe,QAAQ,QAAQ,YAAY,UAAU,CAAC;CACrE,MAAM,aAAa,gBAAgB,OAAO,KAAK;CAE/C,IAAI,QAAQ,IAAI,cAAc;EAC5B,QAAQ,MAAM,wCAAwC,YAAY;EAClE,QAAQ,MAAM,cAAc,aAAa;EACzC,QAAQ,MAAM,cAAc,WAAW,OAAO,SAAS,GAAG;EAC1D,IAAI,YAAY,QAAQ,MAAM,kBAAkB,YAAY;EAC5D,KAAK,MAAM,KAAK,YAAY,QAAQ,MAAM,cAAc,GAAG;CAC7D;CAGA,MAAM,QAAQ,WAAW,WAAW,IAAI,IAAI,IAAI,WAAW,MAAM,KAAK,MAAM,MAAM;CAClF,QAAQ,OAAO,MAAM,UAAU,MAAM,KAAK;CAE1C,MAAM,UAAU,aAAa,MAAM;CACnC,MAAM,cAAc,MAAM,QAAQ,OAAO,UAAU,IAAI,OAAO,aAAa,CAAC;CAC5E,MAAM,QAAQ;EACZ;EACA;EACA;EACA;EACA,GAAG;EACH;EACA,GAAG;EACH,GAAG,OAAO;EACV,GAAG;CACL;CAKA,MAAM,MAAM,UAAU,WAAW;EAAC;EAAM,GADzB,OAAO,cAAc,IAAI,aAAa,OAAO,YAAY,kBAAkB,GACxC;EAAY;EAAM,GAAG;CAAK,GAAG;EAC7E,KAAK;EACL,OAAO;CACT,CAAC;CACD,IAAI,IAAI,OAAO,MAAM,IAAI;CACzB,IAAI,IAAI,QAAQ,OAAO;CACvB,OAAO,IAAI,UAAU;AACvB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"scaffold-C1tqCL_8.js","names":[],"sources":["../src/init/scaffold.ts"],"sourcesContent":["// I/O for `clabox init`: discover the box configs in `<base>/configs/`,\n// (re)write the shell aliases into `<base>/scripts/`, and — for boxes that opt\n// in via `app` — generate a Ghostty config in `<base>/ghostty/` and build a\n// standalone `<appsDir>/<name>.app` (see init/app.ts).\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { buildBoxExtras } from '../sandbox/extras.js';\nimport { type Config, expandHome, listBoxes, loadConfig, resolveBox } from '../utils/config.js';\nimport { buildAliasFiles } from './aliases.js';\nimport { buildApp, canBuildApps } from './app.js';\nimport { appBundlePath, buildGhosttyConfig } from './ghostty.js';\nimport { buildRaycastCommand } from './raycast.js';\n\n/**\n * Box names (sorted, de-duplicated) discovered in `<configsDir>` via the same\n * rules as `-b`: both `<name>.mjs` and `<name>.config.mjs`, `_`-prefixed\n * shared partials (e.g. `_presets.mjs`) skipped.\n */\nexport function discoverProfiles(configsDir: string): string[] {\n if (!fs.existsSync(configsDir)) {\n throw new Error(`clabox init: configs dir not found: ${configsDir}`);\n }\n const names = listBoxes(configsDir);\n if (names.length === 0) {\n throw new Error(`clabox init: no box configs (*.mjs) in ${configsDir}`);\n }\n return names;\n}\n\n/** Remove previously generated artifacts (`index.sh`, `clabox-*.sh`). */\nfunction pruneGenerated(scriptsDir: string): void {\n if (!fs.existsSync(scriptsDir)) return;\n for (const f of fs.readdirSync(scriptsDir)) {\n if (f === 'index.sh' || (f.startsWith('clabox-') && f.endsWith('.sh'))) {\n fs.rmSync(path.join(scriptsDir, f), { force: true });\n }\n }\n}\n\n/** Remove files in `dir` whose name ends with `ext` (a no-op if dir is absent). */\nfunction pruneByExt(dir: string, ext: string): void {\n if (!fs.existsSync(dir)) return;\n for (const f of fs.readdirSync(dir)) {\n if (f.endsWith(ext)) fs.rmSync(path.join(dir, f), { force: true });\n }\n}\n\n/**\n * The `clabox` command baked into the generated Ghostty `command`. Default is a\n * bare `clabox` resolved from PATH at launch time by the `zsh -lic` login shell\n * — this survives package-manager moves (e.g. bun → npm/homebrew) that change\n * the binary's absolute path. Only an explicit `appBuilder.claboxBin` pins an\n * absolute path.\n */\nfunction resolveClaboxBin(configured: string | null): string {\n return configured ? expandHome(configured) : 'clabox';\n}\n\n/**\n * The `CLABOX_CONFIGS_DIR` value to bake into generated commands, or null to\n * omit it. Omit when `<dir>` resolves (realpath, symlinks included) to the\n * runtime default `~/.config/clabox/configs` — then `-b` finds the box via that\n * default at launch time, so no path needs baking (and it stays correct if the\n * dir later moves behind the same symlink). Otherwise bake the absolute path so\n * `-b` resolves the box regardless of the launcher's cwd.\n */\nfunction bakeConfigsDir(dir: string): string | null {\n try {\n // The launched process has no CLABOX_CONFIGS_DIR set (we omit it), so its\n // runtime default is always ~/.config/clabox/configs — compare against that.\n if (fs.realpathSync(dir) === fs.realpathSync(expandHome('~/.config/clabox/configs'))) {\n return null;\n }\n } catch {\n // default dir missing/unresolvable → bake the explicit path.\n }\n return dir;\n}\n\n/** Options for {@link runInit}. */\nexport interface InitOptions {\n /** Base dir holding `configs/` and `scripts/`. Default: `<cwd>/__`. */\n baseDir?: string;\n /** Build the Ghostty apps for `app` boxes. Default: true. */\n buildApps?: boolean;\n /** Limit app building to a single box (by box name or app display name). */\n only?: string | null;\n}\n\n/** A standalone Ghostty app built by `clabox init`. */\nexport interface BuiltApp {\n box: string;\n appPath: string;\n signed: 'identity' | 'adhoc';\n}\n\n/** Result of {@link runInit}. */\nexport interface InitResult {\n profiles: string[];\n scriptsDir: string;\n indexFile: string;\n written: string[];\n /** Apps successfully built. */\n apps: BuiltApp[];\n /** Generated Ghostty config files. */\n ghosttyConfigs: string[];\n /** Generated Raycast command scripts. */\n raycastCommands: string[];\n /** Compiled per-box MCP json files (from `config.mcp`). */\n extraFiles: string[];\n /** Non-fatal issues (e.g. app build skipped/failed). */\n warnings: string[];\n}\n\n/**\n * Compile each box's declarative `mcp` (→ `<configDir>/mcp/<box>.json`) so the\n * files exist ahead of the first run (the same files `run` writes; slug = box\n * name). Best-effort per box: a config that fails to load becomes a warning.\n */\nasync function materializeExtras(\n configsDir: string,\n profiles: string[],\n result: InitResult,\n): Promise<void> {\n for (const name of profiles) {\n try {\n const { config } = await loadConfig(resolveBox(name, configsDir));\n for (const f of buildBoxExtras(config, name).files) {\n fs.mkdirSync(path.dirname(f.path), { recursive: true });\n // 0600 — the MCP json can carry an auth token (see run.ts#writeExtraFiles).\n fs.writeFileSync(f.path, f.content, { mode: 0o600 });\n fs.chmodSync(f.path, 0o600);\n result.extraFiles.push(f.path);\n }\n } catch (e) {\n result.warnings.push(`${name}: extras not materialized — ${(e as Error).message}`);\n }\n }\n}\n\n/** Generate the Ghostty configs and build the apps for every `app` box. */\nasync function buildAppArtifacts(\n base: string,\n configsDir: string,\n profiles: string[],\n only: string | null,\n result: InitResult,\n): Promise<void> {\n // Load each box config; keep the ones that opt into an app (and match `only`).\n const appBoxes: { name: string; config: Config }[] = [];\n for (const name of profiles) {\n const { config } = await loadConfig(resolveBox(name, configsDir));\n if (!config.app) continue;\n if (only && name !== only && config.app.name !== only) continue;\n appBoxes.push({ name, config });\n }\n if (appBoxes.length === 0) return;\n\n const ghosttyDir = path.join(base, 'ghostty');\n const raycastDir = path.join(base, 'raycast');\n fs.mkdirSync(ghosttyDir, { recursive: true });\n fs.mkdirSync(raycastDir, { recursive: true });\n // Only prune on a full run — with `only` we'd orphan other apps' artifacts.\n if (!only) {\n pruneByExt(ghosttyDir, '.config');\n pruneByExt(raycastDir, '.sh');\n }\n\n for (const { name, config } of appBoxes) {\n const app = config.app;\n if (!app) continue; // narrowed above; keeps the type checker happy\n const configPath = path.join(ghosttyDir, `${name}.config`);\n const projectDir = config.cwd ? path.resolve(expandHome(config.cwd)) : null;\n const baseGhostty = config.appBuilder.baseGhosttyConfig\n ? expandHome(config.appBuilder.baseGhosttyConfig)\n : null;\n fs.writeFileSync(\n configPath,\n buildGhosttyConfig({\n app,\n boxName: name,\n projectDir,\n configsDir: bakeConfigsDir(configsDir),\n claboxBin: resolveClaboxBin(config.appBuilder.claboxBin),\n baseGhosttyConfig: baseGhostty,\n }),\n );\n result.ghosttyConfigs.push(configPath);\n\n // Raycast command that opens the (to be) built bundle.\n const appPath = appBundlePath(expandHome(config.appBuilder.appsDir), app);\n const raycastPath = path.join(raycastDir, `${name}.sh`);\n fs.writeFileSync(raycastPath, buildRaycastCommand({ app, appPath }));\n fs.chmodSync(raycastPath, 0o755);\n result.raycastCommands.push(raycastPath);\n\n const check = canBuildApps(config.appBuilder);\n if (!check.ok) {\n result.warnings.push(`${name}: app not built (${check.reason})`);\n continue;\n }\n try {\n const built = buildApp({ boxName: name, app, builder: config.appBuilder, configPath });\n result.apps.push({ box: name, appPath: built.appPath, signed: built.signed });\n } catch (e) {\n result.warnings.push(`${name}: app build failed — ${(e as Error).message}`);\n }\n }\n}\n\n/** Scan the configs dir, (re)write the alias scripts, and build `app` apps. */\nexport async function runInit({\n baseDir,\n buildApps = true,\n only = null,\n}: InitOptions = {}): Promise<InitResult> {\n const base = path.resolve(baseDir ?? path.join(process.cwd(), '__'));\n const configsDir = path.join(base, 'configs');\n const scriptsDir = path.join(base, 'scripts');\n const profiles = discoverProfiles(configsDir);\n\n fs.mkdirSync(scriptsDir, { recursive: true });\n pruneGenerated(scriptsDir);\n\n const files = buildAliasFiles(profiles, { configsDir: bakeConfigsDir(configsDir), scriptsDir });\n for (const f of files) {\n fs.writeFileSync(f.path, f.content);\n if (f.executable) fs.chmodSync(f.path, 0o755);\n }\n\n const result: InitResult = {\n profiles,\n scriptsDir,\n indexFile: path.join(scriptsDir, 'index.sh'),\n written: files.map((f) => f.path),\n apps: [],\n ghosttyConfigs: [],\n raycastCommands: [],\n extraFiles: [],\n warnings: [],\n };\n\n await materializeExtras(configsDir, profiles, result);\n\n if (buildApps) {\n await buildAppArtifacts(base, configsDir, profiles, only, result);\n }\n return result;\n}\n"],"mappings":"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"}