boxdown 1.2.1 → 1.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 (32) hide show
  1. package/README.md +10 -0
  2. package/assets/devcontainer/README.md +12 -1
  3. package/assets/devcontainer/devcontainer.json +1 -1
  4. package/assets/devcontainer/hooks/post-create.sh +12 -1
  5. package/dist/bin/cli.cjs +1 -1
  6. package/dist/bin/cli.mjs +1 -1
  7. package/dist/{main-BDgyf2t5.cjs → main-CT2n9qcb.cjs} +448 -67
  8. package/dist/{main-J4_2Up3o.mjs → main-O__JaiXe.mjs} +431 -68
  9. package/dist/main-O__JaiXe.mjs.map +1 -0
  10. package/dist/main.cjs +4 -1
  11. package/dist/main.d.cts +92 -26
  12. package/dist/main.d.cts.map +1 -1
  13. package/dist/main.d.mts +92 -26
  14. package/dist/main.d.mts.map +1 -1
  15. package/dist/main.mjs +2 -2
  16. package/docs/features/lifecycle.md +13 -0
  17. package/docs/features/setup.md +5 -0
  18. package/docs/features/start-and-shell.md +5 -0
  19. package/docs/superpowers/plans/2026-07-18-architecture-aware-1password-installer.md +163 -0
  20. package/docs/superpowers/plans/2026-07-18-devcontainer-node-image-digest.md +341 -0
  21. package/docs/superpowers/plans/2026-07-19-container-runtime-readiness.md +1536 -0
  22. package/docs/superpowers/specs/2026-07-18-architecture-aware-1password-installer-design.md +63 -0
  23. package/docs/superpowers/specs/2026-07-18-devcontainer-node-image-digest-design.md +108 -0
  24. package/docs/superpowers/specs/2026-07-19-container-runtime-readiness-design.md +353 -0
  25. package/package.json +1 -1
  26. package/src/container-runtime.ts +295 -0
  27. package/src/devcontainer.ts +20 -4
  28. package/src/doctor.ts +48 -22
  29. package/src/main.ts +95 -11
  30. package/src/process.ts +50 -10
  31. package/src/progress.ts +63 -8
  32. package/dist/main-J4_2Up3o.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"main-J4_2Up3o.mjs","names":["isRecord","backupPathFor","writeJsonAtomic","color","isCiEnvironment","#write","#writeRaw","#isTTY","#spinnerFrames","#spinnerIntervalMs","#sectionOpen","#sectionPrinted","#stopStepTimer","#steps","#renderedStepLineCount","#writeLine","color","#stepFrameIndex","#renderChecklist","#updateStep","#startStepTimer","#stopStepTimerIfIdle","#spinner","#renderSpinner","#clearSpinnerLine","#formatStep","#stepMark","#stepTimer","color","errorMessage","#redactions","#now","#disabled","#append","#timestamp","#redact","#stream"],"sources":["../src/claude-app-config.ts","../src/codex-app-config.ts","../src/coding-agents.ts","../src/constants.ts","../src/jsonc.ts","../src/shell.ts","../src/config.ts","../src/devcontainer-cli.ts","../src/process.ts","../src/git-signing.ts","../src/doctor.ts","../src/github-git-auth.ts","../src/metadata.ts","../src/cli-style.ts","../src/progress.ts","../src/ssh-key.ts","../src/ssh-config.ts","../src/status.ts","../src/devcontainer.ts","../src/interactive-prompts.ts","../src/list.ts","../src/logging.ts","../src/paths.ts","../src/package-info.ts","../src/purge.ts","../src/ssh-install-targets.ts","../src/main.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\nimport type { WorkspaceContext } from './paths.ts'\n\nexport const CLAUDE_APP_SUPPORT_DIRNAME = 'Claude'\nexport const CLAUDE_SSH_CONFIGS_FILENAME = 'ssh_configs.json'\n\nexport interface ClaudeSshConfigEntry {\n name: string\n sshHost: string\n id: string\n source?: string\n [key: string]: unknown\n}\n\nexport interface ClaudeSshConfigs {\n configs: ClaudeSshConfigEntry[]\n trustedHosts: string[]\n [key: string]: unknown\n}\n\nexport interface ClaudeSshConfigTargetEntry {\n name: string\n sshHost: string\n}\n\nexport interface InstallClaudeSshConfigResult {\n configPath: string\n backupPath?: string\n changed: boolean\n}\n\nexport interface UninstallClaudeSshConfigResult {\n configPath: string\n backupPath?: string\n changed: boolean\n}\n\nfunction isRecord (value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction parseRequiredString (value: unknown, key: string): string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new Error(`Invalid Claude SSH config: ${key} must be a nonempty string`)\n }\n\n return value.trim()\n}\n\nfunction parseOptionalString (value: unknown, key: string): string | undefined {\n if (value === undefined) {\n return undefined\n }\n\n if (typeof value !== 'string') {\n throw new Error(`Invalid Claude SSH config: ${key} must be a string`)\n }\n\n return value\n}\n\nfunction parseStringArray (value: unknown, key: string): string[] {\n if (value === undefined) {\n return []\n }\n\n if (!Array.isArray(value)) {\n throw new Error(`Invalid Claude SSH config: ${key} must be an array`)\n }\n\n return value.map((item) => {\n if (typeof item !== 'string') {\n throw new Error(`Invalid Claude SSH config: ${key} entries must be strings`)\n }\n\n return item\n })\n}\n\nfunction parseClaudeSshConfigEntry (value: unknown): ClaudeSshConfigEntry {\n if (!isRecord(value)) {\n throw new Error('Invalid Claude SSH config: configs entries must be objects')\n }\n\n const source = parseOptionalString(value.source, 'source')\n const parsed: ClaudeSshConfigEntry = {\n ...value,\n name: parseRequiredString(value.name, 'name'),\n sshHost: parseRequiredString(value.sshHost, 'sshHost'),\n id: parseRequiredString(value.id, 'id')\n }\n\n if (source !== undefined) {\n parsed.source = source\n } else {\n delete parsed.source\n }\n\n return parsed\n}\n\nexport function parseClaudeSshConfigs (value: unknown): ClaudeSshConfigs {\n if (!isRecord(value)) {\n throw new Error('Invalid Claude SSH config: top-level value must be an object')\n }\n\n const configs = value.configs\n if (configs !== undefined && !Array.isArray(configs)) {\n throw new Error('Invalid Claude SSH config: configs must be an array')\n }\n\n return {\n ...value,\n configs: (configs ?? []).map((config) => parseClaudeSshConfigEntry(config)),\n trustedHosts: parseStringArray(value.trustedHosts, 'trustedHosts')\n }\n}\n\nexport function defaultClaudeSshConfigsPath (\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform\n): string {\n if (env.BOXDOWN_CLAUDE_SSH_CONFIGS !== undefined) {\n return env.BOXDOWN_CLAUDE_SSH_CONFIGS\n }\n\n const home = env.HOME ?? homedir()\n\n if (platform === 'darwin') {\n return join(home, 'Library', 'Application Support', CLAUDE_APP_SUPPORT_DIRNAME, CLAUDE_SSH_CONFIGS_FILENAME)\n }\n\n if (platform === 'win32') {\n return join(env.APPDATA ?? join(home, 'AppData', 'Roaming'), CLAUDE_APP_SUPPORT_DIRNAME, CLAUDE_SSH_CONFIGS_FILENAME)\n }\n\n return join(env.XDG_CONFIG_HOME ?? join(home, '.config'), CLAUDE_APP_SUPPORT_DIRNAME, CLAUDE_SSH_CONFIGS_FILENAME)\n}\n\nexport function claudeSshConfigEntryForWorkspace (context: WorkspaceContext, sshHost: string): ClaudeSshConfigTargetEntry {\n return {\n name: context.workspaceBasename,\n sshHost\n }\n}\n\nfunction readClaudeSshConfigsFile (configPath: string): ClaudeSshConfigs {\n if (!existsSync(configPath)) {\n return {\n configs: [],\n trustedHosts: []\n }\n }\n\n let parsed: unknown\n\n try {\n parsed = JSON.parse(readFileSync(configPath, 'utf8')) as unknown\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid Claude SSH config JSON: ${configPath}`, { cause: error })\n }\n\n throw error\n }\n\n return parseClaudeSshConfigs(parsed)\n}\n\nfunction backupPathFor (configPath: string, now: Date): string {\n return `${configPath}.${now.toISOString().replace(/[:.]/gu, '-')}.bak`\n}\n\nfunction writeJsonAtomic (path: string, json: string): void {\n const tmpPath = `${path}.tmp-${process.pid}-${Date.now()}`\n writeFileSync(tmpPath, json)\n renameSync(tmpPath, path)\n}\n\nfunction withTrustedHost (trustedHosts: readonly string[], sshHost: string): string[] {\n return [...new Set([...trustedHosts, sshHost])]\n}\n\nexport function mergeClaudeSshConfigHost (\n config: ClaudeSshConfigs,\n entry: ClaudeSshConfigTargetEntry,\n createId: () => string = randomUUID\n): ClaudeSshConfigs {\n let matched = false\n const configs = config.configs.map((configEntry) => {\n if (configEntry.sshHost !== entry.sshHost) {\n return configEntry\n }\n\n matched = true\n return {\n ...configEntry,\n name: entry.name,\n sshHost: entry.sshHost\n }\n })\n\n if (!matched) {\n configs.push({\n name: entry.name,\n sshHost: entry.sshHost,\n id: createId(),\n source: 'desktop'\n })\n }\n\n return {\n ...config,\n configs,\n trustedHosts: withTrustedHost(config.trustedHosts, entry.sshHost)\n }\n}\n\nexport function removeClaudeSshConfigHost (\n config: ClaudeSshConfigs,\n entry: ClaudeSshConfigTargetEntry\n): ClaudeSshConfigs {\n return {\n ...config,\n configs: config.configs.filter((configEntry) => configEntry.sshHost !== entry.sshHost),\n trustedHosts: config.trustedHosts.filter((trustedHost) => trustedHost !== entry.sshHost)\n }\n}\n\nexport function installClaudeSshConfigHost (\n entry: ClaudeSshConfigTargetEntry,\n options: { configPath?: string, now?: Date, createId?: () => string } = {}\n): InstallClaudeSshConfigResult {\n const configPath = options.configPath ?? defaultClaudeSshConfigsPath()\n const configDir = dirname(configPath)\n const existingConfigExists = existsSync(configPath)\n const existingConfig = readClaudeSshConfigsFile(configPath)\n const nextConfig = mergeClaudeSshConfigHost(existingConfig, entry, options.createId)\n const nextJson = `${JSON.stringify(nextConfig, null, 2)}\\n`\n const existingJson = existingConfigExists ? readFileSync(configPath, 'utf8') : undefined\n\n if (existingJson === nextJson) {\n return {\n configPath,\n changed: false\n }\n }\n\n mkdirSync(configDir, { recursive: true })\n\n let backupPath: string | undefined\n if (existingConfigExists) {\n backupPath = backupPathFor(configPath, options.now ?? new Date())\n copyFileSync(configPath, backupPath)\n }\n\n writeJsonAtomic(configPath, nextJson)\n\n return {\n configPath,\n ...(backupPath === undefined ? {} : { backupPath }),\n changed: true\n }\n}\n\nexport function uninstallClaudeSshConfigHost (\n entry: ClaudeSshConfigTargetEntry,\n options: { configPath?: string, now?: Date } = {}\n): UninstallClaudeSshConfigResult {\n const configPath = options.configPath ?? defaultClaudeSshConfigsPath()\n const existingConfigExists = existsSync(configPath)\n\n if (!existingConfigExists) {\n return {\n configPath,\n changed: false\n }\n }\n\n const existingConfig = readClaudeSshConfigsFile(configPath)\n const nextConfig = removeClaudeSshConfigHost(existingConfig, entry)\n\n if (JSON.stringify(existingConfig) === JSON.stringify(nextConfig)) {\n return {\n configPath,\n changed: false\n }\n }\n\n const nextJson = `${JSON.stringify(nextConfig, null, 2)}\\n`\n const backupPath = backupPathFor(configPath, options.now ?? new Date())\n copyFileSync(configPath, backupPath)\n writeJsonAtomic(configPath, nextJson)\n\n return {\n configPath,\n backupPath,\n changed: true\n }\n}\n","import { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\nimport type { WorkspaceContext } from './paths.ts'\n\nexport const CODEX_APP_CONFIG_VERSION = 1\nexport const CODEX_APP_CONFIG_DIRNAME = 'codex-app'\nexport const CODEX_APP_CONFIG_FILENAME = 'config.json'\nexport const CODEX_GLOBAL_STATE_FILENAME = '.codex-global-state.json'\n\nexport interface CodexAppProjectConfig {\n remotePath: string\n label?: string\n}\n\nexport interface CodexAppRemoteConnectionConfig {\n sshAlias: string\n projects: CodexAppProjectConfig[]\n}\n\nexport interface CodexAppConfig {\n version: 1\n remoteConnectionMaxRetryAttempts?: number\n sshConnectTimeoutSeconds?: number\n remoteConnections: CodexAppRemoteConnectionConfig[]\n}\n\nexport interface CodexAppProjectEntry {\n sshAlias: string\n remotePath: string\n label: string\n}\n\nexport interface InstallCodexAppConfigResult {\n configPath: string\n backupPath?: string\n changed: boolean\n}\n\nexport interface UninstallCodexAppConfigResult {\n configPath: string\n backupPath?: string\n changed: boolean\n}\n\nexport interface UninstallCodexGlobalStateResult {\n statePath: string\n backupPath?: string\n changed: boolean\n}\n\nexport interface InstallCodexGlobalStateResult {\n statePath: string\n backupPath?: string\n changed: boolean\n}\n\nfunction isRecord (value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction parseOptionalNonnegativeInteger (value: unknown, key: string): number | undefined {\n if (value === undefined) {\n return undefined\n }\n\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n throw new Error(`Invalid Codex app config: ${key} must be a nonnegative integer`)\n }\n\n return value\n}\n\nfunction parseOptionalLabel (value: unknown): string | undefined {\n if (value === undefined) {\n return undefined\n }\n\n if (typeof value !== 'string') {\n throw new Error('Invalid Codex app config: project label must be a string')\n }\n\n return value\n}\n\nfunction parseProjectConfig (value: unknown): CodexAppProjectConfig {\n if (!isRecord(value)) {\n throw new Error('Invalid Codex app config: project entries must be objects')\n }\n\n const remotePath = value.remotePath\n if (typeof remotePath !== 'string' || remotePath.trim().length === 0) {\n throw new Error('Invalid Codex app config: project remotePath must be a nonempty string')\n }\n\n const label = parseOptionalLabel(value.label)\n\n return {\n remotePath: normalizeRemotePath(remotePath),\n ...(label === undefined ? {} : { label })\n }\n}\n\nfunction parseRemoteConnectionConfig (value: unknown): CodexAppRemoteConnectionConfig {\n if (!isRecord(value)) {\n throw new Error('Invalid Codex app config: remoteConnections entries must be objects')\n }\n\n const sshAlias = value.sshAlias\n if (typeof sshAlias !== 'string' || sshAlias.trim().length === 0) {\n throw new Error('Invalid Codex app config: sshAlias must be a nonempty string')\n }\n\n const projects = value.projects\n if (projects !== undefined && !Array.isArray(projects)) {\n throw new Error('Invalid Codex app config: projects must be an array')\n }\n\n return {\n sshAlias: sshAlias.trim(),\n projects: (projects ?? []).map((project) => parseProjectConfig(project))\n }\n}\n\nexport function parseCodexAppConfig (value: unknown): CodexAppConfig {\n if (!isRecord(value)) {\n throw new Error('Invalid Codex app config: top-level value must be an object')\n }\n\n const version = value.version\n if (version !== undefined && (!Number.isInteger(version) || version !== CODEX_APP_CONFIG_VERSION)) {\n throw new Error(`Unsupported Codex app config version: ${String(version)}`)\n }\n\n const remoteConnections = value.remoteConnections\n if (remoteConnections !== undefined && !Array.isArray(remoteConnections)) {\n throw new Error('Invalid Codex app config: remoteConnections must be an array')\n }\n\n return {\n version: CODEX_APP_CONFIG_VERSION,\n ...(value.remoteConnectionMaxRetryAttempts === undefined\n ? {}\n : { remoteConnectionMaxRetryAttempts: parseOptionalNonnegativeInteger(value.remoteConnectionMaxRetryAttempts, 'remoteConnectionMaxRetryAttempts') }),\n ...(value.sshConnectTimeoutSeconds === undefined\n ? {}\n : { sshConnectTimeoutSeconds: parseOptionalNonnegativeInteger(value.sshConnectTimeoutSeconds, 'sshConnectTimeoutSeconds') }),\n remoteConnections: (remoteConnections ?? []).map((connection) => parseRemoteConnectionConfig(connection))\n }\n}\n\nexport function defaultCodexAppConfigPath (env: NodeJS.ProcessEnv = process.env): string {\n return env.BOXDOWN_CODEX_APP_CONFIG ?? join(env.HOME ?? homedir(), '.codex', CODEX_APP_CONFIG_DIRNAME, CODEX_APP_CONFIG_FILENAME)\n}\n\nexport function defaultCodexGlobalStatePath (env: NodeJS.ProcessEnv = process.env): string {\n return env.BOXDOWN_CODEX_GLOBAL_STATE ?? join(env.HOME ?? homedir(), '.codex', CODEX_GLOBAL_STATE_FILENAME)\n}\n\nexport function canonicalCodexRemotePathForWorkspace (context: WorkspaceContext): string {\n return `/workspaces/${context.workspaceBasename}`\n}\n\nexport function legacyCodexRemotePathForWorkspace (context: WorkspaceContext): string {\n return `/home/node/${context.workspaceBasename}`\n}\n\nexport function codexRemotePathForWorkspace (context: WorkspaceContext): string {\n return canonicalCodexRemotePathForWorkspace(context)\n}\n\nexport function codexProjectEntryForWorkspace (context: WorkspaceContext, sshAlias: string): CodexAppProjectEntry {\n return {\n sshAlias,\n remotePath: codexRemotePathForWorkspace(context),\n label: context.workspaceBasename\n }\n}\n\nexport function normalizeRemotePath (remotePath: string): string {\n const trimmed = remotePath.trim()\n\n if (trimmed === '/') {\n return trimmed\n }\n\n return trimmed.replace(/\\/+$/u, '')\n}\n\nexport function codexDiscoveredRemoteHostId (sshAlias: string): string {\n return `remote-ssh-discovered:${sshAlias}`\n}\n\nfunction normalizedRemotePathSet (remotePaths: readonly string[] = []): Set<string> {\n return new Set(remotePaths.map((remotePath) => normalizeRemotePath(remotePath)))\n}\n\nexport function mergeCodexAppProject (\n config: CodexAppConfig,\n entry: CodexAppProjectEntry,\n options: { legacyRemotePaths?: readonly string[] } = {}\n): CodexAppConfig {\n const remotePath = normalizeRemotePath(entry.remotePath)\n const legacyRemotePaths = normalizedRemotePathSet(options.legacyRemotePaths)\n let matchedConnection = false\n\n const remoteConnections = config.remoteConnections.map((connection) => {\n if (connection.sshAlias !== entry.sshAlias) {\n return connection\n }\n\n matchedConnection = true\n let matchedProject = false\n const projects: CodexAppProjectConfig[] = []\n\n for (const project of connection.projects) {\n const projectRemotePath = normalizeRemotePath(project.remotePath)\n\n if (projectRemotePath !== remotePath && !legacyRemotePaths.has(projectRemotePath)) {\n projects.push(project)\n continue\n }\n\n if (!matchedProject) {\n projects.push({\n remotePath,\n label: entry.label\n })\n matchedProject = true\n }\n }\n\n if (!matchedProject) {\n projects.push({\n remotePath,\n label: entry.label\n })\n }\n\n return {\n sshAlias: connection.sshAlias,\n projects\n }\n })\n\n if (!matchedConnection) {\n remoteConnections.push({\n sshAlias: entry.sshAlias,\n projects: [{\n remotePath,\n label: entry.label\n }]\n })\n }\n\n return {\n ...config,\n remoteConnections\n }\n}\n\nexport function removeCodexAppProject (\n config: CodexAppConfig,\n entry: CodexAppProjectEntry,\n options: { additionalRemotePaths?: readonly string[] } = {}\n): CodexAppConfig {\n const remotePaths = normalizedRemotePathSet([\n entry.remotePath,\n ...(options.additionalRemotePaths ?? [])\n ])\n const remoteConnections = config.remoteConnections.flatMap((connection) => {\n if (connection.sshAlias !== entry.sshAlias) {\n return [connection]\n }\n\n const projects = connection.projects.filter((project) => !remotePaths.has(normalizeRemotePath(project.remotePath)))\n\n if (projects.length === 0) {\n return []\n }\n\n return [{\n sshAlias: connection.sshAlias,\n projects\n }]\n })\n\n return {\n ...config,\n remoteConnections\n }\n}\n\nfunction cloneJsonObject (value: Record<string, unknown>): Record<string, unknown> {\n return JSON.parse(JSON.stringify(value)) as Record<string, unknown>\n}\n\nfunction removeObjectKey (value: unknown, key: string): void {\n if (isRecord(value)) {\n delete value[key]\n }\n}\n\nfunction removeFromStringArray (value: unknown, removedValues: Set<string>): unknown {\n if (!Array.isArray(value)) {\n return value\n }\n\n return value.filter((item) => typeof item !== 'string' || !removedValues.has(item))\n}\n\nfunction cleanupStringArrayField (container: Record<string, unknown>, key: string, removedValues: Set<string>): void {\n if (Array.isArray(container[key])) {\n container[key] = removeFromStringArray(container[key], removedValues)\n }\n}\n\nfunction cleanupCodexStateContainer (container: Record<string, unknown>, hostId: string, remotePaths: Set<string>): Set<string> {\n const removedProjectIds = new Set<string>()\n const remoteProjects = container['remote-projects']\n\n if (Array.isArray(remoteProjects)) {\n container['remote-projects'] = remoteProjects.filter((project) => {\n if (!isRecord(project)) {\n return true\n }\n\n const matches = project.hostId === hostId &&\n typeof project.remotePath === 'string' &&\n remotePaths.has(normalizeRemotePath(project.remotePath))\n\n if (matches && typeof project.id === 'string') {\n removedProjectIds.add(project.id)\n }\n\n return !matches\n })\n }\n\n const managedConnections = container['codex-managed-remote-connections']\n if (Array.isArray(managedConnections)) {\n container['codex-managed-remote-connections'] = managedConnections.filter((connection) => !isRecord(connection) || connection.hostId !== hostId)\n }\n\n for (const key of [\n 'remote-connection-analytics-id-by-host-id',\n 'remote-connection-auto-connect-by-host-id',\n 'preferred-non-full-access-agent-mode-by-host-id',\n 'agent-mode-by-host-id',\n 'unread-thread-ids-by-host-v1'\n ]) {\n removeObjectKey(container[key], hostId)\n }\n\n if (container['selected-remote-host-id'] === hostId) {\n delete container['selected-remote-host-id']\n }\n\n return removedProjectIds\n}\n\nfunction cleanupProjectReferences (state: Record<string, unknown>, atomState: unknown, removedProjectIds: Set<string>): void {\n if (removedProjectIds.size === 0) {\n return\n }\n\n cleanupStringArrayField(state, 'project-order', removedProjectIds)\n\n for (const projectId of removedProjectIds) {\n removeObjectKey(state['sidebar-collapsed-groups'], projectId)\n }\n\n if (isRecord(atomState)) {\n cleanupStringArrayField(atomState, 'project-order', removedProjectIds)\n for (const projectId of removedProjectIds) {\n removeObjectKey(atomState['sidebar-collapsed-groups'], projectId)\n }\n }\n}\n\nexport function removeCodexGlobalStateProject (\n state: Record<string, unknown>,\n entry: CodexAppProjectEntry,\n options: { additionalRemotePaths?: readonly string[] } = {}\n): Record<string, unknown> {\n const hostId = codexDiscoveredRemoteHostId(entry.sshAlias)\n const remotePaths = normalizedRemotePathSet([\n entry.remotePath,\n ...(options.additionalRemotePaths ?? [])\n ])\n const nextState = cloneJsonObject(state)\n const removedProjectIds = cleanupCodexStateContainer(nextState, hostId, remotePaths)\n const atomState = nextState['electron-persisted-atom-state']\n\n if (isRecord(atomState)) {\n for (const projectId of cleanupCodexStateContainer(atomState, hostId, remotePaths)) {\n removedProjectIds.add(projectId)\n }\n }\n\n cleanupProjectReferences(nextState, atomState, removedProjectIds)\n\n return nextState\n}\n\nfunction normalizeCodexStateContainer (\n container: Record<string, unknown>,\n hostId: string,\n canonicalRemotePath: string,\n legacyRemotePaths: Set<string>\n): Set<string> {\n const removedProjectIds = new Set<string>()\n const remoteProjects = container['remote-projects']\n\n if (!Array.isArray(remoteProjects)) {\n return removedProjectIds\n }\n\n let matchedProject = false\n container['remote-projects'] = remoteProjects.flatMap((project) => {\n if (!isRecord(project) || project.hostId !== hostId || typeof project.remotePath !== 'string') {\n return [project]\n }\n\n const remotePath = normalizeRemotePath(project.remotePath)\n if (remotePath !== canonicalRemotePath && !legacyRemotePaths.has(remotePath)) {\n return [project]\n }\n\n if (matchedProject) {\n if (typeof project.id === 'string') {\n removedProjectIds.add(project.id)\n }\n return []\n }\n\n matchedProject = true\n return [{\n ...project,\n remotePath: canonicalRemotePath\n }]\n })\n\n return removedProjectIds\n}\n\nexport function normalizeCodexGlobalStateProject (\n state: Record<string, unknown>,\n entry: CodexAppProjectEntry,\n options: { legacyRemotePaths?: readonly string[] } = {}\n): Record<string, unknown> {\n const hostId = codexDiscoveredRemoteHostId(entry.sshAlias)\n const canonicalRemotePath = normalizeRemotePath(entry.remotePath)\n const legacyRemotePaths = normalizedRemotePathSet(options.legacyRemotePaths)\n const nextState = cloneJsonObject(state)\n const removedProjectIds = normalizeCodexStateContainer(nextState, hostId, canonicalRemotePath, legacyRemotePaths)\n const atomState = nextState['electron-persisted-atom-state']\n\n if (isRecord(atomState)) {\n for (const projectId of normalizeCodexStateContainer(atomState, hostId, canonicalRemotePath, legacyRemotePaths)) {\n removedProjectIds.add(projectId)\n }\n }\n\n cleanupProjectReferences(nextState, atomState, removedProjectIds)\n\n return nextState\n}\n\nfunction readCodexAppConfigFile (configPath: string): CodexAppConfig {\n if (!existsSync(configPath)) {\n return {\n version: CODEX_APP_CONFIG_VERSION,\n remoteConnections: []\n }\n }\n\n let parsed: unknown\n\n try {\n parsed = JSON.parse(readFileSync(configPath, 'utf8')) as unknown\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid Codex app config JSON: ${configPath}`, { cause: error })\n }\n\n throw error\n }\n\n return parseCodexAppConfig(parsed)\n}\n\nfunction backupPathFor (configPath: string, now: Date): string {\n return `${configPath}.${now.toISOString().replace(/[:.]/gu, '-')}.bak`\n}\n\nfunction writeJsonAtomic (path: string, json: string): void {\n const tmpPath = `${path}.tmp-${process.pid}-${Date.now()}`\n writeFileSync(tmpPath, json)\n renameSync(tmpPath, path)\n}\n\nexport function installCodexAppConfigProject (\n entry: CodexAppProjectEntry,\n options: { configPath?: string, now?: Date, legacyRemotePaths?: readonly string[] } = {}\n): InstallCodexAppConfigResult {\n const configPath = options.configPath ?? defaultCodexAppConfigPath()\n const configDir = dirname(configPath)\n const existingConfigExists = existsSync(configPath)\n const existingConfig = readCodexAppConfigFile(configPath)\n const nextConfig = mergeCodexAppProject(existingConfig, entry, { legacyRemotePaths: options.legacyRemotePaths })\n const nextJson = `${JSON.stringify(nextConfig, null, 2)}\\n`\n const existingJson = existingConfigExists ? readFileSync(configPath, 'utf8') : undefined\n\n if (existingJson === nextJson) {\n return {\n configPath,\n changed: false\n }\n }\n\n mkdirSync(configDir, { recursive: true })\n\n let backupPath: string | undefined\n if (existingConfigExists) {\n backupPath = backupPathFor(configPath, options.now ?? new Date())\n copyFileSync(configPath, backupPath)\n }\n\n writeJsonAtomic(configPath, nextJson)\n\n return {\n configPath,\n ...(backupPath === undefined ? {} : { backupPath }),\n changed: true\n }\n}\n\nexport function uninstallCodexAppConfigProject (\n entry: CodexAppProjectEntry,\n options: { configPath?: string, now?: Date, additionalRemotePaths?: readonly string[] } = {}\n): UninstallCodexAppConfigResult {\n const configPath = options.configPath ?? defaultCodexAppConfigPath()\n const existingConfigExists = existsSync(configPath)\n\n if (!existingConfigExists) {\n return {\n configPath,\n changed: false\n }\n }\n\n const existingConfig = readCodexAppConfigFile(configPath)\n const nextConfig = removeCodexAppProject(existingConfig, entry, { additionalRemotePaths: options.additionalRemotePaths })\n\n if (JSON.stringify(existingConfig) === JSON.stringify(nextConfig)) {\n return {\n configPath,\n changed: false\n }\n }\n\n const nextJson = `${JSON.stringify(nextConfig, null, 2)}\\n`\n const backupPath = backupPathFor(configPath, options.now ?? new Date())\n copyFileSync(configPath, backupPath)\n writeJsonAtomic(configPath, nextJson)\n\n return {\n configPath,\n backupPath,\n changed: true\n }\n}\n\nexport function uninstallCodexGlobalStateProject (\n entry: CodexAppProjectEntry,\n options: { statePath?: string, now?: Date, additionalRemotePaths?: readonly string[] } = {}\n): UninstallCodexGlobalStateResult {\n const statePath = options.statePath ?? defaultCodexGlobalStatePath()\n\n if (!existsSync(statePath)) {\n return {\n statePath,\n changed: false\n }\n }\n\n const existingJson = readFileSync(statePath, 'utf8')\n const existingState = JSON.parse(existingJson) as unknown\n\n if (!isRecord(existingState)) {\n throw new Error(`Invalid Codex global state JSON: ${statePath}`)\n }\n\n const nextState = removeCodexGlobalStateProject(existingState, entry, { additionalRemotePaths: options.additionalRemotePaths })\n const nextJson = `${JSON.stringify(nextState)}\\n`\n\n if (JSON.stringify(existingState) === JSON.stringify(nextState)) {\n return {\n statePath,\n changed: false\n }\n }\n\n const backupPath = backupPathFor(statePath, options.now ?? new Date())\n copyFileSync(statePath, backupPath)\n writeJsonAtomic(statePath, nextJson)\n\n return {\n statePath,\n backupPath,\n changed: true\n }\n}\n\nexport function installCodexGlobalStateProject (\n entry: CodexAppProjectEntry,\n options: { statePath?: string, now?: Date, legacyRemotePaths?: readonly string[] } = {}\n): InstallCodexGlobalStateResult {\n const statePath = options.statePath ?? defaultCodexGlobalStatePath()\n\n if (!existsSync(statePath)) {\n return {\n statePath,\n changed: false\n }\n }\n\n const existingJson = readFileSync(statePath, 'utf8')\n const existingState = JSON.parse(existingJson) as unknown\n\n if (!isRecord(existingState)) {\n throw new Error(`Invalid Codex global state JSON: ${statePath}`)\n }\n\n const nextState = normalizeCodexGlobalStateProject(existingState, entry, { legacyRemotePaths: options.legacyRemotePaths })\n const nextJson = `${JSON.stringify(nextState)}\\n`\n\n if (JSON.stringify(existingState) === JSON.stringify(nextState)) {\n return {\n statePath,\n changed: false\n }\n }\n\n const backupPath = backupPathFor(statePath, options.now ?? new Date())\n copyFileSync(statePath, backupPath)\n writeJsonAtomic(statePath, nextJson)\n\n return {\n statePath,\n backupPath,\n changed: true\n }\n}\n","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_HOST_GITCONFIG_DIR = `${BOXDOWN_CONTAINER_STATE_DIR}/host-gitconfig`\nexport const BOXDOWN_CONTAINER_HOST_GITCONFIG_PATH = `${BOXDOWN_CONTAINER_HOST_GITCONFIG_DIR}/.gitconfig`\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`\nexport const BOXDOWN_CONTAINER_AGENTS_DIR = '/home/node/.agents'\nexport const BOXDOWN_CONTAINER_GITCONFIG_PATH = '/home/node/.gitconfig'\nexport const BOXDOWN_CONTAINER_CODEX_DIR = '/home/node/.codex'\nexport const BOXDOWN_CONTAINER_CODEX_AUTH_PATH = `${BOXDOWN_CONTAINER_CODEX_DIR}/auth.json`\nexport const BOXDOWN_CONTAINER_SECRET_ENV_DIR = '/run/boxdown/secrets'\nexport const BOXDOWN_CONTAINER_SECRET_ENV_BOOTSTRAP = `${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/utils/secret-env-bootstrap.sh`\nexport const BOXDOWN_SECRET_ENV_NAMES = [\n 'ANTHROPIC_API_KEY',\n 'SNYK_TOKEN',\n 'OP_SERVICE_ACCOUNT_TOKEN'\n] as const\n\nexport const PACKAGE_NAME = 'boxdown'\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\nfunction interactiveTermSetupScript (): string {\n return [\n 'if ! infocmp \"${TERM:-xterm-256color}\" >/dev/null 2>&1; then',\n ' export TERM=xterm-256color',\n 'fi',\n 'export COLORTERM=\"${COLORTERM:-truecolor}\"'\n ].join('\\n')\n}\n\nfunction interactiveAgentPathScript (): string {\n return [\n 'codex_home=\"${CODEX_HOME:-${HOME}/.codex}\"',\n 'export PATH=\"${HOME}/.local/bin:${HOME}/.opencode/bin:${codex_home}/packages/standalone/current/bin:${PATH}\"'\n ].join('\\n')\n}\n\nfunction runtimeSecretEnvironmentScript (): string {\n return 'source \"${BASH_ENV:-/opt/boxdown/devcontainer/utils/secret-env-bootstrap.sh}\"'\n}\n\nexport function interactiveShellScript (): string {\n return [\n interactiveTermSetupScript(),\n interactiveTtySetupScript(),\n runtimeSecretEnvironmentScript(),\n 'exec bash -i'\n ].join('\\n')\n}\n\nexport function interactiveCommandScript (): string {\n return [\n interactiveTermSetupScript(),\n interactiveTtySetupScript(),\n interactiveAgentPathScript(),\n runtimeSecretEnvironmentScript(),\n 'exec \"$@\"'\n ].join('\\n')\n}\n","import { mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport {\n BOXDOWN_CONTAINER_AGENTS_DIR,\n BOXDOWN_CONTAINER_CODEX_AUTH_PATH,\n BOXDOWN_CONTAINER_CODEX_DIR,\n BOXDOWN_CONTAINER_DEVCONTAINER_DIR,\n BOXDOWN_CONTAINER_GITCONFIG_PATH,\n BOXDOWN_CONTAINER_HOST_GITCONFIG_DIR,\n BOXDOWN_CONTAINER_SECRET_ENV_BOOTSTRAP,\n BOXDOWN_CONTAINER_SECRET_ENV_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 type { GitSigningPlan } from './git-signing.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\nfunction directoryExists (path: string): boolean {\n try {\n return statSync(path).isDirectory()\n } catch {\n return false\n }\n}\n\nfunction fileExists (path: string): boolean {\n try {\n return statSync(path).isFile()\n } catch {\n return false\n }\n}\n\nfunction mountHasTarget (mount: string, target: string): boolean {\n return mount.split(',').some((part) => part.trim() === `target=${target}`)\n}\n\nfunction hasMountTarget (mounts: string[], target: string): boolean {\n return mounts.some((mount) => mountHasTarget(mount, target))\n}\n\nexport function buildGeneratedDevcontainerConfig (context: WorkspaceContext, signing?: GitSigningPlan): DevcontainerConfig {\n const baseConfig = readBaseDevcontainerConfig(context.assetsDevcontainerDir)\n const mounts = Array.isArray(baseConfig.mounts)\n ? baseConfig.mounts\n .filter((mount): mount is string => typeof mount === 'string')\n .filter((mount) => !mountHasTarget(mount, BOXDOWN_CONTAINER_GITCONFIG_PATH))\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 `type=bind,source=${context.hostGitconfigSnapshotDir},target=${BOXDOWN_CONTAINER_HOST_GITCONFIG_DIR},readonly`,\n `type=bind,source=${context.workspaceSecretEnvDir},target=${BOXDOWN_CONTAINER_SECRET_ENV_DIR},readonly`\n ]\n\n if (\n directoryExists(context.hostAgentsDir) &&\n !hasMountTarget(mounts, BOXDOWN_CONTAINER_AGENTS_DIR)\n ) {\n boxdownMounts.push(`type=bind,source=${context.hostAgentsDir},target=${BOXDOWN_CONTAINER_AGENTS_DIR},readonly`)\n }\n\n if (signing?.enabled === true && signing.agentSocketSource !== undefined) {\n boxdownMounts.push(`type=bind,source=${signing.agentSocketSource},target=/run/boxdown/ssh-agent.sock`)\n boxdownMounts.push(`type=bind,source=${context.gitSigningStateDir},target=/opt/boxdown/state/git-signing,readonly`)\n }\n\n if (\n fileExists(context.hostCodexAuthPath) &&\n !hasMountTarget(mounts, BOXDOWN_CONTAINER_CODEX_DIR) &&\n !hasMountTarget(mounts, BOXDOWN_CONTAINER_CODEX_AUTH_PATH)\n ) {\n boxdownMounts.push(`type=bind,source=${context.hostCodexAuthPath},target=${BOXDOWN_CONTAINER_CODEX_AUTH_PATH},readonly`)\n }\n\n return {\n ...baseConfig,\n name: `Boxdown: ${context.workspaceBasename}`,\n mounts: [...mounts, ...boxdownMounts],\n initializeCommand: [\n `BOXDOWN_WORKSPACE_FOLDER=${shellQuote(context.workspaceFolder)}`,\n `BOXDOWN_HOST_GITCONFIG_PATH=${shellQuote(context.hostGitconfigPath)}`,\n `BOXDOWN_HOST_GITCONFIG_SNAPSHOT_PATH=${shellQuote(context.hostGitconfigSnapshotPath)}`,\n `BOXDOWN_SECRET_ENV_DIR=${shellQuote(context.workspaceSecretEnvDir)}`,\n `BOXDOWN_PROGRESS=${shellQuote('${localEnv:BOXDOWN_PROGRESS}')}`,\n `BOXDOWN_VERBOSE=${shellQuote('${localEnv:BOXDOWN_VERBOSE}')}`,\n 'bash',\n shellQuote(join(context.assetsDevcontainerDir, 'hooks', 'initialize.sh'))\n ].join(' '),\n postCreateCommand: [\n `BOXDOWN_PROGRESS=${shellQuote('${localEnv:BOXDOWN_PROGRESS}')}`,\n `BOXDOWN_VERBOSE=${shellQuote('${localEnv:BOXDOWN_VERBOSE}')}`,\n 'bash',\n shellQuote(`${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/hooks/post-create.sh`)\n ].join(' '),\n postStartCommand: [\n `BOXDOWN_PROGRESS=${shellQuote('${localEnv:BOXDOWN_PROGRESS}')}`,\n `BOXDOWN_VERBOSE=${shellQuote('${localEnv:BOXDOWN_VERBOSE}')}`,\n 'bash',\n shellQuote(`${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/hooks/post-start.sh`)\n ].join(' '),\n containerEnv: {\n ...(baseConfig.containerEnv ?? {}),\n BOXDOWN_CONTAINER_WORKSPACE_FOLDER: '/workspaces/${localWorkspaceFolderBasename}',\n BOXDOWN_WORKSPACE_BASENAME: '${localWorkspaceFolderBasename}',\n BOXDOWN_SECRET_ENV_DIR: BOXDOWN_CONTAINER_SECRET_ENV_DIR,\n BASH_ENV: BOXDOWN_CONTAINER_SECRET_ENV_BOOTSTRAP,\n DEVCONTAINER_SSH_PUBLIC_KEY_FILE: BOXDOWN_CONTAINER_SSH_PUBLIC_KEY_PATH,\n BOXDOWN_GIT_SIGNING_ENABLED: signing?.enabled === true ? '1' : '0',\n BOXDOWN_GIT_SIGNING_KEY_PATH: '/opt/boxdown/state/git-signing/signing-key.pub',\n ...(signing?.enabled === false && signing.reason !== undefined ? { BOXDOWN_GIT_SIGNING_REASON: signing.reason } : {}),\n ...(signing?.enabled === true\n ? {\n BOXDOWN_GIT_SIGNING_SOURCE_SOCKET: '/run/boxdown/ssh-agent.sock',\n SSH_AUTH_SOCK: '/run/boxdown/ssh-agent-node.sock'\n }\n : {})\n }\n }\n}\n\nexport function writeGeneratedDevcontainerConfig (context: WorkspaceContext, signing?: GitSigningPlan): DevcontainerConfig {\n const config = buildGeneratedDevcontainerConfig(context, signing)\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 { 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'\nimport { delimiter } from 'node:path'\n\nimport type { WorkspaceCommandLogger } from './logging.ts'\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 logger?: WorkspaceCommandLogger\n onStdout?: (chunk: Buffer) => void\n onStderr?: (chunk: Buffer) => void\n}\n\nexport interface CommandResult {\n code: number\n stdout: string\n stderr: string\n}\n\nfunction mergedEnv (env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const baseEnv = {\n ...process.env,\n ...(env ?? {})\n }\n\n return {\n ...baseEnv,\n PATH: buildHostToolPath(baseEnv)\n }\n}\n\nfunction uniquePathEntries (entries: readonly string[]): string[] {\n const seen = new Set<string>()\n const result: string[] = []\n\n for (const entry of entries) {\n if (entry.length === 0 || seen.has(entry)) {\n continue\n }\n\n seen.add(entry)\n result.push(entry)\n }\n\n return result\n}\n\nexport function buildHostToolPath (env: NodeJS.ProcessEnv = process.env): string {\n const home = env.HOME\n const existingPath = env.PATH ?? ''\n const configuredPrefix = env.BOXDOWN_HOST_PATH_PREFIX?.split(delimiter) ?? []\n const guiFriendlyPrefix = [\n ...(home === undefined ? [] : [\n `${home}/.local/bin`,\n `${home}/.docker/bin`\n ]),\n '/opt/homebrew/bin',\n '/opt/homebrew/sbin',\n '/usr/local/bin',\n '/usr/local/sbin',\n '/Applications/Docker.app/Contents/Resources/bin',\n '/usr/bin',\n '/bin',\n '/usr/sbin',\n '/sbin'\n ]\n\n return uniquePathEntries([\n ...configuredPrefix,\n ...existingPath.split(delimiter),\n ...guiFriendlyPrefix\n ]).join(delimiter)\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 loggedCommand = options.logger?.startCommand(command, args, { cwd: options.cwd })\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 loggedCommand?.stream('stdout', chunk)\n options.onStdout?.(chunk)\n writeChunk(options.mirrorStdout ?? 'stdout', chunk)\n })\n\n child.stderr.on('data', (chunk: Buffer) => {\n stderrChunks.push(chunk)\n loggedCommand?.stream('stderr', chunk)\n options.onStderr?.(chunk)\n writeChunk(options.mirrorStderr ?? 'stderr', chunk)\n })\n\n let resolved = false\n\n child.on('error', (error) => {\n if (resolved) {\n return\n }\n\n resolved = true\n loggedCommand?.error(error)\n loggedCommand?.finish(127)\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 if (resolved) {\n return\n }\n\n resolved = true\n loggedCommand?.finish(code ?? 1)\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' | 'logger'> = {}): Promise<number> {\n return new Promise((resolve) => {\n const loggedCommand = options.logger?.startCommand(command, args, { cwd: options.cwd })\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 loggedCommand?.error(error)\n loggedCommand?.finish(127)\n process.stderr.write(`${error.message}\\n`)\n resolve(127)\n })\n\n child.on('close', (code) => {\n loggedCommand?.finish(code ?? 1)\n resolve(code ?? 1)\n })\n })\n}\n","import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { isAbsolute, join, resolve } from 'node:path'\n\nimport type { WorkspaceCommandLogger } from './logging.ts'\nimport type { WorkspaceContext } from './paths.ts'\nimport { runBuffered, type CommandResult } from './process.ts'\n\nexport type GitSigningReason = 'agent-unavailable' | 'no-identities' | 'ambiguous-identities' | 'configured-key-unreadable' | 'configured-key-invalid' | 'configured-key-not-loaded' | 'agent-socket-unavailable' | 'docker-probe-image-unavailable' | 'agent-mount-unavailable'\n\nexport interface GitSigningPlan {\n enabled: boolean\n reason?: GitSigningReason\n detail?: string\n publicKey?: string\n agentSocketSource?: string\n}\n\nconst GIT_SIGNING_REASON_MESSAGES: Record<GitSigningReason, string> = {\n 'agent-unavailable': 'the host SSH agent is unavailable',\n 'no-identities': 'the host SSH agent has no loaded identities',\n 'ambiguous-identities': 'multiple SSH identities are loaded and no signing key could be selected safely',\n 'configured-key-unreadable': 'the configured SSH signing-key file could not be read',\n 'configured-key-invalid': 'the configured SSH signing key is not a valid public key',\n 'configured-key-not-loaded': 'the configured SSH signing key is not loaded in the agent',\n 'agent-socket-unavailable': 'the host SSH-agent socket is unavailable',\n 'docker-probe-image-unavailable': 'no local Docker image is available to probe the SSH-agent mount',\n 'agent-mount-unavailable': 'Docker could not mount the host SSH-agent socket'\n}\n\nfunction compactDiagnosticDetail (detail: string): string {\n return detail\n .trim()\n .replace(/\\s+/gu, ' ')\n .slice(0, 2000)\n .replace(/-----BEGIN [^-]*PRIVATE KEY-----.*?(?:-----END [^-]*PRIVATE KEY-----|$)/giu, '[redacted-private-key]')\n .replace(/\\b(?:ssh-[A-Za-z0-9-]+|ecdsa-sha2-[A-Za-z0-9-]+|sk-(?:ssh-[A-Za-z0-9-]+|ecdsa-sha2-[A-Za-z0-9-]+))\\s+[A-Za-z0-9+/=]{16,}/gu, '[redacted-ssh-key]')\n .replace(/\\b(?:github_pat_|gh[pousr]_|glpat-|xox[baprs]-)[A-Za-z0-9_-]{8,}/gu, '[redacted-token]')\n .replace(/\\b(?:Bearer\\s+|token[=:]\\s*)[A-Za-z0-9._~+/-]{8,}/giu, '[redacted-token]')\n .slice(0, 300)\n}\n\nexport function reportGitSigningPlan (\n plan: GitSigningPlan,\n options: {\n logger?: Pick<WorkspaceCommandLogger, 'boxdown'>\n quiet?: boolean\n writeWarning?: (message: string) => void\n } = {}\n): void {\n if (plan.enabled) return\n\n const reason = plan.reason ?? 'agent-unavailable'\n const detail = plan.detail === undefined ? '' : ` detail=${compactDiagnosticDetail(plan.detail)}`\n options.logger?.boxdown(`git-signing: enabled=false reason=${reason}${detail}\\n`)\n\n if (options.quiet !== true) {\n const writeWarning = options.writeWarning ?? ((message: string) => process.stderr.write(message))\n writeWarning(`boxdown: commit signing disabled: ${GIT_SIGNING_REASON_MESSAGES[reason]}; commits will remain unsigned.\\n`)\n }\n}\n\nexport function parseSshPublicKey (value: string): string | undefined {\n const [algorithm, key] = value.trim().split(/\\s+/, 3)\n if (algorithm === undefined || key === undefined || !/^ssh-[A-Za-z0-9-]+$/.test(algorithm) || key.length === 0) {\n return undefined\n }\n\n return `${algorithm} ${key}`\n}\n\nexport interface ConfiguredSshSigningKeyResult {\n key?: string\n reason?: Extract<GitSigningReason, 'configured-key-unreadable' | 'configured-key-invalid'>\n detail?: string\n}\n\nexport function resolveConfiguredSshSigningKey (\n value: string,\n options: { homeDir?: string, workspaceFolder: string }\n): ConfiguredSshSigningKeyResult {\n const inlineValue = value.startsWith('key::') ? value.slice('key::'.length) : value\n const inlineKey = parseSshPublicKey(inlineValue)\n if (inlineKey !== undefined) {\n return { key: inlineKey }\n }\n if (value.startsWith('key::')) {\n return {\n reason: 'configured-key-invalid',\n detail: 'configured inline value is not a valid SSH public key'\n }\n }\n\n let keyPath: string\n if (value.startsWith('~/')) {\n if (options.homeDir === undefined) {\n return {\n reason: 'configured-key-unreadable',\n detail: 'configured public-key file could not be read'\n }\n }\n keyPath = join(options.homeDir, value.slice(2))\n } else {\n keyPath = isAbsolute(value) ? value : resolve(options.workspaceFolder, value)\n }\n\n let publicKeyText: string\n try {\n publicKeyText = readFileSync(keyPath, 'utf8')\n } catch {\n return {\n reason: 'configured-key-unreadable',\n detail: 'configured public-key file could not be read'\n }\n }\n\n const publicKey = parseSshPublicKey(publicKeyText.split(/\\r?\\n/u).find((line) => line.trim().length > 0) ?? '')\n return publicKey === undefined\n ? {\n reason: 'configured-key-invalid',\n detail: 'configured public-key file does not contain a valid SSH public key'\n }\n : { key: publicKey }\n}\n\nexport function selectGitSigningKey (identities: string[], configuredKey?: string, githubKeys?: string[]): { key?: string, reason?: GitSigningReason } {\n const keys = identities.map(parseSshPublicKey).filter((key): key is string => key !== undefined)\n if (keys.length === 0) return { reason: 'no-identities' }\n\n const configured = configuredKey === undefined ? undefined : parseSshPublicKey(configuredKey)\n if (configuredKey !== undefined && configured === undefined) {\n return { reason: 'configured-key-invalid' }\n }\n if (configured !== undefined) {\n return keys.includes(configured) ? { key: configured } : { reason: 'configured-key-not-loaded' }\n }\n\n const github = new Set((githubKeys ?? []).map(parseSshPublicKey).filter((key): key is string => key !== undefined))\n const matches = keys.filter((key) => github.has(key))\n if (matches.length === 1) return { key: matches[0] }\n if (keys.length === 1) return { key: keys[0] }\n return { reason: 'ambiguous-identities' }\n}\n\nexport function writeGitSigningPublicKey (context: WorkspaceContext, key: string): void {\n mkdirSync(context.gitSigningStateDir, { recursive: true, mode: 0o700 })\n writeFileSync(join(context.gitSigningStateDir, 'signing-key.pub'), `${parseSshPublicKey(key) ?? key}\\n`, { mode: 0o644 })\n}\n\ntype GitSigningCommandRunner = (command: string, args: string[]) => Promise<CommandResult>\n\ninterface ResolveGitSigningPlanOptions {\n env?: NodeJS.ProcessEnv\n platform?: NodeJS.Platform\n runCommand?: GitSigningCommandRunner\n}\n\ntype AgentMountProbeResult =\n | { ok: true }\n | { ok: false, reason: Extract<GitSigningReason, 'docker-probe-image-unavailable' | 'agent-mount-unavailable'>, detail: string }\n\nasync function runGitSigningCommand (command: string, args: string[]): Promise<CommandResult> {\n return runBuffered(command, args, { mirrorStdout: false, mirrorStderr: false })\n}\n\nfunction failedCommandDetail (label: string, result: CommandResult): string {\n const stderr = compactDiagnosticDetail(result.stderr)\n return stderr.length === 0\n ? `${label} failed with exit code ${result.code}`\n : `${label} failed with exit code ${result.code}: ${stderr}`\n}\n\nasync function probeDockerAgentMount (source: string, runCommand: GitSigningCommandRunner): Promise<AgentMountProbeResult> {\n const images = await runCommand('docker', ['image', 'ls', '--format', '{{.Repository}}:{{.Tag}}'])\n const image = images.stdout.split(/\\r?\\n/).map((value) => value.trim()).find((value) => value.length > 0 && value !== '<none>:<none>')\n if (images.code !== 0) {\n return {\n ok: false,\n reason: 'agent-mount-unavailable',\n detail: failedCommandDetail('Docker image listing', images)\n }\n }\n if (image === undefined) {\n return {\n ok: false,\n reason: 'docker-probe-image-unavailable',\n detail: 'no tagged local Docker image was found'\n }\n }\n\n const created = await runCommand('docker', ['create', '--pull=never', '--entrypoint', '/bin/true', '--mount', `type=bind,source=${source},target=/run/boxdown/ssh-agent.sock`, image])\n const containerId = created.stdout.trim().split(/\\r?\\n/)[0]\n if (created.code !== 0 || containerId === undefined || containerId.length === 0) {\n return {\n ok: false,\n reason: 'agent-mount-unavailable',\n detail: failedCommandDetail('Docker SSH-agent mount probe', created)\n }\n }\n await runCommand('docker', ['rm', '-f', containerId])\n return { ok: true }\n}\n\nexport async function resolveGitSigningPlan (context: WorkspaceContext, options: ResolveGitSigningPlanOptions = {}): Promise<GitSigningPlan> {\n const runCommand = options.runCommand ?? runGitSigningCommand\n const result = await runCommand('ssh-add', ['-L'])\n if (result.code !== 0) {\n return {\n enabled: false,\n reason: 'agent-unavailable',\n detail: failedCommandDetail('ssh-add -L', result)\n }\n }\n\n const identities = result.stdout.split(/\\r?\\n/)\n const format = await runCommand('git', ['config', '--global', '--get', 'gpg.format'])\n let configuredKey: string | undefined\n if (format.code === 0 && format.stdout.trim() === 'ssh') {\n const signingKey = await runCommand('git', ['config', '--global', '--get', 'user.signingkey'])\n if (signingKey.code === 0 && signingKey.stdout.trim().length > 0) {\n const resolvedKey = resolveConfiguredSshSigningKey(signingKey.stdout.trim(), {\n homeDir: options.env?.HOME ?? process.env.HOME,\n workspaceFolder: context.workspaceFolder\n })\n if (resolvedKey.key === undefined) {\n return {\n enabled: false,\n reason: resolvedKey.reason ?? 'configured-key-invalid',\n detail: resolvedKey.detail\n }\n }\n configuredKey = resolvedKey.key\n }\n }\n let githubKeys: string[] | undefined\n if (configuredKey === undefined && identities.filter((key) => parseSshPublicKey(key) !== undefined).length > 1) {\n const user = await runCommand('gh', ['api', 'user', '--jq', '.login'])\n const login = user.stdout.trim()\n if (user.code === 0 && login.length > 0) {\n const github = await runCommand('gh', ['api', `users/${login}/keys`, '--paginate', '--jq', '.[].key'])\n if (github.code === 0) githubKeys = github.stdout.split(/\\r?\\n/)\n }\n }\n const selected = selectGitSigningKey(identities, configuredKey, githubKeys)\n if (selected.key === undefined) return { enabled: false, reason: selected.reason }\n\n const agentSocketSource = (options.platform ?? process.platform) === 'darwin'\n ? '/run/host-services/ssh-auth.sock'\n : options.env?.SSH_AUTH_SOCK ?? process.env.SSH_AUTH_SOCK\n if (agentSocketSource === undefined || agentSocketSource.length === 0) {\n return {\n enabled: false,\n reason: 'agent-socket-unavailable',\n detail: 'SSH_AUTH_SOCK is not set'\n }\n }\n const mountProbe = await probeDockerAgentMount(agentSocketSource, runCommand)\n if (!mountProbe.ok) {\n return {\n enabled: false,\n reason: mountProbe.reason,\n detail: mountProbe.detail\n }\n }\n\n writeGitSigningPublicKey(context, selected.key)\n return { enabled: true, publicKey: selected.key, agentSocketSource }\n}\n","import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\nimport { resolveDevcontainerCli } from './devcontainer-cli.ts'\nimport { buildGeneratedDevcontainerConfig, type DevcontainerConfig } from './config.ts'\nimport { BOXDOWN_SECRET_ENV_NAMES } from './constants.ts'\nimport { resolveConfiguredSshSigningKey, selectGitSigningKey, type GitSigningReason } from './git-signing.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\nexport interface DoctorCommandResult {\n code: number\n stdout: string\n stderr: string\n}\n\nexport type DoctorCommandRunner = (command: string, args: string[]) => Promise<DoctorCommandResult>\n\nexport interface RunDoctorChecksOptions {\n includeOptional?: boolean\n includeDockerMountProbe?: boolean\n runCommand?: DoctorCommandRunner\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\nfunction secretEnvironmentConfigCheck (context: WorkspaceContext): DoctorCheck {\n let config: DevcontainerConfig\n\n try {\n config = existsSync(context.generatedConfigPath)\n ? JSON.parse(readFileSync(context.generatedConfigPath, 'utf8')) as DevcontainerConfig\n : buildGeneratedDevcontainerConfig(context)\n } catch {\n return {\n name: 'secret-environment-config',\n level: 'warn',\n message: 'Generated config could not be checked for secret-safe environment handling'\n }\n }\n\n const runArgs = Array.isArray(config.runArgs) ? config.runArgs : []\n const containerEnv = config.containerEnv ?? {}\n const unsafe = runArgs.includes('--env-file') ||\n runArgs.some((arg) => arg.includes('.env.development')) ||\n BOXDOWN_SECRET_ENV_NAMES.some((name) => Object.hasOwn(containerEnv, name))\n\n return {\n name: 'secret-environment-config',\n level: unsafe ? 'warn' : 'ok',\n message: unsafe\n ? 'Generated config still exposes Boxdown secrets through Docker environment settings; recreate after upgrading Boxdown'\n : 'Generated config uses runtime-mounted secrets without Docker environment values'\n }\n}\n\nasync function runDoctorCommand (command: string, args: string[]): Promise<DoctorCommandResult> {\n return runBuffered(command, args, {\n mirrorStdout: false,\n mirrorStderr: false\n })\n}\n\nasync function commandWorks (runCommand: DoctorCommandRunner, command: string, args: string[]): Promise<boolean> {\n const result = await runCommand(command, args)\n return result.code === 0\n}\n\nasync function commandExists (runCommand: DoctorCommandRunner, command: string, args: string[]): Promise<boolean> {\n const result = await runCommand(command, args)\n return result.code !== 127\n}\n\nexport async function runDoctorChecks (context: WorkspaceContext, options: RunDoctorChecksOptions = {}): Promise<DoctorCheck[]> {\n const checks: DoctorCheck[] = []\n const runCommand = options.runCommand ?? runDoctorCommand\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 const sshAgent = await runCommand('ssh-add', ['-L'])\n const identityLines = sshAgent.code === 0\n ? sshAgent.stdout.split(/\\r?\\n/).filter((line) => line.trim().startsWith('ssh-'))\n : []\n const identities = identityLines.length\n let configuredKey: string | undefined\n let configuredFailure: { reason: GitSigningReason, detail?: string } | undefined\n const format = await runCommand('git', ['config', '--global', '--get', 'gpg.format'])\n if (format.code === 0 && format.stdout.trim() === 'ssh') {\n const signingKey = await runCommand('git', ['config', '--global', '--get', 'user.signingkey'])\n if (signingKey.code === 0 && signingKey.stdout.trim().length > 0) {\n const resolved = resolveConfiguredSshSigningKey(signingKey.stdout.trim(), {\n homeDir: dirname(context.hostGitconfigPath),\n workspaceFolder: context.workspaceFolder\n })\n if (resolved.key === undefined) {\n configuredFailure = {\n reason: resolved.reason ?? 'configured-key-invalid',\n detail: resolved.detail\n }\n } else {\n configuredKey = resolved.key\n }\n }\n }\n\n const includeOptional = options.includeOptional ?? true\n let ghAvailable = false\n let ghAuth = false\n let githubLogin: string | undefined\n let githubAuthKeys: string[] | undefined\n if (includeOptional) {\n ghAvailable = await commandWorks(runCommand, 'gh', ['--version'])\n if (ghAvailable) {\n ghAuth = await commandWorks(runCommand, 'gh', ['auth', 'status', '--hostname', 'github.com'])\n if (ghAuth && configuredKey === undefined && configuredFailure === undefined && identities > 1) {\n const user = await runCommand('gh', ['api', 'user', '--jq', '.login'])\n githubLogin = user.code === 0 && user.stdout.trim().length > 0 ? user.stdout.trim() : undefined\n if (githubLogin !== undefined) {\n const authentication = await runCommand('gh', ['api', `users/${githubLogin}/keys`, '--paginate', '--jq', '.[].key'])\n if (authentication.code === 0) githubAuthKeys = authentication.stdout.split(/\\r?\\n/)\n }\n }\n }\n }\n\n const selected: { key?: string, reason?: GitSigningReason } = configuredFailure ?? selectGitSigningKey(identityLines, configuredKey, githubAuthKeys)\n const selectedByConfiguration = selected.key !== undefined && configuredKey !== undefined\n const selectedByGithub = selected.key !== undefined && configuredKey === undefined && identities > 1\n const signingMessages: Record<GitSigningReason, string> = {\n 'agent-unavailable': 'SSH agent is unavailable; Boxdown commits will remain unsigned',\n 'no-identities': 'SSH agent has no identities; Boxdown commits will remain unsigned',\n 'ambiguous-identities': 'SSH agent has multiple identities; Boxdown will not guess a signing key and commits will remain unsigned',\n 'configured-key-unreadable': 'Configured SSH signing-key file could not be read; Boxdown commits will remain unsigned',\n 'configured-key-invalid': 'Configured SSH signing key is not a valid public key; Boxdown commits will remain unsigned',\n 'configured-key-not-loaded': 'Configured SSH signing key is not loaded in the agent; Boxdown commits will remain unsigned',\n 'agent-socket-unavailable': 'Host SSH-agent socket is unavailable; Boxdown commits will remain unsigned',\n 'docker-probe-image-unavailable': 'No local Docker image is available to probe commit-signing agent forwarding',\n 'agent-mount-unavailable': 'Docker could not mount the host SSH-agent socket; Boxdown commits will remain unsigned'\n }\n checks.push({\n name: 'git-signing-agent',\n level: sshAgent.code === 0 && selected.key !== undefined ? 'ok' : 'warn',\n message: sshAgent.code !== 0\n ? signingMessages['agent-unavailable']\n : selected.key === undefined\n ? signingMessages[selected.reason ?? 'ambiguous-identities']\n : selectedByConfiguration\n ? 'Configured SSH signing key is loaded in the agent'\n : selectedByGithub\n ? 'GitHub authentication keys identify one SSH agent identity for Boxdown commit signing'\n : 'One SSH agent identity is available for Boxdown commit signing'\n })\n\n checks.push(check(\n 'devcontainers-cli',\n await packagedDevcontainerCliWorks(context, runCommand),\n 'Packaged @devcontainers/cli is available',\n 'Packaged @devcontainers/cli is required but was not available'\n ))\n\n const dockerCliWorks = await commandWorks(runCommand, 'docker', ['--version'])\n checks.push(check(\n 'docker-cli',\n dockerCliWorks,\n 'Docker CLI is available',\n 'Docker CLI is required but was not available'\n ))\n\n const dockerDaemonWorks = await commandWorks(runCommand, 'docker', ['info'])\n checks.push(check(\n 'docker-daemon',\n dockerDaemonWorks,\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(runCommand, 'ssh', ['-V']),\n 'ssh is available',\n 'ssh is required but was not available'\n ))\n\n if (options.includeDockerMountProbe ?? true) {\n checks.push(await checkDockerBindMounts(context, runCommand, dockerCliWorks && dockerDaemonWorks))\n }\n\n checks.push(check(\n 'ssh-keygen',\n await commandExists(runCommand, '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 checks.push(secretEnvironmentConfigCheck(context))\n\n if (includeOptional) {\n if (ghAvailable) {\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 if (ghAuth && selected.key !== undefined) {\n if (githubLogin === undefined) {\n const user = await runCommand('gh', ['api', 'user', '--jq', '.login'])\n githubLogin = user.code === 0 && user.stdout.trim().length > 0 ? user.stdout.trim() : undefined\n }\n const signing = githubLogin !== undefined\n ? await runCommand('gh', ['api', `users/${githubLogin}/ssh_signing_keys`, '--paginate', '--jq', '.[].key'])\n : { code: 1, stdout: '', stderr: '' }\n checks.push({\n name: 'git-signing-github',\n level: signing.code === 0 && signing.stdout.includes(selected.key) ? 'ok' : 'warn',\n message: signing.code !== 0\n ? 'GitHub SSH signing-key registration could not be checked'\n : signing.stdout.includes(selected.key)\n ? 'Selected SSH key is registered with GitHub for commit signing'\n : 'Register the selected public key with GitHub as a signing key to receive Verified badges'\n })\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\n return checks\n}\n\nfunction dockerProbeImage (output: string): string | undefined {\n return output\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .find((image) => image.length > 0 && image !== '<none>:<none>')\n}\n\nfunction dockerMountError (output: string): boolean {\n return /invalid mount config|bind source path does not exist|mount denied|file sharing|mounts denied|permission denied|operation not permitted/i.test(output)\n}\n\nfunction compactOutput (output: string): string {\n return output.trim().replace(/\\s+/g, ' ').slice(0, 300)\n}\n\ninterface DockerMountSource {\n label: string\n path: string\n}\n\nasync function checkDockerBindMounts (\n context: WorkspaceContext,\n runCommand: DoctorCommandRunner,\n dockerReady: boolean\n): Promise<DoctorCheck> {\n if (!dockerReady) {\n return {\n name: 'docker-bind-mounts',\n level: 'warn',\n message: 'Docker bind-mount readiness was not checked because Docker is unavailable'\n }\n }\n\n const imageResult = await runCommand('docker', ['image', 'ls', '--format', '{{.Repository}}:{{.Tag}}'])\n const image = imageResult.code === 0 ? dockerProbeImage(imageResult.stdout) : undefined\n\n if (image === undefined) {\n return {\n name: 'docker-bind-mounts',\n level: 'warn',\n message: 'Docker bind-mount readiness was not checked because no local Docker image is available'\n }\n }\n\n mkdirSync(context.workspaceDataDir, { recursive: true })\n const runtimeProbeDir = mkdtempSync(join(context.workspaceDataDir, 'doctor-mount-probe-'))\n mkdirSync(context.workspaceSecretEnvDir, { recursive: true, mode: 0o700 })\n chmodSync(context.workspaceSecretEnvDir, 0o700)\n const sources: DockerMountSource[] = [\n { label: 'workspace', path: context.workspaceFolder },\n { label: 'Boxdown devcontainer assets', path: context.assetsDevcontainerDir },\n { label: 'Boxdown runtime state', path: runtimeProbeDir },\n { label: 'Boxdown runtime secret state', path: context.workspaceSecretEnvDir }\n ]\n\n try {\n for (const source of sources) {\n const createResult = await runCommand('docker', [\n 'create',\n '--pull=never',\n '--entrypoint',\n '/bin/true',\n '--mount',\n `type=bind,source=${source.path},target=/boxdown-preflight,readonly`,\n image\n ])\n const output = `${createResult.stderr}\\n${createResult.stdout}`\n\n if (createResult.code !== 0) {\n if (dockerMountError(output)) {\n return {\n name: 'docker-bind-mounts',\n level: 'fail',\n message: `Docker cannot bind-mount the ${source.label} path (${source.path}). Check Docker Desktop file sharing and host-folder permissions.`\n }\n }\n\n return {\n name: 'docker-bind-mounts',\n level: 'warn',\n message: `Docker bind-mount readiness could not be checked for ${source.label}: ${compactOutput(output) || 'Docker create failed'}`\n }\n }\n\n const containerId = createResult.stdout.trim().split(/\\r?\\n/)[0]\n if (containerId === undefined || containerId.length === 0) {\n return {\n name: 'docker-bind-mounts',\n level: 'warn',\n message: `Docker bind-mount readiness could not be checked for ${source.label}: Docker did not return a container ID`\n }\n }\n\n const removeResult = await runCommand('docker', ['rm', '-f', containerId])\n if (removeResult.code !== 0) {\n return {\n name: 'docker-bind-mounts',\n level: 'warn',\n message: `Docker bind-mount readiness was checked, but the disposable probe container could not be removed: ${compactOutput(removeResult.stderr) || 'docker rm failed'}`\n }\n }\n }\n } finally {\n rmSync(runtimeProbeDir, { recursive: true, force: true })\n }\n\n return {\n name: 'docker-bind-mounts',\n level: 'ok',\n message: 'Docker can bind-mount Boxdown workspace, assets, and runtime-state paths'\n }\n}\n\nasync function packagedDevcontainerCliWorks (context: WorkspaceContext, runCommand: DoctorCommandRunner): Promise<boolean> {\n try {\n const cli = resolveDevcontainerCli(context)\n return await commandWorks(runCommand, 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","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 { 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 dockerImageId?: string\n dockerImageName?: string\n dockerImageLastSeenAt?: string\n}\n\nexport interface WorkspaceDockerImageMetadata {\n id: string\n name?: 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 (candidate.dockerImageId === undefined || typeof candidate.dockerImageId === 'string') &&\n (candidate.dockerImageName === undefined || typeof candidate.dockerImageName === 'string') &&\n (candidate.dockerImageLastSeenAt === undefined || typeof candidate.dockerImageLastSeenAt === '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 readWorkspaceMetadata (context: WorkspaceContext): WorkspaceMetadata | undefined {\n const metadataPath = workspaceMetadataPath(context)\n\n if (!existsSync(metadataPath)) {\n return undefined\n }\n\n return readWorkspaceMetadataFile(metadataPath)\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 let existingMetadata: WorkspaceMetadata | undefined\n\n if (existsSync(metadataPath)) {\n existingMetadata = readWorkspaceMetadataFile(metadataPath)\n firstSeenAt = existingMetadata.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 ...(existingMetadata?.dockerImageId === undefined ? {} : { dockerImageId: existingMetadata.dockerImageId }),\n ...(existingMetadata?.dockerImageName === undefined ? {} : { dockerImageName: existingMetadata.dockerImageName }),\n ...(existingMetadata?.dockerImageLastSeenAt === undefined ? {} : { dockerImageLastSeenAt: existingMetadata.dockerImageLastSeenAt })\n }\n\n mkdirSync(context.workspaceDataDir, { recursive: true })\n writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}\\n`)\n return metadata\n}\n\nexport function recordWorkspaceDockerImage (\n context: WorkspaceContext,\n image: WorkspaceDockerImageMetadata,\n now = new Date()\n): WorkspaceMetadata | undefined {\n const metadata = readWorkspaceMetadata(context)\n\n if (metadata === undefined) {\n return undefined\n }\n\n const nextMetadata: WorkspaceMetadata = {\n ...metadata,\n dockerImageId: image.id,\n ...(image.name === undefined ? {} : { dockerImageName: image.name }),\n dockerImageLastSeenAt: now.toISOString()\n }\n\n mkdirSync(context.workspaceDataDir, { recursive: true })\n writeFileSync(workspaceMetadataPath(context), `${JSON.stringify(nextMetadata, null, 2)}\\n`)\n return nextMetadata\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","export const ansi = {\n bold: '\\u001B[1m',\n cyan: '\\u001B[36m',\n dim: '\\u001B[2m',\n green: '\\u001B[32m',\n red: '\\u001B[31m',\n yellow: '\\u001B[33m',\n reset: '\\u001B[0m'\n} as const\n\nexport type CliColor = keyof typeof ansi\n\nexport function color (value: string, colorName: CliColor): string {\n return `${ansi[colorName]}${value}${ansi.reset}`\n}\n\nexport function selectedMark (): string {\n return color('■', 'green')\n}\n\nexport function emptyMark (isFocused: boolean): string {\n return color('□', isFocused ? 'cyan' : 'dim')\n}\n\nexport function promptRail (): string {\n return color('│', 'cyan')\n}\n\nexport function formatPromptTitle (title: string): string {\n return `${color('◆', 'cyan')} ${color(title, 'bold')}`\n}\n\nexport function formatPromptEnd (): string {\n return color('└', 'cyan')\n}\n\nexport function formatPromptLabel (label: string, isFocused: boolean): string {\n return color(label, isFocused ? 'bold' : 'dim')\n}\n\nexport function formatPromptDetailLine (detail: string): string {\n return `${promptRail()} ${color(detail, 'dim')}`\n}\n","import { runBuffered, type BufferedCommandOptions, type CommandResult } from './process.ts'\nimport { color, formatPromptEnd, formatPromptTitle, promptRail, selectedMark } from './cli-style.ts'\n\nexport type ProgressOutputTarget = 'stdout' | 'stderr'\nexport type ProgressMode = 'interactive' | 'verbose' | 'none'\nexport type ProgressWriter = (target: ProgressOutputTarget, message: string) => void\nexport type ProgressRawWriter = (target: ProgressOutputTarget, message: string) => void\n\nexport interface ProgressReporterOptions {\n mode?: ProgressMode\n verbose?: boolean\n target?: ProgressOutputTarget\n write?: ProgressWriter\n writeRaw?: ProgressRawWriter\n isTTY?: boolean\n spinnerFrames?: readonly string[]\n spinnerIntervalMs?: number\n}\n\nexport interface ProgressCommandOptions extends Pick<BufferedCommandOptions, 'cwd' | 'env' | 'input'> {\n logger?: BufferedCommandOptions['logger']\n progress?: ProgressReporter\n verboseStdout?: ProgressOutputTarget | false\n verboseStderr?: ProgressOutputTarget | false\n spinnerLabel?: string\n stepId?: string\n}\n\nexport interface ResolveProgressModeOptions {\n verbose?: boolean\n json?: boolean\n target?: ProgressOutputTarget\n env?: NodeJS.ProcessEnv\n isTTY?: boolean\n}\n\nexport type ProgressStepState = 'pending' | 'running' | 'complete' | 'failed' | 'skipped'\n\nexport interface ProgressStepDefinition {\n id: string\n label: string\n}\n\nconst PROGRESS_MARKER_PREFIX = 'BOXDOWN_PROGRESS:'\nconst DEFAULT_FAILURE_TAIL_LINES = 20\nconst DEFAULT_SPINNER_FRAMES = ['◒', '◐', '◓', '◑'] as const\nconst DEFAULT_SPINNER_INTERVAL_MS = 120\n\ninterface ActiveSpinner {\n message: string\n frameIndex: number\n timer?: ReturnType<typeof setInterval>\n tty: boolean\n}\n\ninterface ProgressStep extends ProgressStepDefinition {\n state: ProgressStepState\n}\n\nfunction writeLine (target: ProgressOutputTarget, message: string): void {\n const stream = target === 'stderr' ? process.stderr : process.stdout\n stream.write(`${message}\\n`)\n}\n\nfunction writeRaw (target: ProgressOutputTarget, message: string): void {\n const stream = target === 'stderr' ? process.stderr : process.stdout\n stream.write(message)\n}\n\nfunction targetIsTTY (target: ProgressOutputTarget): boolean {\n const stream = target === 'stderr' ? process.stderr : process.stdout\n return stream.isTTY === true\n}\n\nfunction isCiEnvironment (env: NodeJS.ProcessEnv): boolean {\n const ci = env.CI\n return ci !== undefined && ci !== '' && ci !== '0' && ci !== 'false'\n}\n\nfunction normalizeMessage (message: string): string {\n return message.trim().replace(/\\s+/g, ' ')\n}\n\nexport function resolveProgressMode (options: ResolveProgressModeOptions = {}): ProgressMode {\n if (options.json === true) {\n return 'none'\n }\n\n if (options.verbose === true) {\n return 'verbose'\n }\n\n if (isCiEnvironment(options.env ?? process.env)) {\n return 'verbose'\n }\n\n const target = options.target ?? 'stdout'\n const isTTY = options.isTTY ?? targetIsTTY(target)\n\n return isTTY ? 'interactive' : 'verbose'\n}\n\nexport class ProgressReporter {\n readonly mode: ProgressMode\n readonly verbose: boolean\n readonly target: ProgressOutputTarget\n readonly #write: ProgressWriter\n readonly #writeRaw: ProgressRawWriter\n readonly #isTTY: boolean\n readonly #spinnerFrames: readonly string[]\n readonly #spinnerIntervalMs: number\n #sectionPrinted = false\n #sectionOpen = false\n #spinner: ActiveSpinner | undefined\n #steps: ProgressStep[] = []\n #renderedStepLineCount = 0\n #stepFrameIndex = 0\n #stepTimer: ReturnType<typeof setInterval> | undefined\n\n constructor (options: ProgressReporterOptions = {}) {\n this.mode = options.mode ?? (options.verbose === true ? 'verbose' : 'interactive')\n this.verbose = this.mode === 'verbose'\n this.target = options.target ?? 'stdout'\n this.#write = options.write ?? writeLine\n this.#writeRaw = options.writeRaw ?? writeRaw\n this.#isTTY = options.isTTY ?? targetIsTTY(this.target)\n this.#spinnerFrames = options.spinnerFrames ?? DEFAULT_SPINNER_FRAMES\n this.#spinnerIntervalMs = options.spinnerIntervalMs ?? DEFAULT_SPINNER_INTERVAL_MS\n }\n\n section (title: string): void {\n if (this.mode !== 'interactive') {\n return\n }\n\n if (this.#sectionOpen) {\n this.end()\n } else if (this.#sectionPrinted) {\n this.#write(this.target, '')\n }\n\n this.#write(this.target, formatPromptTitle(title))\n this.#sectionPrinted = true\n this.#sectionOpen = true\n }\n\n end (): void {\n this.stopSpinner()\n this.#stopStepTimer()\n this.#steps = []\n this.#renderedStepLineCount = 0\n\n if (this.mode !== 'interactive') {\n return\n }\n\n if (!this.#sectionOpen) {\n return\n }\n\n this.#write(this.target, formatPromptEnd())\n this.#sectionOpen = false\n }\n\n item (message: string): void {\n if (this.mode !== 'interactive') {\n return\n }\n\n this.#writeLine(`${promptRail()} ${selectedMark()} ${message}`)\n }\n\n detail (message: string): void {\n if (this.mode !== 'interactive') {\n return\n }\n\n this.#writeLine(`${promptRail()} ${color(message, 'dim')}`)\n }\n\n warn (message: string): void {\n if (this.mode === 'none') {\n return\n }\n\n if (this.mode === 'verbose') {\n this.#write(this.target, `Warning: ${message}`)\n return\n }\n\n this.#writeLine(`${promptRail()} ${color('!', 'dim')} ${message}`)\n }\n\n marker (message: string): void {\n if (this.#steps.length > 0) {\n return\n }\n\n const normalized = normalizeMessage(message)\n\n if (normalized.length > 0) {\n this.item(normalized)\n }\n }\n\n setSteps (steps: readonly ProgressStepDefinition[]): void {\n this.#stopStepTimer()\n this.#steps = steps.map((step) => ({\n ...step,\n state: 'pending'\n }))\n this.#stepFrameIndex = 0\n this.#renderedStepLineCount = 0\n this.#renderChecklist()\n }\n\n isChecklistActive (): boolean {\n return this.#steps.length > 0\n }\n\n startStep (id: string): void {\n this.#updateStep(id, 'running')\n this.#startStepTimer()\n }\n\n completeStep (id: string): void {\n this.#updateStep(id, 'complete')\n this.#stopStepTimerIfIdle()\n }\n\n failStep (id: string): void {\n this.#updateStep(id, 'failed')\n this.#stopStepTimerIfIdle()\n }\n\n skipStep (id: string): void {\n this.#updateStep(id, 'skipped')\n this.#stopStepTimerIfIdle()\n }\n\n hasStep (id: string): boolean {\n return this.#steps.some((step) => step.id === id)\n }\n\n startSpinner (message: string): void {\n if (this.mode !== 'interactive') {\n return\n }\n\n const normalized = normalizeMessage(message)\n if (normalized.length === 0) {\n return\n }\n\n this.stopSpinner()\n this.#spinner = {\n message: normalized,\n frameIndex: 0,\n tty: this.#isTTY\n }\n\n if (this.#spinner.tty) {\n this.#renderSpinner()\n this.#spinner.timer = setInterval(() => {\n this.tickSpinner()\n }, this.#spinnerIntervalMs)\n this.#spinner.timer.unref?.()\n return\n }\n\n this.#writeLine(`${promptRail()} ${color(this.#spinnerFrames[0] ?? '◒', 'cyan')} ${normalized}`)\n }\n\n tickSpinner (): void {\n if (this.#steps.some((step) => step.state === 'running')) {\n this.#stepFrameIndex += 1\n this.#renderChecklist()\n return\n }\n\n const spinner = this.#spinner\n if (spinner === undefined || !spinner.tty) {\n return\n }\n\n spinner.frameIndex += 1\n this.#renderSpinner()\n }\n\n stopSpinner (status: 'complete' | 'clear' = 'clear'): void {\n const spinner = this.#spinner\n if (spinner === undefined) {\n return\n }\n\n if (spinner.timer !== undefined) {\n clearInterval(spinner.timer)\n }\n\n if (spinner.tty) {\n this.#clearSpinnerLine()\n }\n\n this.#spinner = undefined\n\n if (status === 'complete') {\n this.item(spinner.message)\n }\n }\n\n commandEnv (env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n return {\n ...(env ?? {}),\n BOXDOWN_VERBOSE: this.verbose ? '1' : '0',\n BOXDOWN_PROGRESS: this.mode === 'interactive' ? '1' : '0'\n }\n }\n\n #writeLine (message: string): void {\n const spinner = this.#spinner\n\n if (spinner !== undefined && spinner.tty) {\n this.#clearSpinnerLine()\n this.#write(this.target, message)\n this.#renderSpinner()\n return\n }\n\n this.#write(this.target, message)\n }\n\n #renderSpinner (): void {\n const spinner = this.#spinner\n if (spinner === undefined) {\n return\n }\n\n const frame = this.#spinnerFrames[spinner.frameIndex % this.#spinnerFrames.length] ?? '◒'\n this.#writeRaw(this.target, `\\r\\u001B[2K${promptRail()} ${color(frame, 'cyan')} ${spinner.message}`)\n }\n\n #clearSpinnerLine (): void {\n this.#writeRaw(this.target, '\\r\\u001B[2K')\n }\n\n #updateStep (id: string, state: ProgressStepState): void {\n const index = this.#steps.findIndex((step) => step.id === id)\n\n if (index === -1) {\n return\n }\n\n const step = this.#steps[index]\n if (step === undefined) {\n return\n }\n\n this.#steps[index] = {\n ...step,\n state\n }\n\n this.#renderChecklist()\n }\n\n #renderChecklist (): void {\n if (this.mode !== 'interactive' || this.#steps.length === 0) {\n return\n }\n\n const lines = this.#steps.map((step) => this.#formatStep(step))\n\n if (this.#isTTY) {\n if (this.#renderedStepLineCount > 0) {\n this.#writeRaw(this.target, `\\u001B[${this.#renderedStepLineCount}A`)\n }\n\n for (const line of lines) {\n this.#writeRaw(this.target, `\\u001B[2K\\r${line}\\n`)\n }\n\n this.#renderedStepLineCount = lines.length\n return\n }\n\n if (this.#renderedStepLineCount === 0) {\n for (const line of lines) {\n this.#write(this.target, line)\n }\n this.#renderedStepLineCount = lines.length\n }\n }\n\n #formatStep (step: ProgressStep): string {\n const label = step.state === 'skipped' ? color(step.label, 'dim') : step.label\n return `${promptRail()} ${this.#stepMark(step.state)} ${label}`\n }\n\n #stepMark (state: ProgressStepState): string {\n if (state === 'running') {\n const frame = this.#spinnerFrames[this.#stepFrameIndex % this.#spinnerFrames.length] ?? '◐'\n return color(frame, 'cyan')\n }\n\n if (state === 'complete') {\n return color('✔', 'green')\n }\n\n if (state === 'failed') {\n return color('!', 'dim')\n }\n\n return color('□', 'dim')\n }\n\n #startStepTimer (): void {\n if (this.mode !== 'interactive' || !this.#isTTY || this.#stepTimer !== undefined) {\n return\n }\n\n this.#stepTimer = setInterval(() => {\n this.tickSpinner()\n }, this.#spinnerIntervalMs)\n this.#stepTimer.unref?.()\n }\n\n #stopStepTimerIfIdle (): void {\n if (this.#steps.some((step) => step.state === 'running')) {\n return\n }\n\n this.#stopStepTimer()\n }\n\n #stopStepTimer (): void {\n if (this.#stepTimer === undefined) {\n return\n }\n\n clearInterval(this.#stepTimer)\n this.#stepTimer = undefined\n }\n}\n\nexport function createProgress (options: ProgressReporterOptions = {}): ProgressReporter {\n return new ProgressReporter(options)\n}\n\nexport function progressMarkerLine (message: string): string {\n return `${PROGRESS_MARKER_PREFIX} ${message}`\n}\n\nfunction isProgressMarkerLine (line: string): boolean {\n return line.trimStart().startsWith(PROGRESS_MARKER_PREFIX)\n}\n\nfunction progressMarkerMessage (line: string): string | undefined {\n const trimmed = line.trimStart()\n\n if (!trimmed.startsWith(PROGRESS_MARKER_PREFIX)) {\n return undefined\n }\n\n return trimmed.slice(PROGRESS_MARKER_PREFIX.length).trim()\n}\n\nfunction createMarkerSink (progress: ProgressReporter): {\n write: (chunk: Buffer) => void\n flush: () => void\n} {\n let pending = ''\n\n function processLine (line: string): void {\n const message = progressMarkerMessage(line)\n\n if (message !== undefined) {\n progress.marker(message)\n }\n }\n\n return {\n write: (chunk: Buffer) => {\n pending += chunk.toString('utf8')\n\n const lines = pending.split(/\\r?\\n/u)\n pending = lines.pop() ?? ''\n\n for (const line of lines) {\n processLine(line)\n }\n },\n flush: () => {\n if (pending.length > 0) {\n processLine(pending)\n pending = ''\n }\n }\n }\n}\n\nfunction outputWithoutProgressMarkers (output: string): string {\n return output\n .split(/\\r?\\n/u)\n .filter((line) => !isProgressMarkerLine(line))\n .join('\\n')\n}\n\nfunction tailLines (output: string, maxLines: number): string[] {\n return output\n .split(/\\r?\\n/u)\n .map((line) => line.trimEnd())\n .filter((line) => line.trim().length > 0)\n .slice(-maxLines)\n}\n\nexport function formatCommandFailure (label: string, result: CommandResult, options: { tailLines?: number } = {}): string {\n const maxLines = options.tailLines ?? DEFAULT_FAILURE_TAIL_LINES\n const stderrTail = tailLines(outputWithoutProgressMarkers(result.stderr), maxLines)\n const stdoutTail = tailLines(outputWithoutProgressMarkers(result.stdout), Math.max(0, maxLines - stderrTail.length))\n const lines = [\n `${label} failed with exit code ${result.code}.`,\n 'Rerun with --verbose to see full command output.'\n ]\n\n if (stderrTail.length > 0) {\n lines.push('', 'stderr tail:', ...stderrTail.map((line) => ` ${line}`))\n }\n\n if (stdoutTail.length > 0) {\n lines.push('', 'stdout tail:', ...stdoutTail.map((line) => ` ${line}`))\n }\n\n return lines.join('\\n')\n}\n\nexport async function runProgressCommand (\n label: string,\n command: string,\n args: string[],\n options: ProgressCommandOptions = {}\n): Promise<CommandResult> {\n const progress = options.progress\n const verbose = progress?.verbose ?? true\n const markerSink = progress !== undefined && !verbose ? createMarkerSink(progress) : undefined\n const checklistStepId = progress !== undefined && options.stepId !== undefined && progress.hasStep(options.stepId)\n ? options.stepId\n : undefined\n\n if (progress !== undefined && !verbose && checklistStepId !== undefined) {\n progress.startStep(checklistStepId)\n } else if (progress !== undefined && !verbose && options.spinnerLabel !== undefined) {\n progress.startSpinner(options.spinnerLabel)\n }\n\n try {\n const result = await runBuffered(command, args, {\n cwd: options.cwd,\n env: progress?.commandEnv(options.env) ?? options.env,\n input: options.input,\n logger: options.logger,\n mirrorStdout: verbose ? (options.verboseStdout ?? 'stdout') : false,\n mirrorStderr: verbose ? (options.verboseStderr ?? 'stderr') : false,\n onStdout: markerSink?.write,\n onStderr: markerSink?.write\n })\n\n markerSink?.flush()\n if (checklistStepId !== undefined) {\n if (result.code === 0) {\n progress?.completeStep(checklistStepId)\n } else {\n progress?.failStep(checklistStepId)\n }\n } else {\n progress?.stopSpinner(result.code === 0 ? 'complete' : 'clear')\n }\n return result\n } catch (error) {\n markerSink?.flush()\n if (checklistStepId !== undefined) {\n progress?.failStep(checklistStepId)\n } else {\n progress?.stopSpinner()\n }\n throw error\n }\n}\n\nexport function assertProgressCommandSucceeded (label: string, result: CommandResult, message: string): void {\n if (result.code !== 0) {\n throw new Error(`${message}\\n${formatCommandFailure(label, result)}`)\n }\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\n\nimport type { WorkspaceContext } from './paths.ts'\nimport { runBuffered } from './process.ts'\nimport { assertProgressCommandSucceeded, type ProgressReporter, runProgressCommand } from './progress.ts'\n\nexport interface EnsureHostSshKeyOptions {\n quiet?: boolean\n progress?: ProgressReporter\n}\n\nexport async function ensureHostSshKey (context: WorkspaceContext, options: boolean | EnsureHostSshKeyOptions = false): Promise<void> {\n const quiet = typeof options === 'boolean' ? options : options.quiet ?? false\n const progress = typeof options === 'boolean' ? undefined : options.progress\n const checklistActive = progress?.isChecklistActive() ?? false\n\n mkdirSync(context.sshKeyDir, { recursive: true, mode: 0o700 })\n\n if (!existsSync(context.sshKeyPath)) {\n if (progress !== undefined && !checklistActive) {\n progress.detail(context.sshKeyPath)\n } else if (progress === undefined && !quiet) {\n process.stderr.write(`Generating Boxdown SSH identity: ${context.sshKeyPath}\\n`)\n }\n\n const args = [\n '-t',\n 'ed25519',\n '-f',\n context.sshKeyPath,\n '-N',\n '',\n '-C',\n `${context.workspaceBasename}-devcontainer`\n ]\n const result = progress === undefined\n ? await runBuffered('ssh-keygen', args, {\n mirrorStdout: quiet ? false : 'stderr',\n mirrorStderr: 'stderr'\n })\n : await runProgressCommand('ssh-keygen create identity', 'ssh-keygen', args, {\n progress,\n spinnerLabel: checklistActive ? undefined : 'Generating Boxdown SSH identity',\n verboseStdout: 'stderr',\n verboseStderr: 'stderr'\n })\n\n if (progress === undefined && result.code !== 0) {\n throw new Error(`ssh-keygen failed while creating ${context.sshKeyPath}`)\n }\n\n if (progress !== undefined) {\n assertProgressCommandSucceeded('ssh-keygen create identity', result, `ssh-keygen failed while creating ${context.sshKeyPath}`)\n }\n }\n\n if (!existsSync(context.sshPublicKeyPath)) {\n if (progress !== undefined && !checklistActive) {\n progress.detail(context.sshPublicKeyPath)\n }\n\n const args = ['-y', '-f', context.sshKeyPath]\n const result = progress === undefined\n ? await runBuffered('ssh-keygen', args, {\n mirrorStdout: false,\n mirrorStderr: 'stderr'\n })\n : await runProgressCommand('ssh-keygen derive public key', 'ssh-keygen', args, {\n progress,\n spinnerLabel: checklistActive ? undefined : 'Writing Boxdown SSH public key',\n verboseStdout: false,\n verboseStderr: 'stderr'\n })\n\n if (progress === undefined && result.code !== 0) {\n throw new Error(`ssh-keygen failed while deriving ${context.sshPublicKeyPath}`)\n }\n\n if (progress !== undefined) {\n assertProgressCommandSucceeded('ssh-keygen derive public key', result, `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, realpathSync, renameSync, 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\ninterface SshConfigMarkerSet {\n begin: string\n end: string\n}\n\nfunction managedSshConfigMarkerSets (alias: string): SshConfigMarkerSet[] {\n return [\n {\n begin: `# BEGIN ${alias} boxdown devcontainer ssh`,\n end: `# END ${alias} boxdown devcontainer ssh`\n },\n {\n begin: `# BEGIN ${alias} devcontainer ssh`,\n end: `# END ${alias} devcontainer ssh`\n }\n ]\n}\n\nfunction malformedSshConfigBlockError (alias: string, markers: SshConfigMarkerSet): Error {\n return new Error(`Refusing to update SSH config for ${alias}: found \"${markers.begin}\" without matching \"${markers.end}\". Repair the config manually before running Boxdown again.`)\n}\n\nfunction overlappingSshConfigBlockError (alias: string, markers: SshConfigMarkerSet, marker: string): Error {\n return new Error(`Refusing to update SSH config for ${alias}: found overlapping managed SSH config marker \"${marker}\" before matching \"${markers.end}\". Repair the config manually before running Boxdown again.`)\n}\n\nfunction isManagedSshConfigMarker (line: string): boolean {\n return /^# (?:BEGIN|END) [A-Za-z0-9_.-]+ (?:boxdown )?devcontainer ssh$/u.test(line)\n}\n\nfunction stripManagedSshConfigBlocks (existingConfig: string, alias: string): { lines: string[], removed: boolean } {\n const markerSets = managedSshConfigMarkerSets(alias)\n const lines = existingConfig.split(/\\r?\\n/)\n const nextLines: string[] = []\n let removed = false\n\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index]\n const markers = markerSets.find((candidate) => candidate.begin === line)\n\n if (markers === undefined) {\n nextLines.push(line ?? '')\n continue\n }\n\n let endIndex = -1\n for (let candidateIndex = index + 1; candidateIndex < lines.length; candidateIndex++) {\n const candidate = lines[candidateIndex] ?? ''\n\n if (candidate === markers.end) {\n endIndex = candidateIndex\n break\n }\n\n if (isManagedSshConfigMarker(candidate)) {\n throw overlappingSshConfigBlockError(alias, markers, candidate)\n }\n }\n\n if (endIndex === -1) {\n throw malformedSshConfigBlockError(alias, markers)\n }\n\n removed = true\n index = endIndex\n }\n\n return { lines: nextLines, removed }\n}\n\nfunction trimTrailingBlankLines (lines: string[]): void {\n while (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop()\n }\n}\n\nfunction trimLeadingBlankLinesBeforeManagedBlock (lines: string[]): void {\n const firstContentIndex = lines.findIndex((line) => line !== '')\n\n if (firstContentIndex > 0 && isManagedSshConfigMarker(lines[firstContentIndex] ?? '')) {\n lines.splice(0, firstContentIndex)\n }\n}\n\nfunction writeFileAtomic (path: string, contents: string, mode: number): void {\n const destinationPath = existsSync(path) ? realpathSync(path) : path\n const tmpPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`\n\n writeFileSync(tmpPath, contents, { mode })\n chmodSync(tmpPath, mode)\n renameSync(tmpPath, destinationPath)\n}\n\nexport function replaceSshConfigBlock (existingConfig: string, alias: string, block: string): string {\n const { lines: nextLines } = stripManagedSshConfigBlocks(existingConfig, alias)\n\n trimTrailingBlankLines(nextLines)\n trimLeadingBlankLinesBeforeManagedBlock(nextLines)\n\n return `${nextLines.join('\\n')}${nextLines.length > 0 ? '\\n\\n' : ''}${block}`\n}\n\nexport function removeSshConfigBlock (existingConfig: string, alias: string): string {\n const { lines: nextLines, removed } = stripManagedSshConfigBlocks(existingConfig, alias)\n\n if (!removed) {\n return existingConfig\n }\n\n trimTrailingBlankLines(nextLines)\n trimLeadingBlankLinesBeforeManagedBlock(nextLines)\n\n return nextLines.length > 0 ? `${nextLines.join('\\n')}\\n` : ''\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 writeFileAtomic(sshConfigPath, nextConfig, 0o600)\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\nexport function uninstallSshConfig (alias: string, options: { quiet?: boolean, configPath?: string } = {}): boolean {\n validateSshAlias(alias)\n\n const sshConfigPath = options.configPath ?? defaultSshConfigPath()\n\n if (!existsSync(sshConfigPath)) {\n if (!options.quiet) {\n process.stdout.write(`SSH alias not installed: ${alias}\\n`)\n process.stdout.write(`SSH config: ${sshConfigPath}\\n`)\n }\n\n return false\n }\n\n const existingConfig = readFileSync(sshConfigPath, 'utf8')\n const nextConfig = removeSshConfigBlock(existingConfig, alias)\n const changed = nextConfig !== existingConfig\n\n if (changed) {\n writeFileAtomic(sshConfigPath, nextConfig, 0o600)\n chmodSync(sshConfigPath, 0o600)\n }\n\n if (!options.quiet) {\n process.stdout.write(changed\n ? `Uninstalled SSH alias: ${alias}\\n`\n : `SSH alias not installed: ${alias}\\n`)\n process.stdout.write(`SSH config: ${sshConfigPath}\\n`)\n }\n\n return changed\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 logPath: string\n logExists: 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 logPath: context.workspaceLogPath,\n logExists: exists(context.workspaceLogPath),\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 ` Command log: ${status.paths.logPath} (${existenceText(status.paths.logExists, 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 { reportGitSigningPlan, resolveGitSigningPlan } from './git-signing.ts'\nimport type { WorkspaceCommandLogger } from './logging.ts'\nimport { recordWorkspaceDockerImage } from './metadata.ts'\nimport type { WorkspaceContext } from './paths.ts'\nimport { runBuffered, runInteractive } from './process.ts'\nimport { assertProgressCommandSucceeded, type ProgressReporter, runProgressCommand } from './progress.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 progress?: ProgressReporter\n logger?: WorkspaceCommandLogger\n reuseRunning?: boolean\n}\n\nexport interface ContainerCommandOptions {\n progress?: ProgressReporter\n logger?: WorkspaceCommandLogger\n}\n\nexport interface TunnelPortForward {\n localPort: number\n remotePort: number\n}\n\nexport interface SshTunnelOptions {\n bindAddress?: string\n remoteHost?: string\n}\n\nexport interface DockerImageInfo {\n id: string\n name?: string\n}\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\nfunction containerProgressEnvArgs (progress?: ProgressReporter): string[] {\n if (progress === undefined) {\n return []\n }\n\n return [\n 'env',\n `BOXDOWN_VERBOSE=${progress.verbose ? '1' : '0'}`,\n `BOXDOWN_PROGRESS=${progress.verbose ? '0' : '1'}`\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, options: { logger?: WorkspaceCommandLogger } = {}): 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 logger: options.logger,\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, options: { logger?: WorkspaceCommandLogger } = {}): 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 logger: options.logger,\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 function parseDockerInspectImage (output: string, containerId: string): DockerImageInfo | undefined {\n const [rawId, rawName] = output.trim().split('|')\n\n if (rawId === undefined || rawId.length === 0) {\n return undefined\n }\n\n let id: unknown\n let name: unknown\n\n try {\n id = JSON.parse(rawId)\n name = rawName === undefined || rawName.length === 0 ? undefined : JSON.parse(rawName)\n } catch (error) {\n throw new Error(`Could not parse docker inspect output for ${containerId}`, { cause: error })\n }\n\n if (typeof id !== 'string' || id.length === 0) return undefined\n\n return {\n id,\n ...(typeof name === 'string' && name.length > 0 ? { name } : {})\n }\n}\n\nexport async function inspectContainerImage (containerId: string, options: { logger?: WorkspaceCommandLogger } = {}): Promise<DockerImageInfo | undefined> {\n const result = await runBuffered('docker', [\n 'inspect',\n '--format',\n '{{json .Image}}|{{json .Config.Image}}',\n containerId\n ], {\n logger: options.logger,\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (result.code !== 0) {\n throw new Error(`Could not inspect devcontainer image for ${containerId}`)\n }\n\n return parseDockerInspectImage(result.stdout, containerId)\n}\n\nasync function recordContainerImageIfPresent (context: WorkspaceContext, containerId: string, logger?: WorkspaceCommandLogger): Promise<void> {\n try {\n const image = await inspectContainerImage(containerId, { logger })\n\n if (image !== undefined) {\n recordWorkspaceDockerImage(context, image)\n }\n } catch {\n process.stderr.write(`Warning: could not record devcontainer image metadata for ${containerId}.\\n`)\n }\n}\n\nexport async function stopWorkspaceContainer (context: WorkspaceContext, options: { logger?: WorkspaceCommandLogger } = {}): Promise<void> {\n const container = await findWorkspaceContainer(context, { logger: options.logger })\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 logger: options.logger,\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, options: { logger?: WorkspaceCommandLogger } = {}): Promise<void> {\n const container = await findWorkspaceContainer(context, { logger: options.logger })\n\n if (container === undefined) {\n process.stdout.write(`No devcontainer found for: ${context.workspaceFolder}\\n`)\n return\n }\n\n await removeContainerById(container.id, { logger: options.logger })\n process.stdout.write(`Removed devcontainer: ${container.id}\\n`)\n}\n\nexport async function removeContainerById (containerId: string, options: { volumes?: boolean, logger?: WorkspaceCommandLogger } = {}): Promise<void> {\n const result = await runBuffered('docker', [\n 'rm',\n '-f',\n ...(options.volumes === true ? ['-v'] : []),\n containerId\n ], {\n logger: options.logger,\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (result.code !== 0) {\n throw new Error(`Could not remove devcontainer ${containerId}`)\n }\n}\n\nfunction dockerImageMissing (stderr: string): boolean {\n return /No such image/i.test(stderr) || /not found/i.test(stderr)\n}\n\nexport async function removeDockerImage (imageId: string, options: { logger?: WorkspaceCommandLogger } = {}): Promise<boolean> {\n const result = await runBuffered('docker', ['image', 'rm', '-f', imageId], {\n logger: options.logger,\n mirrorStdout: false,\n mirrorStderr: false\n })\n\n if (result.code !== 0) {\n if (dockerImageMissing(result.stderr)) {\n process.stdout.write(`Docker image already absent: ${imageId}\\n`)\n return false\n }\n\n throw new Error(`Could not remove Docker image ${imageId}`)\n }\n\n process.stdout.write(`Removed Docker image: ${imageId}\\n`)\n return true\n}\n\nexport async function startDevcontainer (context: WorkspaceContext, options: StartOptions = {}): Promise<string> {\n const progress = options.progress\n const proxyMode = options.proxyMode ?? false\n const hasSshIdentityStep = progress?.hasStep('ssh-identity') === true\n const hasConfigStep = progress?.hasStep('devcontainer-config') === true\n const hasStartStep = progress?.hasStep('devcontainer-start') === true\n\n if (hasSshIdentityStep) {\n progress?.startStep('ssh-identity')\n } else {\n progress?.item('Preparing SSH identity')\n }\n\n try {\n await ensureHostSshKey(context, {\n quiet: proxyMode,\n progress\n })\n if (hasSshIdentityStep) {\n progress?.completeStep('ssh-identity')\n }\n } catch (error) {\n if (hasSshIdentityStep) {\n progress?.failStep('ssh-identity')\n }\n throw error\n }\n\n if (hasConfigStep) {\n progress?.startStep('devcontainer-config')\n } else if (progress !== undefined) {\n progress.item('Writing generated devcontainer config')\n progress.detail(context.generatedConfigPath)\n }\n try {\n const signingPlan = await resolveGitSigningPlan(context)\n reportGitSigningPlan(signingPlan, {\n logger: options.logger,\n quiet: proxyMode,\n ...(progress === undefined\n ? {}\n : {\n writeWarning: (message: string) => {\n progress.warn(message.trimEnd())\n }\n })\n })\n writeGeneratedDevcontainerConfig(context, signingPlan)\n if (hasConfigStep) {\n progress?.completeStep('devcontainer-config')\n }\n } catch (error) {\n if (hasConfigStep) {\n progress?.failStep('devcontainer-config')\n }\n throw error\n }\n\n if (options.reuseRunning === true && options.recreate !== true) {\n const runningContainerId = await findRunningContainerId(context, { logger: options.logger })\n\n if (runningContainerId !== undefined) {\n if (progress === undefined) {\n log(`Using running devcontainer for: ${context.workspaceFolder}`, proxyMode)\n } else if (hasStartStep) {\n progress.startStep('devcontainer-start')\n progress.completeStep('devcontainer-start')\n } else {\n progress.item('Using running devcontainer')\n progress.detail(runningContainerId)\n }\n await recordContainerImageIfPresent(context, runningContainerId, options.logger)\n return runningContainerId\n }\n }\n\n const cli = resolveDevcontainerCli(context)\n if (progress === undefined) {\n log(`Starting devcontainer for: ${context.workspaceFolder}`, proxyMode)\n }\n\n const args = [\n 'up',\n ...devcontainerWorkspaceArgs(context)\n ]\n\n if (options.recreate === true) {\n args.push('--remove-existing-container')\n if (progress === undefined) {\n log('Removing existing dev container so create-time settings apply.', proxyMode)\n } else if (!hasStartStep) {\n progress.item('Removing existing devcontainer before start')\n }\n }\n\n const result = progress === undefined\n ? await runBuffered(cli.command, [...cli.argsPrefix, ...args], {\n mirrorStdout: proxyMode ? 'stderr' : 'stdout',\n mirrorStderr: 'stderr',\n logger: options.logger\n })\n : await runProgressCommand('devcontainer up', cli.command, [...cli.argsPrefix, ...args], {\n progress,\n spinnerLabel: 'Starting devcontainer',\n stepId: 'devcontainer-start',\n verboseStdout: proxyMode ? 'stderr' : 'stdout',\n verboseStderr: 'stderr',\n logger: options.logger\n })\n\n if (progress === undefined && result.code !== 0) {\n throw new Error(`devcontainer up failed for ${context.workspaceFolder}`)\n }\n\n if (progress !== undefined) {\n assertProgressCommandSucceeded('devcontainer up', result, `devcontainer up failed for ${context.workspaceFolder}`)\n }\n\n const containerId = parseContainerIdFromUpOutput(`${result.stdout}\\n${result.stderr}`) ?? await findRunningContainerId(context, { logger: options.logger })\n\n if (containerId === undefined) {\n if (hasStartStep) {\n progress?.failStep('devcontainer-start')\n }\n throw new Error(`Could not resolve devcontainer ID for ${context.workspaceFolder}`)\n }\n\n await recordContainerImageIfPresent(context, containerId, options.logger)\n return containerId\n}\n\nexport async function printPortHint (context: WorkspaceContext, containerId: string, options: { logger?: WorkspaceCommandLogger } = {}): 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 logger: options.logger,\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, options: { logger?: WorkspaceCommandLogger } = {}): 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 ], { logger: options.logger })\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[] = [], options: { logger?: WorkspaceCommandLogger } = {}): 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 ], { logger: options.logger })\n}\n\nexport async function ensureContainerSshRuntime (context: WorkspaceContext, options: ContainerCommandOptions = {}): Promise<void> {\n const cli = resolveDevcontainerCli(context)\n const args = [\n ...cli.argsPrefix,\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n ...containerProgressEnvArgs(options.progress),\n 'bash',\n `${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/utils/ssh-bootstrap.sh`,\n 'runtime'\n ]\n const result = options.progress === undefined\n ? await runBuffered(cli.command, args, {\n mirrorStdout: 'stderr',\n mirrorStderr: 'stderr',\n logger: options.logger\n })\n : await runProgressCommand('prepare SSH runtime', cli.command, args, {\n progress: options.progress,\n spinnerLabel: 'Preparing container SSH runtime',\n stepId: 'ssh-runtime',\n verboseStdout: 'stderr',\n verboseStderr: 'stderr',\n logger: options.logger\n })\n\n if (options.progress === undefined && result.code !== 0) {\n throw new Error('Failed to prepare devcontainer SSH runtime')\n }\n\n if (options.progress !== undefined) {\n assertProgressCommandSucceeded('prepare SSH runtime', result, 'Failed to prepare devcontainer SSH runtime')\n }\n}\n\nexport async function refreshContainerCodingAgentClis (\n context: WorkspaceContext,\n proxyMode = false,\n agents: CodingAgentCli[] = [],\n options: ContainerCommandOptions = {}\n): Promise<void> {\n const cli = resolveDevcontainerCli(context)\n const spinnerLabel = agents.length === 0\n ? 'Refreshing default coding-agent CLIs'\n : `Refreshing coding-agent CLIs: ${agents.map(codingAgentBinary).join(', ')}`\n const args = [\n ...cli.argsPrefix,\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n ...containerProgressEnvArgs(options.progress),\n 'bash',\n `${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/utils/coding-agent-cli-update.sh`,\n 'maybe-update',\n ...agents\n ]\n const result = options.progress === undefined\n ? await runBuffered(cli.command, args, {\n mirrorStdout: proxyMode ? 'stderr' : 'stdout',\n mirrorStderr: 'stderr',\n logger: options.logger\n })\n : await runProgressCommand('refresh coding-agent CLIs', cli.command, args, {\n progress: options.progress,\n spinnerLabel,\n stepId: 'coding-agent-refresh',\n verboseStdout: proxyMode ? 'stderr' : 'stdout',\n verboseStderr: 'stderr',\n logger: options.logger\n })\n\n if (result.code !== 0) {\n if (options.progress === undefined) {\n process.stderr.write('Warning: could not refresh one or more coding-agent CLIs inside the devcontainer.\\n')\n } else {\n options.progress.warn('Could not refresh one or more coding-agent CLIs inside the devcontainer.')\n }\n }\n}\n\nexport async function ensureContainerCodingAgentCli (\n context: WorkspaceContext,\n agent: CodingAgentCli,\n options: ContainerCommandOptions = {}\n): Promise<void> {\n const cli = resolveDevcontainerCli(context)\n const spinnerLabel = `Preparing ${codingAgentBinary(agent)} inside the devcontainer`\n const args = [\n ...cli.argsPrefix,\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n ...containerProgressEnvArgs(options.progress),\n 'bash',\n `${BOXDOWN_CONTAINER_DEVCONTAINER_DIR}/utils/coding-agent-cli-update.sh`,\n 'ensure',\n agent\n ]\n const result = options.progress === undefined\n ? await runBuffered(cli.command, args, {\n mirrorStdout: 'stdout',\n mirrorStderr: 'stderr',\n logger: options.logger\n })\n : await runProgressCommand(`prepare ${codingAgentBinary(agent)}`, cli.command, args, {\n progress: options.progress,\n spinnerLabel,\n stepId: 'agent-cli',\n verboseStdout: 'stdout',\n verboseStderr: 'stderr',\n logger: options.logger\n })\n\n if (options.progress === undefined && result.code !== 0) {\n throw new Error(`Could not install or refresh ${codingAgentBinary(agent)} inside the devcontainer`)\n }\n\n if (options.progress !== undefined) {\n assertProgressCommandSucceeded(`prepare ${codingAgentBinary(agent)}`, result, `Could not install or refresh ${codingAgentBinary(agent)} inside the devcontainer`)\n }\n}\n\nexport async function runSshdProxy (containerId: string, options: { logger?: WorkspaceCommandLogger } = {}): 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 ], { logger: options.logger })\n}\n\nexport function sshTunnelArgs (alias: string, ports: TunnelPortForward[], options: SshTunnelOptions = {}): string[] {\n const bindAddress = options.bindAddress ?? '127.0.0.1'\n const remoteHost = options.remoteHost ?? 'localhost'\n\n return [\n '-N',\n '-o',\n 'ExitOnForwardFailure=yes',\n ...ports.flatMap((port) => [\n '-L',\n `${bindAddress}:${port.localPort}:${remoteHost}:${port.remotePort}`\n ]),\n alias\n ]\n}\n\nexport async function openSshTunnel (alias: string, ports: TunnelPortForward[], options: SshTunnelOptions & { logger?: WorkspaceCommandLogger } = {}): Promise<number> {\n const { logger, ...tunnelOptions } = options\n return runInteractive('ssh', sshTunnelArgs(alias, ports, tunnelOptions), { logger })\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, options: ContainerCommandOptions = {}): Promise<void> {\n const progress = options.progress\n const hasConfigStep = progress?.hasStep('gh-auth-config') === true\n const hasTokenStep = progress?.hasStep('gh-token-read') === true\n const hasGitAuthStep = progress?.hasStep('gh-git-auth') === true\n\n if (hasConfigStep) {\n progress?.startStep('gh-auth-config')\n } else {\n progress?.item('Preparing generated config for GitHub auth refresh')\n }\n\n try {\n await ensureHostSshKey(context, {\n quiet: true,\n progress\n })\n const signingPlan = await resolveGitSigningPlan(context)\n reportGitSigningPlan(signingPlan, {\n logger: options.logger,\n ...(progress === undefined\n ? {}\n : {\n writeWarning: (message: string) => {\n progress.warn(message.trimEnd())\n }\n })\n })\n writeGeneratedDevcontainerConfig(context, signingPlan)\n if (hasConfigStep) {\n progress?.completeStep('gh-auth-config')\n }\n } catch (error) {\n if (hasConfigStep) {\n progress?.failStep('gh-auth-config')\n }\n throw error\n }\n\n if (hasTokenStep) {\n progress?.startStep('gh-token-read')\n } else {\n progress?.item('Reading host GitHub CLI token')\n }\n\n let token: string\n try {\n token = await hostGhTokenOrEmpty()\n if (hasTokenStep) {\n progress?.completeStep('gh-token-read')\n }\n } catch (error) {\n if (hasTokenStep) {\n progress?.failStep('gh-token-read')\n }\n throw error\n }\n\n if (token.length === 0) {\n progress?.skipStep('gh-auth-refresh')\n progress?.skipStep('gh-git-auth')\n progress?.skipStep('gh-auth-verify')\n if (progress === undefined) {\n process.stderr.write('Warning: Host GitHub CLI token unavailable; skipping container auth refresh.\\n')\n } else {\n progress.warn('Host GitHub CLI token unavailable; skipping container auth refresh.')\n }\n return\n }\n\n options.logger?.addRedaction(token)\n\n const cli = resolveDevcontainerCli(context)\n const loginArgs = [\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 const login = progress === undefined\n ? await runBuffered(cli.command, loginArgs, {\n input: `${token}\\n`,\n logger: options.logger,\n mirrorStdout: false,\n mirrorStderr: false\n })\n : await runProgressCommand('refresh GitHub CLI auth', cli.command, loginArgs, {\n input: `${token}\\n`,\n progress,\n logger: options.logger,\n spinnerLabel: 'Refreshing GitHub CLI auth inside the devcontainer',\n stepId: 'gh-auth-refresh',\n verboseStdout: false,\n verboseStderr: false\n })\n\n if (login.code !== 0) {\n progress?.skipStep('gh-git-auth')\n progress?.skipStep('gh-auth-verify')\n if (progress === undefined) {\n process.stderr.write('Warning: could not refresh GitHub CLI auth inside the devcontainer.\\n')\n } else {\n progress.warn('Could not refresh GitHub CLI auth inside the devcontainer.')\n }\n return\n }\n\n if (hasGitAuthStep) {\n progress?.startStep('gh-git-auth')\n } else {\n progress?.item('Configuring workspace GitHub Git auth')\n }\n\n let gitAuthConfigured: boolean\n try {\n gitAuthConfigured = await configureWorkspaceGithubGitAuth(context.workspaceFolder)\n if (hasGitAuthStep) {\n if (gitAuthConfigured) {\n progress?.completeStep('gh-git-auth')\n } else {\n progress?.failStep('gh-git-auth')\n }\n }\n } catch (error) {\n if (hasGitAuthStep) {\n progress?.failStep('gh-git-auth')\n }\n throw error\n }\n\n if (!gitAuthConfigured) {\n if (progress === undefined) {\n process.stderr.write('Warning: GitHub CLI auth refreshed, but GitHub Git auth was not configured for this workspace.\\n')\n } else {\n progress.warn('GitHub CLI auth refreshed, but GitHub Git auth was not configured for this workspace.')\n }\n }\n\n const verifyArgs = [\n ...cli.argsPrefix,\n 'exec',\n ...devcontainerWorkspaceArgs(context),\n '--',\n 'gh',\n 'auth',\n 'status',\n '--hostname',\n 'github.com'\n ]\n const verify = progress === undefined\n ? await runBuffered(cli.command, verifyArgs, {\n mirrorStdout: false,\n mirrorStderr: false,\n logger: options.logger\n })\n : await runProgressCommand('verify GitHub CLI auth', cli.command, verifyArgs, {\n progress,\n logger: options.logger,\n spinnerLabel: 'Verifying GitHub CLI auth inside the devcontainer',\n stepId: 'gh-auth-verify',\n verboseStdout: false,\n verboseStderr: false\n })\n\n if (verify.code === 0) {\n if (progress === undefined) {\n process.stdout.write('GitHub CLI auth refreshed inside the devcontainer.\\n')\n } else if (!progress.hasStep('gh-auth-verify')) {\n progress.item('GitHub CLI auth refreshed inside the devcontainer')\n }\n } else {\n if (progress === undefined) {\n process.stderr.write('Warning: GitHub CLI auth refresh completed, but verification failed.\\n')\n } else {\n progress.warn('GitHub CLI auth refresh completed, but verification failed.')\n }\n }\n}\n","import { createInterface } from 'node:readline'\n\nimport { color, emptyMark, formatPromptDetailLine, formatPromptEnd, formatPromptLabel, formatPromptTitle, promptRail, selectedMark, type CliColor } from './cli-style.ts'\n\nexport interface MultiSelectDescriptionSegment {\n text: string\n color: CliColor\n}\n\nexport interface MultiSelectChoice<T extends string> {\n value: T\n label: string\n description: string\n focusedDescription?: readonly MultiSelectDescriptionSegment[]\n}\n\nexport type MultiSelectPromptResult<T extends string> =\n | { status: 'selected', values: T[] }\n | { status: 'skipped', values: [] }\n | { status: 'cancelled', values: [] }\n | { status: 'non-interactive', values: [] }\n\nexport type PromptInput = NodeJS.ReadableStream & {\n isTTY?: boolean\n setRawMode?: (mode: boolean) => void\n resume: () => PromptInput\n pause: () => PromptInput\n}\n\nexport type PromptOutput = NodeJS.WritableStream & {\n isTTY?: boolean\n columns?: number\n}\n\nexport interface MultiSelectPromptOptions<T extends string> {\n title: string\n choices: readonly MultiSelectChoice<T>[]\n skipLabel: string\n summaryLabel?: string\n input?: PromptInput\n output?: PromptOutput\n env?: NodeJS.ProcessEnv\n}\n\nexport type TextPromptResult =\n | { status: 'submitted', value: string }\n | { status: 'cancelled', value?: undefined }\n | { status: 'non-interactive', value?: undefined }\n\nexport interface TextPromptOptions {\n title: string\n details?: readonly string[]\n defaultValue?: string\n summaryLabel: string\n validate?: (value: string) => string | undefined\n input?: PromptInput\n output?: PromptOutput\n env?: NodeJS.ProcessEnv\n}\n\nexport type ConfirmPromptResult =\n | { status: 'confirmed' }\n | { status: 'denied' }\n | { status: 'cancelled' }\n | { status: 'non-interactive' }\n\nexport interface ConfirmPromptOptions {\n title: string\n details?: readonly string[]\n confirmLabel: string\n cancelLabel: string\n summaryLabel: string\n input?: PromptInput\n output?: PromptOutput\n env?: NodeJS.ProcessEnv\n}\n\nfunction isCiEnvironment (env: NodeJS.ProcessEnv): boolean {\n const ci = env.CI\n return ci !== undefined && ci !== '' && ci !== '0' && ci !== 'false'\n}\n\nexport function canPromptInteractively (input: PromptInput, output: PromptOutput, env: NodeJS.ProcessEnv): boolean {\n return !isCiEnvironment(env) && input.isTTY === true && output.isTTY === true\n}\n\nconst ansiPattern = /\\u001B\\[[0-?]*[ -/]*[@-~]/gu\n\nfunction visibleLength (value: string): number {\n return value.replace(ansiPattern, '').length\n}\n\nfunction terminalColumns (output: PromptOutput): number {\n return Number.isInteger(output.columns) && output.columns !== undefined && output.columns > 0\n ? output.columns\n : 80\n}\n\nfunction renderedRowCount (lines: readonly string[], output: PromptOutput): number {\n const columns = terminalColumns(output)\n return lines.reduce((rows, line) => rows + Math.max(1, Math.ceil(visibleLength(line) / columns)), 0)\n}\n\nfunction renderPromptLines (\n output: PromptOutput,\n lines: readonly string[],\n previousRows: number\n): number {\n if (previousRows > 0) {\n output.write(`\\u001B[${previousRows}A\\r\\u001B[J`)\n }\n\n for (const line of lines) {\n output.write(`\\u001B[2K\\r${line}\\n`)\n }\n\n return renderedRowCount(lines, output)\n}\n\nfunction formatChoiceLine <T extends string> (\n choice: MultiSelectChoice<T>,\n isFocused: boolean,\n isSelected: boolean\n): string {\n const mark = isSelected ? selectedMark() : emptyMark(isFocused)\n const description = isFocused && choice.focusedDescription !== undefined\n ? `${color(' - ', 'dim')}${choice.focusedDescription.map((segment) => color(segment.text, segment.color)).join('')}`\n : color(` - ${choice.description}`, 'dim')\n return `${promptRail()} ${mark} ${formatPromptLabel(choice.label, isFocused)}${description}`\n}\n\nfunction formatSkipLine (skipLabel: string, isFocused: boolean, selectedCount: number): string {\n const mark = selectedCount === 0 ? selectedMark() : emptyMark(isFocused)\n return `${promptRail()} ${mark} ${formatPromptLabel(skipLabel, isFocused)}`\n}\n\nfunction formatConfirmLine (\n label: string,\n isFocused: boolean\n): string {\n const mark = isFocused ? selectedMark() : emptyMark(false)\n return `${promptRail()} ${mark} ${formatPromptLabel(label, isFocused)}`\n}\n\nfunction formatMultiSelectFinalLine <T extends string> (\n result: MultiSelectPromptResult<T>,\n choices: readonly MultiSelectChoice<T>[],\n summaryLabel: string\n): string {\n if (result.status === 'cancelled') {\n return `${summaryLabel}: canceled`\n }\n\n if (result.status !== 'selected') {\n return `${summaryLabel}: skipped`\n }\n\n const selectedLabels = choices\n .filter((choice) => result.values.includes(choice.value))\n .map((choice) => choice.label)\n .join(', ')\n\n return `${summaryLabel}: ${selectedLabels}`\n}\n\nfunction formatTextFinalLine (result: TextPromptResult, summaryLabel: string): string {\n if (result.status === 'cancelled') {\n return `${summaryLabel}: canceled`\n }\n\n if (result.status === 'non-interactive') {\n return `${summaryLabel}: skipped`\n }\n\n return `${summaryLabel}: ${result.value}`\n}\n\nfunction formatConfirmFinalLine (result: ConfirmPromptResult, summaryLabel: string): string {\n if (result.status === 'confirmed') {\n return `${summaryLabel}: confirmed`\n }\n\n if (result.status === 'cancelled') {\n return `${summaryLabel}: canceled`\n }\n\n return `${summaryLabel}: canceled`\n}\n\nfunction resultFromValues <T extends string> (values: T[]): MultiSelectPromptResult<T> {\n return values.length === 0\n ? { status: 'skipped', values: [] }\n : { status: 'selected', values }\n}\n\nfunction parseLineSelection <T extends string> (\n answer: string,\n choices: readonly MultiSelectChoice<T>[]\n): { values: T[] } | { error: string } {\n const trimmed = answer.trim()\n\n if (trimmed === '' || trimmed === '0' || /^skip$/iu.test(trimmed)) {\n return { values: [] }\n }\n\n const selected = new Set<T>()\n const tokens = trimmed.split(/[,\\s]+/u).filter((token) => token.length > 0)\n\n for (const token of tokens) {\n const byNumber = /^[0-9]+$/u.test(token) ? Number(token) : undefined\n const choice = byNumber === undefined\n ? choices.find((candidate) => candidate.value === token)\n : choices[byNumber - 1]\n\n if (choice === undefined) {\n return { error: `Unknown selection: ${token}` }\n }\n\n selected.add(choice.value)\n }\n\n return { values: [...selected] }\n}\n\nfunction askLine (input: PromptInput, output: PromptOutput, question: string): Promise<string | undefined> {\n const rl = createInterface({\n input,\n output,\n terminal: false\n })\n\n return new Promise((resolve) => {\n let settled = false\n\n function settle (answer: string | undefined): void {\n if (settled) {\n return\n }\n\n settled = true\n rl.close()\n resolve(answer)\n }\n\n rl.once('close', () => {\n settle(undefined)\n })\n\n rl.question(question, (answer) => {\n settle(answer)\n })\n })\n}\n\nasync function promptLineMultiSelect <T extends string> (\n options: Required<Pick<MultiSelectPromptOptions<T>, 'title' | 'choices' | 'skipLabel' | 'summaryLabel' | 'input' | 'output'>>\n): Promise<MultiSelectPromptResult<T>> {\n options.output.write(`${formatPromptTitle(options.title)}\\n`)\n\n options.choices.forEach((choice, index) => {\n options.output.write(`${promptRail()} ${index + 1}) ${choice.label} - ${choice.description}\\n`)\n })\n\n options.output.write(`${promptRail()} 0) ${options.skipLabel}\\n`)\n\n while (true) {\n const answer = await askLine(options.input, options.output, `${promptRail()} `)\n\n if (answer === undefined) {\n return { status: 'cancelled', values: [] }\n }\n\n const parsed = parseLineSelection(answer, options.choices)\n\n if ('values' in parsed) {\n const result = resultFromValues(parsed.values)\n options.output.write(`${formatPromptEnd()}\\n${formatMultiSelectFinalLine(result, options.choices, options.summaryLabel)}\\n`)\n return result\n }\n\n options.output.write(`${promptRail()} ${parsed.error}\\n`)\n }\n}\n\nfunction promptRawMultiSelect <T extends string> (\n options: Required<Pick<MultiSelectPromptOptions<T>, 'title' | 'choices' | 'skipLabel' | 'summaryLabel' | 'input' | 'output'>>\n): Promise<MultiSelectPromptResult<T>> {\n return new Promise((resolve) => {\n const selected = new Set<T>()\n let focusedIndex = options.choices.length\n let settled = false\n let renderedRows = 0\n\n function lines (): string[] {\n return [\n formatPromptTitle(options.title),\n promptRail(),\n ...options.choices.map((choice, index) => formatChoiceLine(\n choice,\n focusedIndex === index,\n selected.has(choice.value)\n )),\n formatSkipLine(options.skipLabel, focusedIndex === options.choices.length, selected.size),\n formatPromptEnd()\n ]\n }\n\n function render (): void {\n const nextLines = lines()\n renderedRows = renderPromptLines(options.output, nextLines, renderedRows)\n }\n\n function cleanup (): void {\n options.input.removeListener('data', onData)\n options.input.setRawMode?.(false)\n options.input.pause()\n options.output.write('\\u001B[?25h')\n }\n\n function finish (result: MultiSelectPromptResult<T>): void {\n if (settled) {\n return\n }\n\n settled = true\n cleanup()\n options.output.write(`${formatMultiSelectFinalLine(result, options.choices, options.summaryLabel)}\\n`)\n resolve(result)\n }\n\n function submit (): void {\n if (focusedIndex === options.choices.length) {\n finish({ status: 'skipped', values: [] })\n return\n }\n\n finish(resultFromValues([...selected]))\n }\n\n function toggleFocused (): void {\n const focusedChoice = options.choices[focusedIndex]\n\n if (focusedChoice === undefined) {\n selected.clear()\n render()\n return\n }\n\n if (selected.has(focusedChoice.value)) {\n selected.delete(focusedChoice.value)\n } else {\n selected.add(focusedChoice.value)\n }\n\n render()\n }\n\n function moveFocus (direction: 1 | -1): void {\n const rowCount = options.choices.length + 1\n focusedIndex = (focusedIndex + direction + rowCount) % rowCount\n render()\n }\n\n function handleKey (key: string): void {\n if (key === '\\u0003' || key === '\\u0004' || key === '\\u001B') {\n finish({ status: 'cancelled', values: [] })\n return\n }\n\n if (key === '\\r' || key === '\\n') {\n submit()\n return\n }\n\n if (key === ' ') {\n toggleFocused()\n return\n }\n\n if (key === 'k') {\n moveFocus(-1)\n return\n }\n\n if (key === 'j') {\n moveFocus(1)\n }\n }\n\n function handleText (text: string): void {\n for (let index = 0; index < text.length;) {\n if (text.startsWith('\\u001B[A', index)) {\n moveFocus(-1)\n index += 3\n continue\n }\n\n if (text.startsWith('\\u001B[B', index)) {\n moveFocus(1)\n index += 3\n continue\n }\n\n handleKey(text[index] ?? '')\n index += 1\n }\n }\n\n function onData (chunk: string | Buffer): void {\n handleText(Buffer.isBuffer(chunk) ? chunk.toString('utf8') : chunk)\n }\n\n options.output.write('\\u001B[?25l')\n options.input.setRawMode?.(true)\n options.input.resume()\n options.input.on('data', onData)\n render()\n })\n}\n\nexport async function promptMultiSelect <T extends string> (\n options: MultiSelectPromptOptions<T>\n): Promise<MultiSelectPromptResult<T>> {\n const input = options.input ?? process.stdin\n const output = options.output ?? process.stdout\n const env = options.env ?? process.env\n const summaryLabel = options.summaryLabel ?? 'Selection'\n\n if (!canPromptInteractively(input, output, env)) {\n return { status: 'non-interactive', values: [] }\n }\n\n if (typeof input.setRawMode !== 'function') {\n return promptLineMultiSelect({\n title: options.title,\n choices: options.choices,\n skipLabel: options.skipLabel,\n summaryLabel,\n input,\n output\n })\n }\n\n try {\n return await promptRawMultiSelect({\n title: options.title,\n choices: options.choices,\n skipLabel: options.skipLabel,\n summaryLabel,\n input,\n output\n })\n } catch {\n return promptLineMultiSelect({\n title: options.title,\n choices: options.choices,\n skipLabel: options.skipLabel,\n summaryLabel,\n input,\n output\n })\n }\n}\n\nexport async function promptText (options: TextPromptOptions): Promise<TextPromptResult> {\n const input = options.input ?? process.stdin\n const output = options.output ?? process.stdout\n const env = options.env ?? process.env\n\n if (!canPromptInteractively(input, output, env)) {\n return { status: 'non-interactive' }\n }\n\n output.write(`${formatPromptTitle(options.title)}\\n`)\n\n for (const detail of options.details ?? []) {\n output.write(`${formatPromptDetailLine(detail)}\\n`)\n }\n\n while (true) {\n const defaultText = options.defaultValue === undefined ? '' : color(` (${options.defaultValue})`, 'dim')\n const answer = await askLine(input, output, `${promptRail()} ${defaultText} `)\n\n if (answer === undefined || answer === '\\u0003' || answer === '\\u0004' || answer === '\\u001B') {\n const result: TextPromptResult = { status: 'cancelled' }\n output.write(`${formatPromptEnd()}\\n${formatTextFinalLine(result, options.summaryLabel)}\\n`)\n return result\n }\n\n const value = answer.trim() === '' && options.defaultValue !== undefined\n ? options.defaultValue\n : answer.trim()\n const error = options.validate?.(value)\n\n if (error === undefined) {\n const result: TextPromptResult = { status: 'submitted', value }\n output.write(`${formatPromptEnd()}\\n${formatTextFinalLine(result, options.summaryLabel)}\\n`)\n return result\n }\n\n output.write(`${promptRail()} ${error}\\n`)\n }\n}\n\nfunction promptLineConfirm (\n options: Required<Pick<ConfirmPromptOptions, 'title' | 'details' | 'confirmLabel' | 'cancelLabel' | 'summaryLabel' | 'input' | 'output'>>\n): Promise<ConfirmPromptResult> {\n options.output.write(`${formatPromptTitle(options.title)}\\n`)\n\n for (const detail of options.details) {\n options.output.write(`${formatPromptDetailLine(detail)}\\n`)\n }\n\n return new Promise((resolve) => {\n async function ask (): Promise<void> {\n const answer = await askLine(options.input, options.output, `${promptRail()} ${options.confirmLabel}? [y/N] `)\n\n if (answer === undefined || answer === '\\u0003' || answer === '\\u0004' || answer === '\\u001B') {\n const result: ConfirmPromptResult = { status: 'cancelled' }\n options.output.write(`${formatPromptEnd()}\\n${formatConfirmFinalLine(result, options.summaryLabel)}\\n`)\n resolve(result)\n return\n }\n\n if (answer.trim() === '' || /^n(?:o)?$/iu.test(answer.trim())) {\n const result: ConfirmPromptResult = { status: 'denied' }\n options.output.write(`${formatPromptEnd()}\\n${formatConfirmFinalLine(result, options.summaryLabel)}\\n`)\n resolve(result)\n return\n }\n\n if (/^y(?:es)?$/iu.test(answer.trim())) {\n const result: ConfirmPromptResult = { status: 'confirmed' }\n options.output.write(`${formatPromptEnd()}\\n${formatConfirmFinalLine(result, options.summaryLabel)}\\n`)\n resolve(result)\n return\n }\n\n options.output.write(`${promptRail()} Enter y or n.\\n`)\n await ask()\n }\n\n void ask()\n })\n}\n\nfunction promptRawConfirm (\n options: Required<Pick<ConfirmPromptOptions, 'title' | 'details' | 'confirmLabel' | 'cancelLabel' | 'summaryLabel' | 'input' | 'output'>>\n): Promise<ConfirmPromptResult> {\n return new Promise((resolve) => {\n let focusedIndex = 0\n let settled = false\n let renderedRows = 0\n\n function lines (): string[] {\n return [\n formatPromptTitle(options.title),\n promptRail(),\n ...options.details.map((detail) => formatPromptDetailLine(detail)),\n formatConfirmLine(options.cancelLabel, focusedIndex === 0),\n formatConfirmLine(options.confirmLabel, focusedIndex === 1),\n formatPromptEnd()\n ]\n }\n\n function render (): void {\n const nextLines = lines()\n renderedRows = renderPromptLines(options.output, nextLines, renderedRows)\n }\n\n function cleanup (): void {\n options.input.removeListener('data', onData)\n options.input.setRawMode?.(false)\n options.input.pause()\n options.output.write('\\u001B[?25h')\n }\n\n function finish (result: ConfirmPromptResult): void {\n if (settled) {\n return\n }\n\n settled = true\n cleanup()\n options.output.write(`${formatConfirmFinalLine(result, options.summaryLabel)}\\n`)\n resolve(result)\n }\n\n function moveFocus (): void {\n focusedIndex = focusedIndex === 0 ? 1 : 0\n render()\n }\n\n function submit (): void {\n finish(focusedIndex === 1 ? { status: 'confirmed' } : { status: 'denied' })\n }\n\n function handleKey (key: string): void {\n if (key === '\\u0003' || key === '\\u0004' || key === '\\u001B') {\n finish({ status: 'cancelled' })\n return\n }\n\n if (key === '\\r' || key === '\\n') {\n submit()\n return\n }\n\n if (key === ' ' || key === 'j' || key === 'k' || key === 'h' || key === 'l') {\n moveFocus()\n return\n }\n\n if (key === 'y' || key === 'Y') {\n finish({ status: 'confirmed' })\n return\n }\n\n if (key === 'n' || key === 'N') {\n finish({ status: 'denied' })\n }\n }\n\n function handleText (text: string): void {\n for (let index = 0; index < text.length;) {\n if (text.startsWith('\\u001B[A', index) || text.startsWith('\\u001B[B', index) || text.startsWith('\\u001B[C', index) || text.startsWith('\\u001B[D', index)) {\n moveFocus()\n index += 3\n continue\n }\n\n handleKey(text[index] ?? '')\n index += 1\n }\n }\n\n function onData (chunk: string | Buffer): void {\n handleText(Buffer.isBuffer(chunk) ? chunk.toString('utf8') : chunk)\n }\n\n options.output.write('\\u001B[?25l')\n options.input.setRawMode?.(true)\n options.input.resume()\n options.input.on('data', onData)\n render()\n })\n}\n\nexport async function promptConfirm (options: ConfirmPromptOptions): Promise<ConfirmPromptResult> {\n const input = options.input ?? process.stdin\n const output = options.output ?? process.stdout\n const env = options.env ?? process.env\n const details = options.details ?? []\n\n if (!canPromptInteractively(input, output, env)) {\n return { status: 'non-interactive' }\n }\n\n if (typeof input.setRawMode !== 'function') {\n return promptLineConfirm({\n title: options.title,\n details,\n confirmLabel: options.confirmLabel,\n cancelLabel: options.cancelLabel,\n summaryLabel: options.summaryLabel,\n input,\n output\n })\n }\n\n try {\n return await promptRawConfirm({\n title: options.title,\n details,\n confirmLabel: options.confirmLabel,\n cancelLabel: options.cancelLabel,\n summaryLabel: options.summaryLabel,\n input,\n output\n })\n } catch {\n return promptLineConfirm({\n title: options.title,\n details,\n confirmLabel: options.confirmLabel,\n cancelLabel: options.cancelLabel,\n summaryLabel: options.summaryLabel,\n input,\n output\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 containerLabel(entry)\n ])\n const headers = ['STATE', 'REPO', 'PATH', '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\nexport function formatWorkspaceListDetailsText (entries: WorkspaceListEntry[]): string {\n if (entries.length === 0) {\n return 'Boxdown list\\n\\nNo Boxdown workspaces found.\\n'\n }\n\n const details = entries.map((entry) => [\n `${entry.state} ${entry.workspaceBasename}`,\n ` ${pad('path', 9)}: ${entry.workspaceFolder}`,\n ` ${pad('ssh alias', 9)}: ${entry.sshAlias}`,\n ` ${pad('container', 9)}: ${containerLabel(entry)}`\n ].join('\\n')).join('\\n\\n')\n\n return `Boxdown list\\n\\n${details}\\n`\n}\n","import { appendFileSync, mkdirSync } from 'node:fs'\nimport { dirname } from 'node:path'\n\nimport type { WorkspaceContext } from './paths.ts'\n\nexport type LogStreamName = 'stdout' | 'stderr' | 'boxdown'\n\nexport interface WorkspaceCommandLoggerOptions {\n redactions?: string[]\n now?: () => Date\n}\n\nexport interface LoggedCommand {\n stream: (stream: Extract<LogStreamName, 'stdout' | 'stderr'>, chunk: Buffer | string) => void\n error: (error: unknown) => void\n finish: (code: number) => void\n}\n\nfunction errorMessage (error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction argvText (command: string, args: string[]): string {\n return JSON.stringify([command, ...args])\n}\n\nexport function redactKnownSecretEnvironmentAssignments (value: string): string {\n return value\n .replace(/ANTHROPIC_API_KEY=[^\\s,\"\\]}]+/gu, 'ANTHROPIC_API_KEY=[redacted]')\n .replace(/SNYK_TOKEN=[^\\s,\"\\]}]+/gu, 'SNYK_TOKEN=[redacted]')\n .replace(/OP_SERVICE_ACCOUNT_TOKEN=[^\\s,\"\\]}]+/gu, 'OP_SERVICE_ACCOUNT_TOKEN=[redacted]')\n}\n\nexport class WorkspaceCommandLogger {\n readonly logPath: string\n readonly workspaceFolder: string\n readonly #redactions: string[]\n readonly #now: () => Date\n #disabled = false\n\n constructor (context: Pick<WorkspaceContext, 'workspaceFolder' | 'workspaceLogPath'>, options: WorkspaceCommandLoggerOptions = {}) {\n this.logPath = context.workspaceLogPath\n this.workspaceFolder = context.workspaceFolder\n this.#redactions = options.redactions?.filter((value) => value.length > 0) ?? []\n this.#now = options.now ?? (() => new Date())\n }\n\n addRedaction (value: string): void {\n if (value.length > 0) {\n this.#redactions.push(value)\n }\n }\n\n disable (): void {\n this.#disabled = true\n }\n\n section (title: string, details: Record<string, string | number | boolean | undefined> = {}): void {\n this.#append([\n '',\n `${this.#timestamp()} === ${this.#redact(title)} ===`,\n `${this.#timestamp()} workspace: ${this.#redact(this.workspaceFolder)}`,\n ...Object.entries(details)\n .filter((entry): entry is [string, string | number | boolean] => entry[1] !== undefined)\n .map(([key, value]) => `${this.#timestamp()} ${key}: ${this.#redact(String(value))}`)\n ])\n }\n\n boxdown (chunk: Buffer | string): void {\n this.#stream('boxdown', chunk)\n }\n\n startCommand (command: string, args: string[], options: { cwd?: string } = {}): LoggedCommand {\n const startedAt = Date.now()\n\n this.#append([\n `${this.#timestamp()} command start: ${this.#redact(argvText(command, args))}`,\n ...(options.cwd === undefined ? [] : [`${this.#timestamp()} cwd: ${this.#redact(options.cwd)}`])\n ])\n\n return {\n stream: (stream, chunk) => {\n this.#stream(stream, chunk)\n },\n error: (error) => {\n this.#append([`${this.#timestamp()} command error: ${this.#redact(errorMessage(error))}`])\n },\n finish: (code) => {\n this.#append([`${this.#timestamp()} command exit: ${code} (${Date.now() - startedAt}ms)`])\n }\n }\n }\n\n #timestamp (): string {\n return `[${this.#now().toISOString()}]`\n }\n\n #redact (value: string): string {\n return this.#redactions.reduce(\n (current, redaction) => current.replaceAll(redaction, '[redacted]'),\n redactKnownSecretEnvironmentAssignments(value)\n )\n }\n\n #stream (stream: LogStreamName, chunk: Buffer | string): void {\n const text = this.#redact(Buffer.isBuffer(chunk) ? chunk.toString('utf8') : chunk)\n const lines = text.split(/\\r?\\n/u)\n\n if (lines.at(-1) === '') {\n lines.pop()\n }\n\n if (lines.length === 0) {\n return\n }\n\n this.#append(lines.map((line) => `${this.#timestamp()} [${stream}] ${line}`))\n }\n\n #append (lines: string[]): void {\n if (this.#disabled) {\n return\n }\n\n try {\n mkdirSync(dirname(this.logPath), { recursive: true })\n appendFileSync(this.logPath, `${lines.join('\\n')}\\n`)\n } catch {\n this.#disabled = true\n }\n }\n}\n\nexport function createWorkspaceCommandLogger (\n context: Pick<WorkspaceContext, 'workspaceFolder' | 'workspaceLogPath'>,\n options: WorkspaceCommandLoggerOptions = {}\n): WorkspaceCommandLogger {\n return new WorkspaceCommandLogger(context, options)\n}\n\nexport async function withLoggedProcessOutput<T> (\n logger: WorkspaceCommandLogger,\n action: () => Promise<T>\n): Promise<T> {\n const stdoutWrite = process.stdout.write\n const stderrWrite = process.stderr.write\n\n process.stdout.write = function patchedStdoutWrite (this: typeof process.stdout, chunk: string | Uint8Array, ...args: unknown[]): boolean {\n logger.boxdown(Buffer.isBuffer(chunk) ? chunk : String(chunk))\n return stdoutWrite.call(this, chunk, ...args as []) as boolean\n } as typeof process.stdout.write\n\n process.stderr.write = function patchedStderrWrite (this: typeof process.stderr, chunk: string | Uint8Array, ...args: unknown[]): boolean {\n logger.boxdown(Buffer.isBuffer(chunk) ? chunk : String(chunk))\n return stderrWrite.call(this, chunk, ...args as []) as boolean\n } as typeof process.stderr.write\n\n try {\n return await action()\n } finally {\n process.stdout.write = stdoutWrite\n process.stderr.write = stderrWrite\n }\n}\n","import { createHash } from 'node:crypto'\nimport { existsSync, realpathSync, statSync } from 'node:fs'\nimport { homedir, tmpdir } 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 runtimeRoot: string\n workspaceCacheDir: string\n workspaceDataDir: string\n workspaceRuntimeDir: string\n workspaceSecretEnvDir: string\n generatedConfigPath: string\n hostAgentsDir: string\n hostCodexAuthPath: string\n hostGitconfigPath: string\n hostGitconfigSnapshotDir: string\n hostGitconfigSnapshotPath: string\n gitSigningStateDir: string\n gitSigningPublicKeyPath: string\n sshKeyDir: string\n sshKeyPath: string\n sshPublicKeyPath: string\n sshPublicKeyRuntimeDir: string\n sshPublicKeyRuntimePath: string\n workspaceLogPath: string\n}\n\nexport interface WorkspaceContextIdentity {\n workspaceFolder: string\n workspaceBasename: string\n workspaceId: 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 defaultRuntimeRoot (env: NodeJS.ProcessEnv = process.env): string {\n if (env.BOXDOWN_RUNTIME_HOME) {\n return env.BOXDOWN_RUNTIME_HOME\n }\n\n if (env.XDG_RUNTIME_DIR) {\n return join(env.XDG_RUNTIME_DIR, PACKAGE_NAME)\n }\n\n return join(tmpdir(), `${PACKAGE_NAME}-${process.getuid?.() ?? 'user'}`)\n}\n\nexport function defaultHostAgentsDir (env: NodeJS.ProcessEnv = process.env): string {\n return join(env.HOME ?? homedir(), '.agents')\n}\n\nexport function defaultHostCodexAuthPath (env: NodeJS.ProcessEnv = process.env): string {\n return join(env.HOME ?? homedir(), '.codex', 'auth.json')\n}\n\nexport function defaultHostGitconfigPath (env: NodeJS.ProcessEnv = process.env): string {\n return join(env.HOME ?? homedir(), '.gitconfig')\n}\n\nexport function createWorkspaceContextFromIdentity (\n identity: WorkspaceContextIdentity,\n options: Omit<WorkspaceContextOptions, 'workspace' | 'cwd'> = {}\n): WorkspaceContext {\n const env = options.env ?? process.env\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 runtimeRoot = defaultRuntimeRoot(env)\n const hostAgentsDir = defaultHostAgentsDir(env)\n const hostCodexAuthPath = defaultHostCodexAuthPath(env)\n const workspaceCacheDir = join(cacheRoot, 'workspaces', identity.workspaceId)\n const workspaceDataDir = join(dataRoot, 'workspaces', identity.workspaceId)\n const workspaceRuntimeDir = join(runtimeRoot, 'workspaces', identity.workspaceId)\n const hostGitconfigSnapshotDir = join(workspaceDataDir, 'gitconfig')\n\n return {\n workspaceFolder: identity.workspaceFolder,\n workspaceBasename: identity.workspaceBasename,\n workspaceId: identity.workspaceId,\n packageRoot,\n assetsDevcontainerDir,\n cacheRoot,\n dataRoot,\n runtimeRoot,\n workspaceCacheDir,\n workspaceDataDir,\n workspaceRuntimeDir,\n workspaceSecretEnvDir: join(workspaceRuntimeDir, 'secrets'),\n generatedConfigPath: join(workspaceCacheDir, 'devcontainer.json'),\n hostAgentsDir,\n hostCodexAuthPath,\n hostGitconfigPath: defaultHostGitconfigPath(env),\n hostGitconfigSnapshotDir,\n hostGitconfigSnapshotPath: join(hostGitconfigSnapshotDir, '.gitconfig'),\n gitSigningStateDir: join(workspaceDataDir, 'git-signing'),\n gitSigningPublicKeyPath: join(workspaceDataDir, 'git-signing', 'signing-key.pub'),\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 workspaceLogPath: join(workspaceDataDir, 'boxdown.log')\n }\n}\n\nexport function createWorkspaceContext (options: WorkspaceContextOptions = {}): WorkspaceContext {\n const workspaceFolder = resolveWorkspaceFolder(options.workspace, options.cwd)\n\n return createWorkspaceContextFromIdentity({\n workspaceFolder,\n workspaceBasename: basename(workspaceFolder),\n workspaceId: workspaceIdFor(workspaceFolder)\n }, options)\n}\n","import { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport { packageRootFromImportMeta } from './paths.ts'\n\ninterface PackageJson {\n version?: unknown\n}\n\nexport function readPackageVersion (packageRoot = packageRootFromImportMeta(import.meta.url)): string {\n const packageJson = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8')) as PackageJson\n\n if (typeof packageJson.version !== 'string' || packageJson.version.length === 0) {\n throw new Error('Boxdown package.json is missing a valid version.')\n }\n\n return packageJson.version\n}\n","import { existsSync, rmSync } from 'node:fs'\nimport { basename, dirname, isAbsolute, join, parse, relative, resolve } from 'node:path'\n\nimport { claudeSshConfigEntryForWorkspace, uninstallClaudeSshConfigHost } from './claude-app-config.ts'\nimport { codexProjectEntryForWorkspace, legacyCodexRemotePathForWorkspace, uninstallCodexAppConfigProject, uninstallCodexGlobalStateProject } from './codex-app-config.ts'\nimport { findWorkspaceContainer, inspectContainerImage, removeContainerById, removeDockerImage } from './devcontainer.ts'\nimport type { WorkspaceCommandLogger } from './logging.ts'\nimport { readWorkspaceMetadata, type WorkspaceMetadata } from './metadata.ts'\nimport type { WorkspaceContext } from './paths.ts'\nimport { defaultSshAlias, uninstallSshConfig } from './ssh-config.ts'\nimport type { ContainerSummary } from './status.ts'\n\nexport interface PurgeOptions {\n alias?: string\n logger?: WorkspaceCommandLogger\n}\n\nfunction errorMessage (error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nasync function runPurgeStep (label: string, action: () => Promise<void> | void): Promise<boolean> {\n try {\n await action()\n return false\n } catch (error) {\n process.stderr.write(`Failed ${label}: ${errorMessage(error)}\\n`)\n return true\n }\n}\n\nfunction uniqueAliases (aliases: Array<string | undefined>): string[] {\n return [...new Set(aliases.filter((alias): alias is string => alias !== undefined))]\n}\n\nfunction pathIsInsideOrSame (parent: string, candidate: string): boolean {\n const path = relative(parent, candidate)\n return path === '' || (!path.startsWith('..') && !isAbsolute(path))\n}\n\nfunction assertSafeWorkspaceStateDir (\n context: WorkspaceContext,\n path: string,\n root: string\n): void {\n const resolvedPath = resolve(path)\n const resolvedRoot = resolve(root)\n const expectedPath = resolve(join(resolvedRoot, 'workspaces', context.workspaceId))\n\n if (resolvedPath !== expectedPath) {\n throw new Error(`Refusing to purge unexpected state path: ${path}`)\n }\n\n if (resolvedRoot === parse(resolvedRoot).root) {\n throw new Error(`Refusing to purge state under filesystem root: ${path}`)\n }\n\n if (basename(resolvedPath) !== context.workspaceId || basename(dirname(resolvedPath)) !== 'workspaces') {\n throw new Error(`Refusing to purge non-workspace state path: ${path}`)\n }\n\n if (pathIsInsideOrSame(resolve(context.workspaceFolder), resolvedPath)) {\n throw new Error(`Refusing to purge state inside the workspace repository: ${path}`)\n }\n\n if (!pathIsInsideOrSame(resolvedRoot, resolvedPath)) {\n throw new Error(`Refusing to purge state outside its root: ${path}`)\n }\n}\n\nfunction removeWorkspaceStateDir (\n context: WorkspaceContext,\n label: string,\n path: string,\n root: string\n): void {\n assertSafeWorkspaceStateDir(context, path, root)\n\n if (!existsSync(path)) {\n process.stdout.write(`${label} absent: ${path}\\n`)\n return\n }\n\n rmSync(path, { recursive: true, force: true })\n process.stdout.write(`Removed ${label}: ${path}\\n`)\n}\n\nexport function removeWorkspaceRuntimeState (context: WorkspaceContext): void {\n removeWorkspaceStateDir(context, 'workspace runtime directory', context.workspaceRuntimeDir, context.runtimeRoot)\n}\n\nasync function purgeAliasIntegrations (context: WorkspaceContext, alias: string): Promise<boolean> {\n let failed = false\n\n failed = await runPurgeStep(`SSH alias ${alias}`, () => {\n const changed = uninstallSshConfig(alias, { quiet: true })\n process.stdout.write(changed\n ? `Removed SSH alias: ${alias}\\n`\n : `SSH alias absent: ${alias}\\n`)\n }) || failed\n\n const entry = codexProjectEntryForWorkspace(context, alias)\n const legacyRemotePath = legacyCodexRemotePathForWorkspace(context)\n\n failed = await runPurgeStep(`Codex app config for ${alias}`, () => {\n const result = uninstallCodexAppConfigProject(entry, {\n additionalRemotePaths: [legacyRemotePath]\n })\n process.stdout.write(result.changed\n ? `Removed Codex remote project: ${entry.label} (${alias})\\n`\n : `Codex remote project absent: ${entry.label} (${alias})\\n`)\n }) || failed\n\n failed = await runPurgeStep(`Codex app state for ${alias}`, () => {\n const result = uninstallCodexGlobalStateProject(entry, {\n additionalRemotePaths: [legacyRemotePath]\n })\n process.stdout.write(result.changed\n ? `Removed Codex sidebar state: ${entry.label} (${alias})\\n`\n : `Codex sidebar state absent: ${entry.label} (${alias})\\n`)\n }) || failed\n\n const claudeEntry = claudeSshConfigEntryForWorkspace(context, alias)\n\n failed = await runPurgeStep(`Claude SSH config for ${alias}`, () => {\n const result = uninstallClaudeSshConfigHost(claudeEntry)\n process.stdout.write(result.changed\n ? `Removed Claude SSH remote: ${claudeEntry.name} (${alias})\\n`\n : `Claude SSH remote absent: ${claudeEntry.name} (${alias})\\n`)\n }) || failed\n\n return failed\n}\n\nexport async function purgeWorkspace (context: WorkspaceContext, options: PurgeOptions = {}): Promise<number> {\n let failed = false\n let metadata: WorkspaceMetadata | undefined\n let container: ContainerSummary | undefined\n let dockerImageId: string | undefined\n\n process.stdout.write(`Purging Boxdown workspace: ${context.workspaceFolder}\\n`)\n\n failed = await runPurgeStep('workspace metadata snapshot', () => {\n metadata = readWorkspaceMetadata(context)\n dockerImageId = metadata?.dockerImageId\n process.stdout.write(metadata === undefined\n ? `Workspace metadata absent: ${context.workspaceDataDir}\\n`\n : `Snapshot workspace metadata: ${context.workspaceDataDir}\\n`)\n }) || failed\n\n for (const alias of uniqueAliases([\n options.alias,\n metadata?.sshAlias,\n defaultSshAlias(context.workspaceBasename)\n ])) {\n failed = await purgeAliasIntegrations(context, alias) || failed\n }\n\n failed = await runPurgeStep('workspace devcontainer lookup', async () => {\n container = await findWorkspaceContainer(context, { logger: options.logger })\n\n if (container === undefined) {\n process.stdout.write(`Devcontainer absent: ${context.workspaceFolder}\\n`)\n } else {\n process.stdout.write(`Found devcontainer: ${container.id}\\n`)\n }\n }) || failed\n\n const currentContainer = container\n\n if (currentContainer !== undefined) {\n failed = await runPurgeStep(`Docker image inspect for ${currentContainer.id}`, async () => {\n const image = await inspectContainerImage(currentContainer.id, { logger: options.logger })\n\n if (image === undefined) {\n process.stdout.write(`Docker image not recorded by container inspect: ${currentContainer.id}\\n`)\n return\n }\n\n dockerImageId = image.id\n process.stdout.write(image.name === undefined\n ? `Resolved Docker image: ${image.id}\\n`\n : `Resolved Docker image: ${image.id} (${image.name})\\n`)\n }) || failed\n\n failed = await runPurgeStep(`devcontainer ${currentContainer.id}`, async () => {\n await removeContainerById(currentContainer.id, { volumes: true, logger: options.logger })\n process.stdout.write(`Removed devcontainer with volumes: ${currentContainer.id}\\n`)\n }) || failed\n }\n\n if (dockerImageId === undefined) {\n process.stdout.write('Docker image absent: no inspected or recorded image ID\\n')\n } else {\n const removedImageId = dockerImageId\n failed = await runPurgeStep(`Docker image ${removedImageId}`, async () => {\n await removeDockerImage(removedImageId, { logger: options.logger })\n }) || failed\n }\n\n failed = await runPurgeStep('workspace runtime directory', () => {\n removeWorkspaceRuntimeState(context)\n }) || failed\n\n failed = await runPurgeStep('workspace cache directory', () => {\n removeWorkspaceStateDir(context, 'workspace cache', context.workspaceCacheDir, context.cacheRoot)\n }) || failed\n\n failed = await runPurgeStep('workspace data directory', () => {\n options.logger?.boxdown(`Removing workspace data: ${context.workspaceDataDir}\\n`)\n options.logger?.disable()\n removeWorkspaceStateDir(context, 'workspace data', context.workspaceDataDir, context.dataRoot)\n }) || failed\n\n return failed ? 1 : 0\n}\n","import { claudeSshConfigEntryForWorkspace, installClaudeSshConfigHost } from './claude-app-config.ts'\nimport { codexProjectEntryForWorkspace, installCodexAppConfigProject, installCodexGlobalStateProject, legacyCodexRemotePathForWorkspace } from './codex-app-config.ts'\nimport type { WorkspaceContext } from './paths.ts'\n\nexport type SshConfigInstallTarget = 'codex' | 'claude'\n\nexport interface SshInstallTargetDefinition {\n value: SshConfigInstallTarget\n label: string\n description: string\n flag: string\n install: (context: WorkspaceContext, alias: string, options?: SshInstallTargetInstallOptions) => Promise<void> | void\n}\n\nexport interface SshInstallTargetInstallOptions {\n quiet?: boolean\n}\n\nfunction installCodexTarget (context: WorkspaceContext, alias: string, options: SshInstallTargetInstallOptions = {}): void {\n const entry = codexProjectEntryForWorkspace(context, alias)\n const legacyRemotePath = legacyCodexRemotePathForWorkspace(context)\n const result = installCodexAppConfigProject(entry, { legacyRemotePaths: [legacyRemotePath] })\n const stateResult = installCodexGlobalStateProject(entry, { legacyRemotePaths: [legacyRemotePath] })\n\n if (options.quiet === true) {\n return\n }\n\n process.stdout.write(`\\nCodex app config: ${result.configPath}\\n`)\n process.stdout.write(result.changed\n ? `Installed Codex remote project: ${entry.label} (${entry.remotePath})\\n`\n : `Codex remote project already up to date: ${entry.label} (${entry.remotePath})\\n`)\n\n if (result.backupPath !== undefined) {\n process.stdout.write(`Codex app config backup: ${result.backupPath}\\n`)\n }\n\n if (stateResult.backupPath !== undefined) {\n process.stdout.write(`Codex app state backup: ${stateResult.backupPath}\\n`)\n }\n\n process.stdout.write('Restart Codex to apply the remote project entry.\\n')\n}\n\nfunction installClaudeTarget (context: WorkspaceContext, alias: string, options: SshInstallTargetInstallOptions = {}): void {\n const entry = claudeSshConfigEntryForWorkspace(context, alias)\n const result = installClaudeSshConfigHost(entry)\n\n if (options.quiet === true) {\n return\n }\n\n process.stdout.write(`\\nClaude SSH config: ${result.configPath}\\n`)\n process.stdout.write(result.changed\n ? `Installed Claude SSH remote: ${entry.name} (${entry.sshHost})\\n`\n : `Claude SSH remote already up to date: ${entry.name} (${entry.sshHost})\\n`)\n\n if (result.backupPath !== undefined) {\n process.stdout.write(`Claude SSH config backup: ${result.backupPath}\\n`)\n }\n\n process.stdout.write('Restart Claude to apply the SSH remote entry.\\n')\n}\n\nexport const SSH_INSTALL_TARGETS: readonly SshInstallTargetDefinition[] = [\n {\n value: 'codex',\n label: 'Codex',\n description: 'Register this SSH alias as a Codex app remote project.',\n flag: '--target codex',\n install: installCodexTarget\n },\n {\n value: 'claude',\n label: 'Claude',\n description: 'Register this SSH alias as a Claude app SSH remote.',\n flag: '--target claude',\n install: installClaudeTarget\n }\n]\n\nexport function supportedSshInstallTargetsText (): string {\n return SSH_INSTALL_TARGETS.map((target) => target.value).join(', ')\n}\n\nexport function sshInstallTargetFlagHintsText (): string {\n return SSH_INSTALL_TARGETS.map((target) => target.flag).join(' ')\n}\n\nexport function isSshConfigInstallTarget (value: string): value is SshConfigInstallTarget {\n return SSH_INSTALL_TARGETS.some((target) => target.value === value)\n}\n\nexport function dedupeSshInstallTargets (targets: readonly SshConfigInstallTarget[]): SshConfigInstallTarget[] {\n return [...new Set(targets)]\n}\n\nexport async function installSshInstallTarget (\n context: WorkspaceContext,\n alias: string,\n targetValue: SshConfigInstallTarget,\n options: SshInstallTargetInstallOptions = {}\n): Promise<void> {\n const target = SSH_INSTALL_TARGETS.find((candidate) => candidate.value === targetValue)\n\n if (target === undefined) {\n throw new Error(`Unsupported ssh install target: ${targetValue}`)\n }\n\n await target.install(context, alias, options)\n}\n","import { existsSync } from 'node:fs'\n\nimport { claudeSshConfigEntryForWorkspace, uninstallClaudeSshConfigHost } from './claude-app-config.ts'\nimport { codexProjectEntryForWorkspace, legacyCodexRemotePathForWorkspace, uninstallCodexAppConfigProject, uninstallCodexGlobalStateProject } from './codex-app-config.ts'\nimport { codingAgentBinary, codingAgentFromCommand, type CodingAgentCli } from './coding-agents.ts'\nimport { buildGeneratedDevcontainerConfig, publishContainerPortFromConfig } from './config.ts'\nimport { doctorHasFailures, formatDoctorText, runDoctorChecks, type DoctorCheck } from './doctor.ts'\nimport { startDevcontainer, printPortHint, openShell, openCodingAgentCli, ensureContainerSshRuntime, runSshdProxy, refreshContainerGhAuth, refreshContainerCodingAgentClis, ensureContainerCodingAgentCli, findRunningContainerId, findWorkspaceContainer, stopWorkspaceContainer, removeWorkspaceContainer, listWorkspaceContainers, openSshTunnel, type TunnelPortForward } from './devcontainer.ts'\nimport { canPromptInteractively, promptConfirm, promptMultiSelect, promptText, type PromptInput, type PromptOutput } from './interactive-prompts.ts'\nimport { createWorkspaceListEntries, formatWorkspaceListDetailsText, formatWorkspaceListText } from './list.ts'\nimport { createWorkspaceCommandLogger, withLoggedProcessOutput, type WorkspaceCommandLogger } from './logging.ts'\nimport { listWorkspaceMetadata, readWorkspaceMetadata, writeWorkspaceMetadata, type WorkspaceMetadata } from './metadata.ts'\nimport { readPackageVersion } from './package-info.ts'\nimport { createWorkspaceContext, createWorkspaceContextFromIdentity, defaultDataRoot, type WorkspaceContext } from './paths.ts'\nimport { createProgress, resolveProgressMode, type ProgressReporter, type ProgressOutputTarget, type ProgressStepDefinition } from './progress.ts'\nimport { purgeWorkspace, removeWorkspaceRuntimeState } from './purge.ts'\nimport { defaultSshAlias, installSshConfig, uninstallSshConfig } from './ssh-config.ts'\nimport { dedupeSshInstallTargets, installSshInstallTarget, isSshConfigInstallTarget, SSH_INSTALL_TARGETS, sshInstallTargetFlagHintsText, supportedSshInstallTargetsText, type SshConfigInstallTarget } from './ssh-install-targets.ts'\nimport { createStatusInfo, formatStatusText, statusIsHealthy } from './status.ts'\nimport type { CliColor } from './cli-style.ts'\n\nexport type BoxdownCommand =\n | 'help'\n | 'version'\n | 'setup'\n | 'start'\n | 'list'\n | 'status'\n | 'stop'\n | 'down'\n | 'purge'\n | 'doctor'\n | 'ssh-install'\n | 'ssh-uninstall'\n | 'ssh-proxy'\n | 'tunnel'\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 workspaces?: string[]\n alias?: string\n targets?: SshConfigInstallTarget[]\n tunnelPorts?: TunnelPortForward[]\n recreate: boolean\n json: boolean\n details?: boolean\n verbose: boolean\n}\n\nexport interface RunCliOptions {\n promptInput?: PromptInput\n promptOutput?: PromptOutput\n env?: NodeJS.ProcessEnv\n runDoctorChecks?: typeof runDoctorChecks\n setupWorkspace?: typeof setupWorkspace\n}\n\nexport const USAGE = `Usage:\n boxdown setup [--workspace <path>] [--alias <name>] [--recreate] [--target <name>]...\n boxdown start [--workspace <path>] [--recreate]\n boxdown codex [--workspace <path>] [--recreate] [-- <codex args...>]\n boxdown claude [--workspace <path>] [--recreate] [-- <claude args...>]\n boxdown opencode [--workspace <path>] [--recreate] [-- <opencode args...>]\n boxdown antigravity [--workspace <path>] [--recreate] [-- <agy args...>]\n boxdown list [--details] [--json|--format json]\n boxdown status [--workspace <path>] [--alias <name>] [--json|--format json]\n boxdown stop [--workspace <path>]\n boxdown down [--workspace <path>]...\n boxdown purge [--workspace <path|ssh-alias|repo>] [--alias <name>]\n boxdown doctor [--workspace <path>]\n boxdown ssh install [--workspace <path>] [--alias <name>] [--target <name>]...\n boxdown ssh uninstall [--workspace <path>] [--alias <name>]\n boxdown ssh-proxy [--workspace <path>] [--alias <name>]\n boxdown tunnel [--port <port>] [--port <local:remote>] [--workspace <path>] [--alias <name>]\n boxdown refresh-gh-token [--workspace <path>]\n boxdown refresh-gh-token-running [--workspace <path>]\n\nCommands:\n setup Prepare the workspace devcontainer and SSH/app\n integration without opening a shell.\n start, shell Start or reuse the workspace devcontainer, then open\n an interactive shell inside it.\n codex Start or reuse the devcontainer, then launch Codex.\n claude, cc Start or reuse the devcontainer, then launch Claude\n Code.\n opencode Start or reuse the devcontainer, then launch\n OpenCode, installing it first when needed.\n antigravity Start or reuse the devcontainer, then launch\n Antigravity CLI (agy), installing it first when\n needed.\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 purge Remove the workspace devcontainer, exact Docker\n image, managed SSH/app config, and Boxdown\n cache/data for this workspace. Prompts for\n tracked workspaces from untracked directories.\n doctor Check required host tools and Boxdown assets.\n ssh install Install or update an SSH host alias for the workspace\n devcontainer.\n ssh uninstall Remove Boxdown's managed SSH host alias block and\n matching Codex/Claude app entries.\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 tunnel Start or reuse the devcontainer, then keep an SSH\n local port tunnel open for host/browser access.\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 Repeatable with down. With purge, also accepts PATH,\n SSH ALIAS, or an unambiguous REPO from boxdown list.\n Without --workspace, purge only targets the current\n directory when it is tracked; otherwise interactive\n terminals prompt for tracked workspaces.\n --alias <name> SSH host alias. Defaults to <repo-name>-devcontainer.\n --target <name> Optional SSH install target. Repeatable. Supported by\n setup and ssh install: codex, claude.\n --port <port> Tunnel a local port to the same remote port, or use\n <local:remote>. Repeatable. Supported by tunnel.\n --recreate Remove the existing devcontainer before starting.\n --json Print JSON output. Supported by status and list.\n --format json Print JSON output. Equivalent to --json.\n --details Print detailed human list output. Supported by list.\n --verbose Stream raw Docker, devcontainer, and hook command output.\n Lifecycle commands append the same managed output to the\n per-workspace command log either way.\n --help, -h Show help.\n --version, -v Show version.\n`\n\nexport function commandWritesWorkspaceMetadata (command: BoxdownCommand): boolean {\n return [\n 'setup',\n 'start',\n 'ssh-install',\n 'ssh-proxy',\n 'tunnel',\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 const workspaces: string[] = []\n let alias: string | undefined\n const targets: SshConfigInstallTarget[] = []\n const tunnelPorts: TunnelPortForward[] = []\n let recreate = false\n let json = false\n let details = false\n let verbose = false\n let passthroughArgs: string[] | undefined\n const positional: string[] = []\n\n function workspaceFields (command: BoxdownCommand): Pick<ParsedCli, 'workspace' | 'workspaces'> {\n if (workspaces.length > 1 && command !== 'down') {\n throw new Error('--workspace can only be repeated with down')\n }\n\n return {\n workspace: workspaces[0],\n ...(command === 'down' && workspaces.length > 0 ? { workspaces: [...workspaces] } : {})\n }\n }\n\n function parsed (command: BoxdownCommand): ParsedCli {\n if (details && json) {\n throw new Error('--details cannot be combined with JSON output')\n }\n\n if (json && command !== 'status' && command !== 'list') {\n throw new Error('--json is only supported with status and list')\n }\n\n if (details && command !== 'list') {\n throw new Error('--details is only supported with list')\n }\n\n if (passthroughArgs !== undefined) {\n throw new Error('-- passthrough is only supported with coding-agent commands')\n }\n\n if (targets.length > 0 && command !== 'setup' && command !== 'ssh-install') {\n throw new Error('--target is only supported with setup and ssh install')\n }\n\n if (tunnelPorts.length > 0 && command !== 'tunnel') {\n throw new Error('--port is only supported with tunnel')\n }\n\n if (recreate && command === 'purge') {\n throw new Error('--recreate is not supported with purge')\n }\n\n const parsedTargets = dedupeSshInstallTargets(targets)\n\n return {\n command,\n ...workspaceFields(command),\n alias,\n ...(parsedTargets.length === 0 ? {} : { targets: parsedTargets }),\n ...(tunnelPorts.length === 0 ? {} : { tunnelPorts }),\n recreate,\n json,\n ...(details ? { details } : {}),\n verbose\n }\n }\n\n function parsedCodingAgent (agent: CodingAgentCli): ParsedCli {\n if (details && json) {\n throw new Error('--details cannot be combined with JSON output')\n }\n\n if (json) {\n throw new Error('--json is only supported with status and list')\n }\n\n if (details) {\n throw new Error('--details is only supported with list')\n }\n\n if (targets.length > 0) {\n throw new Error('--target is only supported with setup and ssh install')\n }\n\n if (tunnelPorts.length > 0) {\n throw new Error('--port is only supported with tunnel')\n }\n\n return {\n command: 'coding-agent',\n agent,\n agentArgs: passthroughArgs ?? [],\n ...workspaceFields('coding-agent'),\n alias,\n recreate,\n json,\n verbose\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 === '--version' || arg === '-v') {\n return parsed('version')\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 workspaces.push(value)\n continue\n }\n\n if (arg === '--target') {\n const value = args.shift()\n if (value === undefined) {\n throw new Error('--target requires a value')\n }\n\n if (!isSshConfigInstallTarget(value)) {\n throw new Error(`Unsupported ssh install target: ${value}`)\n }\n\n targets.push(value)\n continue\n }\n\n if (arg === '--port') {\n const value = args.shift()\n if (value === undefined) {\n throw new Error('--port requires a value')\n }\n tunnelPorts.push(parseTunnelPort(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 === '--format') {\n const value = args.shift()\n if (value === undefined) {\n throw new Error('--format requires a value')\n }\n\n if (value !== 'json') {\n throw new Error(`Unsupported format: ${value}`)\n }\n\n json = true\n continue\n }\n\n if (arg === '--details') {\n details = true\n continue\n }\n\n if (arg === '--verbose') {\n verbose = 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 if (positional[0] === 'setup' && positional.length === 1) {\n return parsed('setup')\n }\n\n if (positional[0] === 'codex' && positional[1] === 'repair') {\n throw new Error(`Unknown command: ${positional.join(' ')}`)\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] === 'purge' && positional.length === 1) {\n return parsed('purge')\n }\n\n if (positional[0] === 'doctor' && positional.length === 1) {\n return parsed('doctor')\n }\n\n if (positional[0] === 'ssh') {\n if (positional.length === 1 || (positional[1] === 'install' && positional.length === 2)) {\n return parsed('ssh-install')\n }\n\n if (positional[1] === 'uninstall' && positional.length === 2) {\n return parsed('ssh-uninstall')\n }\n\n throw new Error(`Unknown ssh command: ${positional.slice(1).join(' ')}. Usage: boxdown ssh [install|uninstall] [--workspace <path>] [--alias <name>] [--target <name>]...`)\n }\n\n if (positional[0] === 'ssh-proxy' && positional.length === 1) {\n return parsed('ssh-proxy')\n }\n\n if (positional[0] === 'tunnel' && positional.length === 1) {\n return parsed('tunnel')\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\nfunction parsePortNumber (value: string): number {\n if (!/^[0-9]+$/.test(value)) {\n throw new Error(`Invalid tunnel port: ${value}`)\n }\n\n const port = Number(value)\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(`Invalid tunnel port: ${value}`)\n }\n\n return port\n}\n\nexport function parseTunnelPort (value: string): TunnelPortForward {\n const parts = value.split(':')\n\n if (parts.length === 1) {\n const port = parsePortNumber(parts[0] ?? '')\n return {\n localPort: port,\n remotePort: port\n }\n }\n\n if (parts.length === 2) {\n return {\n localPort: parsePortNumber(parts[0] ?? ''),\n remotePort: parsePortNumber(parts[1] ?? '')\n }\n }\n\n throw new Error(`Invalid tunnel port: ${value}`)\n}\n\nexport function parseTunnelPortList (value: string): TunnelPortForward[] {\n const tokens = value.split(/[,\\s]+/u).filter((token) => token.length > 0)\n\n if (tokens.length === 0) {\n throw new Error('tunnel requires at least one --port value')\n }\n\n return tokens.map((token) => parseTunnelPort(token))\n}\n\ninterface ResolvedDownWorkspaces {\n workspaces: string[] | undefined\n cancelled: boolean\n}\n\ninterface PurgeTarget {\n context: WorkspaceContext\n argv: string[]\n}\n\ninterface ResolvedPurgeTargets {\n targets: PurgeTarget[]\n cancelled: boolean\n batch: boolean\n}\n\nfunction createLifecycleLogger (context: WorkspaceContext, command: string, argv: string[]): WorkspaceCommandLogger {\n const logger = createWorkspaceCommandLogger(context)\n logger.section(`boxdown ${command}`, {\n argv: JSON.stringify(argv),\n cwd: process.cwd()\n })\n return logger\n}\n\nasync function runLoggedLifecycle<T> (\n context: WorkspaceContext,\n command: string,\n argv: string[],\n action: (logger: WorkspaceCommandLogger) => Promise<T>\n): Promise<T> {\n const logger = createLifecycleLogger(context, command, argv)\n\n try {\n return await withLoggedProcessOutput(logger, async () => action(logger))\n } catch (error) {\n logger.boxdown(`Error: ${error instanceof Error ? error.message : String(error)}\\n`)\n throw error\n }\n}\n\nfunction uniqueWorkspaceMetadata (metadata: WorkspaceMetadata[]): WorkspaceMetadata[] {\n return [...new Map(metadata.map((entry) => [entry.workspaceId, entry])).values()]\n}\n\nfunction workspaceMetadataContext (metadata: WorkspaceMetadata): WorkspaceContext {\n return createWorkspaceContextFromIdentity({\n workspaceFolder: metadata.workspaceFolder,\n workspaceBasename: metadata.workspaceBasename,\n workspaceId: metadata.workspaceId\n })\n}\n\nfunction purgeWorkspaceStateColor (state: string): CliColor {\n if (state === 'running') {\n return 'green'\n }\n\n if (state === 'exited') {\n return 'yellow'\n }\n\n return 'red'\n}\n\nfunction ambiguousWorkspaceSelectorError (selector: string, matches: WorkspaceMetadata[]): Error {\n const matchList = matches\n .map((entry) => ` - ${entry.workspaceBasename}: ${entry.workspaceFolder} (${entry.sshAlias})`)\n .join('\\n')\n\n return new Error(`Workspace selector is ambiguous: ${selector}\\nUse the PATH or SSH ALIAS from \"boxdown list\":\\n${matchList}`)\n}\n\nfunction resolvePurgeWorkspaceContext (workspace: string | undefined): WorkspaceContext {\n if (workspace === undefined) {\n return createWorkspaceContext()\n }\n\n try {\n return createWorkspaceContext({ workspace })\n } catch {\n // Purge can target stale metadata, so values copied from `boxdown list`\n // should work even when the repository path no longer exists.\n }\n\n const metadata = listWorkspaceMetadata(defaultDataRoot())\n\n for (const matches of [\n metadata.filter((entry) => entry.workspaceFolder === workspace),\n metadata.filter((entry) => entry.sshAlias === workspace),\n metadata.filter((entry) => entry.workspaceBasename === workspace)\n ]) {\n const uniqueMatches = uniqueWorkspaceMetadata(matches)\n\n if (uniqueMatches.length === 1) {\n return workspaceMetadataContext(uniqueMatches[0] as WorkspaceMetadata)\n }\n\n if (uniqueMatches.length > 1) {\n throw ambiguousWorkspaceSelectorError(workspace, uniqueMatches)\n }\n }\n\n throw new Error(`Workspace does not exist and no Boxdown list entry matches PATH, SSH ALIAS, or REPO: ${workspace}`)\n}\n\nasync function resolvePurgeTargets (\n parsed: ParsedCli,\n options: RunCliOptions,\n argv: string[]\n): Promise<ResolvedPurgeTargets> {\n if (parsed.workspace !== undefined) {\n return {\n targets: [{\n context: resolvePurgeWorkspaceContext(parsed.workspace),\n argv\n }],\n cancelled: false,\n batch: false\n }\n }\n\n const context = createWorkspaceContext()\n const metadata = readWorkspaceMetadata(context)\n\n if (metadata?.workspaceFolder === context.workspaceFolder) {\n return {\n targets: [{\n context,\n argv\n }],\n cancelled: false,\n batch: false\n }\n }\n\n const input = options.promptInput ?? process.stdin\n const output = options.promptOutput ?? process.stdout\n const env = options.env ?? process.env\n\n if (!canPromptInteractively(input, output, env)) {\n throw new Error('Current directory is not a tracked Boxdown workspace. Run boxdown purge from a tracked workspace or pass --workspace <PATH|SSH ALIAS|REPO>.')\n }\n\n const entries = createWorkspaceListEntries(\n listWorkspaceMetadata(defaultDataRoot()),\n await listWorkspaceContainers(),\n existsSync\n )\n\n if (entries.length === 0) {\n throw new Error('No Boxdown workspaces found to purge.')\n }\n\n const entriesById = new Map(entries.map((entry) => [entry.workspaceId, entry]))\n const result = await promptMultiSelect<string>({\n title: 'Purge Boxdown workspaces?',\n choices: entries.map((entry) => ({\n value: entry.workspaceId,\n label: entry.workspaceBasename,\n description: `(${entry.state}) ${entry.workspaceFolder}`,\n focusedDescription: [\n { text: `(${entry.state})`, color: purgeWorkspaceStateColor(entry.state) },\n { text: ` ${entry.workspaceFolder}`, color: 'dim' }\n ]\n })),\n skipLabel: 'Cancel',\n summaryLabel: 'Purge workspaces',\n input,\n output,\n env\n })\n\n if (result.status === 'selected') {\n return {\n targets: result.values.map((workspaceId) => {\n const entry = entriesById.get(workspaceId)\n\n if (entry === undefined) {\n throw new Error(`Selected Boxdown workspace disappeared: ${workspaceId}`)\n }\n\n return {\n context: workspaceMetadataContext(entry),\n argv: ['purge', '--workspace', entry.workspaceFolder]\n }\n }),\n cancelled: false,\n batch: true\n }\n }\n\n if (result.status === 'non-interactive') {\n throw new Error('Current directory is not a tracked Boxdown workspace. Run boxdown purge from a tracked workspace or pass --workspace <PATH|SSH ALIAS|REPO>.')\n }\n\n return {\n targets: [],\n cancelled: true,\n batch: true\n }\n}\n\nasync function confirmPurgeTargets (\n resolved: ResolvedPurgeTargets,\n parsed: ParsedCli,\n options: RunCliOptions\n): Promise<boolean> {\n if (!resolved.batch) {\n const target = resolved.targets[0]\n\n if (target === undefined) {\n return false\n }\n\n return confirmPurgeWorkspace(target.context, parsed, options)\n }\n\n const result = await promptConfirm({\n title: 'Purge selected Boxdown workspaces?',\n details: [\n `${resolved.targets.length} workspaces selected:`,\n ...resolved.targets.map((target) => `Workspace: ${target.context.workspaceFolder}`),\n 'Removes devcontainers, recorded images, SSH/Codex entries, cache, and data.',\n parsed.alias === undefined ? 'Alias: default and recorded aliases' : `Alias: ${parsed.alias}, default, and recorded aliases`\n ],\n confirmLabel: 'Purge selected',\n cancelLabel: 'Cancel',\n summaryLabel: 'Purge workspaces',\n input: options.promptInput,\n output: options.promptOutput,\n env: options.env\n })\n\n return result.status === 'confirmed' || result.status === 'non-interactive'\n}\n\nasync function runPurgeCommand (parsed: ParsedCli, argv: string[], options: RunCliOptions): Promise<number> {\n const resolved = await resolvePurgeTargets(parsed, options, argv)\n\n if (resolved.cancelled) {\n process.stderr.write('Canceled purge.\\n')\n return 1\n }\n\n if (resolved.targets.length === 0) {\n process.stderr.write('No Boxdown workspaces selected for purge.\\n')\n return 1\n }\n\n if (!await confirmPurgeTargets(resolved, parsed, options)) {\n process.stderr.write('Canceled purge.\\n')\n return 1\n }\n\n let failed = false\n\n for (const target of resolved.targets) {\n try {\n const code = await runLoggedLifecycle(target.context, 'purge', target.argv, async (logger) => purgeWorkspace(target.context, {\n alias: parsed.alias,\n logger\n }))\n\n failed = code !== 0 || failed\n } catch (error) {\n failed = true\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n }\n }\n\n return failed ? 1 : 0\n}\n\nasync function resolveDownWorkspaces (\n workspaces: string[] | undefined,\n options: RunCliOptions\n): Promise<ResolvedDownWorkspaces> {\n if (workspaces !== undefined && workspaces.length > 0) {\n return { workspaces, cancelled: false }\n }\n\n const context = createWorkspaceContext()\n const metadata = readWorkspaceMetadata(context)\n\n if (metadata?.workspaceFolder === context.workspaceFolder) {\n return { workspaces: undefined, cancelled: false }\n }\n\n const input = options.promptInput ?? process.stdin\n const output = options.promptOutput ?? process.stdout\n const env = options.env ?? process.env\n\n if (!canPromptInteractively(input, output, env)) {\n return { workspaces: undefined, cancelled: false }\n }\n\n const entries = createWorkspaceListEntries(\n listWorkspaceMetadata(defaultDataRoot()),\n await listWorkspaceContainers(),\n existsSync\n ).filter((entry) => entry.repoExists)\n\n if (entries.length === 0) {\n return { workspaces: undefined, cancelled: false }\n }\n\n const result = await promptMultiSelect<string>({\n title: 'Remove Boxdown devcontainers?',\n choices: entries.map((entry) => ({\n value: entry.workspaceFolder,\n label: entry.workspaceBasename,\n description: `${entry.state} - ${entry.workspaceFolder}`\n })),\n skipLabel: 'Cancel',\n summaryLabel: 'Down workspaces',\n input,\n output,\n env\n })\n\n if (result.status === 'selected') {\n return { workspaces: result.values, cancelled: false }\n }\n\n if (result.status === 'non-interactive') {\n return { workspaces: undefined, cancelled: false }\n }\n\n return { workspaces: undefined, cancelled: true }\n}\n\nasync function runDownCommand (workspaces: string[] | undefined, options: RunCliOptions): Promise<number> {\n const resolved = await resolveDownWorkspaces(workspaces, options)\n\n if (resolved.cancelled) {\n process.stderr.write('Canceled down.\\n')\n return 1\n }\n\n const targetWorkspaces = resolved.workspaces === undefined || resolved.workspaces.length === 0 ? [undefined] : resolved.workspaces\n let failed = false\n\n for (const workspace of targetWorkspaces) {\n try {\n const context = createWorkspaceContext({ workspace })\n await runLoggedLifecycle(context, 'down', ['down', ...(workspace === undefined ? [] : ['--workspace', workspace])], async (logger) => {\n await removeWorkspaceContainer(context, { logger })\n removeWorkspaceRuntimeState(context)\n })\n } catch (error) {\n failed = true\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n }\n }\n\n return failed ? 1 : 0\n}\n\ninterface ResolvedSshInstallTargets {\n targets: SshConfigInstallTarget[]\n cancelled: boolean\n skippedNonInteractive: boolean\n}\n\ninterface ResolvedTunnelPorts {\n tunnelPorts: TunnelPortForward[]\n cancelled: boolean\n}\n\nasync function resolveTunnelPorts (\n parsed: ParsedCli,\n context: ReturnType<typeof createWorkspaceContext>,\n options: RunCliOptions\n): Promise<ResolvedTunnelPorts> {\n if (parsed.tunnelPorts !== undefined && parsed.tunnelPorts.length > 0) {\n return {\n tunnelPorts: parsed.tunnelPorts,\n cancelled: false\n }\n }\n\n const input = options.promptInput ?? process.stdin\n const output = options.promptOutput ?? process.stdout\n const env = options.env ?? process.env\n\n if (!canPromptInteractively(input, output, env)) {\n return {\n tunnelPorts: [],\n cancelled: false\n }\n }\n\n const defaultPort = publishContainerPortFromConfig(buildGeneratedDevcontainerConfig(context))\n const result = await promptText({\n title: 'Tunnel port(s) to forward?',\n details: ['Use a port like 3030, or a mapping like 8080:3031.'],\n defaultValue: defaultPort,\n summaryLabel: 'Tunnel ports',\n validate: (value) => {\n try {\n parseTunnelPortList(value)\n return undefined\n } catch (error) {\n return error instanceof Error ? error.message : String(error)\n }\n },\n input,\n output,\n env\n })\n\n if (result.status === 'submitted') {\n return {\n tunnelPorts: parseTunnelPortList(result.value),\n cancelled: false\n }\n }\n\n return {\n tunnelPorts: [],\n cancelled: result.status === 'cancelled'\n }\n}\n\nasync function confirmPurgeWorkspace (\n context: ReturnType<typeof createWorkspaceContext>,\n parsed: ParsedCli,\n options: RunCliOptions\n): Promise<boolean> {\n const result = await promptConfirm({\n title: 'Purge Boxdown workspace?',\n details: [\n `Workspace: ${context.workspaceFolder}`,\n 'Removes devcontainer, recorded image, SSH/Codex entries, cache, and data.',\n parsed.alias === undefined ? 'Alias: default and recorded aliases' : `Alias: ${parsed.alias}, default, and recorded aliases`\n ],\n confirmLabel: 'Purge',\n cancelLabel: 'Cancel',\n summaryLabel: 'Purge',\n input: options.promptInput,\n output: options.promptOutput,\n env: options.env\n })\n\n return result.status === 'confirmed' || result.status === 'non-interactive'\n}\n\nasync function resolveSshInstallTargets (\n parsed: ParsedCli,\n options: RunCliOptions\n): Promise<ResolvedSshInstallTargets> {\n if (parsed.targets !== undefined) {\n return {\n targets: parsed.targets,\n cancelled: false,\n skippedNonInteractive: false\n }\n }\n\n const result = await promptMultiSelect<SshConfigInstallTarget>({\n title: 'Install optional SSH targets?',\n choices: SSH_INSTALL_TARGETS.map((target) => ({\n value: target.value,\n label: target.label,\n description: target.description\n })),\n skipLabel: 'Skip optional targets',\n summaryLabel: 'Optional SSH targets',\n input: options.promptInput,\n output: options.promptOutput,\n env: options.env\n })\n\n return {\n targets: result.values,\n cancelled: result.status === 'cancelled',\n skippedNonInteractive: result.status === 'non-interactive'\n }\n}\n\nfunction printSkippedSshInstallTargets (command: 'setup' | 'ssh install'): void {\n process.stdout.write(`\\nNo optional SSH install targets selected. Run boxdown ${command} ${sshInstallTargetFlagHintsText()} to install optional targets explicitly. Supported targets: ${supportedSshInstallTargetsText()}.\\n`)\n}\n\ninterface SetupWorkspaceOptions {\n recreate?: boolean\n targets?: SshConfigInstallTarget[]\n progress?: ProgressReporter\n logger?: WorkspaceCommandLogger\n start?: typeof startDevcontainer\n installSsh?: typeof installSshConfig\n installTarget?: typeof installSshInstallTarget\n}\n\nexport async function setupWorkspace (\n context: WorkspaceContext,\n alias: string,\n options: SetupWorkspaceOptions = {}\n): Promise<void> {\n await (options.start ?? startDevcontainer)(context, {\n recreate: options.recreate,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n ...(options.progress === undefined ? {} : { progress: options.progress })\n })\n\n const hasSshAliasStep = options.progress?.hasStep('ssh-alias') === true\n\n if (options.progress?.mode === 'interactive') {\n if (hasSshAliasStep) {\n options.progress.startStep('ssh-alias')\n } else {\n options.progress.item('Installing SSH alias')\n options.progress.detail(alias)\n }\n\n try {\n await (options.installSsh ?? installSshConfig)(context, alias, { quiet: true })\n if (hasSshAliasStep) {\n options.progress.completeStep('ssh-alias')\n }\n } catch (error) {\n if (hasSshAliasStep) {\n options.progress.failStep('ssh-alias')\n }\n throw error\n }\n } else {\n await (options.installSsh ?? installSshConfig)(context, alias)\n }\n\n const installTarget = options.installTarget ?? installSshInstallTarget\n for (const target of options.targets ?? []) {\n const stepId = `ssh-target:${target}`\n const hasTargetStep = options.progress?.hasStep(stepId) === true\n\n if (hasTargetStep) {\n options.progress?.startStep(stepId)\n } else if (options.progress?.mode === 'interactive') {\n options.progress.item(`Installing ${target} SSH target`)\n }\n\n try {\n await installTarget(context, alias, target, {\n quiet: options.progress?.mode === 'interactive'\n })\n if (hasTargetStep) {\n options.progress?.completeStep(stepId)\n }\n } catch (error) {\n if (hasTargetStep) {\n options.progress?.failStep(stepId)\n }\n throw error\n }\n }\n}\n\nfunction createCliProgress (\n parsed: ParsedCli,\n target: ProgressOutputTarget = 'stdout',\n options: { env?: NodeJS.ProcessEnv } = {}\n): ProgressReporter {\n return createProgress({\n mode: resolveProgressMode({\n verbose: parsed.verbose,\n json: parsed.json,\n target,\n env: options.env\n }),\n target\n })\n}\n\nfunction startProgressSteps (): ProgressStepDefinition[] {\n return [\n { id: 'ssh-identity', label: 'Preparing SSH identity' },\n { id: 'devcontainer-config', label: 'Writing generated devcontainer config' },\n { id: 'devcontainer-start', label: 'Starting devcontainer' }\n ]\n}\n\nfunction sshTargetProgressLabel (target: SshConfigInstallTarget): string {\n const label = SSH_INSTALL_TARGETS.find((candidate) => candidate.value === target)?.label ?? target\n return `Installing ${label} SSH target`\n}\n\nfunction setupProgressSteps (targets: readonly SshConfigInstallTarget[]): ProgressStepDefinition[] {\n return [\n ...startProgressSteps(),\n { id: 'ssh-alias', label: 'Installing SSH alias' },\n ...targets.map((target) => ({\n id: `ssh-target:${target}`,\n label: sshTargetProgressLabel(target)\n }))\n ]\n}\n\nfunction setupPreflightProgressSteps (): ProgressStepDefinition[] {\n return [{ id: 'setup-preflight', label: 'Checking host readiness' }]\n}\n\nfunction setupPreflightFailureMessage (checks: DoctorCheck[]): string {\n const failures = checks\n .filter((check) => check.level === 'fail')\n .map((check) => `- ${check.name}: ${check.message}`)\n\n return `Setup preflight failed:\\n${failures.join('\\n')}`\n}\n\nasync function runSetupPreflight (\n context: WorkspaceContext,\n alias: string,\n parsed: ParsedCli,\n options: RunCliOptions\n): Promise<void> {\n const progress = createCliProgress(parsed, 'stdout', { env: options.env })\n const doctor = options.runDoctorChecks ?? runDoctorChecks\n\n await withProgressSection(progress, 'Boxdown setup', [\n `Workspace: ${context.workspaceFolder}`,\n `SSH alias: ${alias}`\n ], async () => {\n progress.setSteps(setupPreflightProgressSteps())\n progress.startStep('setup-preflight')\n const checks = await doctor(context, { includeOptional: false })\n\n for (const check of checks.filter((item) => item.level === 'warn')) {\n progress.warn(`${check.name}: ${check.message}`)\n }\n\n if (doctorHasFailures(checks)) {\n progress.failStep('setup-preflight')\n throw new Error(setupPreflightFailureMessage(checks))\n }\n\n progress.completeStep('setup-preflight')\n })\n}\n\nfunction sshAliasProgressStep (label: string): ProgressStepDefinition {\n return { id: 'ssh-alias', label }\n}\n\nfunction tunnelProgressSteps (): ProgressStepDefinition[] {\n return [\n sshAliasProgressStep('Updating SSH alias'),\n ...startProgressSteps()\n ]\n}\n\nfunction sshProxyProgressSteps (): ProgressStepDefinition[] {\n return [\n sshAliasProgressStep('Updating SSH alias'),\n ...startProgressSteps(),\n { id: 'coding-agent-refresh', label: 'Refreshing default coding-agent CLIs' },\n { id: 'ssh-runtime', label: 'Preparing container SSH runtime' }\n ]\n}\n\nfunction codingAgentProgressSteps (agent: CodingAgentCli): ProgressStepDefinition[] {\n return [\n ...startProgressSteps(),\n { id: 'agent-cli', label: `Preparing ${codingAgentBinary(agent)} inside the devcontainer` }\n ]\n}\n\nfunction ghAuthProgressSteps (includeStart: boolean): ProgressStepDefinition[] {\n return [\n ...(includeStart ? startProgressSteps() : [{ id: 'devcontainer-running', label: 'Using running devcontainer' }]),\n { id: 'gh-auth-config', label: 'Preparing generated config for GitHub auth refresh' },\n { id: 'gh-token-read', label: 'Reading host GitHub CLI token' },\n { id: 'gh-auth-refresh', label: 'Refreshing GitHub CLI auth inside the devcontainer' },\n { id: 'gh-git-auth', label: 'Configuring workspace GitHub Git auth' },\n { id: 'gh-auth-verify', label: 'Verifying GitHub CLI auth inside the devcontainer' }\n ]\n}\n\nasync function withProgressSection<T> (\n progress: ProgressReporter,\n title: string,\n details: readonly string[],\n run: () => Promise<T>\n): Promise<T> {\n progress.section(title)\n for (const detail of details) {\n progress.detail(detail)\n }\n\n try {\n return await run()\n } finally {\n progress.end()\n }\n}\n\nexport async function runCli (argv: string[] = process.argv.slice(2), options: RunCliOptions = {}): 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 === 'version') {\n process.stdout.write(`${readPackageVersion()}\\n`)\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 if (parsed.details) {\n process.stdout.write(formatWorkspaceListDetailsText(entries))\n } else {\n process.stdout.write(formatWorkspaceListText(entries))\n }\n\n return 0\n }\n\n if (parsed.command === 'down') {\n return runDownCommand(parsed.workspaces, options)\n }\n\n if (parsed.command === 'purge') {\n return await runPurgeCommand(parsed, argv, options)\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 (parsed.command !== 'ssh-install' && parsed.command !== 'setup' && parsed.command !== 'tunnel' && commandWritesWorkspaceMetadata(parsed.command)) {\n writeWorkspaceMetadata(context, alias)\n }\n\n if (parsed.command === 'ssh-install') {\n const resolvedTargets = await resolveSshInstallTargets(parsed, options)\n\n if (resolvedTargets.cancelled) {\n process.stderr.write('Canceled SSH install.\\n')\n return 1\n }\n\n writeWorkspaceMetadata(context, alias)\n await installSshConfig(context, alias)\n\n if (resolvedTargets.skippedNonInteractive) {\n printSkippedSshInstallTargets('ssh install')\n }\n\n for (const target of resolvedTargets.targets) {\n await installSshInstallTarget(context, alias, target)\n }\n\n return 0\n }\n\n if (parsed.command === 'ssh-uninstall') {\n uninstallSshConfig(alias)\n const entry = codexProjectEntryForWorkspace(context, alias)\n const legacyRemotePath = legacyCodexRemotePathForWorkspace(context)\n const result = uninstallCodexAppConfigProject(entry, {\n additionalRemotePaths: [legacyRemotePath]\n })\n\n process.stdout.write(`\\nCodex app config: ${result.configPath}\\n`)\n process.stdout.write(result.changed\n ? `Removed Codex remote project: ${entry.label} (${entry.remotePath})\\n`\n : `Codex remote project not installed: ${entry.label} (${entry.remotePath})\\n`)\n\n if (result.backupPath !== undefined) {\n process.stdout.write(`Codex app config backup: ${result.backupPath}\\n`)\n }\n\n const stateResult = uninstallCodexGlobalStateProject(entry, {\n additionalRemotePaths: [legacyRemotePath]\n })\n\n process.stdout.write(`\\nCodex app state: ${stateResult.statePath}\\n`)\n process.stdout.write(stateResult.changed\n ? `Removed Codex sidebar state: ${entry.label} (${entry.remotePath})\\n`\n : `Codex sidebar state not installed: ${entry.label} (${entry.remotePath})\\n`)\n\n if (stateResult.backupPath !== undefined) {\n process.stdout.write(`Codex app state backup: ${stateResult.backupPath}\\n`)\n }\n\n const claudeEntry = claudeSshConfigEntryForWorkspace(context, alias)\n const claudeResult = uninstallClaudeSshConfigHost(claudeEntry)\n\n process.stdout.write(`\\nClaude SSH config: ${claudeResult.configPath}\\n`)\n process.stdout.write(claudeResult.changed\n ? `Removed Claude SSH remote: ${claudeEntry.name} (${claudeEntry.sshHost})\\n`\n : `Claude SSH remote not installed: ${claudeEntry.name} (${claudeEntry.sshHost})\\n`)\n\n if (claudeResult.backupPath !== undefined) {\n process.stdout.write(`Claude SSH config backup: ${claudeResult.backupPath}\\n`)\n }\n\n process.stdout.write('Restart Codex and Claude to apply the remote project removal.\\n')\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 return runLoggedLifecycle(context, 'stop', argv, async (logger) => {\n await stopWorkspaceContainer(context, { logger })\n return 0\n })\n }\n\n if (parsed.command === 'doctor') {\n const checks = await (options.runDoctorChecks ?? runDoctorChecks)(context)\n process.stdout.write(formatDoctorText(checks))\n return doctorHasFailures(checks) ? 1 : 0\n }\n\n if (parsed.command === 'setup') {\n await runSetupPreflight(context, alias, parsed, options)\n const resolvedTargets = await resolveSshInstallTargets(parsed, options)\n\n if (resolvedTargets.cancelled) {\n process.stderr.write('Canceled setup.\\n')\n return 1\n }\n\n writeWorkspaceMetadata(context, alias)\n const progress = createCliProgress(parsed, 'stdout', { env: options.env })\n await runLoggedLifecycle(context, 'setup', argv, async (logger) => {\n await withProgressSection(progress, 'Boxdown setup', [\n `Workspace: ${context.workspaceFolder}`,\n `SSH alias: ${alias}`\n ], async () => {\n progress.setSteps(setupProgressSteps(resolvedTargets.targets))\n await (options.setupWorkspace ?? setupWorkspace)(context, alias, {\n recreate: parsed.recreate,\n targets: resolvedTargets.targets,\n progress,\n logger\n })\n })\n })\n\n if (resolvedTargets.skippedNonInteractive) {\n printSkippedSshInstallTargets('setup')\n }\n\n return 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 return runLoggedLifecycle(context, 'ssh-proxy', argv, async (logger) => {\n const progress = createCliProgress(parsed, 'stderr', { env: options.env })\n const containerId = await withProgressSection(progress, 'Boxdown SSH proxy', [\n `Workspace: ${context.workspaceFolder}`,\n `SSH alias: ${alias}`\n ], async () => {\n progress.setSteps(sshProxyProgressSteps())\n progress.startStep('ssh-alias')\n try {\n await installSshConfig(context, alias, { quiet: true })\n progress.completeStep('ssh-alias')\n } catch (error) {\n progress.failStep('ssh-alias')\n throw error\n }\n const startedContainerId = await startDevcontainer(context, {\n recreate: parsed.recreate,\n proxyMode: true,\n progress,\n logger,\n reuseRunning: true\n })\n await refreshContainerCodingAgentClis(context, true, [], { progress, logger })\n await ensureContainerSshRuntime(context, { progress, logger })\n return startedContainerId\n })\n return runSshdProxy(containerId, { logger })\n })\n }\n\n if (parsed.command === 'tunnel') {\n const resolvedTunnelPorts = await resolveTunnelPorts(parsed, context, options)\n\n if (resolvedTunnelPorts.cancelled) {\n process.stderr.write('Canceled tunnel.\\n')\n return 1\n }\n\n const tunnelPorts = resolvedTunnelPorts.tunnelPorts\n if (tunnelPorts.length === 0) {\n throw new Error('tunnel requires at least one --port value')\n }\n\n writeWorkspaceMetadata(context, alias)\n return runLoggedLifecycle(context, 'tunnel', argv, async (logger) => {\n const progress = createCliProgress(parsed, 'stdout', { env: options.env })\n await withProgressSection(progress, 'Boxdown tunnel', [\n `Workspace: ${context.workspaceFolder}`,\n `SSH alias: ${alias}`\n ], async () => {\n progress.setSteps(tunnelProgressSteps())\n progress.startStep('ssh-alias')\n try {\n await installSshConfig(context, alias, { quiet: true })\n progress.completeStep('ssh-alias')\n } catch (error) {\n progress.failStep('ssh-alias')\n throw error\n }\n await startDevcontainer(context, {\n recreate: parsed.recreate,\n progress,\n logger,\n reuseRunning: true\n })\n })\n\n const forwards = tunnelPorts\n .map((port) => `127.0.0.1:${port.localPort} -> localhost:${port.remotePort}`)\n .join(', ')\n\n process.stdout.write(`Forwarding ${forwards}\\n`)\n process.stdout.write('Press Ctrl-C to stop the tunnel.\\n')\n\n return openSshTunnel(alias, tunnelPorts, { logger })\n })\n }\n\n if (parsed.command === 'refresh-gh-token-running') {\n return runLoggedLifecycle(context, 'refresh-gh-token-running', argv, async (logger) => {\n const containerId = await findRunningContainerId(context, { logger })\n if (containerId === undefined) {\n throw new Error(`No running devcontainer found for: ${context.workspaceFolder}`)\n }\n const progress = createCliProgress(parsed, 'stdout', { env: options.env })\n await withProgressSection(progress, 'Boxdown GitHub auth refresh', [\n `Workspace: ${context.workspaceFolder}`\n ], async () => {\n progress.setSteps(ghAuthProgressSteps(false))\n progress.startStep('devcontainer-running')\n progress.completeStep('devcontainer-running')\n await refreshContainerGhAuth(context, { progress, logger })\n })\n return 0\n })\n }\n\n if (parsed.command === 'refresh-gh-token') {\n return runLoggedLifecycle(context, 'refresh-gh-token', argv, async (logger) => {\n const progress = createCliProgress(parsed, 'stdout', { env: options.env })\n await withProgressSection(progress, 'Boxdown GitHub auth refresh', [\n `Workspace: ${context.workspaceFolder}`\n ], async () => {\n progress.setSteps(ghAuthProgressSteps(true))\n await startDevcontainer(context, { progress, logger })\n await refreshContainerGhAuth(context, { progress, logger })\n })\n return 0\n })\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 return runLoggedLifecycle(context, agent, argv, async (logger) => {\n const progress = createCliProgress(parsed, 'stdout', { env: options.env })\n await withProgressSection(progress, `Boxdown ${agent}`, [\n `Workspace: ${context.workspaceFolder}`\n ], async () => {\n progress.setSteps(codingAgentProgressSteps(agent))\n await startDevcontainer(context, {\n recreate: parsed.recreate,\n progress,\n logger\n })\n await ensureContainerCodingAgentCli(context, agent, { progress, logger })\n })\n return openCodingAgentCli(context, agent, parsed.agentArgs ?? [], { logger })\n })\n }\n\n return runLoggedLifecycle(context, 'start', argv, async (logger) => {\n const progress = createCliProgress(parsed, 'stdout', { env: options.env })\n const containerId = await withProgressSection(progress, 'Boxdown start', [\n `Workspace: ${context.workspaceFolder}`\n ], async () => {\n progress.setSteps(startProgressSteps())\n return await startDevcontainer(context, {\n recreate: parsed.recreate,\n progress,\n logger\n })\n })\n await printPortHint(context, containerId, { logger })\n return openShell(context, { logger })\n })\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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"}