boxdown 1.0.0 → 1.2.1

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 (76) hide show
  1. package/README.md +135 -12
  2. package/assets/devcontainer/README.md +65 -21
  3. package/assets/devcontainer/devcontainer.json +27 -15
  4. package/assets/devcontainer/hooks/initialize.sh +76 -22
  5. package/assets/devcontainer/hooks/post-create.sh +70 -12
  6. package/assets/devcontainer/hooks/post-start.sh +20 -13
  7. package/assets/devcontainer/ssh-config-install.sh +12 -3
  8. package/assets/devcontainer/start.sh +721 -44
  9. package/assets/devcontainer/utils/coding-agent-cli-update.sh +267 -3
  10. package/assets/devcontainer/utils/deps-install.sh +68 -0
  11. package/assets/devcontainer/utils/git-config-bootstrap.sh +128 -0
  12. package/assets/devcontainer/utils/git-signing-bootstrap.sh +109 -0
  13. package/assets/devcontainer/utils/python-bootstrap.sh +69 -0
  14. package/assets/devcontainer/utils/secret-env-bootstrap.sh +22 -0
  15. package/assets/devcontainer/utils/ssh-agent-proxy-bootstrap.sh +27 -0
  16. package/assets/devcontainer/utils/ssh-agent-proxy.mjs +39 -0
  17. package/assets/devcontainer/utils/ssh-bootstrap.sh +9 -0
  18. package/dist/bin/cli.cjs +1 -1
  19. package/dist/bin/cli.mjs +1 -1
  20. package/dist/main-BDgyf2t5.cjs +5758 -0
  21. package/dist/main-J4_2Up3o.mjs +5718 -0
  22. package/dist/main-J4_2Up3o.mjs.map +1 -0
  23. package/dist/main.cjs +5 -2
  24. package/dist/main.d.cts +501 -4
  25. package/dist/main.d.cts.map +1 -1
  26. package/dist/main.d.mts +501 -4
  27. package/dist/main.d.mts.map +1 -1
  28. package/dist/main.mjs +2 -2
  29. package/docs/README.md +1 -0
  30. package/docs/architecture.md +32 -0
  31. package/docs/development.md +13 -6
  32. package/docs/features/README.md +2 -0
  33. package/docs/features/commit-signing.md +94 -0
  34. package/docs/features/generated-config-and-state.md +73 -5
  35. package/docs/features/github-auth-refresh.md +15 -2
  36. package/docs/features/lifecycle.md +103 -11
  37. package/docs/features/setup.md +66 -0
  38. package/docs/features/ssh-config-and-proxy.md +228 -7
  39. package/docs/features/start-and-shell.md +45 -5
  40. package/docs/superpowers/plans/2026-07-11-default-commit-signing.md +110 -0
  41. package/docs/superpowers/plans/2026-07-11-progress-ci-regression.md +125 -0
  42. package/docs/superpowers/plans/2026-07-17-node-ssh-agent-proxy-signing.md +132 -0
  43. package/docs/superpowers/plans/2026-07-17-runtime-secret-environment.md +174 -0
  44. package/docs/superpowers/specs/2026-07-11-default-commit-signing-design.md +416 -0
  45. package/docs/superpowers/specs/2026-07-11-progress-ci-regression-design.md +43 -0
  46. package/docs/superpowers/specs/2026-07-17-node-ssh-agent-proxy-design.md +63 -0
  47. package/docs/superpowers/specs/2026-07-17-runtime-secret-environment-design.md +194 -0
  48. package/docs/testing.md +35 -2
  49. package/docs/todo.md +2 -2
  50. package/package.json +1 -1
  51. package/src/claude-app-config.ts +304 -0
  52. package/src/cli-style.ts +43 -0
  53. package/src/codex-app-config.ts +656 -0
  54. package/src/config.ts +80 -10
  55. package/src/constants.ts +12 -0
  56. package/src/devcontainer.ts +511 -64
  57. package/src/doctor.ts +292 -30
  58. package/src/git-signing.ts +267 -0
  59. package/src/interactive-prompts.ts +692 -0
  60. package/src/list.ts +16 -2
  61. package/src/logging.ts +164 -0
  62. package/src/main.ts +1214 -63
  63. package/src/metadata.ts +52 -3
  64. package/src/package-info.ts +18 -0
  65. package/src/paths.ts +71 -11
  66. package/src/process.ts +80 -2
  67. package/src/progress.ts +593 -0
  68. package/src/purge.ts +216 -0
  69. package/src/shell.ts +25 -0
  70. package/src/ssh-config.ts +134 -16
  71. package/src/ssh-install-targets.ts +111 -0
  72. package/src/ssh-key.ts +53 -13
  73. package/src/status.ts +5 -0
  74. package/dist/main-BuEptwlL.cjs +0 -1707
  75. package/dist/main-ZFTrSVgt.mjs +0 -1685
  76. package/dist/main-ZFTrSVgt.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"main-ZFTrSVgt.mjs","names":[],"sources":["../src/coding-agents.ts","../src/constants.ts","../src/devcontainer-cli.ts","../src/process.ts","../src/doctor.ts","../src/jsonc.ts","../src/shell.ts","../src/config.ts","../src/github-git-auth.ts","../src/ssh-key.ts","../src/ssh-config.ts","../src/status.ts","../src/devcontainer.ts","../src/list.ts","../src/metadata.ts","../src/paths.ts","../src/main.ts"],"sourcesContent":["export type CodingAgentCli = 'codex' | 'opencode' | 'claude' | 'antigravity'\nexport type CodingAgentCommandAlias = CodingAgentCli | 'cc'\n\nconst CODING_AGENT_ALIASES: Record<CodingAgentCommandAlias, CodingAgentCli> = {\n codex: 'codex',\n opencode: 'opencode',\n claude: 'claude',\n cc: 'claude',\n antigravity: 'antigravity'\n}\n\nexport function codingAgentFromCommand (command: string): CodingAgentCli | undefined {\n return CODING_AGENT_ALIASES[command as CodingAgentCommandAlias]\n}\n\nexport function codingAgentBinary (agent: CodingAgentCli): string {\n if (agent === 'antigravity') {\n return 'agy'\n }\n\n return agent\n}\n","export const DEVCONTAINER_CLI_VERSION = '0.84.1'\n\nexport const BOXDOWN_CONTAINER_DEVCONTAINER_DIR = '/opt/boxdown/devcontainer'\nexport const BOXDOWN_CONTAINER_STATE_DIR = '/opt/boxdown/state'\nexport const BOXDOWN_CONTAINER_SSH_DIR = `${BOXDOWN_CONTAINER_STATE_DIR}/ssh`\nexport const BOXDOWN_CONTAINER_SSH_PUBLIC_KEY_PATH = `${BOXDOWN_CONTAINER_SSH_DIR}/id_ed25519.pub`\n\nexport const PACKAGE_NAME = 'boxdown'\n","import { existsSync, readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dirname, join, resolve } from 'node:path'\n\nimport { DEVCONTAINER_CLI_VERSION } from './constants.ts'\nimport type { WorkspaceContext } from './paths.ts'\n\nexport interface DevcontainerCliCommand {\n command: string\n argsPrefix: string[]\n path: string\n version: string\n}\n\ninterface PackageJson {\n bin?: string | Record<string, string>\n version?: string\n}\n\nfunction devcontainerBinFromPackageJson (packageJson: PackageJson): string | undefined {\n return typeof packageJson.bin === 'string' ? packageJson.bin : packageJson.bin?.devcontainer\n}\n\nexport function resolveDevcontainerCli (context: WorkspaceContext): DevcontainerCliCommand {\n const requireFromBoxdown = createRequire(join(context.packageRoot, 'package.json'))\n let packageJsonPath: string\n\n try {\n packageJsonPath = requireFromBoxdown.resolve('@devcontainers/cli/package.json')\n } catch (error) {\n throw new Error(`Boxdown's packaged @devcontainers/cli dependency is missing. Reinstall boxdown so @devcontainers/cli@${DEVCONTAINER_CLI_VERSION} is available.`, { cause: error })\n }\n\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as PackageJson\n const bin = devcontainerBinFromPackageJson(packageJson)\n\n if (packageJson.version !== DEVCONTAINER_CLI_VERSION) {\n throw new Error(`Boxdown expected @devcontainers/cli@${DEVCONTAINER_CLI_VERSION} but resolved ${packageJson.version ?? 'an unknown version'}.`)\n }\n\n if (bin === undefined) {\n throw new Error('Boxdown resolved @devcontainers/cli, but the package does not expose a devcontainer binary.')\n }\n\n const cliPath = resolve(dirname(packageJsonPath), bin)\n\n if (!existsSync(cliPath)) {\n throw new Error(`Boxdown resolved @devcontainers/cli, but its devcontainer binary is missing: ${cliPath}`)\n }\n\n return {\n command: process.execPath,\n argsPrefix: [cliPath],\n path: cliPath,\n version: packageJson.version\n }\n}\n","import { spawn } from 'node:child_process'\n\nexport interface BufferedCommandOptions {\n cwd?: string\n env?: NodeJS.ProcessEnv\n input?: string\n mirrorStdout?: 'stdout' | 'stderr' | false\n mirrorStderr?: 'stdout' | 'stderr' | false\n}\n\nexport interface CommandResult {\n code: number\n stdout: string\n stderr: string\n}\n\nfunction mergedEnv (env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n return {\n ...process.env,\n ...(env ?? {})\n }\n}\n\nfunction writeChunk (target: 'stdout' | 'stderr' | false, chunk: Buffer): void {\n if (target === 'stdout') {\n process.stdout.write(chunk)\n } else if (target === 'stderr') {\n process.stderr.write(chunk)\n }\n}\n\nexport function runBuffered (command: string, args: string[], options: BufferedCommandOptions = {}): Promise<CommandResult> {\n return new Promise((resolve) => {\n const child = spawn(command, args, {\n cwd: options.cwd,\n env: mergedEnv(options.env),\n stdio: ['pipe', 'pipe', 'pipe']\n })\n\n const stdoutChunks: Buffer[] = []\n const stderrChunks: Buffer[] = []\n\n child.stdout.on('data', (chunk: Buffer) => {\n stdoutChunks.push(chunk)\n writeChunk(options.mirrorStdout ?? 'stdout', chunk)\n })\n\n child.stderr.on('data', (chunk: Buffer) => {\n stderrChunks.push(chunk)\n writeChunk(options.mirrorStderr ?? 'stderr', chunk)\n })\n\n child.on('error', (error) => {\n resolve({\n code: 127,\n stdout: Buffer.concat(stdoutChunks).toString('utf8'),\n stderr: `${Buffer.concat(stderrChunks).toString('utf8')}${error.message}\\n`\n })\n })\n\n child.on('close', (code) => {\n resolve({\n code: code ?? 1,\n stdout: Buffer.concat(stdoutChunks).toString('utf8'),\n stderr: Buffer.concat(stderrChunks).toString('utf8')\n })\n })\n\n if (options.input !== undefined) {\n child.stdin.end(options.input)\n } else {\n child.stdin.end()\n }\n })\n}\n\nexport function runInteractive (command: string, args: string[], options: Pick<BufferedCommandOptions, 'cwd' | 'env'> = {}): Promise<number> {\n return new Promise((resolve) => {\n const child = spawn(command, args, {\n cwd: options.cwd,\n env: mergedEnv(options.env),\n stdio: 'inherit'\n })\n\n child.on('error', (error) => {\n process.stderr.write(`${error.message}\\n`)\n resolve(127)\n })\n\n child.on('close', (code) => {\n resolve(code ?? 1)\n })\n })\n}\n","import { existsSync } from 'node:fs'\n\nimport { resolveDevcontainerCli } from './devcontainer-cli.ts'\nimport type { WorkspaceContext } from './paths.ts'\nimport { runBuffered } from './process.ts'\n\nexport type DoctorLevel = 'ok' | 'fail' | 'warn'\n\nexport interface DoctorCheck {\n name: string\n level: DoctorLevel\n message: string\n}\n\nfunction nodeVersionPasses (version: string): boolean {\n const major = Number.parseInt(version.split('.')[0] ?? '', 10)\n return Number.isInteger(major) && major >= 24\n}\n\nfunction check (name: string, pass: boolean, okMessage: string, failMessage: string): DoctorCheck {\n return {\n name,\n level: pass ? 'ok' : 'fail',\n message: pass ? okMessage : failMessage\n }\n}\n\nasync function commandWorks (command: string, args: string[]): Promise<boolean> {\n const result = await runBuffered(command, args, {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n return result.code === 0\n}\n\nasync function commandExists (command: string, args: string[]): Promise<boolean> {\n const result = await runBuffered(command, args, {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n return result.code !== 127\n}\n\nexport async function runDoctorChecks (context: WorkspaceContext): Promise<DoctorCheck[]> {\n const checks: DoctorCheck[] = []\n const nodeVersion = process.versions.node\n\n checks.push(check(\n 'node',\n nodeVersionPasses(nodeVersion),\n `Node ${nodeVersion}`,\n `Node ${nodeVersion}; expected >=24.0.0`\n ))\n\n checks.push(check(\n 'devcontainers-cli',\n await packagedDevcontainerCliWorks(context),\n 'Packaged @devcontainers/cli is available',\n 'Packaged @devcontainers/cli is required but was not available'\n ))\n\n checks.push(check(\n 'docker-cli',\n await commandWorks('docker', ['--version']),\n 'Docker CLI is available',\n 'Docker CLI is required but was not available'\n ))\n\n checks.push(check(\n 'docker-daemon',\n await commandWorks('docker', ['info']),\n 'Docker daemon is reachable',\n 'Docker daemon is required but was not reachable'\n ))\n\n checks.push(check(\n 'ssh',\n await commandExists('ssh', ['-V']),\n 'ssh is available',\n 'ssh is required but was not available'\n ))\n\n checks.push(check(\n 'ssh-keygen',\n await commandExists('ssh-keygen', ['-?']),\n 'ssh-keygen is available',\n 'ssh-keygen is required but was not available'\n ))\n\n checks.push(check(\n 'assets',\n existsSync(context.assetsDevcontainerDir),\n `Devcontainer assets found at ${context.assetsDevcontainerDir}`,\n `Missing Boxdown devcontainer assets: ${context.assetsDevcontainerDir}`\n ))\n\n if (await commandWorks('gh', ['--version'])) {\n const ghAuth = await commandWorks('gh', ['auth', 'status', '--hostname', 'github.com'])\n checks.push({\n name: 'gh-auth',\n level: ghAuth ? 'ok' : 'warn',\n message: ghAuth ? 'GitHub CLI auth is available' : 'GitHub CLI is available but not authenticated'\n })\n } else {\n checks.push({\n name: 'gh',\n level: 'warn',\n message: 'GitHub CLI is optional and was not available'\n })\n }\n\n return checks\n}\n\nasync function packagedDevcontainerCliWorks (context: WorkspaceContext): Promise<boolean> {\n try {\n const cli = resolveDevcontainerCli(context)\n return await commandWorks(cli.command, [...cli.argsPrefix, '--version'])\n } catch {\n return false\n }\n}\n\nexport function doctorHasFailures (checks: DoctorCheck[]): boolean {\n return checks.some((item) => item.level === 'fail')\n}\n\nexport function formatDoctorText (checks: DoctorCheck[]): string {\n const lines = ['Boxdown doctor', '']\n\n for (const item of checks) {\n lines.push(`[${item.level}] ${item.name}: ${item.message}`)\n }\n\n lines.push('', doctorHasFailures(checks) ? 'Result: failed' : 'Result: ok')\n return `${lines.join('\\n')}\\n`\n}\n","export function stripJsonComments (input: string): string {\n let output = ''\n let inString = false\n let escaped = false\n\n for (let index = 0; index < input.length; index += 1) {\n const char = input[index]\n const next = input[index + 1]\n\n if (char === undefined) {\n break\n }\n\n if (inString) {\n output += char\n\n if (escaped) {\n escaped = false\n } else if (char === '\\\\') {\n escaped = true\n } else if (char === '\"') {\n inString = false\n }\n\n continue\n }\n\n if (char === '\"') {\n inString = true\n output += char\n continue\n }\n\n if (char === '/' && next === '/') {\n while (index < input.length && input[index] !== '\\n') {\n index += 1\n }\n\n if (input[index] === '\\n') {\n output += '\\n'\n }\n\n continue\n }\n\n if (char === '/' && next === '*') {\n index += 2\n\n while (index < input.length) {\n if (input[index] === '\\n') {\n output += '\\n'\n }\n\n if (input[index] === '*' && input[index + 1] === '/') {\n index += 1\n break\n }\n\n index += 1\n }\n\n continue\n }\n\n output += char\n }\n\n return output\n}\n\nexport function stripTrailingCommas (input: string): string {\n let output = ''\n let inString = false\n let escaped = false\n\n for (let index = 0; index < input.length; index += 1) {\n const char = input[index]\n\n if (char === undefined) {\n break\n }\n\n if (inString) {\n output += char\n\n if (escaped) {\n escaped = false\n } else if (char === '\\\\') {\n escaped = true\n } else if (char === '\"') {\n inString = false\n }\n\n continue\n }\n\n if (char === '\"') {\n inString = true\n output += char\n continue\n }\n\n if (char === ',') {\n let nextIndex = index + 1\n\n while (/\\s/.test(input[nextIndex] ?? '')) {\n nextIndex += 1\n }\n\n if (input[nextIndex] === '}' || input[nextIndex] === ']') {\n continue\n }\n }\n\n output += char\n }\n\n return output\n}\n\nexport function parseJsonc <T> (input: string): T {\n return JSON.parse(stripTrailingCommas(stripJsonComments(input))) as T\n}\n","export function shellQuote (value: string): string {\n if (value.length === 0) {\n return \"''\"\n }\n\n return `'${value.replaceAll(\"'\", \"'\\\\''\")}'`\n}\n\nexport function sshConfigQuote (value: string): string {\n return `\"${value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')}\"`\n}\n\nexport const DEFAULT_TTY_MAX_COLUMNS = 120\n\nexport function interactiveShellEnvArgs (env: NodeJS.ProcessEnv = process.env): string[] {\n return [\n `TERM=${env.TERM ?? 'xterm-256color'}`,\n 'COLORTERM=truecolor',\n `BOXDOWN_TTY_NORMALIZE=${env.BOXDOWN_TTY_NORMALIZE ?? '1'}`,\n `BOXDOWN_TTY_MAX_COLUMNS=${env.BOXDOWN_TTY_MAX_COLUMNS ?? String(DEFAULT_TTY_MAX_COLUMNS)}`\n ]\n}\n\nfunction interactiveTtySetupScript (): string {\n return [\n 'if [ -t 0 ]; then',\n ' case \"${BOXDOWN_TTY_NORMALIZE:-1}\" in',\n ' 0|false|FALSE|no|NO|off|OFF) ;;',\n ' *)',\n ' max_columns=\"${BOXDOWN_TTY_MAX_COLUMNS:-120}\"',\n ' if [ \"$max_columns\" -gt 0 ] 2>/dev/null; then',\n ' set -- $(stty size 2>/dev/null || true)',\n ' rows=\"${1:-}\"',\n ' columns=\"${2:-}\"',\n ' if [ -n \"$columns\" ] && [ \"$columns\" -gt \"$max_columns\" ] 2>/dev/null; then',\n ' stty cols \"$max_columns\" 2>/dev/null || true',\n ' export COLUMNS=\"$max_columns\"',\n ' if [ -n \"$rows\" ]; then export LINES=\"$rows\"; fi',\n ' printf \"Boxdown: terminal width clamped to %s columns (was %s). Set BOXDOWN_TTY_NORMALIZE=0 to disable.\\\\n\" \"$max_columns\" \"$columns\" >&2',\n ' fi',\n ' fi',\n ' ;;',\n ' esac',\n 'fi',\n ].join('\\n')\n}\n\nexport function interactiveShellScript (): string {\n return [\n interactiveTtySetupScript(),\n 'exec bash -i'\n ].join('\\n')\n}\n\nexport function interactiveCommandScript (): string {\n return [\n interactiveTtySetupScript(),\n 'exec \"$@\"'\n ].join('\\n')\n}\n","import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport {\n BOXDOWN_CONTAINER_DEVCONTAINER_DIR,\n BOXDOWN_CONTAINER_SSH_DIR,\n BOXDOWN_CONTAINER_SSH_PUBLIC_KEY_PATH\n} from './constants.ts'\nimport { parseJsonc } from './jsonc.ts'\nimport type { WorkspaceContext } from './paths.ts'\nimport { shellQuote } from './shell.ts'\n\nexport interface DevcontainerConfig {\n name?: string\n mounts?: string[]\n containerEnv?: Record<string, string>\n runArgs?: string[]\n initializeCommand?: string\n postCreateCommand?: string\n postStartCommand?: string\n [key: string]: unknown\n}\n\nexport function readBaseDevcontainerConfig (assetsDevcontainerDir: string): DevcontainerConfig {\n const configPath = join(assetsDevcontainerDir, 'devcontainer.json')\n return parseJsonc<DevcontainerConfig>(readFileSync(configPath, 'utf8'))\n}\n\nexport function buildGeneratedDevcontainerConfig (context: WorkspaceContext): DevcontainerConfig {\n const baseConfig = readBaseDevcontainerConfig(context.assetsDevcontainerDir)\n const mounts = Array.isArray(baseConfig.mounts)\n ? baseConfig.mounts.filter((mount): mount is string => typeof mount === 'string')\n : []\n\n const boxdownMounts = [\n `type=bind,source=${context.assetsDevcontainerDir},target=${BOXDOWN_CONTAINER_DEVCONTAINER_DIR},readonly`,\n `type=bind,source=${context.sshPublicKeyRuntimeDir},target=${BOXDOWN_CONTAINER_SSH_DIR},readonly`\n ]\n\n return {\n ...baseConfig,\n name: `Boxdown: ${context.workspaceBasename}`,\n mounts: [...mounts, ...boxdownMounts],\n initializeCommand: `BOXDOWN_WORKSPACE_FOLDER=${shellQuote(context.workspaceFolder)} bash ${shellQuote(join(context.assetsDevcontainerDir, 'hooks', 'initialize.sh'))}`,\n postCreateCommand: `bash ${shellQuote(`${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/hooks/post-create.sh`)}`,\n postStartCommand: `bash ${shellQuote(`${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/hooks/post-start.sh`)}`,\n containerEnv: {\n ...(baseConfig.containerEnv ?? {}),\n BOXDOWN_CONTAINER_WORKSPACE_FOLDER: '/workspaces/${localWorkspaceFolderBasename}',\n BOXDOWN_WORKSPACE_BASENAME: '${localWorkspaceFolderBasename}',\n DEVCONTAINER_SSH_PUBLIC_KEY_FILE: BOXDOWN_CONTAINER_SSH_PUBLIC_KEY_PATH\n }\n }\n}\n\nexport function writeGeneratedDevcontainerConfig (context: WorkspaceContext): DevcontainerConfig {\n const config = buildGeneratedDevcontainerConfig(context)\n mkdirSync(context.workspaceCacheDir, { recursive: true })\n writeFileSync(context.generatedConfigPath, `${JSON.stringify(config, null, 2)}\\n`)\n return config\n}\n\nexport function publishContainerPortFromConfig (config: DevcontainerConfig): string | undefined {\n return config.runArgs?.find((arg) => /^[0-9.]+::[0-9]+$/.test(arg))?.split('::')[1]\n}\n","import { runBuffered } from './process.ts'\n\nexport function canonicalGithubRemoteUrl (remoteUrl: string): string | undefined {\n const trimmed = remoteUrl.trim()\n const scpLike = /^git@github\\.com:([^/]+)\\/(.+)$/i.exec(trimmed)\n\n if (scpLike !== null) {\n return canonicalGithubUrlFromParts(scpLike[1], scpLike[2])\n }\n\n try {\n const parsed = new URL(trimmed)\n const protocol = parsed.protocol.toLowerCase()\n const host = parsed.hostname.toLowerCase()\n\n if (host !== 'github.com') {\n return undefined\n }\n\n if (protocol === 'ssh:' && parsed.username !== 'git') {\n return undefined\n }\n\n if (protocol !== 'https:' && protocol !== 'ssh:') {\n return undefined\n }\n\n const parts = parsed.pathname.split('/').filter((part) => part.length > 0)\n if (parts.length !== 2) {\n return undefined\n }\n\n const [owner, repo] = parts\n return canonicalGithubUrlFromParts(owner, repo)\n } catch {\n return undefined\n }\n}\n\nfunction canonicalGithubUrlFromParts (owner: string | undefined, repo: string | undefined): string | undefined {\n if (owner === undefined || repo === undefined) {\n return undefined\n }\n\n const normalizedOwner = owner.trim()\n const normalizedRepo = repo.trim().replace(/\\/+$/, '').replace(/\\.git$/i, '')\n\n if (\n normalizedOwner.length === 0 ||\n normalizedRepo.length === 0 ||\n normalizedOwner.includes('/') ||\n normalizedRepo.includes('/')\n ) {\n return undefined\n }\n\n return `https://github.com/${normalizedOwner}/${normalizedRepo}.git`\n}\n\nexport async function configureWorkspaceGithubGitAuth (workspaceFolder: string): Promise<boolean> {\n const insideWorkTree = await runWorkspaceGit(workspaceFolder, ['rev-parse', '--is-inside-work-tree'])\n\n if (insideWorkTree.code !== 0 || insideWorkTree.stdout.trim() !== 'true') {\n return false\n }\n\n const remoteConfig = await runWorkspaceGit(workspaceFolder, ['config', '--local', '--get-regexp', '^remote\\\\..*\\\\.url$'])\n\n if (remoteConfig.code !== 0) {\n return false\n }\n\n const githubRemotes = parseGithubRemoteConfig(remoteConfig.stdout)\n\n if (githubRemotes.length === 0) {\n return false\n }\n\n for (const remote of githubRemotes) {\n const fetchUrl = await runWorkspaceGit(workspaceFolder, ['remote', 'set-url', remote.name, remote.url])\n if (fetchUrl.code !== 0) {\n return false\n }\n\n const pushUrl = await runWorkspaceGit(workspaceFolder, ['remote', 'set-url', '--push', remote.name, remote.url])\n if (pushUrl.code !== 0) {\n return false\n }\n }\n\n await runWorkspaceGit(workspaceFolder, ['config', '--local', '--unset-all', 'credential.https://github.com.helper'])\n\n const resetHelper = await runWorkspaceGit(workspaceFolder, ['config', '--local', '--add', 'credential.https://github.com.helper', ''])\n if (resetHelper.code !== 0) {\n return false\n }\n\n const ghHelper = await runWorkspaceGit(workspaceFolder, ['config', '--local', '--add', 'credential.https://github.com.helper', '!gh auth git-credential'])\n if (ghHelper.code !== 0) {\n return false\n }\n\n for (const remoteUrl of new Set(githubRemotes.map((remote) => remote.url))) {\n const rewrite = await runWorkspaceGit(workspaceFolder, ['config', '--local', '--replace-all', `url.${remoteUrl}.insteadOf`, remoteUrl])\n if (rewrite.code !== 0) {\n return false\n }\n }\n\n return true\n}\n\nfunction parseGithubRemoteConfig (configOutput: string): Array<{ name: string, url: string }> {\n const remotes: Array<{ name: string, url: string }> = []\n\n for (const line of configOutput.split(/\\r?\\n/)) {\n const match = /^remote\\.(.+)\\.url\\s+(.+)$/.exec(line)\n if (match === null) {\n continue\n }\n\n const name = match[1]\n const rawUrl = match[2]\n if (name === undefined || rawUrl === undefined) {\n continue\n }\n\n const url = canonicalGithubRemoteUrl(rawUrl)\n if (url !== undefined) {\n remotes.push({ name, url })\n }\n }\n\n return remotes\n}\n\nasync function runWorkspaceGit (workspaceFolder: string, args: string[]) {\n return runBuffered('git', args, {\n cwd: workspaceFolder,\n mirrorStdout: false,\n mirrorStderr: false\n })\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\n\nimport type { WorkspaceContext } from './paths.ts'\nimport { runBuffered } from './process.ts'\n\nexport async function ensureHostSshKey (context: WorkspaceContext, quiet = false): Promise<void> {\n mkdirSync(context.sshKeyDir, { recursive: true, mode: 0o700 })\n\n if (!existsSync(context.sshKeyPath)) {\n if (!quiet) {\n process.stderr.write(`Generating Boxdown SSH identity: ${context.sshKeyPath}\\n`)\n }\n\n const result = await runBuffered('ssh-keygen', [\n '-t',\n 'ed25519',\n '-f',\n context.sshKeyPath,\n '-N',\n '',\n '-C',\n `${context.workspaceBasename}-devcontainer`\n ], {\n mirrorStdout: quiet ? false : 'stderr',\n mirrorStderr: 'stderr'\n })\n\n if (result.code !== 0) {\n throw new Error(`ssh-keygen failed while creating ${context.sshKeyPath}`)\n }\n }\n\n if (!existsSync(context.sshPublicKeyPath)) {\n const result = await runBuffered('ssh-keygen', ['-y', '-f', context.sshKeyPath], {\n mirrorStdout: false,\n mirrorStderr: 'stderr'\n })\n\n if (result.code !== 0) {\n throw new Error(`ssh-keygen failed while deriving ${context.sshPublicKeyPath}`)\n }\n\n writeFileSync(context.sshPublicKeyPath, result.stdout)\n }\n\n mkdirSync(context.sshPublicKeyRuntimeDir, { recursive: true, mode: 0o755 })\n writeFileSync(context.sshPublicKeyRuntimePath, readFileSync(context.sshPublicKeyPath, 'utf8'))\n\n chmodSync(context.sshKeyPath, 0o600)\n chmodSync(context.sshPublicKeyPath, 0o644)\n chmodSync(context.sshPublicKeyRuntimePath, 0o644)\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\nimport type { WorkspaceContext } from './paths.ts'\nimport { shellQuote, sshConfigQuote } from './shell.ts'\nimport { ensureHostSshKey } from './ssh-key.ts'\n\nexport function defaultSshAlias (workspaceBasename: string): string {\n return `${workspaceBasename}-devcontainer`\n}\n\nexport function validateSshAlias (alias: string): void {\n if (!/^[A-Za-z0-9_.-]+$/.test(alias)) {\n throw new Error(`SSH alias contains unsupported characters: ${alias}`)\n }\n}\n\nexport function defaultSshConfigPath (env: NodeJS.ProcessEnv = process.env): string {\n return env.BOXDOWN_SSH_CONFIG ?? env.DEVCONTAINER_SSH_CONFIG ?? join(env.HOME ?? '', '.ssh', 'config')\n}\n\nexport function buildProxyCommand (context: WorkspaceContext, alias: string): string {\n const cliPath = join(context.packageRoot, 'dist', 'bin', 'cli.cjs')\n\n return `${shellQuote(process.execPath)} ${shellQuote(cliPath)} ssh-proxy --workspace ${shellQuote(context.workspaceFolder)} --alias ${shellQuote(alias)}`\n}\n\nexport function buildSshConfigBlock (context: WorkspaceContext, alias: string): string {\n validateSshAlias(alias)\n\n return [\n `# BEGIN ${alias} boxdown devcontainer ssh`,\n `Host ${alias}`,\n ` HostName ${alias}`,\n ' User node',\n ' IdentityFile none',\n ` IdentityFile ${sshConfigQuote(context.sshKeyPath)}`,\n ' IdentitiesOnly yes',\n ` ProxyCommand ${buildProxyCommand(context, alias)}`,\n ' StrictHostKeyChecking no',\n ' UserKnownHostsFile /dev/null',\n ' LogLevel ERROR',\n `# END ${alias} boxdown devcontainer ssh`,\n ''\n ].join('\\n')\n}\n\nexport function replaceSshConfigBlock (existingConfig: string, alias: string, block: string): string {\n const begin = `# BEGIN ${alias} boxdown devcontainer ssh`\n const end = `# END ${alias} boxdown devcontainer ssh`\n const lines = existingConfig.split(/\\r?\\n/)\n const nextLines: string[] = []\n let skipping = false\n\n for (const line of lines) {\n if (line === begin) {\n skipping = true\n continue\n }\n\n if (line === end) {\n skipping = false\n continue\n }\n\n if (!skipping) {\n nextLines.push(line)\n }\n }\n\n while (nextLines.length > 0 && nextLines[nextLines.length - 1] === '') {\n nextLines.pop()\n }\n\n return `${nextLines.join('\\n')}${nextLines.length > 0 ? '\\n\\n' : ''}${block}`\n}\n\nexport async function installSshConfig (context: WorkspaceContext, alias: string, options: { quiet?: boolean, configPath?: string } = {}): Promise<void> {\n validateSshAlias(alias)\n await ensureHostSshKey(context, options.quiet ?? false)\n\n const sshConfigPath = options.configPath ?? defaultSshConfigPath()\n const sshConfigDir = dirname(sshConfigPath)\n mkdirSync(sshConfigDir, { recursive: true, mode: 0o700 })\n\n if (!existsSync(sshConfigPath)) {\n writeFileSync(sshConfigPath, '')\n }\n\n chmodSync(sshConfigDir, 0o700)\n chmodSync(sshConfigPath, 0o600)\n\n const existingConfig = readFileSync(sshConfigPath, 'utf8')\n const block = buildSshConfigBlock(context, alias)\n const nextConfig = replaceSshConfigBlock(existingConfig, alias, block)\n\n if (nextConfig !== existingConfig) {\n writeFileSync(sshConfigPath, nextConfig)\n if (!options.quiet) {\n process.stdout.write(`Installed SSH alias: ${alias}\\n`)\n }\n } else if (!options.quiet) {\n process.stdout.write(`SSH alias already up to date: ${alias}\\n`)\n }\n\n chmodSync(sshConfigPath, 0o600)\n\n if (!options.quiet) {\n process.stdout.write(`SSH config: ${sshConfigPath}\\n`)\n process.stdout.write(`Identity file: ${context.sshKeyPath}\\n\\n`)\n process.stdout.write(`Validate with:\\n ssh ${alias} 'whoami && pwd'\\n`)\n }\n}\n","import { readFileSync } from 'node:fs'\n\nimport type { WorkspaceContext } from './paths.ts'\nimport { buildSshConfigBlock, defaultSshConfigPath } from './ssh-config.ts'\n\nexport type SshAliasSource = 'default' | 'provided'\nexport type SshManagedBlockState = 'missing' | 'installed' | 'outdated'\n\nexport interface ContainerSummary {\n id: string\n name?: string\n state?: string\n status?: string\n localFolder?: string\n}\n\nexport interface StatusInfo {\n workspace: {\n folder: string\n basename: string\n id: string\n }\n ssh: {\n alias: string\n aliasSource: SshAliasSource\n configPath: string\n configExists: boolean\n managedBlockState: SshManagedBlockState\n keyPath: string\n keyExists: boolean\n publicKeyPath: string\n publicKeyExists: boolean\n publicKeyRuntimePath: string\n publicKeyRuntimeExists: boolean\n }\n paths: {\n cacheRoot: string\n dataRoot: string\n workspaceCacheDir: string\n workspaceDataDir: string\n generatedConfigPath: string\n generatedConfigExists: boolean\n assetsDevcontainerDir: string\n assetsDevcontainerExists: boolean\n }\n container: {\n found: boolean\n running: boolean\n id?: string\n name?: string\n state?: string\n status?: string\n }\n}\n\nexport interface SshConfigStatus {\n configPath: string\n configExists: boolean\n managedBlockState: SshManagedBlockState\n}\n\ninterface DockerPsJson {\n ID?: unknown\n Names?: unknown\n State?: unknown\n Status?: unknown\n Labels?: unknown\n}\n\nfunction dockerLabelsFromString (labels: string): Record<string, string> {\n return Object.fromEntries(labels\n .split(',')\n .map((label) => label.trim())\n .filter((label) => label.length > 0)\n .map((label) => {\n const separator = label.indexOf('=')\n return separator === -1 ? [label, ''] : [label.slice(0, separator), label.slice(separator + 1)]\n }))\n}\n\nexport function parseDockerPsJsonLines (output: string): ContainerSummary[] {\n const lines = output.split(/\\r?\\n/).filter((line) => line.trim().length > 0)\n\n return lines.map((line) => {\n let parsed: DockerPsJson\n\n try {\n parsed = JSON.parse(line) as DockerPsJson\n } catch {\n throw new Error(`Could not parse docker ps output: ${line}`)\n }\n\n if (typeof parsed.ID !== 'string' || parsed.ID.length === 0) {\n throw new Error(`Docker ps output is missing container ID: ${line}`)\n }\n\n return {\n id: parsed.ID,\n name: typeof parsed.Names === 'string' && parsed.Names.length > 0 ? parsed.Names : undefined,\n state: typeof parsed.State === 'string' && parsed.State.length > 0 ? parsed.State : undefined,\n status: typeof parsed.Status === 'string' && parsed.Status.length > 0 ? parsed.Status : undefined,\n localFolder: typeof parsed.Labels === 'string' ? dockerLabelsFromString(parsed.Labels)['devcontainer.local_folder'] : undefined\n }\n })\n}\n\nfunction readFileUtf8 (path: string): string {\n return readFileSync(path, 'utf8')\n}\n\nfunction managedSshBlockMarkers (alias: string): { begin: string, end: string } {\n return {\n begin: `# BEGIN ${alias} boxdown devcontainer ssh`,\n end: `# END ${alias} boxdown devcontainer ssh`\n }\n}\n\nfunction findManagedSshConfigBlock (config: string, alias: string): string | undefined {\n const { begin, end } = managedSshBlockMarkers(alias)\n const beginIndex = config.indexOf(begin)\n\n if (beginIndex === -1) {\n return undefined\n }\n\n const endIndex = config.indexOf(end, beginIndex)\n\n if (endIndex === -1) {\n return ''\n }\n\n const afterEndMarkerIndex = endIndex + end.length\n const afterEndLineIndex = config[afterEndMarkerIndex] === '\\n' ? afterEndMarkerIndex + 1 : afterEndMarkerIndex\n\n return config.slice(beginIndex, afterEndLineIndex)\n}\n\nexport function inspectSshConfigStatus (\n context: WorkspaceContext,\n alias: string,\n configPath: string,\n exists: (path: string) => boolean,\n readFile: (path: string) => string = readFileUtf8\n): SshConfigStatus {\n const configExists = exists(configPath)\n\n if (!configExists) {\n return {\n configPath,\n configExists,\n managedBlockState: 'missing'\n }\n }\n\n const config = readFile(configPath)\n const managedBlock = findManagedSshConfigBlock(config, alias)\n\n if (managedBlock === undefined) {\n return {\n configPath,\n configExists,\n managedBlockState: 'missing'\n }\n }\n\n return {\n configPath,\n configExists,\n managedBlockState: managedBlock === buildSshConfigBlock(context, alias) ? 'installed' : 'outdated'\n }\n}\n\nexport function createStatusInfo (\n context: WorkspaceContext,\n alias: string,\n container: ContainerSummary | undefined,\n exists: (path: string) => boolean,\n options: {\n aliasSource?: SshAliasSource\n sshConfigPath?: string\n readFile?: (path: string) => string\n } = {}\n): StatusInfo {\n const state = container?.state?.toLowerCase()\n const sshConfig = inspectSshConfigStatus(\n context,\n alias,\n options.sshConfigPath ?? defaultSshConfigPath(),\n exists,\n options.readFile\n )\n\n return {\n workspace: {\n folder: context.workspaceFolder,\n basename: context.workspaceBasename,\n id: context.workspaceId\n },\n ssh: {\n alias,\n aliasSource: options.aliasSource ?? 'provided',\n configPath: sshConfig.configPath,\n configExists: sshConfig.configExists,\n managedBlockState: sshConfig.managedBlockState,\n keyPath: context.sshKeyPath,\n keyExists: exists(context.sshKeyPath),\n publicKeyPath: context.sshPublicKeyPath,\n publicKeyExists: exists(context.sshPublicKeyPath),\n publicKeyRuntimePath: context.sshPublicKeyRuntimePath,\n publicKeyRuntimeExists: exists(context.sshPublicKeyRuntimePath)\n },\n paths: {\n cacheRoot: context.cacheRoot,\n dataRoot: context.dataRoot,\n workspaceCacheDir: context.workspaceCacheDir,\n workspaceDataDir: context.workspaceDataDir,\n generatedConfigPath: context.generatedConfigPath,\n generatedConfigExists: exists(context.generatedConfigPath),\n assetsDevcontainerDir: context.assetsDevcontainerDir,\n assetsDevcontainerExists: exists(context.assetsDevcontainerDir)\n },\n container: {\n found: container !== undefined,\n running: state === 'running',\n id: container?.id,\n name: container?.name,\n state: container?.state,\n status: container?.status\n }\n }\n}\n\nexport function statusIsHealthy (status: StatusInfo): boolean {\n return status.paths.generatedConfigExists &&\n status.paths.assetsDevcontainerExists &&\n status.ssh.keyExists &&\n status.ssh.publicKeyExists &&\n status.ssh.publicKeyRuntimeExists &&\n status.container.found &&\n status.container.running\n}\n\nconst color = {\n green: '\\u001B[32m',\n red: '\\u001B[31m',\n reset: '\\u001B[0m'\n}\n\nfunction colorize (value: string, colorName: 'green' | 'red', enabled: boolean): string {\n if (!enabled) {\n return value\n }\n\n return `${color[colorName]}${value}${color.reset}`\n}\n\nfunction existenceText (value: boolean, colorEnabled: boolean): string {\n return colorize(value ? 'exists' : 'missing', value ? 'green' : 'red', colorEnabled)\n}\n\nfunction runningText (value: boolean, colorEnabled: boolean): string {\n return colorize(value ? 'yes' : 'no', value ? 'green' : 'red', colorEnabled)\n}\n\nfunction managedBlockText (state: SshManagedBlockState, colorEnabled: boolean): string {\n return colorize(state, state === 'installed' ? 'green' : 'red', colorEnabled)\n}\n\nfunction aliasSourceText (source: SshAliasSource): string {\n return source === 'default' ? 'computed default' : 'provided'\n}\n\nfunction installedText (state: SshManagedBlockState): string {\n return state === 'installed' ? 'installed' : 'not installed'\n}\n\nfunction stateText (state: string, healthy: boolean, colorEnabled: boolean): string {\n return colorize(state, healthy ? 'green' : 'red', colorEnabled)\n}\n\nexport function formatStatusText (status: StatusInfo, options: { color?: boolean } = {}): string {\n const colorEnabled = options.color ?? false\n const containerState = status.container.found ? status.container.state ?? 'unknown' : 'absent'\n const healthy = statusIsHealthy(status)\n const lines = [\n 'Boxdown status',\n '',\n 'Workspace:',\n ` Path: ${status.workspace.folder}`,\n ` Name: ${status.workspace.basename}`,\n ` ID: ${status.workspace.id}`,\n ` SSH alias: ${status.ssh.alias} (${aliasSourceText(status.ssh.aliasSource)}; ${installedText(status.ssh.managedBlockState)})`,\n '',\n 'Paths:',\n ` Cache root: ${status.paths.cacheRoot}`,\n ` Data root: ${status.paths.dataRoot}`,\n ` Workspace cache: ${status.paths.workspaceCacheDir}`,\n ` Workspace data: ${status.paths.workspaceDataDir}`,\n ` Generated config: ${status.paths.generatedConfigPath} (${existenceText(status.paths.generatedConfigExists, colorEnabled)})`,\n ` Devcontainer assets: ${status.paths.assetsDevcontainerDir} (${existenceText(status.paths.assetsDevcontainerExists, colorEnabled)})`,\n '',\n 'SSH:',\n ` SSH config: ${status.ssh.configPath} (${existenceText(status.ssh.configExists, colorEnabled)})`,\n ` Boxdown SSH block: ${managedBlockText(status.ssh.managedBlockState, colorEnabled)}`,\n ` Private key: ${status.ssh.keyPath} (${existenceText(status.ssh.keyExists, colorEnabled)})`,\n ` Public key: ${status.ssh.publicKeyPath} (${existenceText(status.ssh.publicKeyExists, colorEnabled)})`,\n ` Runtime public key: ${status.ssh.publicKeyRuntimePath} (${existenceText(status.ssh.publicKeyRuntimeExists, colorEnabled)})`,\n '',\n 'Container:',\n ` State: ${stateText(containerState, healthy, colorEnabled)}`,\n ` Running: ${runningText(status.container.running, colorEnabled)}`\n ]\n\n if (status.container.id !== undefined) {\n lines.push(` ID: ${status.container.id}`)\n }\n\n if (status.container.name !== undefined) {\n lines.push(` Name: ${status.container.name}`)\n }\n\n if (status.container.status !== undefined) {\n lines.push(` Docker status: ${status.container.status}`)\n }\n\n return `${lines.join('\\n')}\\n`\n}\n","import {\n BOXDOWN_CONTAINER_DEVCONTAINER_DIR\n} from './constants.ts'\nimport { buildGeneratedDevcontainerConfig, publishContainerPortFromConfig, writeGeneratedDevcontainerConfig } from './config.ts'\nimport { codingAgentBinary, type CodingAgentCli } from './coding-agents.ts'\nimport { resolveDevcontainerCli } from './devcontainer-cli.ts'\nimport { configureWorkspaceGithubGitAuth } from './github-git-auth.ts'\nimport type { WorkspaceContext } from './paths.ts'\nimport { runBuffered, runInteractive } from './process.ts'\nimport { interactiveCommandScript, interactiveShellEnvArgs, interactiveShellScript } from './shell.ts'\nimport { ensureHostSshKey } from './ssh-key.ts'\nimport { type ContainerSummary, parseDockerPsJsonLines } from './status.ts'\n\nexport interface StartOptions {\n recreate?: boolean\n proxyMode?: boolean\n reuseRunning?: boolean\n}\n\nfunction devcontainerWorkspaceArgs (context: WorkspaceContext): string[] {\n return [\n '--workspace-folder',\n context.workspaceFolder,\n '--override-config',\n context.generatedConfigPath\n ]\n}\n\nfunction log (message: string, proxyMode = false): void {\n if (proxyMode) {\n process.stderr.write(`${message}\\n`)\n } else {\n process.stdout.write(`${message}\\n`)\n }\n}\n\nexport function parseContainerIdFromUpOutput (output: string): string | undefined {\n return /\"containerId\"\\s*:\\s*\"([^\"]+)\"/.exec(output)?.[1]\n}\n\nexport async function findWorkspaceContainer (context: WorkspaceContext): Promise<ContainerSummary | undefined> {\n const result = await runBuffered('docker', [\n 'ps',\n '-a',\n '--filter',\n `label=devcontainer.local_folder=${context.workspaceFolder}`,\n '--format',\n '{{json .}}'\n ], {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (result.code !== 0) {\n throw new Error(`Could not inspect devcontainer for ${context.workspaceFolder}`)\n }\n\n return parseDockerPsJsonLines(result.stdout)[0]\n}\n\nexport async function listWorkspaceContainers (): Promise<ContainerSummary[] | undefined> {\n const result = await runBuffered('docker', [\n 'ps',\n '-a',\n '--filter',\n 'label=devcontainer.local_folder',\n '--format',\n '{{json .}}'\n ], {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (result.code !== 0) {\n return undefined\n }\n\n return parseDockerPsJsonLines(result.stdout)\n}\n\nexport async function findRunningContainerId (context: WorkspaceContext): Promise<string | undefined> {\n const result = await runBuffered('docker', [\n 'ps',\n '--filter',\n `label=devcontainer.local_folder=${context.workspaceFolder}`,\n '--format',\n '{{.ID}}'\n ], {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (result.code !== 0) {\n return undefined\n }\n\n return result.stdout.split(/\\r?\\n/).find((line) => line.length > 0)\n}\n\nexport async function stopWorkspaceContainer (context: WorkspaceContext): Promise<void> {\n const container = await findWorkspaceContainer(context)\n\n if (container === undefined) {\n process.stdout.write(`No devcontainer found for: ${context.workspaceFolder}\\n`)\n return\n }\n\n if (container.state?.toLowerCase() !== 'running') {\n process.stdout.write(`Devcontainer is not running for: ${context.workspaceFolder}\\n`)\n return\n }\n\n const result = await runBuffered('docker', ['stop', container.id], {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (result.code !== 0) {\n throw new Error(`Could not stop devcontainer ${container.id}`)\n }\n\n process.stdout.write(`Stopped devcontainer: ${container.id}\\n`)\n}\n\nexport async function removeWorkspaceContainer (context: WorkspaceContext): Promise<void> {\n const container = await findWorkspaceContainer(context)\n\n if (container === undefined) {\n process.stdout.write(`No devcontainer found for: ${context.workspaceFolder}\\n`)\n return\n }\n\n const result = await runBuffered('docker', ['rm', '-f', container.id], {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (result.code !== 0) {\n throw new Error(`Could not remove devcontainer ${container.id}`)\n }\n\n process.stdout.write(`Removed devcontainer: ${container.id}\\n`)\n}\n\nexport async function startDevcontainer (context: WorkspaceContext, options: StartOptions = {}): Promise<string> {\n await ensureHostSshKey(context, options.proxyMode ?? false)\n writeGeneratedDevcontainerConfig(context)\n\n if (options.reuseRunning === true && options.recreate !== true) {\n const runningContainerId = await findRunningContainerId(context)\n\n if (runningContainerId !== undefined) {\n log(`Using running devcontainer for: ${context.workspaceFolder}`, options.proxyMode)\n return runningContainerId\n }\n }\n\n const cli = resolveDevcontainerCli(context)\n log(`Starting devcontainer for: ${context.workspaceFolder}`, options.proxyMode)\n\n const args = [\n 'up',\n ...devcontainerWorkspaceArgs(context)\n ]\n\n if (options.recreate === true) {\n args.push('--remove-existing-container')\n log('Removing existing dev container so create-time settings apply.', options.proxyMode)\n }\n\n const result = await runBuffered(cli.command, [...cli.argsPrefix, ...args], {\n mirrorStdout: options.proxyMode === true ? 'stderr' : 'stdout',\n mirrorStderr: 'stderr'\n })\n\n if (result.code !== 0) {\n throw new Error(`devcontainer up failed for ${context.workspaceFolder}`)\n }\n\n const containerId = parseContainerIdFromUpOutput(`${result.stdout}\\n${result.stderr}`) ?? await findRunningContainerId(context)\n\n if (containerId === undefined) {\n throw new Error(`Could not resolve devcontainer ID for ${context.workspaceFolder}`)\n }\n\n return containerId\n}\n\nexport async function printPortHint (context: WorkspaceContext, containerId: string): Promise<void> {\n const config = buildGeneratedDevcontainerConfig(context)\n const containerPort = publishContainerPortFromConfig(config)\n\n if (containerPort === undefined) {\n process.stderr.write('Warning: could not find a runArgs publish port.\\n')\n return\n }\n\n const result = await runBuffered('docker', ['port', containerId, `${containerPort}/tcp`], {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n const hostBinding = result.stdout.split(/\\r?\\n/).find((line) => line.length > 0)\n\n if (result.code === 0 && hostBinding !== undefined) {\n process.stdout.write(`\\nDev server available at: http://${hostBinding}\\n\\n`)\n } else {\n process.stderr.write(`Warning: container is running but port ${containerPort}/tcp is not mapped.\\n`)\n }\n}\n\nexport async function openShell (context: WorkspaceContext): Promise<number> {\n const cli = resolveDevcontainerCli(context)\n process.stdout.write('Dropping into container shell...\\n')\n\n return runInteractive(cli.command, [\n ...cli.argsPrefix,\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n 'env',\n ...interactiveShellEnvArgs(),\n 'bash',\n '-c',\n interactiveShellScript()\n ])\n}\n\nexport function codingAgentDevcontainerExecArgs (context: WorkspaceContext, agent: CodingAgentCli, agentArgs: string[] = []): string[] {\n return [\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n 'env',\n ...interactiveShellEnvArgs(),\n 'bash',\n '-c',\n interactiveCommandScript(),\n 'boxdown-agent',\n codingAgentBinary(agent),\n ...agentArgs\n ]\n}\n\nexport async function openCodingAgentCli (context: WorkspaceContext, agent: CodingAgentCli, agentArgs: string[] = []): Promise<number> {\n const cli = resolveDevcontainerCli(context)\n process.stdout.write(`Dropping into ${codingAgentBinary(agent)} inside the devcontainer...\\n`)\n\n return runInteractive(cli.command, [\n ...cli.argsPrefix,\n ...codingAgentDevcontainerExecArgs(context, agent, agentArgs)\n ])\n}\n\nexport async function ensureContainerSshRuntime (context: WorkspaceContext): Promise<void> {\n const cli = resolveDevcontainerCli(context)\n const result = await runBuffered(cli.command, [\n ...cli.argsPrefix,\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n 'bash',\n `${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/utils/ssh-bootstrap.sh`,\n 'runtime'\n ], {\n mirrorStdout: 'stderr',\n mirrorStderr: 'stderr'\n })\n\n if (result.code !== 0) {\n throw new Error('Failed to prepare devcontainer SSH runtime')\n }\n}\n\nexport async function refreshContainerCodingAgentClis (context: WorkspaceContext, proxyMode = false, agents: CodingAgentCli[] = []): Promise<void> {\n const cli = resolveDevcontainerCli(context)\n const result = await runBuffered(cli.command, [\n ...cli.argsPrefix,\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n 'bash',\n `${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/utils/coding-agent-cli-update.sh`,\n 'maybe-update',\n ...agents\n ], {\n mirrorStdout: proxyMode ? 'stderr' : 'stdout',\n mirrorStderr: 'stderr'\n })\n\n if (result.code !== 0) {\n process.stderr.write('Warning: could not refresh one or more coding-agent CLIs inside the devcontainer.\\n')\n }\n}\n\nexport async function runSshdProxy (containerId: string): Promise<number> {\n return runInteractive('docker', [\n 'exec',\n '-i',\n containerId,\n '/usr/sbin/sshd',\n '-i',\n '-o',\n 'LogLevel=QUIET',\n '-o',\n 'PubkeyAuthentication=yes',\n '-o',\n 'PasswordAuthentication=no',\n '-o',\n 'KbdInteractiveAuthentication=no',\n '-o',\n 'AllowTcpForwarding=yes',\n '-o',\n 'AllowStreamLocalForwarding=yes',\n '-o',\n 'PermitTTY=yes'\n ])\n}\n\nasync function hostGhTokenOrEmpty (): Promise<string> {\n const result = await runBuffered('gh', ['auth', 'token'], {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (result.code !== 0) {\n return ''\n }\n\n return result.stdout.trim()\n}\n\nexport async function refreshContainerGhAuth (context: WorkspaceContext): Promise<void> {\n await ensureHostSshKey(context, true)\n writeGeneratedDevcontainerConfig(context)\n\n const token = await hostGhTokenOrEmpty()\n\n if (token.length === 0) {\n return\n }\n\n const cli = resolveDevcontainerCli(context)\n const login = await runBuffered(cli.command, [\n ...cli.argsPrefix,\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n 'gh',\n 'auth',\n 'login',\n '--hostname',\n 'github.com',\n '--git-protocol',\n 'https',\n '--with-token',\n '--insecure-storage'\n ], {\n input: `${token}\\n`,\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (login.code !== 0) {\n process.stderr.write('Warning: could not refresh GitHub CLI auth inside the devcontainer.\\n')\n return\n }\n\n const gitAuthConfigured = await configureWorkspaceGithubGitAuth(context.workspaceFolder)\n if (!gitAuthConfigured) {\n process.stderr.write('Warning: GitHub CLI auth refreshed, but GitHub Git auth was not configured for this workspace.\\n')\n }\n\n const verify = await runBuffered(cli.command, [\n ...cli.argsPrefix,\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n 'gh',\n 'auth',\n 'status',\n '--hostname',\n 'github.com'\n ], {\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (verify.code === 0) {\n process.stdout.write('GitHub CLI auth refreshed inside the devcontainer.\\n')\n } else {\n process.stderr.write('Warning: GitHub CLI auth refresh completed, but verification failed.\\n')\n }\n}\n","import type { WorkspaceMetadata } from './metadata.ts'\nimport type { ContainerSummary } from './status.ts'\n\nexport interface WorkspaceListEntry extends WorkspaceMetadata {\n repoExists: boolean\n state: string\n container: {\n found: boolean\n running: boolean\n id?: string\n name?: string\n state?: string\n status?: string\n }\n}\n\nfunction containerState (container: ContainerSummary | undefined, dockerAvailable: boolean): string {\n if (!dockerAvailable) {\n return 'unknown'\n }\n\n return container?.state?.toLowerCase() ?? 'absent'\n}\n\nfunction displayState (repoExists: boolean, container: ContainerSummary | undefined, dockerAvailable: boolean): string {\n if (!repoExists) {\n return 'missing'\n }\n\n return containerState(container, dockerAvailable)\n}\n\nexport function createWorkspaceListEntries (\n metadata: WorkspaceMetadata[],\n containers: ContainerSummary[] | undefined,\n exists: (path: string) => boolean\n): WorkspaceListEntry[] {\n const dockerAvailable = containers !== undefined\n const containersByWorkspace = new Map(\n (containers ?? [])\n .filter((container) => container.localFolder !== undefined)\n .map((container) => [container.localFolder as string, container])\n )\n\n return metadata\n .map((item) => {\n const container = containersByWorkspace.get(item.workspaceFolder)\n const repoExists = exists(item.workspaceFolder)\n const state = displayState(repoExists, container, dockerAvailable)\n\n return {\n ...item,\n repoExists,\n state,\n container: {\n found: container !== undefined,\n running: container?.state?.toLowerCase() === 'running',\n id: container?.id,\n name: container?.name,\n state: container?.state ?? (dockerAvailable ? undefined : 'unknown'),\n status: container?.status\n }\n }\n })\n .sort((a, b) => a.workspaceBasename.localeCompare(b.workspaceBasename) || a.workspaceFolder.localeCompare(b.workspaceFolder))\n}\n\nfunction pad (value: string, width: number): string {\n return value.padEnd(width, ' ')\n}\n\nfunction containerLabel (entry: WorkspaceListEntry): string {\n if (!entry.container.found) {\n return '-'\n }\n\n return entry.container.name ?? entry.container.id ?? '-'\n}\n\nexport function formatWorkspaceListText (entries: WorkspaceListEntry[]): string {\n if (entries.length === 0) {\n return 'Boxdown list\\n\\nNo Boxdown workspaces found.\\n'\n }\n\n const rows = entries.map((entry) => [\n entry.state,\n entry.workspaceBasename,\n entry.workspaceFolder,\n entry.sshAlias,\n containerLabel(entry)\n ])\n const headers = ['STATE', 'REPO', 'PATH', 'SSH ALIAS', 'CONTAINER']\n const widths = headers.map((header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0)))\n const lines = [\n 'Boxdown list',\n '',\n headers.map((header, index) => pad(header, widths[index] ?? header.length)).join(' '),\n rows.map((row) => row.map((value, index) => pad(value, widths[index] ?? value.length)).join(' ')).join('\\n')\n ]\n\n return `${lines.join('\\n')}\\n`\n}\n","import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { WorkspaceContext } from './paths.ts'\n\nexport const WORKSPACE_METADATA_VERSION = 1\n\nexport interface WorkspaceMetadata {\n version: 1\n workspaceId: string\n workspaceFolder: string\n workspaceBasename: string\n sshAlias: string\n firstSeenAt: string\n lastSeenAt: string\n}\n\nfunction isWorkspaceMetadata (value: unknown): value is WorkspaceMetadata {\n if (value === null || typeof value !== 'object') {\n return false\n }\n\n const candidate = value as Record<string, unknown>\n\n return candidate.version === WORKSPACE_METADATA_VERSION &&\n typeof candidate.workspaceId === 'string' &&\n typeof candidate.workspaceFolder === 'string' &&\n typeof candidate.workspaceBasename === 'string' &&\n typeof candidate.sshAlias === 'string' &&\n typeof candidate.firstSeenAt === 'string' &&\n typeof candidate.lastSeenAt === 'string'\n}\n\nexport function workspaceMetadataPath (context: WorkspaceContext): string {\n return join(context.workspaceDataDir, 'metadata.json')\n}\n\nexport function readWorkspaceMetadataFile (path: string): WorkspaceMetadata {\n const parsed = JSON.parse(readFileSync(path, 'utf8')) as unknown\n\n if (!isWorkspaceMetadata(parsed)) {\n throw new Error(`Invalid Boxdown workspace metadata: ${path}`)\n }\n\n return parsed\n}\n\nexport function writeWorkspaceMetadata (context: WorkspaceContext, sshAlias: string, now = new Date()): WorkspaceMetadata {\n const metadataPath = workspaceMetadataPath(context)\n const timestamp = now.toISOString()\n let firstSeenAt = timestamp\n\n if (existsSync(metadataPath)) {\n firstSeenAt = readWorkspaceMetadataFile(metadataPath).firstSeenAt\n }\n\n const metadata: WorkspaceMetadata = {\n version: WORKSPACE_METADATA_VERSION,\n workspaceId: context.workspaceId,\n workspaceFolder: context.workspaceFolder,\n workspaceBasename: context.workspaceBasename,\n sshAlias,\n firstSeenAt,\n lastSeenAt: timestamp\n }\n\n mkdirSync(context.workspaceDataDir, { recursive: true })\n writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}\\n`)\n return metadata\n}\n\nexport function listWorkspaceMetadata (dataRoot: string): WorkspaceMetadata[] {\n const workspacesDir = join(dataRoot, 'workspaces')\n\n if (!existsSync(workspacesDir)) {\n return []\n }\n\n return readdirSync(workspacesDir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => join(workspacesDir, entry.name, 'metadata.json'))\n .filter((metadataPath) => existsSync(metadataPath))\n .map((metadataPath) => readWorkspaceMetadataFile(metadataPath))\n}\n","import { createHash } from 'node:crypto'\nimport { existsSync, realpathSync, statSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { PACKAGE_NAME } from './constants.ts'\n\nexport interface WorkspaceContextOptions {\n workspace?: string\n cwd?: string\n env?: NodeJS.ProcessEnv\n packageRoot?: string\n assetsDevcontainerDir?: string\n}\n\nexport interface WorkspaceContext {\n workspaceFolder: string\n workspaceBasename: string\n workspaceId: string\n packageRoot: string\n assetsDevcontainerDir: string\n cacheRoot: string\n dataRoot: string\n workspaceCacheDir: string\n workspaceDataDir: string\n generatedConfigPath: string\n sshKeyDir: string\n sshKeyPath: string\n sshPublicKeyPath: string\n sshPublicKeyRuntimeDir: string\n sshPublicKeyRuntimePath: string\n}\n\nexport function packageRootFromImportMeta (importMetaUrl = import.meta.url): string {\n return dirname(dirname(fileURLToPath(importMetaUrl)))\n}\n\nexport function workspaceIdFor (workspaceFolder: string): string {\n return createHash('sha256').update(workspaceFolder).digest('hex').slice(0, 16)\n}\n\nexport function resolveWorkspaceFolder (workspace: string | undefined, cwd = process.cwd()): string {\n const candidate = resolve(cwd, workspace ?? '.')\n\n if (!existsSync(candidate)) {\n throw new Error(`Workspace does not exist: ${candidate}`)\n }\n\n if (!statSync(candidate).isDirectory()) {\n throw new Error(`Workspace is not a directory: ${candidate}`)\n }\n\n return realpathSync(candidate)\n}\n\nexport function defaultCacheRoot (env: NodeJS.ProcessEnv = process.env): string {\n if (env.BOXDOWN_CACHE_HOME) {\n return env.BOXDOWN_CACHE_HOME\n }\n\n if (env.XDG_CACHE_HOME) {\n return join(env.XDG_CACHE_HOME, PACKAGE_NAME)\n }\n\n return join(homedir(), '.cache', PACKAGE_NAME)\n}\n\nexport function defaultDataRoot (env: NodeJS.ProcessEnv = process.env): string {\n if (env.BOXDOWN_DATA_HOME) {\n return env.BOXDOWN_DATA_HOME\n }\n\n if (env.XDG_DATA_HOME) {\n return join(env.XDG_DATA_HOME, PACKAGE_NAME)\n }\n\n return join(homedir(), '.local', 'share', PACKAGE_NAME)\n}\n\nexport function createWorkspaceContext (options: WorkspaceContextOptions = {}): WorkspaceContext {\n const env = options.env ?? process.env\n const workspaceFolder = resolveWorkspaceFolder(options.workspace, options.cwd)\n const workspaceBasename = basename(workspaceFolder)\n const workspaceId = workspaceIdFor(workspaceFolder)\n const packageRoot = options.packageRoot ?? packageRootFromImportMeta()\n const assetsDevcontainerDir = options.assetsDevcontainerDir ?? env.BOXDOWN_DEVCONTAINER_ASSETS_DIR ?? join(packageRoot, 'assets', 'devcontainer')\n const cacheRoot = defaultCacheRoot(env)\n const dataRoot = defaultDataRoot(env)\n const workspaceCacheDir = join(cacheRoot, 'workspaces', workspaceId)\n const workspaceDataDir = join(dataRoot, 'workspaces', workspaceId)\n\n return {\n workspaceFolder,\n workspaceBasename,\n workspaceId,\n packageRoot,\n assetsDevcontainerDir,\n cacheRoot,\n dataRoot,\n workspaceCacheDir,\n workspaceDataDir,\n generatedConfigPath: join(workspaceCacheDir, 'devcontainer.json'),\n sshKeyDir: join(workspaceDataDir, 'ssh'),\n sshKeyPath: join(workspaceDataDir, 'ssh', 'id_ed25519'),\n sshPublicKeyPath: join(workspaceDataDir, 'ssh', 'id_ed25519.pub'),\n sshPublicKeyRuntimeDir: join(workspaceDataDir, 'ssh-public'),\n sshPublicKeyRuntimePath: join(workspaceDataDir, 'ssh-public', 'id_ed25519.pub')\n }\n}\n","import { existsSync } from 'node:fs'\n\nimport { codingAgentFromCommand, type CodingAgentCli } from './coding-agents.ts'\nimport { doctorHasFailures, formatDoctorText, runDoctorChecks } from './doctor.ts'\nimport { startDevcontainer, printPortHint, openShell, openCodingAgentCli, ensureContainerSshRuntime, runSshdProxy, refreshContainerGhAuth, refreshContainerCodingAgentClis, findRunningContainerId, findWorkspaceContainer, stopWorkspaceContainer, removeWorkspaceContainer, listWorkspaceContainers } from './devcontainer.ts'\nimport { createWorkspaceListEntries, formatWorkspaceListText } from './list.ts'\nimport { listWorkspaceMetadata, writeWorkspaceMetadata } from './metadata.ts'\nimport { createWorkspaceContext, defaultDataRoot } from './paths.ts'\nimport { defaultSshAlias, installSshConfig } from './ssh-config.ts'\nimport { createStatusInfo, formatStatusText, statusIsHealthy } from './status.ts'\n\nexport type BoxdownCommand =\n | 'help'\n | 'start'\n | 'list'\n | 'status'\n | 'stop'\n | 'down'\n | 'doctor'\n | 'ssh-config-install'\n | 'ssh-proxy'\n | 'refresh-gh-token'\n | 'refresh-gh-token-running'\n | 'coding-agent'\n\nexport interface ParsedCli {\n command: BoxdownCommand\n agent?: CodingAgentCli\n agentArgs?: string[]\n workspace?: string\n alias?: string\n recreate: boolean\n json: boolean\n}\n\nexport const USAGE = `Usage:\n boxdown start [--workspace <path>] [--recreate]\n boxdown codex [--workspace <path>] [--recreate] [-- <codex args...>]\n boxdown claude [--workspace <path>] [--recreate] [-- <claude args...>]\n boxdown cc [--workspace <path>] [--recreate] [-- <claude args...>]\n boxdown opencode [--workspace <path>] [--recreate] [-- <opencode args...>]\n boxdown antigravity [--workspace <path>] [--recreate] [-- <agy args...>]\n boxdown list [--json]\n boxdown status [--workspace <path>] [--alias <name>] [--json]\n boxdown stop [--workspace <path>]\n boxdown down [--workspace <path>]\n boxdown doctor [--workspace <path>]\n boxdown ssh-config install [--workspace <path>] [--alias <name>]\n boxdown ssh-proxy [--workspace <path>] [--alias <name>]\n boxdown refresh-gh-token [--workspace <path>]\n boxdown refresh-gh-token-running [--workspace <path>]\n\nCommands:\n start Start or reuse the workspace devcontainer, then open\n an interactive shell inside it. Alias: shell.\n codex Start or reuse the devcontainer, then launch Codex.\n claude Start or reuse the devcontainer, then launch Claude\n Code. Alias: cc.\n opencode Start or reuse the devcontainer, then launch\n OpenCode.\n antigravity Start or reuse the devcontainer, then launch\n Antigravity CLI (agy).\n list List Boxdown-known devcontainer workspaces from any\n directory.\n status Show workspace state, generated paths, SSH key paths,\n and the matching devcontainer state.\n stop Stop the workspace devcontainer if it is running.\n down Remove the workspace devcontainer. Keeps Boxdown\n cache, generated config, data, and SSH keys.\n doctor Check required host tools and Boxdown assets.\n ssh-config install Install or update an SSH host alias for the workspace\n devcontainer.\n ssh-proxy Internal command used by the generated SSH\n ProxyCommand. Starts or reuses the devcontainer and\n bridges SSH over docker exec.\n refresh-gh-token Start or reuse the devcontainer, then copy host\n GitHub CLI auth into the container when available.\n refresh-gh-token-running Refresh GitHub CLI auth only if the workspace\n devcontainer is already running.\n\nOptions:\n --workspace <path> Target project directory. Defaults to the current directory.\n --alias <name> SSH host alias. Defaults to <repo-name>-devcontainer.\n --recreate Remove the existing devcontainer before starting.\n --json Print JSON output. Supported by status and list.\n --help, -h Show help.\n`\n\nexport function commandWritesWorkspaceMetadata (command: BoxdownCommand): boolean {\n return [\n 'start',\n 'ssh-config-install',\n 'ssh-proxy',\n 'refresh-gh-token',\n 'refresh-gh-token-running',\n 'coding-agent'\n ].includes(command)\n}\n\nexport function parseCliArgs (argv: string[]): ParsedCli {\n const args = [...argv]\n let workspace: string | undefined\n let alias: string | undefined\n let recreate = false\n let json = false\n let passthroughArgs: string[] | undefined\n const positional: string[] = []\n\n function parsed (command: BoxdownCommand): ParsedCli {\n if (json && command !== 'status' && command !== 'list') {\n throw new Error('--json is only supported with status and list')\n }\n\n if (passthroughArgs !== undefined) {\n throw new Error('-- passthrough is only supported with coding-agent commands')\n }\n\n return { command, workspace, alias, recreate, json }\n }\n\n function parsedCodingAgent (agent: CodingAgentCli): ParsedCli {\n if (json) {\n throw new Error('--json is only supported with status and list')\n }\n\n return {\n command: 'coding-agent',\n agent,\n agentArgs: passthroughArgs ?? [],\n workspace,\n alias,\n recreate,\n json\n }\n }\n\n while (args.length > 0) {\n const arg = args.shift()\n\n if (arg === undefined) {\n break\n }\n\n if (arg === '--') {\n passthroughArgs = args.splice(0)\n break\n }\n\n if (arg === '--help' || arg === '-h') {\n return parsed('help')\n }\n\n if (arg === '--workspace') {\n const value = args.shift()\n if (value === undefined) {\n throw new Error('--workspace requires a value')\n }\n workspace = value\n continue\n }\n\n if (arg === '--alias') {\n const value = args.shift()\n if (value === undefined) {\n throw new Error('--alias requires a value')\n }\n alias = value\n continue\n }\n\n if (arg === '--recreate') {\n recreate = true\n continue\n }\n\n if (arg === '--json') {\n json = true\n continue\n }\n\n if (arg.startsWith('-')) {\n throw new Error(`Unknown option: ${arg}`)\n }\n\n positional.push(arg)\n }\n\n if (positional.length === 0) {\n return parsed('help')\n }\n\n if (positional[0] === 'start' || positional[0] === 'shell') {\n return parsed('start')\n }\n\n const codingAgent = codingAgentFromCommand(positional[0] ?? '')\n if (codingAgent !== undefined) {\n if (positional.length > 1) {\n throw new Error('Coding-agent CLI arguments must come after --')\n }\n\n return parsedCodingAgent(codingAgent)\n }\n\n if (positional[0] === 'list' && positional.length === 1) {\n return parsed('list')\n }\n\n if (positional[0] === 'status' && positional.length === 1) {\n return parsed('status')\n }\n\n if (positional[0] === 'stop' && positional.length === 1) {\n return parsed('stop')\n }\n\n if (positional[0] === 'down' && positional.length === 1) {\n return parsed('down')\n }\n\n if (positional[0] === 'doctor' && positional.length === 1) {\n return parsed('doctor')\n }\n\n if (positional[0] === 'ssh-config') {\n if (positional.length === 1 || (positional[1] === 'install' && positional.length === 2)) {\n return parsed('ssh-config-install')\n }\n\n throw new Error(`Unknown ssh-config command: ${positional.slice(1).join(' ')}. Usage: boxdown ssh-config [install] [--workspace <path>] [--alias <name>]`)\n }\n\n if (positional[0] === 'ssh-proxy' && positional.length === 1) {\n return parsed('ssh-proxy')\n }\n\n if (positional[0] === 'refresh-gh-token' && positional.length === 1) {\n return parsed('refresh-gh-token')\n }\n\n if (positional[0] === 'refresh-gh-token-running' && positional.length === 1) {\n return parsed('refresh-gh-token-running')\n }\n\n throw new Error(`Unknown command: ${positional.join(' ')}`)\n}\n\nexport async function runCli (argv: string[] = process.argv.slice(2)): Promise<number> {\n try {\n const parsed = parseCliArgs(argv)\n\n if (parsed.command === 'help') {\n process.stdout.write(USAGE)\n return 0\n }\n\n if (parsed.command === 'list') {\n const metadata = listWorkspaceMetadata(defaultDataRoot())\n const containers = await listWorkspaceContainers()\n const entries = createWorkspaceListEntries(metadata, containers, existsSync)\n\n if (parsed.json) {\n process.stdout.write(`${JSON.stringify(entries, null, 2)}\\n`)\n } else {\n process.stdout.write(formatWorkspaceListText(entries))\n }\n\n return 0\n }\n\n const context = createWorkspaceContext({ workspace: parsed.workspace })\n const alias = parsed.alias ?? defaultSshAlias(context.workspaceBasename)\n const aliasSource = parsed.alias === undefined ? 'default' : 'provided'\n\n if (commandWritesWorkspaceMetadata(parsed.command)) {\n writeWorkspaceMetadata(context, alias)\n }\n\n if (parsed.command === 'ssh-config-install') {\n await installSshConfig(context, alias)\n return 0\n }\n\n if (parsed.command === 'status') {\n const container = await findWorkspaceContainer(context)\n const status = createStatusInfo(context, alias, container, existsSync, { aliasSource })\n\n if (parsed.json) {\n process.stdout.write(`${JSON.stringify(status, null, 2)}\\n`)\n } else {\n process.stdout.write(formatStatusText(status, { color: true }))\n }\n\n return statusIsHealthy(status) ? 0 : 1\n }\n\n if (parsed.command === 'stop') {\n await stopWorkspaceContainer(context)\n return 0\n }\n\n if (parsed.command === 'down') {\n await removeWorkspaceContainer(context)\n return 0\n }\n\n if (parsed.command === 'doctor') {\n const checks = await runDoctorChecks(context)\n process.stdout.write(formatDoctorText(checks))\n return doctorHasFailures(checks) ? 1 : 0\n }\n\n if (!existsSync(context.assetsDevcontainerDir)) {\n throw new Error(`Missing Boxdown devcontainer assets: ${context.assetsDevcontainerDir}`)\n }\n\n if (parsed.command === 'ssh-proxy') {\n await installSshConfig(context, alias, { quiet: true })\n const containerId = await startDevcontainer(context, {\n recreate: parsed.recreate,\n proxyMode: true,\n reuseRunning: true\n })\n await refreshContainerCodingAgentClis(context, true)\n await ensureContainerSshRuntime(context)\n return runSshdProxy(containerId)\n }\n\n if (parsed.command === 'refresh-gh-token-running') {\n const containerId = await findRunningContainerId(context)\n if (containerId === undefined) {\n throw new Error(`No running devcontainer found for: ${context.workspaceFolder}`)\n }\n await refreshContainerGhAuth(context)\n return 0\n }\n\n if (parsed.command === 'refresh-gh-token') {\n await startDevcontainer(context)\n await refreshContainerGhAuth(context)\n return 0\n }\n\n if (parsed.command === 'coding-agent') {\n const agent = parsed.agent\n if (agent === undefined) {\n throw new Error('Missing coding-agent command')\n }\n\n await startDevcontainer(context, { recreate: parsed.recreate })\n await refreshContainerCodingAgentClis(context, false, [agent])\n return openCodingAgentCli(context, agent, parsed.agentArgs ?? [])\n }\n\n const containerId = await startDevcontainer(context, { recreate: parsed.recreate })\n await printPortHint(context, containerId)\n return openShell(context)\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n return 1\n }\n}\n"],"mappings":"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"}