@willjackson/claude-code-bridge 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/index.ts","../src/cli/commands/start.ts","../src/cli/utils.ts","../src/cli/commands/stop.ts","../src/cli/commands/status.ts","../src/cli/commands/connect.ts","../src/cli/commands/discover.ts","../src/cli/commands/info.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry point for claude-code-bridge\n *\n * Commands:\n * start Start the bridge server\n * stop Stop the running bridge\n * status Show bridge status and connected peers\n * connect Connect to a remote bridge\n * discover Discover bridges on local network\n * info Show environment and configuration info\n *\n * Global options:\n * --verbose, -v Enable verbose logging\n * --config Path to config file\n */\n\nimport { Command } from 'commander';\nimport { createLogger } from '../utils/logger.js';\nimport { createStartCommand } from './commands/start.js';\nimport { createStopCommand } from './commands/stop.js';\nimport { createStatusCommand } from './commands/status.js';\nimport { createConnectCommand } from './commands/connect.js';\nimport { createDiscoverCommand } from './commands/discover.js';\nimport { createInfoCommand } from './commands/info.js';\n\n// Read version from package.json\n// Since we're building with tsup, we import it directly\nconst VERSION = '0.1.0';\n\nconst logger = createLogger('cli');\n\n/**\n * Global options interface\n */\nexport interface GlobalOptions {\n verbose?: boolean;\n config?: string;\n}\n\n/**\n * Create and configure the CLI program\n */\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name('claude-bridge')\n .description('Bidirectional communication system for Claude Code instances across environments')\n .version(VERSION, '-V, --version', 'Output the version number')\n .option('-v, --verbose', 'Enable verbose logging')\n .option('--config <path>', 'Path to config file');\n\n // Hook to process global options before commands\n program.hook('preAction', (thisCommand) => {\n const opts = thisCommand.opts() as GlobalOptions;\n if (opts.verbose) {\n // Set log level to debug when verbose is enabled\n process.env.LOG_LEVEL = 'debug';\n }\n });\n\n return program;\n}\n\n/**\n * Get global options from the program\n */\nexport function getGlobalOptions(program: Command): GlobalOptions {\n return program.opts() as GlobalOptions;\n}\n\n/**\n * Main CLI entry point\n */\nexport async function main(): Promise<void> {\n const program = createProgram();\n\n // Add commands\n program.addCommand(createStartCommand());\n program.addCommand(createStopCommand());\n program.addCommand(createStatusCommand());\n program.addCommand(createConnectCommand());\n program.addCommand(createDiscoverCommand());\n program.addCommand(createInfoCommand());\n\n // Parse arguments and execute\n await program.parseAsync(process.argv);\n}\n\n// Run CLI if executed directly\nmain().catch((error: Error) => {\n logger.error({ err: error }, 'CLI error');\n process.exit(1);\n});\n\n// Export for programmatic use\nexport { createProgram as createCLI };\n","/**\n * CLI start command - Start the bridge server\n *\n * Options:\n * --port, -p Port to listen on (default: 8765 in container, 8766 native)\n * --host, -h Host to bind to (default: 0.0.0.0)\n * --connect, -c URL to connect to on startup\n * --auto, -a Auto-detect environment and configure\n * --daemon, -d Run in background\n * --with-handlers Enable file reading and task handling capabilities\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { minimatch } from 'minimatch';\nimport { createLogger } from '../../utils/logger.js';\nimport { loadConfigSync, type BridgeConfig as UtilsBridgeConfig } from '../../utils/config.js';\nimport { Bridge, type BridgeConfig, type BridgeMode, type TaskRequest, type FileChunk } from '../../bridge/core.js';\nimport { detectEnvironment, getDefaultConfig } from '../../environment/detect.js';\nimport { setupGracefulShutdown, handleUnhandledRejections } from '../utils.js';\nimport type { GlobalOptions } from '../index.js';\n\nconst logger = createLogger('cli:start');\n\n/**\n * Options for the start command\n */\nexport interface StartCommandOptions {\n port?: string;\n host?: string;\n connect?: string;\n auto?: boolean;\n daemon?: boolean;\n withHandlers?: boolean;\n}\n\n/**\n * Get the PID file path\n */\nfunction getPidFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'bridge.pid');\n}\n\n/**\n * Ensure the .claude-bridge directory exists\n */\nfunction ensureBridgeDir(): void {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n if (!fs.existsSync(bridgeDir)) {\n fs.mkdirSync(bridgeDir, { recursive: true });\n }\n}\n\n/**\n * Write PID file for daemon mode\n */\nfunction writePidFile(pid: number): void {\n ensureBridgeDir();\n const pidFile = getPidFilePath();\n fs.writeFileSync(pidFile, pid.toString(), 'utf-8');\n}\n\n/**\n * Remove PID file on shutdown\n */\nfunction removePidFile(): void {\n const pidFile = getPidFilePath();\n if (fs.existsSync(pidFile)) {\n fs.unlinkSync(pidFile);\n }\n}\n\n/**\n * Check if a bridge is already running by checking the PID file\n */\nfunction isAlreadyRunning(): { running: boolean; pid?: number } {\n const pidFile = getPidFilePath();\n if (!fs.existsSync(pidFile)) {\n return { running: false };\n }\n\n try {\n const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);\n // Check if process is still running\n process.kill(pid, 0); // Signal 0 checks existence without killing\n return { running: true, pid };\n } catch {\n // Process doesn't exist, clean up stale PID file\n removePidFile();\n return { running: false };\n }\n}\n\n/**\n * Get all files in a directory recursively\n */\nfunction getFilesRecursively(dir: string, baseDir: string = dir): string[] {\n const files: string[] = [];\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = path.relative(baseDir, fullPath);\n\n if (entry.isDirectory()) {\n // Skip common directories\n if (['node_modules', '.git', 'dist', 'build', '.next', 'coverage'].includes(entry.name)) {\n continue;\n }\n files.push(...getFilesRecursively(fullPath, baseDir));\n } else if (entry.isFile()) {\n files.push(relativePath);\n }\n }\n } catch {\n // Ignore permission errors\n }\n\n return files;\n}\n\n/**\n * Check if a file matches any of the patterns\n */\nfunction matchesPatterns(filePath: string, patterns: string[]): boolean {\n return patterns.some(pattern => minimatch(filePath, pattern, { dot: true }));\n}\n\n/**\n * Read file contents safely\n */\nfunction readFileSafe(filePath: string, maxSize: number = 100000): string | null {\n try {\n const stats = fs.statSync(filePath);\n if (stats.size > maxSize) {\n return `[File too large: ${stats.size} bytes]`;\n }\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n}\n\n/**\n * Register handlers for file reading and task processing\n */\nfunction registerHandlers(\n bridge: Bridge,\n config: { includePatterns: string[]; excludePatterns: string[] }\n): void {\n const cwd = process.cwd();\n\n // Handler for context requests - find and return relevant files\n bridge.onContextRequested(async (query: string, peerId: string): Promise<FileChunk[]> => {\n logger.info({ query, peerId }, 'Context requested');\n\n const files = getFilesRecursively(cwd);\n const chunks: FileChunk[] = [];\n const queryLower = query.toLowerCase();\n const queryTerms = queryLower.split(/\\s+/).filter(t => t.length > 2);\n\n for (const file of files) {\n // Check exclude patterns\n if (matchesPatterns(file, config.excludePatterns)) {\n continue;\n }\n\n // Check if file matches query or include patterns\n const fileLower = file.toLowerCase();\n const matchesQuery = queryTerms.some(term => fileLower.includes(term));\n const matchesInclude = matchesPatterns(file, config.includePatterns);\n\n if (matchesQuery || matchesInclude) {\n const fullPath = path.join(cwd, file);\n const content = readFileSafe(fullPath);\n\n if (content !== null) {\n chunks.push({\n path: file,\n content,\n language: path.extname(file).slice(1) || undefined,\n });\n }\n\n // Limit number of files returned\n if (chunks.length >= 20) {\n break;\n }\n }\n }\n\n logger.info({ fileCount: chunks.length, query }, 'Context response prepared');\n return chunks;\n });\n\n // Handler for incoming tasks\n bridge.onTaskReceived(async (task: TaskRequest, peerId: string) => {\n logger.info({ taskId: task.id, description: task.description, peerId }, 'Task received');\n\n // Get project info for the response\n const projectInfo: Record<string, unknown> = {\n cwd,\n platform: process.platform,\n nodeVersion: process.version,\n };\n\n // Try to read package.json for project details\n const pkgPath = path.join(cwd, 'package.json');\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));\n projectInfo.name = pkg.name;\n projectInfo.version = pkg.version;\n projectInfo.description = pkg.description;\n projectInfo.dependencies = Object.keys(pkg.dependencies || {});\n projectInfo.devDependencies = Object.keys(pkg.devDependencies || {});\n } catch {\n // Ignore parse errors\n }\n }\n\n // List top-level files and directories\n try {\n const entries = fs.readdirSync(cwd, { withFileTypes: true });\n projectInfo.structure = entries\n .filter(e => !e.name.startsWith('.') && e.name !== 'node_modules')\n .map(e => ({\n name: e.name,\n type: e.isDirectory() ? 'directory' : 'file',\n }));\n } catch {\n // Ignore errors\n }\n\n // Get source files summary\n const allFiles = getFilesRecursively(cwd);\n const sourceFiles = allFiles.filter(f =>\n matchesPatterns(f, config.includePatterns) &&\n !matchesPatterns(f, config.excludePatterns)\n );\n projectInfo.sourceFileCount = sourceFiles.length;\n projectInfo.sourceFiles = sourceFiles.slice(0, 50); // First 50 files\n\n return {\n success: true,\n data: {\n message: `Task received and analyzed: ${task.description}`,\n scope: task.scope,\n projectInfo,\n },\n };\n });\n\n // Handler for incoming context sync\n bridge.onContextReceived((context, peerId) => {\n logger.info(\n {\n peerId,\n fileCount: context.files?.length || 0,\n summary: context.summary\n },\n 'Context received from peer'\n );\n\n if (context.files) {\n for (const file of context.files) {\n console.log(` 📄 Received: ${file.path} (${file.content?.length || 0} chars)`);\n }\n }\n if (context.summary) {\n console.log(` 📝 Summary: ${context.summary}`);\n }\n });\n\n logger.info('Handlers registered for context requests, tasks, and context sync');\n console.log(' Handlers: enabled (file reading & task processing)');\n}\n\n/**\n * Build bridge configuration from CLI options and config file\n */\nfunction buildBridgeConfig(\n options: StartCommandOptions,\n globalOptions: GlobalOptions\n): BridgeConfig {\n // Load config file first\n const fileConfig = loadConfigSync(globalOptions.config);\n\n // Detect environment if --auto is specified\n let envConfig: Partial<BridgeConfig> = {};\n if (options.auto) {\n const env = detectEnvironment();\n const defaultEnvConfig = getDefaultConfig(env);\n logger.info({ environment: env.type, isContainer: env.isContainer }, 'Auto-detected environment');\n\n // Map the environment defaults to BridgeConfig format\n envConfig = {\n mode: defaultEnvConfig.mode as BridgeMode,\n instanceName: defaultEnvConfig.instanceName,\n listen: defaultEnvConfig.listen,\n connect: defaultEnvConfig.connect,\n };\n }\n\n // CLI options override everything\n const cliConfig: Partial<BridgeConfig> = {};\n\n if (options.port) {\n cliConfig.listen = {\n ...cliConfig.listen,\n port: parseInt(options.port, 10),\n host: options.host ?? '0.0.0.0',\n };\n }\n\n if (options.host && !cliConfig.listen) {\n cliConfig.listen = {\n port: fileConfig.listen.port,\n host: options.host,\n };\n }\n\n if (options.connect) {\n cliConfig.connect = {\n url: options.connect,\n };\n }\n\n // Determine mode based on configuration\n let mode: BridgeMode = 'peer';\n const hasListen = cliConfig.listen || envConfig.listen || fileConfig.listen;\n const hasConnect = cliConfig.connect || envConfig.connect || fileConfig.connect;\n\n if (hasListen && !hasConnect) {\n mode = 'host';\n } else if (hasConnect && !hasListen) {\n mode = 'client';\n }\n\n // Build final config with priority: CLI > env auto-detect > file config > defaults\n const finalConfig: BridgeConfig = {\n mode: cliConfig.mode ?? envConfig.mode ?? fileConfig.mode ?? mode,\n instanceName:\n cliConfig.instanceName ??\n envConfig.instanceName ??\n fileConfig.instanceName ??\n `bridge-${process.pid}`,\n listen: {\n port: cliConfig.listen?.port ?? envConfig.listen?.port ?? fileConfig.listen.port,\n host: cliConfig.listen?.host ?? envConfig.listen?.host ?? fileConfig.listen.host,\n },\n taskTimeout: fileConfig.interaction.taskTimeout,\n contextSharing: {\n autoSync: fileConfig.contextSharing.autoSync,\n syncInterval: fileConfig.contextSharing.syncInterval,\n },\n };\n\n // Add connect config if present\n const connectUrl = cliConfig.connect?.url ?? envConfig.connect?.url ?? fileConfig.connect?.url;\n if (connectUrl) {\n finalConfig.connect = {\n url: connectUrl,\n };\n }\n\n return finalConfig;\n}\n\n/**\n * Start the bridge server\n */\nasync function startBridge(\n options: StartCommandOptions,\n globalOptions: GlobalOptions\n): Promise<void> {\n // Check if already running\n const { running, pid } = isAlreadyRunning();\n if (running) {\n console.error(`Bridge is already running (PID: ${pid})`);\n process.exit(1);\n }\n\n // Build configuration\n const config = buildBridgeConfig(options, globalOptions);\n\n // Log startup info\n console.log('Starting Claude Code Bridge...');\n console.log(` Instance: ${config.instanceName}`);\n console.log(` Mode: ${config.mode}`);\n\n if (config.listen) {\n console.log(` Listening: ${config.listen.host}:${config.listen.port}`);\n }\n\n if (config.connect) {\n console.log(` Connecting to: ${config.connect.url}`);\n }\n\n // Handle daemon mode\n if (options.daemon) {\n // For daemon mode, we would fork the process\n // For now, just write PID and continue (simplified implementation)\n console.log(' Running in daemon mode');\n writePidFile(process.pid);\n }\n\n // Create and start bridge\n const bridge = new Bridge(config);\n\n // Set up graceful shutdown handling\n setupGracefulShutdown({\n cleanup: async () => {\n logger.info('Stopping bridge...');\n await bridge.stop();\n logger.info('Bridge stopped');\n },\n afterCleanup: options.daemon ? removePidFile : undefined,\n verbose: true,\n timeout: 10000,\n });\n\n // Handle unhandled promise rejections\n handleUnhandledRejections({\n exit: false,\n logger: (msg, err) => logger.error({ error: err.message }, msg),\n });\n\n // Load config for handler patterns\n const fileConfig = loadConfigSync(globalOptions.config);\n\n try {\n await bridge.start();\n\n // Register handlers if --with-handlers is enabled\n if (options.withHandlers) {\n registerHandlers(bridge, {\n includePatterns: fileConfig.contextSharing.includePatterns,\n excludePatterns: fileConfig.contextSharing.excludePatterns,\n });\n }\n\n // Write PID file if running in daemon mode\n if (options.daemon) {\n writePidFile(process.pid);\n }\n\n console.log('Bridge started successfully.');\n console.log(`Connected peers: ${bridge.getPeerCount()}`);\n\n // Log connection info for users\n if (config.listen) {\n console.log(`\\nTo connect from another bridge:`);\n console.log(` claude-bridge connect ws://localhost:${config.listen.port}`);\n }\n\n // Keep the process running\n if (!options.daemon) {\n console.log('\\nPress Ctrl+C to stop.');\n }\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to start bridge');\n console.error(`Failed to start bridge: ${(error as Error).message}`);\n if (options.daemon) {\n removePidFile();\n }\n process.exit(1);\n }\n}\n\n/**\n * Create the start command\n */\nexport function createStartCommand(): Command {\n const command = new Command('start');\n\n command\n .description('Start the bridge server')\n .option('-p, --port <port>', 'Port to listen on (default: 8765 in container, 8766 native)')\n .option('-h, --host <host>', 'Host to bind to (default: 0.0.0.0)')\n .option('-c, --connect <url>', 'URL to connect to on startup (e.g., ws://localhost:8765)')\n .option('-a, --auto', 'Auto-detect environment and configure')\n .option('-d, --daemon', 'Run in background')\n .option('--with-handlers', 'Enable file reading and task handling capabilities')\n .action(async (options: StartCommandOptions) => {\n // Get global options from parent command\n const globalOptions = command.parent?.opts() as GlobalOptions;\n await startBridge(options, globalOptions);\n });\n\n return command;\n}\n\n/**\n * Export the command for use in CLI\n */\nexport { createStartCommand as startCommand };\n","/**\n * CLI output formatting utilities\n *\n * Provides helpers for colored output, table formatting, progress spinners,\n * and option parsing/validation.\n */\n\n/**\n * ANSI color codes for terminal output\n */\nexport const colors = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n\n // Foreground colors\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n gray: '\\x1b[90m',\n} as const;\n\n/**\n * Check if terminal supports colors\n */\nexport function supportsColor(): boolean {\n // Disable colors if NO_COLOR env var is set\n if (process.env.NO_COLOR !== undefined) {\n return false;\n }\n\n // Enable colors if FORCE_COLOR is set\n if (process.env.FORCE_COLOR !== undefined) {\n return true;\n }\n\n // Check if stdout is a TTY\n if (typeof process.stdout.isTTY !== 'undefined' && process.stdout.isTTY) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Apply color to text (only if terminal supports it)\n */\nexport function colorize(text: string, color: keyof typeof colors): string {\n if (!supportsColor()) {\n return text;\n }\n return `${colors[color]}${text}${colors.reset}`;\n}\n\n/**\n * Print success message (green)\n */\nexport function success(message: string): void {\n console.log(colorize('✓ ' + message, 'green'));\n}\n\n/**\n * Print error message (red)\n */\nexport function error(message: string): void {\n console.error(colorize('✗ ' + message, 'red'));\n}\n\n/**\n * Print warning message (yellow)\n */\nexport function warning(message: string): void {\n console.log(colorize('⚠ ' + message, 'yellow'));\n}\n\n/**\n * Print info message (blue)\n */\nexport function info(message: string): void {\n console.log(colorize('ℹ ' + message, 'blue'));\n}\n\n/**\n * Print debug message (gray)\n */\nexport function debug(message: string): void {\n console.log(colorize('⋯ ' + message, 'gray'));\n}\n\n/**\n * Table column configuration\n */\nexport interface TableColumn {\n title: string;\n width: number;\n align?: 'left' | 'right' | 'center';\n}\n\n/**\n * Table row data (key-value pairs matching column titles)\n */\nexport type TableRow = Record<string, string | number | undefined>;\n\n/**\n * Pad a string to a specific width with alignment\n */\nexport function padToWidth(\n text: string,\n width: number,\n align: 'left' | 'right' | 'center' = 'left'\n): string {\n const str = String(text).slice(0, width);\n const padding = width - str.length;\n\n if (align === 'right') {\n return ' '.repeat(padding) + str;\n } else if (align === 'center') {\n const leftPad = Math.floor(padding / 2);\n const rightPad = padding - leftPad;\n return ' '.repeat(leftPad) + str + ' '.repeat(rightPad);\n } else {\n return str + ' '.repeat(padding);\n }\n}\n\n/**\n * Print a formatted table\n */\nexport function printTable(\n columns: TableColumn[],\n rows: TableRow[],\n options: { indent?: number; borderStyle?: 'simple' | 'none' } = {}\n): void {\n const indent = ' '.repeat(options.indent ?? 0);\n const borderStyle = options.borderStyle ?? 'simple';\n\n // Print header\n const headerRow = columns\n .map((col) => padToWidth(col.title, col.width, col.align))\n .join(' ');\n console.log(indent + colorize(headerRow, 'bold'));\n\n // Print separator\n if (borderStyle === 'simple') {\n const separator = columns\n .map((col) => '-'.repeat(col.width))\n .join(' ');\n console.log(indent + separator);\n }\n\n // Print rows\n for (const row of rows) {\n const rowText = columns\n .map((col) => {\n // Find matching key case-insensitively\n const key = Object.keys(row).find(\n (k) => k.toLowerCase() === col.title.toLowerCase()\n );\n const value = key ? String(row[key] ?? '') : '';\n return padToWidth(value, col.width, col.align);\n })\n .join(' ');\n console.log(indent + rowText);\n }\n}\n\n/**\n * Spinner frames for progress indication\n */\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\n/**\n * Progress spinner for long operations\n */\nexport class Spinner {\n private message: string;\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private frameIndex = 0;\n private stream = process.stdout;\n\n constructor(message: string) {\n this.message = message;\n }\n\n /**\n * Start the spinner animation\n */\n start(): void {\n if (!supportsColor() || !this.stream.isTTY) {\n // Non-TTY: just print the message once\n console.log(`... ${this.message}`);\n return;\n }\n\n // Hide cursor\n this.stream.write('\\x1b[?25l');\n\n this.intervalId = setInterval(() => {\n const frame = SPINNER_FRAMES[this.frameIndex];\n this.stream.write(\n `\\r${colorize(frame, 'cyan')} ${this.message}`\n );\n this.frameIndex = (this.frameIndex + 1) % SPINNER_FRAMES.length;\n }, 80);\n }\n\n /**\n * Update the spinner message\n */\n update(message: string): void {\n this.message = message;\n }\n\n /**\n * Stop the spinner with a success message\n */\n succeed(message?: string): void {\n this.stop();\n success(message ?? this.message);\n }\n\n /**\n * Stop the spinner with an error message\n */\n fail(message?: string): void {\n this.stop();\n error(message ?? this.message);\n }\n\n /**\n * Stop the spinner with a warning message\n */\n warn(message?: string): void {\n this.stop();\n warning(message ?? this.message);\n }\n\n /**\n * Stop the spinner (no message)\n */\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n\n if (supportsColor() && this.stream.isTTY) {\n // Clear line and show cursor\n this.stream.write('\\r\\x1b[K');\n this.stream.write('\\x1b[?25h');\n }\n }\n}\n\n/**\n * Create and start a new spinner\n */\nexport function spinner(message: string): Spinner {\n const s = new Spinner(message);\n s.start();\n return s;\n}\n\n/**\n * Parsed start command options\n */\nexport interface ParsedStartOptions {\n listen?: {\n port: number;\n host: string;\n };\n connect?: {\n url: string;\n };\n autoDetect: boolean;\n daemon: boolean;\n}\n\n/**\n * Parse and validate start command options\n */\nexport function parseStartOptions(options: {\n port?: string;\n host?: string;\n connect?: string;\n auto?: boolean;\n daemon?: boolean;\n}): ParsedStartOptions {\n const result: ParsedStartOptions = {\n autoDetect: options.auto ?? false,\n daemon: options.daemon ?? false,\n };\n\n // Parse port\n if (options.port) {\n const port = parseInt(options.port, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n throw new Error(`Invalid port: ${options.port}. Must be between 1 and 65535.`);\n }\n result.listen = {\n port,\n host: options.host ?? '0.0.0.0',\n };\n } else if (options.host) {\n // Host specified without port, use default port\n result.listen = {\n port: 8765,\n host: options.host,\n };\n }\n\n // Parse connect URL\n if (options.connect) {\n validateWebSocketUrl(options.connect);\n result.connect = {\n url: options.connect,\n };\n }\n\n return result;\n}\n\n/**\n * Validate a WebSocket URL\n */\nexport function validateWebSocketUrl(url: string): void {\n if (!url.startsWith('ws://') && !url.startsWith('wss://')) {\n throw new Error(\n `Invalid URL protocol. Expected ws:// or wss://, got: ${url}`\n );\n }\n\n try {\n const parsed = new URL(url);\n if (!parsed.hostname) {\n throw new Error('URL must include a hostname');\n }\n } catch (e) {\n if (e instanceof Error && e.message.includes('Invalid URL')) {\n throw new Error(`Invalid URL format: ${url}`);\n }\n throw e;\n }\n}\n\n/**\n * Parsed connect command options\n */\nexport interface ParsedConnectOptions {\n url: string;\n}\n\n/**\n * Parse and validate connect command options\n */\nexport function parseConnectOptions(options: {\n url?: string;\n}): ParsedConnectOptions {\n if (!options.url) {\n throw new Error('URL is required');\n }\n\n validateWebSocketUrl(options.url);\n\n return {\n url: options.url,\n };\n}\n\n/**\n * Format duration in human-readable form\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n if (ms < 60000) {\n return `${(ms / 1000).toFixed(1)}s`;\n }\n if (ms < 3600000) {\n const minutes = Math.floor(ms / 60000);\n const seconds = Math.round((ms % 60000) / 1000);\n return `${minutes}m ${seconds}s`;\n }\n const hours = Math.floor(ms / 3600000);\n const minutes = Math.round((ms % 3600000) / 60000);\n return `${hours}h ${minutes}m`;\n}\n\n/**\n * Format bytes in human-readable form\n */\nexport function formatBytes(bytes: number): string {\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n let unitIndex = 0;\n let value = bytes;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex++;\n }\n\n return `${value.toFixed(unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`;\n}\n\n/**\n * Shutdown handler type\n */\nexport type ShutdownHandler = (signal: string) => Promise<void>;\n\n/**\n * Options for setting up graceful shutdown\n */\nexport interface GracefulShutdownOptions {\n /**\n * Cleanup function to call on shutdown\n */\n cleanup: () => Promise<void>;\n\n /**\n * Additional cleanup to call after main cleanup (e.g., removing PID file)\n */\n afterCleanup?: () => void;\n\n /**\n * Whether to show shutdown messages\n * @default true\n */\n verbose?: boolean;\n\n /**\n * Timeout in milliseconds before forcing exit\n * @default 10000\n */\n timeout?: number;\n}\n\n/**\n * Set up graceful shutdown handlers for SIGTERM and SIGINT\n *\n * Handles process signals to ensure clean shutdown of bridges and connections.\n * - SIGTERM: Sent by `kill` command or process managers\n * - SIGINT: Sent by Ctrl+C in terminal\n *\n * @param options Shutdown configuration options\n * @returns Function to remove the handlers (for testing)\n */\nexport function setupGracefulShutdown(options: GracefulShutdownOptions): () => void {\n const {\n cleanup,\n afterCleanup,\n verbose = true,\n timeout = 10000,\n } = options;\n\n let isShuttingDown = false;\n\n const handler: ShutdownHandler = async (signal: string) => {\n // Prevent multiple shutdown attempts\n if (isShuttingDown) {\n if (verbose) {\n console.log('Shutdown already in progress...');\n }\n return;\n }\n isShuttingDown = true;\n\n if (verbose) {\n console.log(`\\nReceived ${signal}, shutting down gracefully...`);\n }\n\n // Set up force exit timeout\n const forceExitTimeout = setTimeout(() => {\n if (verbose) {\n console.error('Shutdown timeout - forcing exit');\n }\n process.exit(1);\n }, timeout);\n\n try {\n await cleanup();\n\n if (afterCleanup) {\n afterCleanup();\n }\n\n clearTimeout(forceExitTimeout);\n\n if (verbose) {\n console.log('Shutdown complete.');\n }\n process.exit(0);\n } catch (error) {\n clearTimeout(forceExitTimeout);\n if (verbose) {\n console.error(`Error during shutdown: ${(error as Error).message}`);\n }\n process.exit(1);\n }\n };\n\n // Register handlers\n const sigintHandler = () => handler('SIGINT');\n const sigtermHandler = () => handler('SIGTERM');\n\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n // Return cleanup function\n return () => {\n process.off('SIGINT', sigintHandler);\n process.off('SIGTERM', sigtermHandler);\n };\n}\n\n/**\n * Handle unhandled promise rejections\n *\n * Logs unhandled rejections and optionally exits the process.\n *\n * @param options Configuration options\n */\nexport function handleUnhandledRejections(options: {\n exit?: boolean;\n logger?: (message: string, error: Error) => void;\n} = {}): void {\n const { exit = false, logger = console.error } = options;\n\n process.on('unhandledRejection', (reason, promise) => {\n const error = reason instanceof Error ? reason : new Error(String(reason));\n logger('Unhandled promise rejection:', error);\n\n if (exit) {\n process.exit(1);\n }\n });\n}\n","/**\n * CLI stop command - Stop the running bridge\n *\n * Reads the PID from ~/.claude-bridge/bridge.pid and sends SIGTERM\n * to gracefully stop the running bridge process.\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { createLogger } from '../../utils/logger.js';\n\nconst logger = createLogger('cli:stop');\n\n/**\n * Get the PID file path\n */\nfunction getPidFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'bridge.pid');\n}\n\n/**\n * Remove PID file\n */\nfunction removePidFile(): void {\n const pidFile = getPidFilePath();\n if (fs.existsSync(pidFile)) {\n fs.unlinkSync(pidFile);\n }\n}\n\n/**\n * Read PID from file\n * Returns null if file doesn't exist or is invalid\n */\nfunction readPidFile(): number | null {\n const pidFile = getPidFilePath();\n if (!fs.existsSync(pidFile)) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(pidFile, 'utf-8').trim();\n const pid = parseInt(content, 10);\n if (isNaN(pid) || pid <= 0) {\n logger.warn({ content }, 'Invalid PID file content');\n return null;\n }\n return pid;\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to read PID file');\n return null;\n }\n}\n\n/**\n * Check if a process is running\n */\nfunction isProcessRunning(pid: number): boolean {\n try {\n // Signal 0 checks if the process exists without sending a signal\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Wait for a process to exit with timeout\n */\nasync function waitForProcessExit(\n pid: number,\n timeoutMs: number = 5000\n): Promise<boolean> {\n const startTime = Date.now();\n const checkInterval = 100;\n\n while (Date.now() - startTime < timeoutMs) {\n if (!isProcessRunning(pid)) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, checkInterval));\n }\n\n return false;\n}\n\n/**\n * Stop the bridge process\n */\nasync function stopBridge(): Promise<void> {\n const pid = readPidFile();\n\n if (pid === null) {\n console.log('Bridge is not running (no PID file found).');\n return;\n }\n\n // Check if process is actually running\n if (!isProcessRunning(pid)) {\n console.log(`Bridge is not running (stale PID file, process ${pid} not found).`);\n // Clean up stale PID file\n removePidFile();\n return;\n }\n\n console.log(`Stopping bridge (PID: ${pid})...`);\n\n try {\n // Send SIGTERM for graceful shutdown\n process.kill(pid, 'SIGTERM');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ESRCH') {\n // Process doesn't exist\n console.log('Bridge process not found.');\n removePidFile();\n return;\n }\n if ((error as NodeJS.ErrnoException).code === 'EPERM') {\n console.error(`Permission denied: cannot stop bridge (PID: ${pid}).`);\n console.error('Try running with elevated privileges.');\n process.exit(1);\n }\n throw error;\n }\n\n // Wait for process to exit\n const exited = await waitForProcessExit(pid);\n\n if (exited) {\n console.log('Bridge stopped successfully.');\n // Clean up PID file if the process didn't do it\n removePidFile();\n } else {\n console.log('Bridge is still shutting down. Check status with: claude-bridge status');\n // Optionally could try SIGKILL here, but we'll leave that to the user\n console.log(`To force stop: kill -9 ${pid}`);\n }\n}\n\n/**\n * Create the stop command\n */\nexport function createStopCommand(): Command {\n const command = new Command('stop');\n\n command\n .description('Stop the running bridge')\n .action(async () => {\n try {\n await stopBridge();\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to stop bridge');\n console.error(`Failed to stop bridge: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createStopCommand as stopCommand };\n","/**\n * CLI status command - Show bridge status and connected peers\n *\n * Displays whether the bridge is running, what port it's on,\n * and lists connected peers in a formatted table.\n *\n * Options:\n * --port Check status for a specific port\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { createLogger } from '../../utils/logger.js';\n\nconst logger = createLogger('cli:status');\n\n/**\n * Options for the status command\n */\nexport interface StatusCommandOptions {\n port?: string;\n}\n\n/**\n * Bridge status information\n */\nexport interface BridgeStatus {\n running: boolean;\n pid?: number;\n port?: number;\n peers?: PeerStatus[];\n}\n\n/**\n * Peer status information\n */\nexport interface PeerStatus {\n id: string;\n name: string;\n connectedAt: string;\n lastActivity: string;\n}\n\n/**\n * Get the PID file path\n */\nfunction getPidFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'bridge.pid');\n}\n\n/**\n * Get the status file path (where bridge writes current status)\n */\nfunction getStatusFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'status.json');\n}\n\n/**\n * Read PID from file\n */\nfunction readPidFile(): number | null {\n const pidFile = getPidFilePath();\n if (!fs.existsSync(pidFile)) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(pidFile, 'utf-8').trim();\n const pid = parseInt(content, 10);\n if (isNaN(pid) || pid <= 0) {\n return null;\n }\n return pid;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a process is running\n */\nfunction isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read status file written by the bridge\n */\nfunction readStatusFile(): { port?: number; peers?: PeerStatus[] } | null {\n const statusFile = getStatusFilePath();\n if (!fs.existsSync(statusFile)) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(statusFile, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Format a date for display\n */\nfunction formatDate(dateStr: string): string {\n try {\n const date = new Date(dateStr);\n return date.toLocaleString();\n } catch {\n return dateStr;\n }\n}\n\n/**\n * Pad a string to a specific width\n */\nfunction padRight(str: string, width: number): string {\n return str.padEnd(width);\n}\n\n/**\n * Print peer table\n */\nfunction printPeerTable(peers: PeerStatus[]): void {\n if (peers.length === 0) {\n console.log(' No peers connected.');\n return;\n }\n\n // Column headers and widths\n const cols = {\n id: { title: 'ID', width: 38 },\n name: { title: 'Name', width: 20 },\n connected: { title: 'Connected', width: 22 },\n lastActivity: { title: 'Last Activity', width: 22 },\n };\n\n // Print header\n console.log('');\n console.log(\n ' ' +\n padRight(cols.id.title, cols.id.width) +\n padRight(cols.name.title, cols.name.width) +\n padRight(cols.connected.title, cols.connected.width) +\n padRight(cols.lastActivity.title, cols.lastActivity.width)\n );\n\n // Print separator\n const separator =\n ' ' +\n '-'.repeat(cols.id.width - 1) +\n ' ' +\n '-'.repeat(cols.name.width - 1) +\n ' ' +\n '-'.repeat(cols.connected.width - 1) +\n ' ' +\n '-'.repeat(cols.lastActivity.width - 1);\n console.log(separator);\n\n // Print rows\n for (const peer of peers) {\n const row =\n ' ' +\n padRight(peer.id, cols.id.width) +\n padRight(peer.name.slice(0, cols.name.width - 1), cols.name.width) +\n padRight(formatDate(peer.connectedAt), cols.connected.width) +\n padRight(formatDate(peer.lastActivity), cols.lastActivity.width);\n console.log(row);\n }\n\n console.log('');\n}\n\n/**\n * Get bridge status\n */\nfunction getBridgeStatus(): BridgeStatus {\n const pid = readPidFile();\n\n if (pid === null) {\n return { running: false };\n }\n\n if (!isProcessRunning(pid)) {\n // PID file exists but process is not running\n return { running: false };\n }\n\n // Process is running, try to get more details\n const statusInfo = readStatusFile();\n\n return {\n running: true,\n pid,\n port: statusInfo?.port,\n peers: statusInfo?.peers,\n };\n}\n\n/**\n * Show bridge status\n */\nfunction showStatus(options: StatusCommandOptions): void {\n console.log('Claude Code Bridge Status');\n console.log('='.repeat(26));\n console.log('');\n\n const status = getBridgeStatus();\n\n if (!status.running) {\n console.log('Status: stopped');\n console.log('');\n console.log('To start the bridge:');\n console.log(' claude-bridge start');\n return;\n }\n\n console.log('Status: running');\n console.log(`PID: ${status.pid}`);\n\n if (status.port !== undefined) {\n console.log(`Port: ${status.port}`);\n }\n\n console.log('');\n console.log('Connected Peers:');\n\n if (status.peers) {\n printPeerTable(status.peers);\n } else {\n console.log(' Unable to retrieve peer information.');\n console.log(' (Status file not found or unreadable)');\n }\n\n console.log('To stop the bridge:');\n console.log(' claude-bridge stop');\n}\n\n/**\n * Create the status command\n */\nexport function createStatusCommand(): Command {\n const command = new Command('status');\n\n command\n .description('Show bridge status and connected peers')\n .option('-p, --port <port>', 'Check status for a specific port')\n .action((options: StatusCommandOptions) => {\n try {\n showStatus(options);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to get status');\n console.error(`Failed to get status: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createStatusCommand as statusCommand };\n","/**\n * CLI connect command - Connect to a remote bridge\n *\n * Takes a WebSocket URL and initiates a connection to a remote bridge.\n * This is a one-time connection test that verifies connectivity.\n *\n * Usage:\n * claude-bridge connect ws://localhost:8765\n */\n\nimport { Command } from 'commander';\nimport { createLogger } from '../../utils/logger.js';\nimport { WebSocketTransport } from '../../transport/websocket.js';\nimport { ConnectionState } from '../../transport/interface.js';\n\nconst logger = createLogger('cli:connect');\n\n/**\n * Validate WebSocket URL format\n * Returns true if valid, throws Error if invalid\n */\nexport function validateWebSocketUrl(url: string): boolean {\n // Check for ws:// or wss:// protocol\n if (!url.startsWith('ws://') && !url.startsWith('wss://')) {\n throw new Error(`Invalid URL protocol. Expected ws:// or wss://, got: ${url}`);\n }\n\n try {\n const parsed = new URL(url);\n\n // Ensure we have a valid hostname\n if (!parsed.hostname) {\n throw new Error('URL must include a hostname');\n }\n\n // Ensure we have a port (for WebSocket connections)\n if (!parsed.port) {\n // Default ports\n const defaultPort = parsed.protocol === 'wss:' ? '443' : '80';\n logger.debug(`No port specified, will use default: ${defaultPort}`);\n }\n\n return true;\n } catch (error) {\n if (error instanceof Error && error.message.includes('Invalid URL')) {\n throw new Error(`Invalid URL format: ${url}`);\n }\n throw error;\n }\n}\n\n/**\n * Connect to a remote bridge\n */\nasync function connectToBridge(url: string): Promise<void> {\n // Validate URL format\n try {\n validateWebSocketUrl(url);\n } catch (error) {\n console.error(`Error: ${(error as Error).message}`);\n process.exit(1);\n }\n\n console.log(`Connecting to bridge at ${url}...`);\n\n const transport = new WebSocketTransport();\n\n // Set up connection timeout\n const timeoutMs = 10000;\n const timeout = setTimeout(() => {\n console.error(`Error: Connection timeout after ${timeoutMs / 1000} seconds`);\n transport.disconnect().catch(() => {});\n process.exit(1);\n }, timeoutMs);\n\n try {\n // Attempt connection\n await transport.connect({\n url,\n reconnect: false, // Don't auto-reconnect for this test\n });\n\n clearTimeout(timeout);\n\n if (transport.getState() === ConnectionState.CONNECTED) {\n console.log('Successfully connected to bridge!');\n console.log('');\n console.log('Connection details:');\n console.log(` URL: ${url}`);\n console.log(` State: ${ConnectionState[transport.getState()]}`);\n console.log('');\n console.log('To start a bridge that auto-connects on startup:');\n console.log(` claude-bridge start --connect ${url}`);\n } else {\n console.error(`Connection failed. State: ${ConnectionState[transport.getState()]}`);\n process.exit(1);\n }\n\n // Clean up - disconnect after successful test\n await transport.disconnect();\n console.log('\\nConnection test complete. Disconnected.');\n } catch (error) {\n clearTimeout(timeout);\n const errorMessage = (error as Error).message;\n console.error(`Error: Failed to connect - ${errorMessage}`);\n\n // Provide helpful suggestions\n if (errorMessage.includes('ECONNREFUSED')) {\n console.log('');\n console.log('Suggestions:');\n console.log(' - Ensure a bridge is running at the specified address');\n console.log(' - Check the port number is correct');\n console.log(' - Verify no firewall is blocking the connection');\n } else if (errorMessage.includes('ENOTFOUND')) {\n console.log('');\n console.log('Suggestions:');\n console.log(' - Check the hostname is correct');\n console.log(' - Ensure DNS resolution is working');\n }\n\n process.exit(1);\n }\n}\n\n/**\n * Create the connect command\n */\nexport function createConnectCommand(): Command {\n const command = new Command('connect');\n\n command\n .description('Connect to a remote bridge')\n .argument('<url>', 'WebSocket URL to connect to (e.g., ws://localhost:8765)')\n .action(async (url: string) => {\n try {\n await connectToBridge(url);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Connect command failed');\n console.error(`Error: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createConnectCommand as connectCommand };\n","/**\n * CLI discover command - Discover bridges on local network\n *\n * Finds running Docker containers with bridge labels and\n * lists Docksal/DDEV/Lando projects with bridges.\n */\n\nimport { Command } from 'commander';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n type DiscoveredPeer,\n discoverDockerPeers,\n discoverDocksalProjects,\n discoverDdevProjects,\n discoverLandoProjects,\n} from '../../transport/discovery.js';\n\nconst logger = createLogger('cli:discover');\n\n/**\n * Print discovered peers table\n */\nfunction printPeersTable(peers: DiscoveredPeer[]): void {\n if (peers.length === 0) {\n console.log('No bridges found.');\n console.log('');\n console.log('Suggestions:');\n console.log(' - Start a bridge: claude-bridge start');\n console.log(' - Add bridge labels to Docker containers');\n console.log(' - Install bridge addon in your Docksal/DDEV project');\n return;\n }\n\n // Column widths\n const cols = {\n name: { title: 'Name', width: 25 },\n source: { title: 'Source', width: 12 },\n url: { title: 'URL', width: 35 },\n status: { title: 'Status', width: 12 },\n };\n\n // Print header\n console.log(\n cols.name.title.padEnd(cols.name.width) +\n cols.source.title.padEnd(cols.source.width) +\n cols.url.title.padEnd(cols.url.width) +\n cols.status.title.padEnd(cols.status.width)\n );\n\n // Print separator\n console.log(\n '-'.repeat(cols.name.width - 1) +\n ' ' +\n '-'.repeat(cols.source.width - 1) +\n ' ' +\n '-'.repeat(cols.url.width - 1) +\n ' ' +\n '-'.repeat(cols.status.width - 1)\n );\n\n // Print rows\n for (const peer of peers) {\n const row =\n peer.name.slice(0, cols.name.width - 1).padEnd(cols.name.width) +\n peer.source.padEnd(cols.source.width) +\n peer.url.slice(0, cols.url.width - 1).padEnd(cols.url.width) +\n (peer.status || 'unknown').padEnd(cols.status.width);\n console.log(row);\n }\n\n console.log('');\n console.log('To connect to a bridge:');\n console.log(' claude-bridge connect <url>');\n}\n\n/**\n * Discover all local bridges\n */\nasync function discoverBridges(): Promise<void> {\n console.log('Discovering bridges on local network...\\n');\n\n const allPeers: DiscoveredPeer[] = [];\n\n // Discover from all sources\n const dockerPeers = discoverDockerPeers();\n allPeers.push(...dockerPeers);\n logger.debug({ count: dockerPeers.length }, 'Docker peers discovered');\n\n const docksalPeers = discoverDocksalProjects();\n allPeers.push(...docksalPeers);\n logger.debug({ count: docksalPeers.length }, 'Docksal peers discovered');\n\n const ddevPeers = discoverDdevProjects();\n allPeers.push(...ddevPeers);\n logger.debug({ count: ddevPeers.length }, 'DDEV peers discovered');\n\n const landoPeers = discoverLandoProjects();\n allPeers.push(...landoPeers);\n logger.debug({ count: landoPeers.length }, 'Lando peers discovered');\n\n printPeersTable(allPeers);\n}\n\n/**\n * Create the discover command\n */\nexport function createDiscoverCommand(): Command {\n const command = new Command('discover');\n\n command\n .description('Discover bridges on local network')\n .action(async () => {\n try {\n await discoverBridges();\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Discover command failed');\n console.error(`Error: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createDiscoverCommand as discoverCommand };\n","/**\n * CLI info command - Show environment and configuration info\n *\n * Displays information about the current environment, detected\n * container type, network configuration, and loaded config values.\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { createLogger } from '../../utils/logger.js';\nimport { loadConfigSync, DEFAULT_CONFIG } from '../../utils/config.js';\nimport {\n detectEnvironment,\n getHostGateway,\n getDefaultConfig,\n} from '../../environment/detect.js';\nimport type { GlobalOptions } from '../index.js';\n\nconst logger = createLogger('cli:info');\n\n/**\n * Get the config file path that would be loaded\n */\nfunction getConfigFilePath(): string | null {\n // Check project local config first\n const localConfig = path.join(process.cwd(), '.claude-bridge.yml');\n if (fs.existsSync(localConfig)) {\n return localConfig;\n }\n\n // Check home directory\n const homeConfig = path.join(os.homedir(), '.claude-bridge', 'config.yml');\n if (fs.existsSync(homeConfig)) {\n return homeConfig;\n }\n\n return null;\n}\n\n/**\n * Format a value for display (handle undefined, objects, etc.)\n */\nfunction formatValue(value: unknown): string {\n if (value === undefined) {\n return '(not set)';\n }\n if (value === null) {\n return '(null)';\n }\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n return String(value);\n}\n\n/**\n * Print a section header\n */\nfunction printSection(title: string): void {\n console.log('');\n console.log(title);\n console.log('-'.repeat(title.length));\n}\n\n/**\n * Print a key-value pair\n */\nfunction printKeyValue(key: string, value: unknown, indent: number = 0): void {\n const prefix = ' '.repeat(indent);\n console.log(`${prefix}${key}: ${formatValue(value)}`);\n}\n\n/**\n * Show environment and configuration info\n */\nfunction showInfo(globalOptions: GlobalOptions): void {\n console.log('Claude Code Bridge - Environment Information');\n console.log('='.repeat(45));\n\n // Environment Detection\n printSection('Environment');\n const env = detectEnvironment();\n printKeyValue('Type', env.type);\n printKeyValue('Platform', env.platform);\n printKeyValue('Is Container', env.isContainer);\n printKeyValue('Project Name', env.projectName);\n printKeyValue('Project Root', env.projectRoot);\n\n // Network Configuration\n printSection('Network');\n const hostGateway = getHostGateway();\n const envDefaults = getDefaultConfig(env);\n const listenPort = envDefaults.listen?.port ?? 8765;\n const listenHost = envDefaults.listen?.host ?? '0.0.0.0';\n printKeyValue('Host Gateway', hostGateway);\n printKeyValue('Recommended Port', listenPort);\n printKeyValue('Default Host', listenHost);\n\n if (env.isContainer) {\n console.log('');\n console.log(' Note: To connect from host machine:');\n console.log(` ws://localhost:${listenPort}`);\n console.log('');\n console.log(' To connect to host from this container:');\n console.log(` ws://${hostGateway}:8766`);\n }\n\n // Configuration\n printSection('Configuration');\n const configPath = globalOptions.config || getConfigFilePath();\n printKeyValue('Config File', configPath || '(using defaults)');\n\n const config = loadConfigSync(globalOptions.config);\n\n console.log('');\n console.log(' Current Settings:');\n printKeyValue('Mode', config.mode, 2);\n printKeyValue('Instance Name', config.instanceName, 2);\n\n console.log('');\n console.log(' Listen:');\n printKeyValue('Port', config.listen.port, 2);\n printKeyValue('Host', config.listen.host, 2);\n\n console.log('');\n console.log(' Connect:');\n printKeyValue('URL', config.connect?.url, 2);\n\n console.log('');\n console.log(' Context Sharing:');\n printKeyValue('Auto Sync', config.contextSharing.autoSync, 2);\n printKeyValue('Sync Interval', `${config.contextSharing.syncInterval}ms`, 2);\n printKeyValue('Max Chunk Tokens', config.contextSharing.maxChunkTokens, 2);\n\n if (config.contextSharing.includePatterns.length > 0) {\n console.log(' Include Patterns:');\n for (const pattern of config.contextSharing.includePatterns) {\n console.log(` - ${pattern}`);\n }\n }\n\n if (config.contextSharing.excludePatterns.length > 0) {\n console.log(' Exclude Patterns:');\n for (const pattern of config.contextSharing.excludePatterns) {\n console.log(` - ${pattern}`);\n }\n }\n\n console.log('');\n console.log(' Interaction:');\n printKeyValue('Require Confirmation', config.interaction.requireConfirmation, 2);\n printKeyValue('Notify On Activity', config.interaction.notifyOnActivity, 2);\n printKeyValue('Task Timeout', `${config.interaction.taskTimeout}ms`, 2);\n\n // System Info\n printSection('System');\n printKeyValue('Node Version', process.version);\n printKeyValue('OS', `${os.type()} ${os.release()}`);\n printKeyValue('Arch', os.arch());\n printKeyValue('Home Directory', os.homedir());\n printKeyValue('Working Directory', process.cwd());\n\n // Environment Variables (relevant ones)\n printSection('Environment Variables');\n const relevantEnvVars = [\n 'DOCKSAL_STACK',\n 'DOCKSAL_PROJECT',\n 'IS_DDEV_PROJECT',\n 'DDEV_PROJECT',\n 'LANDO',\n 'LANDO_APP_NAME',\n 'LOG_LEVEL',\n ];\n\n let hasEnvVars = false;\n for (const varName of relevantEnvVars) {\n const value = process.env[varName];\n if (value !== undefined) {\n printKeyValue(varName, value);\n hasEnvVars = true;\n }\n }\n\n if (!hasEnvVars) {\n console.log(' (no relevant environment variables set)');\n }\n\n console.log('');\n}\n\n/**\n * Create the info command\n */\nexport function createInfoCommand(): Command {\n const command = new Command('info');\n\n command\n .description('Show environment and configuration info')\n .action(() => {\n try {\n // Get global options from parent command\n const globalOptions = command.parent?.opts() as GlobalOptions ?? {};\n showInfo(globalOptions);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Info command failed');\n console.error(`Error: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createInfoCommand as infoCommand };\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAS,WAAAA,gBAAe;;;ACLxB,SAAS,eAAe;AACxB,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,YAAY,QAAQ;AACpB,SAAS,iBAAiB;;;ACmbnB,SAAS,sBAAsB,SAA8C;AAClF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,EACZ,IAAI;AAEJ,MAAI,iBAAiB;AAErB,QAAM,UAA2B,OAAO,WAAmB;AAEzD,QAAI,gBAAgB;AAClB,UAAI,SAAS;AACX,gBAAQ,IAAI,iCAAiC;AAAA,MAC/C;AACA;AAAA,IACF;AACA,qBAAiB;AAEjB,QAAI,SAAS;AACX,cAAQ,IAAI;AAAA,WAAc,MAAM,+BAA+B;AAAA,IACjE;AAGA,UAAM,mBAAmB,WAAW,MAAM;AACxC,UAAI,SAAS;AACX,gBAAQ,MAAM,iCAAiC;AAAA,MACjD;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB,GAAG,OAAO;AAEV,QAAI;AACF,YAAM,QAAQ;AAEd,UAAI,cAAc;AAChB,qBAAa;AAAA,MACf;AAEA,mBAAa,gBAAgB;AAE7B,UAAI,SAAS;AACX,gBAAQ,IAAI,oBAAoB;AAAA,MAClC;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB,SAAS,OAAO;AACd,mBAAa,gBAAgB;AAC7B,UAAI,SAAS;AACX,gBAAQ,MAAM,0BAA2B,MAAgB,OAAO,EAAE;AAAA,MACpE;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,QAAM,gBAAgB,MAAM,QAAQ,QAAQ;AAC5C,QAAM,iBAAiB,MAAM,QAAQ,SAAS;AAE9C,UAAQ,GAAG,UAAU,aAAa;AAClC,UAAQ,GAAG,WAAW,cAAc;AAGpC,SAAO,MAAM;AACX,YAAQ,IAAI,UAAU,aAAa;AACnC,YAAQ,IAAI,WAAW,cAAc;AAAA,EACvC;AACF;AASO,SAAS,0BAA0B,UAGtC,CAAC,GAAS;AACZ,QAAM,EAAE,OAAO,OAAO,QAAAC,UAAS,QAAQ,MAAM,IAAI;AAEjD,UAAQ,GAAG,sBAAsB,CAAC,QAAQ,YAAY;AACpD,UAAM,QAAQ,kBAAkB,QAAQ,SAAS,IAAI,MAAM,OAAO,MAAM,CAAC;AACzE,IAAAA,QAAO,gCAAgC,KAAK;AAE5C,QAAI,MAAM;AACR,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACH;;;ADpgBA,IAAM,SAAS,aAAa,WAAW;AAiBvC,SAAS,iBAAyB;AAChC,QAAM,YAAiB,UAAQ,WAAQ,GAAG,gBAAgB;AAC1D,SAAY,UAAK,WAAW,YAAY;AAC1C;AAKA,SAAS,kBAAwB;AAC/B,QAAM,YAAiB,UAAQ,WAAQ,GAAG,gBAAgB;AAC1D,MAAI,CAAI,cAAW,SAAS,GAAG;AAC7B,IAAG,aAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC7C;AACF;AAKA,SAAS,aAAa,KAAmB;AACvC,kBAAgB;AAChB,QAAM,UAAU,eAAe;AAC/B,EAAG,iBAAc,SAAS,IAAI,SAAS,GAAG,OAAO;AACnD;AAKA,SAAS,gBAAsB;AAC7B,QAAM,UAAU,eAAe;AAC/B,MAAO,cAAW,OAAO,GAAG;AAC1B,IAAG,cAAW,OAAO;AAAA,EACvB;AACF;AAKA,SAAS,mBAAuD;AAC9D,QAAM,UAAU,eAAe;AAC/B,MAAI,CAAI,cAAW,OAAO,GAAG;AAC3B,WAAO,EAAE,SAAS,MAAM;AAAA,EAC1B;AAEA,MAAI;AACF,UAAM,MAAM,SAAY,gBAAa,SAAS,OAAO,EAAE,KAAK,GAAG,EAAE;AAEjE,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO,EAAE,SAAS,MAAM,IAAI;AAAA,EAC9B,QAAQ;AAEN,kBAAc;AACd,WAAO,EAAE,SAAS,MAAM;AAAA,EAC1B;AACF;AAKA,SAAS,oBAAoB,KAAa,UAAkB,KAAe;AACzE,QAAM,QAAkB,CAAC;AAEzB,MAAI;AACF,UAAM,UAAa,eAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAE3D,eAAW,SAAS,SAAS;AAC3B,YAAM,WAAgB,UAAK,KAAK,MAAM,IAAI;AAC1C,YAAM,eAAoB,cAAS,SAAS,QAAQ;AAEpD,UAAI,MAAM,YAAY,GAAG;AAEvB,YAAI,CAAC,gBAAgB,QAAQ,QAAQ,SAAS,SAAS,UAAU,EAAE,SAAS,MAAM,IAAI,GAAG;AACvF;AAAA,QACF;AACA,cAAM,KAAK,GAAG,oBAAoB,UAAU,OAAO,CAAC;AAAA,MACtD,WAAW,MAAM,OAAO,GAAG;AACzB,cAAM,KAAK,YAAY;AAAA,MACzB;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKA,SAAS,gBAAgB,UAAkB,UAA6B;AACtE,SAAO,SAAS,KAAK,aAAW,UAAU,UAAU,SAAS,EAAE,KAAK,KAAK,CAAC,CAAC;AAC7E;AAKA,SAAS,aAAa,UAAkB,UAAkB,KAAuB;AAC/E,MAAI;AACF,UAAM,QAAW,YAAS,QAAQ;AAClC,QAAI,MAAM,OAAO,SAAS;AACxB,aAAO,oBAAoB,MAAM,IAAI;AAAA,IACvC;AACA,WAAU,gBAAa,UAAU,OAAO;AAAA,EAC1C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,iBACP,QACA,QACM;AACN,QAAM,MAAM,QAAQ,IAAI;AAGxB,SAAO,mBAAmB,OAAO,OAAe,WAAyC;AACvF,WAAO,KAAK,EAAE,OAAO,OAAO,GAAG,mBAAmB;AAElD,UAAM,QAAQ,oBAAoB,GAAG;AACrC,UAAM,SAAsB,CAAC;AAC7B,UAAM,aAAa,MAAM,YAAY;AACrC,UAAM,aAAa,WAAW,MAAM,KAAK,EAAE,OAAO,OAAK,EAAE,SAAS,CAAC;AAEnE,eAAW,QAAQ,OAAO;AAExB,UAAI,gBAAgB,MAAM,OAAO,eAAe,GAAG;AACjD;AAAA,MACF;AAGA,YAAM,YAAY,KAAK,YAAY;AACnC,YAAM,eAAe,WAAW,KAAK,UAAQ,UAAU,SAAS,IAAI,CAAC;AACrE,YAAM,iBAAiB,gBAAgB,MAAM,OAAO,eAAe;AAEnE,UAAI,gBAAgB,gBAAgB;AAClC,cAAM,WAAgB,UAAK,KAAK,IAAI;AACpC,cAAM,UAAU,aAAa,QAAQ;AAErC,YAAI,YAAY,MAAM;AACpB,iBAAO,KAAK;AAAA,YACV,MAAM;AAAA,YACN;AAAA,YACA,UAAe,aAAQ,IAAI,EAAE,MAAM,CAAC,KAAK;AAAA,UAC3C,CAAC;AAAA,QACH;AAGA,YAAI,OAAO,UAAU,IAAI;AACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,KAAK,EAAE,WAAW,OAAO,QAAQ,MAAM,GAAG,2BAA2B;AAC5E,WAAO;AAAA,EACT,CAAC;AAGD,SAAO,eAAe,OAAO,MAAmB,WAAmB;AACjE,WAAO,KAAK,EAAE,QAAQ,KAAK,IAAI,aAAa,KAAK,aAAa,OAAO,GAAG,eAAe;AAGvF,UAAM,cAAuC;AAAA,MAC3C;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB,aAAa,QAAQ;AAAA,IACvB;AAGA,UAAM,UAAe,UAAK,KAAK,cAAc;AAC7C,QAAO,cAAW,OAAO,GAAG;AAC1B,UAAI;AACF,cAAM,MAAM,KAAK,MAAS,gBAAa,SAAS,OAAO,CAAC;AACxD,oBAAY,OAAO,IAAI;AACvB,oBAAY,UAAU,IAAI;AAC1B,oBAAY,cAAc,IAAI;AAC9B,oBAAY,eAAe,OAAO,KAAK,IAAI,gBAAgB,CAAC,CAAC;AAC7D,oBAAY,kBAAkB,OAAO,KAAK,IAAI,mBAAmB,CAAC,CAAC;AAAA,MACrE,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,QAAI;AACF,YAAM,UAAa,eAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAC3D,kBAAY,YAAY,QACrB,OAAO,OAAK,CAAC,EAAE,KAAK,WAAW,GAAG,KAAK,EAAE,SAAS,cAAc,EAChE,IAAI,QAAM;AAAA,QACT,MAAM,EAAE;AAAA,QACR,MAAM,EAAE,YAAY,IAAI,cAAc;AAAA,MACxC,EAAE;AAAA,IACN,QAAQ;AAAA,IAER;AAGA,UAAM,WAAW,oBAAoB,GAAG;AACxC,UAAM,cAAc,SAAS;AAAA,MAAO,OAClC,gBAAgB,GAAG,OAAO,eAAe,KACzC,CAAC,gBAAgB,GAAG,OAAO,eAAe;AAAA,IAC5C;AACA,gBAAY,kBAAkB,YAAY;AAC1C,gBAAY,cAAc,YAAY,MAAM,GAAG,EAAE;AAEjD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,QACJ,SAAS,+BAA+B,KAAK,WAAW;AAAA,QACxD,OAAO,KAAK;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAGD,SAAO,kBAAkB,CAAC,SAAS,WAAW;AAC5C,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA,WAAW,QAAQ,OAAO,UAAU;AAAA,QACpC,SAAS,QAAQ;AAAA,MACnB;AAAA,MACA;AAAA,IACF;AAEA,QAAI,QAAQ,OAAO;AACjB,iBAAW,QAAQ,QAAQ,OAAO;AAChC,gBAAQ,IAAI,yBAAkB,KAAK,IAAI,KAAK,KAAK,SAAS,UAAU,CAAC,SAAS;AAAA,MAChF;AAAA,IACF;AACA,QAAI,QAAQ,SAAS;AACnB,cAAQ,IAAI,wBAAiB,QAAQ,OAAO,EAAE;AAAA,IAChD;AAAA,EACF,CAAC;AAED,SAAO,KAAK,mEAAmE;AAC/E,UAAQ,IAAI,sDAAsD;AACpE;AAKA,SAAS,kBACP,SACA,eACc;AAEd,QAAM,aAAa,eAAe,cAAc,MAAM;AAGtD,MAAI,YAAmC,CAAC;AACxC,MAAI,QAAQ,MAAM;AAChB,UAAM,MAAM,kBAAkB;AAC9B,UAAM,mBAAmB,iBAAiB,GAAG;AAC7C,WAAO,KAAK,EAAE,aAAa,IAAI,MAAM,aAAa,IAAI,YAAY,GAAG,2BAA2B;AAGhG,gBAAY;AAAA,MACV,MAAM,iBAAiB;AAAA,MACvB,cAAc,iBAAiB;AAAA,MAC/B,QAAQ,iBAAiB;AAAA,MACzB,SAAS,iBAAiB;AAAA,IAC5B;AAAA,EACF;AAGA,QAAM,YAAmC,CAAC;AAE1C,MAAI,QAAQ,MAAM;AAChB,cAAU,SAAS;AAAA,MACjB,GAAG,UAAU;AAAA,MACb,MAAM,SAAS,QAAQ,MAAM,EAAE;AAAA,MAC/B,MAAM,QAAQ,QAAQ;AAAA,IACxB;AAAA,EACF;AAEA,MAAI,QAAQ,QAAQ,CAAC,UAAU,QAAQ;AACrC,cAAU,SAAS;AAAA,MACjB,MAAM,WAAW,OAAO;AAAA,MACxB,MAAM,QAAQ;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS;AACnB,cAAU,UAAU;AAAA,MAClB,KAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAGA,MAAI,OAAmB;AACvB,QAAM,YAAY,UAAU,UAAU,UAAU,UAAU,WAAW;AACrE,QAAM,aAAa,UAAU,WAAW,UAAU,WAAW,WAAW;AAExE,MAAI,aAAa,CAAC,YAAY;AAC5B,WAAO;AAAA,EACT,WAAW,cAAc,CAAC,WAAW;AACnC,WAAO;AAAA,EACT;AAGA,QAAM,cAA4B;AAAA,IAChC,MAAM,UAAU,QAAQ,UAAU,QAAQ,WAAW,QAAQ;AAAA,IAC7D,cACE,UAAU,gBACV,UAAU,gBACV,WAAW,gBACX,UAAU,QAAQ,GAAG;AAAA,IACvB,QAAQ;AAAA,MACN,MAAM,UAAU,QAAQ,QAAQ,UAAU,QAAQ,QAAQ,WAAW,OAAO;AAAA,MAC5E,MAAM,UAAU,QAAQ,QAAQ,UAAU,QAAQ,QAAQ,WAAW,OAAO;AAAA,IAC9E;AAAA,IACA,aAAa,WAAW,YAAY;AAAA,IACpC,gBAAgB;AAAA,MACd,UAAU,WAAW,eAAe;AAAA,MACpC,cAAc,WAAW,eAAe;AAAA,IAC1C;AAAA,EACF;AAGA,QAAM,aAAa,UAAU,SAAS,OAAO,UAAU,SAAS,OAAO,WAAW,SAAS;AAC3F,MAAI,YAAY;AACd,gBAAY,UAAU;AAAA,MACpB,KAAK;AAAA,IACP;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAe,YACb,SACA,eACe;AAEf,QAAM,EAAE,SAAS,IAAI,IAAI,iBAAiB;AAC1C,MAAI,SAAS;AACX,YAAQ,MAAM,mCAAmC,GAAG,GAAG;AACvD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,SAAS,kBAAkB,SAAS,aAAa;AAGvD,UAAQ,IAAI,gCAAgC;AAC5C,UAAQ,IAAI,eAAe,OAAO,YAAY,EAAE;AAChD,UAAQ,IAAI,WAAW,OAAO,IAAI,EAAE;AAEpC,MAAI,OAAO,QAAQ;AACjB,YAAQ,IAAI,gBAAgB,OAAO,OAAO,IAAI,IAAI,OAAO,OAAO,IAAI,EAAE;AAAA,EACxE;AAEA,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAI,oBAAoB,OAAO,QAAQ,GAAG,EAAE;AAAA,EACtD;AAGA,MAAI,QAAQ,QAAQ;AAGlB,YAAQ,IAAI,0BAA0B;AACtC,iBAAa,QAAQ,GAAG;AAAA,EAC1B;AAGA,QAAM,SAAS,IAAI,OAAO,MAAM;AAGhC,wBAAsB;AAAA,IACpB,SAAS,YAAY;AACnB,aAAO,KAAK,oBAAoB;AAChC,YAAM,OAAO,KAAK;AAClB,aAAO,KAAK,gBAAgB;AAAA,IAC9B;AAAA,IACA,cAAc,QAAQ,SAAS,gBAAgB;AAAA,IAC/C,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAGD,4BAA0B;AAAA,IACxB,MAAM;AAAA,IACN,QAAQ,CAAC,KAAK,QAAQ,OAAO,MAAM,EAAE,OAAO,IAAI,QAAQ,GAAG,GAAG;AAAA,EAChE,CAAC;AAGD,QAAM,aAAa,eAAe,cAAc,MAAM;AAEtD,MAAI;AACF,UAAM,OAAO,MAAM;AAGnB,QAAI,QAAQ,cAAc;AACxB,uBAAiB,QAAQ;AAAA,QACvB,iBAAiB,WAAW,eAAe;AAAA,QAC3C,iBAAiB,WAAW,eAAe;AAAA,MAC7C,CAAC;AAAA,IACH;AAGA,QAAI,QAAQ,QAAQ;AAClB,mBAAa,QAAQ,GAAG;AAAA,IAC1B;AAEA,YAAQ,IAAI,8BAA8B;AAC1C,YAAQ,IAAI,oBAAoB,OAAO,aAAa,CAAC,EAAE;AAGvD,QAAI,OAAO,QAAQ;AACjB,cAAQ,IAAI;AAAA,gCAAmC;AAC/C,cAAQ,IAAI,0CAA0C,OAAO,OAAO,IAAI,EAAE;AAAA,IAC5E;AAGA,QAAI,CAAC,QAAQ,QAAQ;AACnB,cAAQ,IAAI,yBAAyB;AAAA,IACvC;AAAA,EACF,SAAS,OAAO;AACd,WAAO,MAAM,EAAE,OAAQ,MAAgB,QAAQ,GAAG,wBAAwB;AAC1E,YAAQ,MAAM,2BAA4B,MAAgB,OAAO,EAAE;AACnE,QAAI,QAAQ,QAAQ;AAClB,oBAAc;AAAA,IAChB;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAKO,SAAS,qBAA8B;AAC5C,QAAM,UAAU,IAAI,QAAQ,OAAO;AAEnC,UACG,YAAY,yBAAyB,EACrC,OAAO,qBAAqB,6DAA6D,EACzF,OAAO,qBAAqB,oCAAoC,EAChE,OAAO,uBAAuB,0DAA0D,EACxF,OAAO,cAAc,uCAAuC,EAC5D,OAAO,gBAAgB,mBAAmB,EAC1C,OAAO,mBAAmB,oDAAoD,EAC9E,OAAO,OAAO,YAAiC;AAE9C,UAAM,gBAAgB,QAAQ,QAAQ,KAAK;AAC3C,UAAM,YAAY,SAAS,aAAa;AAAA,EAC1C,CAAC;AAEH,SAAO;AACT;;;AEzeA,SAAS,WAAAC,gBAAe;AACxB,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,YAAYC,SAAQ;AAGpB,IAAMC,UAAS,aAAa,UAAU;AAKtC,SAASC,kBAAyB;AAChC,QAAM,YAAiB,WAAQ,YAAQ,GAAG,gBAAgB;AAC1D,SAAY,WAAK,WAAW,YAAY;AAC1C;AAKA,SAASC,iBAAsB;AAC7B,QAAM,UAAUD,gBAAe;AAC/B,MAAO,eAAW,OAAO,GAAG;AAC1B,IAAG,eAAW,OAAO;AAAA,EACvB;AACF;AAMA,SAAS,cAA6B;AACpC,QAAM,UAAUA,gBAAe;AAC/B,MAAI,CAAI,eAAW,OAAO,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAa,iBAAa,SAAS,OAAO,EAAE,KAAK;AACvD,UAAM,MAAM,SAAS,SAAS,EAAE;AAChC,QAAI,MAAM,GAAG,KAAK,OAAO,GAAG;AAC1B,MAAAD,QAAO,KAAK,EAAE,QAAQ,GAAG,0BAA0B;AACnD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,IAAAA,QAAO,MAAM,EAAE,OAAQ,MAAgB,QAAQ,GAAG,yBAAyB;AAC3E,WAAO;AAAA,EACT;AACF;AAKA,SAAS,iBAAiB,KAAsB;AAC9C,MAAI;AAEF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAe,mBACb,KACA,YAAoB,KACF;AAClB,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,gBAAgB;AAEtB,SAAO,KAAK,IAAI,IAAI,YAAY,WAAW;AACzC,QAAI,CAAC,iBAAiB,GAAG,GAAG;AAC1B,aAAO;AAAA,IACT;AACA,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,aAAa,CAAC;AAAA,EACnE;AAEA,SAAO;AACT;AAKA,eAAe,aAA4B;AACzC,QAAM,MAAM,YAAY;AAExB,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,4CAA4C;AACxD;AAAA,EACF;AAGA,MAAI,CAAC,iBAAiB,GAAG,GAAG;AAC1B,YAAQ,IAAI,kDAAkD,GAAG,cAAc;AAE/E,IAAAE,eAAc;AACd;AAAA,EACF;AAEA,UAAQ,IAAI,yBAAyB,GAAG,MAAM;AAE9C,MAAI;AAEF,YAAQ,KAAK,KAAK,SAAS;AAAA,EAC7B,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAS;AAErD,cAAQ,IAAI,2BAA2B;AACvC,MAAAA,eAAc;AACd;AAAA,IACF;AACA,QAAK,MAAgC,SAAS,SAAS;AACrD,cAAQ,MAAM,+CAA+C,GAAG,IAAI;AACpE,cAAQ,MAAM,uCAAuC;AACrD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM;AAAA,EACR;AAGA,QAAM,SAAS,MAAM,mBAAmB,GAAG;AAE3C,MAAI,QAAQ;AACV,YAAQ,IAAI,8BAA8B;AAE1C,IAAAA,eAAc;AAAA,EAChB,OAAO;AACL,YAAQ,IAAI,wEAAwE;AAEpF,YAAQ,IAAI,0BAA0B,GAAG,EAAE;AAAA,EAC7C;AACF;AAKO,SAAS,oBAA6B;AAC3C,QAAM,UAAU,IAAIC,SAAQ,MAAM;AAElC,UACG,YAAY,yBAAyB,EACrC,OAAO,YAAY;AAClB,QAAI;AACF,YAAM,WAAW;AAAA,IACnB,SAAS,OAAO;AACd,MAAAH,QAAO,MAAM,EAAE,OAAQ,MAAgB,QAAQ,GAAG,uBAAuB;AACzE,cAAQ,MAAM,0BAA2B,MAAgB,OAAO,EAAE;AAClE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,SAAO;AACT;;;ACxJA,SAAS,WAAAI,gBAAe;AACxB,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,YAAYC,SAAQ;AAGpB,IAAMC,UAAS,aAAa,YAAY;AAgCxC,SAASC,kBAAyB;AAChC,QAAM,YAAiB,WAAQ,YAAQ,GAAG,gBAAgB;AAC1D,SAAY,WAAK,WAAW,YAAY;AAC1C;AAKA,SAAS,oBAA4B;AACnC,QAAM,YAAiB,WAAQ,YAAQ,GAAG,gBAAgB;AAC1D,SAAY,WAAK,WAAW,aAAa;AAC3C;AAKA,SAASC,eAA6B;AACpC,QAAM,UAAUD,gBAAe;AAC/B,MAAI,CAAI,eAAW,OAAO,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAa,iBAAa,SAAS,OAAO,EAAE,KAAK;AACvD,UAAM,MAAM,SAAS,SAAS,EAAE;AAChC,QAAI,MAAM,GAAG,KAAK,OAAO,GAAG;AAC1B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAASE,kBAAiB,KAAsB;AAC9C,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,iBAAiE;AACxE,QAAM,aAAa,kBAAkB;AACrC,MAAI,CAAI,eAAW,UAAU,GAAG;AAC9B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAa,iBAAa,YAAY,OAAO;AACnD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,WAAW,SAAyB;AAC3C,MAAI;AACF,UAAM,OAAO,IAAI,KAAK,OAAO;AAC7B,WAAO,KAAK,eAAe;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,SAAS,KAAa,OAAuB;AACpD,SAAO,IAAI,OAAO,KAAK;AACzB;AAKA,SAAS,eAAe,OAA2B;AACjD,MAAI,MAAM,WAAW,GAAG;AACtB,YAAQ,IAAI,uBAAuB;AACnC;AAAA,EACF;AAGA,QAAM,OAAO;AAAA,IACX,IAAI,EAAE,OAAO,MAAM,OAAO,GAAG;AAAA,IAC7B,MAAM,EAAE,OAAO,QAAQ,OAAO,GAAG;AAAA,IACjC,WAAW,EAAE,OAAO,aAAa,OAAO,GAAG;AAAA,IAC3C,cAAc,EAAE,OAAO,iBAAiB,OAAO,GAAG;AAAA,EACpD;AAGA,UAAQ,IAAI,EAAE;AACd,UAAQ;AAAA,IACN,OACE,SAAS,KAAK,GAAG,OAAO,KAAK,GAAG,KAAK,IACrC,SAAS,KAAK,KAAK,OAAO,KAAK,KAAK,KAAK,IACzC,SAAS,KAAK,UAAU,OAAO,KAAK,UAAU,KAAK,IACnD,SAAS,KAAK,aAAa,OAAO,KAAK,aAAa,KAAK;AAAA,EAC7D;AAGA,QAAM,YACJ,OACA,IAAI,OAAO,KAAK,GAAG,QAAQ,CAAC,IAC5B,MACA,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,IAC9B,MACA,IAAI,OAAO,KAAK,UAAU,QAAQ,CAAC,IACnC,MACA,IAAI,OAAO,KAAK,aAAa,QAAQ,CAAC;AACxC,UAAQ,IAAI,SAAS;AAGrB,aAAW,QAAQ,OAAO;AACxB,UAAM,MACJ,OACA,SAAS,KAAK,IAAI,KAAK,GAAG,KAAK,IAC/B,SAAS,KAAK,KAAK,MAAM,GAAG,KAAK,KAAK,QAAQ,CAAC,GAAG,KAAK,KAAK,KAAK,IACjE,SAAS,WAAW,KAAK,WAAW,GAAG,KAAK,UAAU,KAAK,IAC3D,SAAS,WAAW,KAAK,YAAY,GAAG,KAAK,aAAa,KAAK;AACjE,YAAQ,IAAI,GAAG;AAAA,EACjB;AAEA,UAAQ,IAAI,EAAE;AAChB;AAKA,SAAS,kBAAgC;AACvC,QAAM,MAAMD,aAAY;AAExB,MAAI,QAAQ,MAAM;AAChB,WAAO,EAAE,SAAS,MAAM;AAAA,EAC1B;AAEA,MAAI,CAACC,kBAAiB,GAAG,GAAG;AAE1B,WAAO,EAAE,SAAS,MAAM;AAAA,EAC1B;AAGA,QAAM,aAAa,eAAe;AAElC,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA,MAAM,YAAY;AAAA,IAClB,OAAO,YAAY;AAAA,EACrB;AACF;AAKA,SAAS,WAAW,SAAqC;AACvD,UAAQ,IAAI,2BAA2B;AACvC,UAAQ,IAAI,IAAI,OAAO,EAAE,CAAC;AAC1B,UAAQ,IAAI,EAAE;AAEd,QAAM,SAAS,gBAAgB;AAE/B,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,IAAI,iBAAiB;AAC7B,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,sBAAsB;AAClC,YAAQ,IAAI,uBAAuB;AACnC;AAAA,EACF;AAEA,UAAQ,IAAI,iBAAiB;AAC7B,UAAQ,IAAI,QAAQ,OAAO,GAAG,EAAE;AAEhC,MAAI,OAAO,SAAS,QAAW;AAC7B,YAAQ,IAAI,SAAS,OAAO,IAAI,EAAE;AAAA,EACpC;AAEA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,kBAAkB;AAE9B,MAAI,OAAO,OAAO;AAChB,mBAAe,OAAO,KAAK;AAAA,EAC7B,OAAO;AACL,YAAQ,IAAI,wCAAwC;AACpD,YAAQ,IAAI,yCAAyC;AAAA,EACvD;AAEA,UAAQ,IAAI,qBAAqB;AACjC,UAAQ,IAAI,sBAAsB;AACpC;AAKO,SAAS,sBAA+B;AAC7C,QAAM,UAAU,IAAIC,SAAQ,QAAQ;AAEpC,UACG,YAAY,wCAAwC,EACpD,OAAO,qBAAqB,kCAAkC,EAC9D,OAAO,CAAC,YAAkC;AACzC,QAAI;AACF,iBAAW,OAAO;AAAA,IACpB,SAAS,OAAO;AACd,MAAAJ,QAAO,MAAM,EAAE,OAAQ,MAAgB,QAAQ,GAAG,sBAAsB;AACxE,cAAQ,MAAM,yBAA0B,MAAgB,OAAO,EAAE;AACjE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,SAAO;AACT;;;AClQA,SAAS,WAAAK,gBAAe;AAKxB,IAAMC,UAAS,aAAa,aAAa;AAMlC,SAAS,qBAAqB,KAAsB;AAEzD,MAAI,CAAC,IAAI,WAAW,OAAO,KAAK,CAAC,IAAI,WAAW,QAAQ,GAAG;AACzD,UAAM,IAAI,MAAM,wDAAwD,GAAG,EAAE;AAAA,EAC/E;AAEA,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAG1B,QAAI,CAAC,OAAO,UAAU;AACpB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAGA,QAAI,CAAC,OAAO,MAAM;AAEhB,YAAM,cAAc,OAAO,aAAa,SAAS,QAAQ;AACzD,MAAAA,QAAO,MAAM,wCAAwC,WAAW,EAAE;AAAA,IACpE;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,aAAa,GAAG;AACnE,YAAM,IAAI,MAAM,uBAAuB,GAAG,EAAE;AAAA,IAC9C;AACA,UAAM;AAAA,EACR;AACF;AAKA,eAAe,gBAAgB,KAA4B;AAEzD,MAAI;AACF,yBAAqB,GAAG;AAAA,EAC1B,SAAS,OAAO;AACd,YAAQ,MAAM,UAAW,MAAgB,OAAO,EAAE;AAClD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAI,2BAA2B,GAAG,KAAK;AAE/C,QAAM,YAAY,IAAI,mBAAmB;AAGzC,QAAM,YAAY;AAClB,QAAM,UAAU,WAAW,MAAM;AAC/B,YAAQ,MAAM,mCAAmC,YAAY,GAAI,UAAU;AAC3E,cAAU,WAAW,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACrC,YAAQ,KAAK,CAAC;AAAA,EAChB,GAAG,SAAS;AAEZ,MAAI;AAEF,UAAM,UAAU,QAAQ;AAAA,MACtB;AAAA,MACA,WAAW;AAAA;AAAA,IACb,CAAC;AAED,iBAAa,OAAO;AAEpB,QAAI,UAAU,SAAS,mCAAiC;AACtD,cAAQ,IAAI,mCAAmC;AAC/C,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,qBAAqB;AACjC,cAAQ,IAAI,UAAU,GAAG,EAAE;AAC3B,cAAQ,IAAI,YAAY,gBAAgB,UAAU,SAAS,CAAC,CAAC,EAAE;AAC/D,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,kDAAkD;AAC9D,cAAQ,IAAI,mCAAmC,GAAG,EAAE;AAAA,IACtD,OAAO;AACL,cAAQ,MAAM,6BAA6B,gBAAgB,UAAU,SAAS,CAAC,CAAC,EAAE;AAClF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,UAAU,WAAW;AAC3B,YAAQ,IAAI,2CAA2C;AAAA,EACzD,SAAS,OAAO;AACd,iBAAa,OAAO;AACpB,UAAM,eAAgB,MAAgB;AACtC,YAAQ,MAAM,8BAA8B,YAAY,EAAE;AAG1D,QAAI,aAAa,SAAS,cAAc,GAAG;AACzC,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,cAAc;AAC1B,cAAQ,IAAI,yDAAyD;AACrE,cAAQ,IAAI,sCAAsC;AAClD,cAAQ,IAAI,mDAAmD;AAAA,IACjE,WAAW,aAAa,SAAS,WAAW,GAAG;AAC7C,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,cAAc;AAC1B,cAAQ,IAAI,mCAAmC;AAC/C,cAAQ,IAAI,sCAAsC;AAAA,IACpD;AAEA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAKO,SAAS,uBAAgC;AAC9C,QAAM,UAAU,IAAIC,SAAQ,SAAS;AAErC,UACG,YAAY,4BAA4B,EACxC,SAAS,SAAS,yDAAyD,EAC3E,OAAO,OAAO,QAAgB;AAC7B,QAAI;AACF,YAAM,gBAAgB,GAAG;AAAA,IAC3B,SAAS,OAAO;AACd,MAAAD,QAAO,MAAM,EAAE,OAAQ,MAAgB,QAAQ,GAAG,wBAAwB;AAC1E,cAAQ,MAAM,UAAW,MAAgB,OAAO,EAAE;AAClD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,SAAO;AACT;;;ACzIA,SAAS,WAAAE,gBAAe;AAUxB,IAAMC,UAAS,aAAa,cAAc;AAK1C,SAAS,gBAAgB,OAA+B;AACtD,MAAI,MAAM,WAAW,GAAG;AACtB,YAAQ,IAAI,mBAAmB;AAC/B,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,cAAc;AAC1B,YAAQ,IAAI,yCAAyC;AACrD,YAAQ,IAAI,4CAA4C;AACxD,YAAQ,IAAI,uDAAuD;AACnE;AAAA,EACF;AAGA,QAAM,OAAO;AAAA,IACX,MAAM,EAAE,OAAO,QAAQ,OAAO,GAAG;AAAA,IACjC,QAAQ,EAAE,OAAO,UAAU,OAAO,GAAG;AAAA,IACrC,KAAK,EAAE,OAAO,OAAO,OAAO,GAAG;AAAA,IAC/B,QAAQ,EAAE,OAAO,UAAU,OAAO,GAAG;AAAA,EACvC;AAGA,UAAQ;AAAA,IACN,KAAK,KAAK,MAAM,OAAO,KAAK,KAAK,KAAK,IACpC,KAAK,OAAO,MAAM,OAAO,KAAK,OAAO,KAAK,IAC1C,KAAK,IAAI,MAAM,OAAO,KAAK,IAAI,KAAK,IACpC,KAAK,OAAO,MAAM,OAAO,KAAK,OAAO,KAAK;AAAA,EAC9C;AAGA,UAAQ;AAAA,IACN,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,IAC5B,MACA,IAAI,OAAO,KAAK,OAAO,QAAQ,CAAC,IAChC,MACA,IAAI,OAAO,KAAK,IAAI,QAAQ,CAAC,IAC7B,MACA,IAAI,OAAO,KAAK,OAAO,QAAQ,CAAC;AAAA,EACpC;AAGA,aAAW,QAAQ,OAAO;AACxB,UAAM,MACJ,KAAK,KAAK,MAAM,GAAG,KAAK,KAAK,QAAQ,CAAC,EAAE,OAAO,KAAK,KAAK,KAAK,IAC9D,KAAK,OAAO,OAAO,KAAK,OAAO,KAAK,IACpC,KAAK,IAAI,MAAM,GAAG,KAAK,IAAI,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,KAAK,KAC1D,KAAK,UAAU,WAAW,OAAO,KAAK,OAAO,KAAK;AACrD,YAAQ,IAAI,GAAG;AAAA,EACjB;AAEA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,yBAAyB;AACrC,UAAQ,IAAI,+BAA+B;AAC7C;AAKA,eAAe,kBAAiC;AAC9C,UAAQ,IAAI,2CAA2C;AAEvD,QAAM,WAA6B,CAAC;AAGpC,QAAM,cAAc,oBAAoB;AACxC,WAAS,KAAK,GAAG,WAAW;AAC5B,EAAAA,QAAO,MAAM,EAAE,OAAO,YAAY,OAAO,GAAG,yBAAyB;AAErE,QAAM,eAAe,wBAAwB;AAC7C,WAAS,KAAK,GAAG,YAAY;AAC7B,EAAAA,QAAO,MAAM,EAAE,OAAO,aAAa,OAAO,GAAG,0BAA0B;AAEvE,QAAM,YAAY,qBAAqB;AACvC,WAAS,KAAK,GAAG,SAAS;AAC1B,EAAAA,QAAO,MAAM,EAAE,OAAO,UAAU,OAAO,GAAG,uBAAuB;AAEjE,QAAM,aAAa,sBAAsB;AACzC,WAAS,KAAK,GAAG,UAAU;AAC3B,EAAAA,QAAO,MAAM,EAAE,OAAO,WAAW,OAAO,GAAG,wBAAwB;AAEnE,kBAAgB,QAAQ;AAC1B;AAKO,SAAS,wBAAiC;AAC/C,QAAM,UAAU,IAAIC,SAAQ,UAAU;AAEtC,UACG,YAAY,mCAAmC,EAC/C,OAAO,YAAY;AAClB,QAAI;AACF,YAAM,gBAAgB;AAAA,IACxB,SAAS,OAAO;AACd,MAAAD,QAAO,MAAM,EAAE,OAAQ,MAAgB,QAAQ,GAAG,yBAAyB;AAC3E,cAAQ,MAAM,UAAW,MAAgB,OAAO,EAAE;AAClD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,SAAO;AACT;;;ACnHA,SAAS,WAAAE,gBAAe;AACxB,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,YAAYC,SAAQ;AAUpB,IAAMC,UAAS,aAAa,UAAU;AAKtC,SAAS,oBAAmC;AAE1C,QAAM,cAAmB,WAAK,QAAQ,IAAI,GAAG,oBAAoB;AACjE,MAAO,eAAW,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AAGA,QAAM,aAAkB,WAAQ,YAAQ,GAAG,kBAAkB,YAAY;AACzE,MAAO,eAAW,UAAU,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKA,SAAS,YAAY,OAAwB;AAC3C,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AACA,SAAO,OAAO,KAAK;AACrB;AAKA,SAAS,aAAa,OAAqB;AACzC,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,KAAK;AACjB,UAAQ,IAAI,IAAI,OAAO,MAAM,MAAM,CAAC;AACtC;AAKA,SAAS,cAAc,KAAa,OAAgB,SAAiB,GAAS;AAC5E,QAAM,SAAS,KAAK,OAAO,MAAM;AACjC,UAAQ,IAAI,GAAG,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,EAAE;AACtD;AAKA,SAAS,SAAS,eAAoC;AACpD,UAAQ,IAAI,8CAA8C;AAC1D,UAAQ,IAAI,IAAI,OAAO,EAAE,CAAC;AAG1B,eAAa,aAAa;AAC1B,QAAM,MAAM,kBAAkB;AAC9B,gBAAc,QAAQ,IAAI,IAAI;AAC9B,gBAAc,YAAY,IAAI,QAAQ;AACtC,gBAAc,gBAAgB,IAAI,WAAW;AAC7C,gBAAc,gBAAgB,IAAI,WAAW;AAC7C,gBAAc,gBAAgB,IAAI,WAAW;AAG7C,eAAa,SAAS;AACtB,QAAM,cAAc,eAAe;AACnC,QAAM,cAAc,iBAAiB,GAAG;AACxC,QAAM,aAAa,YAAY,QAAQ,QAAQ;AAC/C,QAAM,aAAa,YAAY,QAAQ,QAAQ;AAC/C,gBAAc,gBAAgB,WAAW;AACzC,gBAAc,oBAAoB,UAAU;AAC5C,gBAAc,gBAAgB,UAAU;AAExC,MAAI,IAAI,aAAa;AACnB,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,uCAAuC;AACnD,YAAQ,IAAI,sBAAsB,UAAU,EAAE;AAC9C,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,2CAA2C;AACvD,YAAQ,IAAI,YAAY,WAAW,OAAO;AAAA,EAC5C;AAGA,eAAa,eAAe;AAC5B,QAAM,aAAa,cAAc,UAAU,kBAAkB;AAC7D,gBAAc,eAAe,cAAc,kBAAkB;AAE7D,QAAM,SAAS,eAAe,cAAc,MAAM;AAElD,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,qBAAqB;AACjC,gBAAc,QAAQ,OAAO,MAAM,CAAC;AACpC,gBAAc,iBAAiB,OAAO,cAAc,CAAC;AAErD,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,WAAW;AACvB,gBAAc,QAAQ,OAAO,OAAO,MAAM,CAAC;AAC3C,gBAAc,QAAQ,OAAO,OAAO,MAAM,CAAC;AAE3C,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,YAAY;AACxB,gBAAc,OAAO,OAAO,SAAS,KAAK,CAAC;AAE3C,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,oBAAoB;AAChC,gBAAc,aAAa,OAAO,eAAe,UAAU,CAAC;AAC5D,gBAAc,iBAAiB,GAAG,OAAO,eAAe,YAAY,MAAM,CAAC;AAC3E,gBAAc,oBAAoB,OAAO,eAAe,gBAAgB,CAAC;AAEzE,MAAI,OAAO,eAAe,gBAAgB,SAAS,GAAG;AACpD,YAAQ,IAAI,uBAAuB;AACnC,eAAW,WAAW,OAAO,eAAe,iBAAiB;AAC3D,cAAQ,IAAI,WAAW,OAAO,EAAE;AAAA,IAClC;AAAA,EACF;AAEA,MAAI,OAAO,eAAe,gBAAgB,SAAS,GAAG;AACpD,YAAQ,IAAI,uBAAuB;AACnC,eAAW,WAAW,OAAO,eAAe,iBAAiB;AAC3D,cAAQ,IAAI,WAAW,OAAO,EAAE;AAAA,IAClC;AAAA,EACF;AAEA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,gBAAgB;AAC5B,gBAAc,wBAAwB,OAAO,YAAY,qBAAqB,CAAC;AAC/E,gBAAc,sBAAsB,OAAO,YAAY,kBAAkB,CAAC;AAC1E,gBAAc,gBAAgB,GAAG,OAAO,YAAY,WAAW,MAAM,CAAC;AAGtE,eAAa,QAAQ;AACrB,gBAAc,gBAAgB,QAAQ,OAAO;AAC7C,gBAAc,MAAM,GAAM,SAAK,CAAC,IAAO,YAAQ,CAAC,EAAE;AAClD,gBAAc,QAAW,SAAK,CAAC;AAC/B,gBAAc,kBAAqB,YAAQ,CAAC;AAC5C,gBAAc,qBAAqB,QAAQ,IAAI,CAAC;AAGhD,eAAa,uBAAuB;AACpC,QAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,aAAa;AACjB,aAAW,WAAW,iBAAiB;AACrC,UAAM,QAAQ,QAAQ,IAAI,OAAO;AACjC,QAAI,UAAU,QAAW;AACvB,oBAAc,SAAS,KAAK;AAC5B,mBAAa;AAAA,IACf;AAAA,EACF;AAEA,MAAI,CAAC,YAAY;AACf,YAAQ,IAAI,2CAA2C;AAAA,EACzD;AAEA,UAAQ,IAAI,EAAE;AAChB;AAKO,SAAS,oBAA6B;AAC3C,QAAM,UAAU,IAAIC,SAAQ,MAAM;AAElC,UACG,YAAY,yCAAyC,EACrD,OAAO,MAAM;AACZ,QAAI;AAEF,YAAM,gBAAgB,QAAQ,QAAQ,KAAK,KAAsB,CAAC;AAClE,eAAS,aAAa;AAAA,IACxB,SAAS,OAAO;AACd,MAAAD,QAAO,MAAM,EAAE,OAAQ,MAAgB,QAAQ,GAAG,qBAAqB;AACvE,cAAQ,MAAM,UAAW,MAAgB,OAAO,EAAE;AAClD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,SAAO;AACT;;;APzLA,IAAM,UAAU;AAEhB,IAAME,UAAS,aAAa,KAAK;AAa1B,SAAS,gBAAyB;AACvC,QAAM,UAAU,IAAIC,SAAQ;AAE5B,UACG,KAAK,eAAe,EACpB,YAAY,kFAAkF,EAC9F,QAAQ,SAAS,iBAAiB,2BAA2B,EAC7D,OAAO,iBAAiB,wBAAwB,EAChD,OAAO,mBAAmB,qBAAqB;AAGlD,UAAQ,KAAK,aAAa,CAAC,gBAAgB;AACzC,UAAM,OAAO,YAAY,KAAK;AAC9B,QAAI,KAAK,SAAS;AAEhB,cAAQ,IAAI,YAAY;AAAA,IAC1B;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAKO,SAAS,iBAAiB,SAAiC;AAChE,SAAO,QAAQ,KAAK;AACtB;AAKA,eAAsB,OAAsB;AAC1C,QAAM,UAAU,cAAc;AAG9B,UAAQ,WAAW,mBAAmB,CAAC;AACvC,UAAQ,WAAW,kBAAkB,CAAC;AACtC,UAAQ,WAAW,oBAAoB,CAAC;AACxC,UAAQ,WAAW,qBAAqB,CAAC;AACzC,UAAQ,WAAW,sBAAsB,CAAC;AAC1C,UAAQ,WAAW,kBAAkB,CAAC;AAGtC,QAAM,QAAQ,WAAW,QAAQ,IAAI;AACvC;AAGA,KAAK,EAAE,MAAM,CAAC,UAAiB;AAC7B,EAAAD,QAAO,MAAM,EAAE,KAAK,MAAM,GAAG,WAAW;AACxC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["Command","logger","Command","fs","path","os","logger","getPidFilePath","removePidFile","Command","Command","fs","path","os","logger","getPidFilePath","readPidFile","isProcessRunning","Command","Command","logger","Command","Command","logger","Command","Command","fs","path","os","logger","Command","logger","Command"]}
1
+ {"version":3,"sources":["../src/cli/index.ts","../src/cli/commands/start.ts","../src/cli/utils.ts","../src/cli/commands/stop.ts","../src/cli/commands/status.ts","../src/cli/commands/connect.ts","../src/cli/commands/discover.ts","../src/cli/commands/info.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry point for claude-code-bridge\n *\n * Commands:\n * start Start the bridge server\n * stop Stop the running bridge\n * status Show bridge status and connected peers\n * connect Connect to a remote bridge\n * discover Discover bridges on local network\n * info Show environment and configuration info\n *\n * Global options:\n * --verbose, -v Enable verbose logging\n * --config Path to config file\n */\n\nimport { Command } from 'commander';\nimport { createLogger } from '../utils/logger.js';\nimport { createStartCommand } from './commands/start.js';\nimport { createStopCommand } from './commands/stop.js';\nimport { createStatusCommand } from './commands/status.js';\nimport { createConnectCommand } from './commands/connect.js';\nimport { createDiscoverCommand } from './commands/discover.js';\nimport { createInfoCommand } from './commands/info.js';\n\n// Read version from package.json\n// Since we're building with tsup, we import it directly\nconst VERSION = '0.1.0';\n\nconst logger = createLogger('cli');\n\n/**\n * Global options interface\n */\nexport interface GlobalOptions {\n verbose?: boolean;\n config?: string;\n}\n\n/**\n * Create and configure the CLI program\n */\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name('claude-bridge')\n .description('Bidirectional communication system for Claude Code instances across environments')\n .version(VERSION, '-V, --version', 'Output the version number')\n .option('-v, --verbose', 'Enable verbose logging')\n .option('--config <path>', 'Path to config file');\n\n // Hook to process global options before commands\n program.hook('preAction', (thisCommand) => {\n const opts = thisCommand.opts() as GlobalOptions;\n if (opts.verbose) {\n // Set log level to debug when verbose is enabled\n process.env.LOG_LEVEL = 'debug';\n }\n });\n\n return program;\n}\n\n/**\n * Get global options from the program\n */\nexport function getGlobalOptions(program: Command): GlobalOptions {\n return program.opts() as GlobalOptions;\n}\n\n/**\n * Main CLI entry point\n */\nexport async function main(): Promise<void> {\n const program = createProgram();\n\n // Add commands\n program.addCommand(createStartCommand());\n program.addCommand(createStopCommand());\n program.addCommand(createStatusCommand());\n program.addCommand(createConnectCommand());\n program.addCommand(createDiscoverCommand());\n program.addCommand(createInfoCommand());\n\n // Parse arguments and execute\n await program.parseAsync(process.argv);\n}\n\n// Run CLI if executed directly\nmain().catch((error: Error) => {\n logger.error({ err: error }, 'CLI error');\n process.exit(1);\n});\n\n// Export for programmatic use\nexport { createProgram as createCLI };\n","/**\n * CLI start command - Start the bridge server\n *\n * Options:\n * --port, -p Port to listen on (default: 8765 in container, 8766 native)\n * --host, -h Host to bind to (default: 0.0.0.0)\n * --connect, -c URL to connect to on startup\n * --auto, -a Auto-detect environment and configure\n * --daemon, -d Run in background\n * --with-handlers Enable file reading and task handling capabilities\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { minimatch } from 'minimatch';\nimport { createLogger } from '../../utils/logger.js';\nimport { loadConfigSync, type BridgeConfig as UtilsBridgeConfig } from '../../utils/config.js';\nimport { Bridge, type BridgeConfig, type BridgeMode, type TaskRequest, type FileChunk } from '../../bridge/core.js';\nimport { detectEnvironment, getDefaultConfig } from '../../environment/detect.js';\nimport { setupGracefulShutdown, handleUnhandledRejections } from '../utils.js';\nimport type { GlobalOptions } from '../index.js';\n\nconst logger = createLogger('cli:start');\n\n/**\n * Options for the start command\n */\nexport interface StartCommandOptions {\n port?: string;\n host?: string;\n connect?: string;\n auto?: boolean;\n daemon?: boolean;\n withHandlers?: boolean;\n}\n\n/**\n * Get the PID file path\n */\nfunction getPidFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'bridge.pid');\n}\n\n/**\n * Ensure the .claude-bridge directory exists\n */\nfunction ensureBridgeDir(): void {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n if (!fs.existsSync(bridgeDir)) {\n fs.mkdirSync(bridgeDir, { recursive: true });\n }\n}\n\n/**\n * Write PID file for daemon mode\n */\nfunction writePidFile(pid: number): void {\n ensureBridgeDir();\n const pidFile = getPidFilePath();\n fs.writeFileSync(pidFile, pid.toString(), 'utf-8');\n}\n\n/**\n * Remove PID file on shutdown\n */\nfunction removePidFile(): void {\n const pidFile = getPidFilePath();\n if (fs.existsSync(pidFile)) {\n fs.unlinkSync(pidFile);\n }\n}\n\n/**\n * Check if a bridge is already running by checking the PID file\n */\nfunction isAlreadyRunning(): { running: boolean; pid?: number } {\n const pidFile = getPidFilePath();\n if (!fs.existsSync(pidFile)) {\n return { running: false };\n }\n\n try {\n const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);\n // Check if process is still running\n process.kill(pid, 0); // Signal 0 checks existence without killing\n return { running: true, pid };\n } catch {\n // Process doesn't exist, clean up stale PID file\n removePidFile();\n return { running: false };\n }\n}\n\n/**\n * Get all files in a directory recursively\n */\nfunction getFilesRecursively(dir: string, baseDir: string = dir): string[] {\n const files: string[] = [];\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = path.relative(baseDir, fullPath);\n\n if (entry.isDirectory()) {\n // Skip common directories\n if (['node_modules', '.git', 'dist', 'build', '.next', 'coverage'].includes(entry.name)) {\n continue;\n }\n files.push(...getFilesRecursively(fullPath, baseDir));\n } else if (entry.isFile()) {\n files.push(relativePath);\n }\n }\n } catch {\n // Ignore permission errors\n }\n\n return files;\n}\n\n/**\n * Check if a file matches any of the patterns\n */\nfunction matchesPatterns(filePath: string, patterns: string[]): boolean {\n return patterns.some(pattern => minimatch(filePath, pattern, { dot: true }));\n}\n\n/**\n * Read file contents safely\n */\nfunction readFileSafe(filePath: string, maxSize: number = 100000): string | null {\n try {\n const stats = fs.statSync(filePath);\n if (stats.size > maxSize) {\n return `[File too large: ${stats.size} bytes]`;\n }\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n}\n\n/**\n * Register handlers for file reading and task processing\n */\nfunction registerHandlers(\n bridge: Bridge,\n config: { includePatterns: string[]; excludePatterns: string[] }\n): void {\n const cwd = process.cwd();\n\n // Handler for context requests - find and return relevant files\n bridge.onContextRequested(async (query: string, peerId: string): Promise<FileChunk[]> => {\n logger.info({ query, peerId }, 'Context requested');\n\n const files = getFilesRecursively(cwd);\n const chunks: FileChunk[] = [];\n const queryLower = query.toLowerCase();\n const queryTerms = queryLower.split(/\\s+/).filter(t => t.length > 2);\n\n for (const file of files) {\n // Check exclude patterns\n if (matchesPatterns(file, config.excludePatterns)) {\n continue;\n }\n\n // Check if file matches query or include patterns\n const fileLower = file.toLowerCase();\n const matchesQuery = queryTerms.some(term => fileLower.includes(term));\n const matchesInclude = matchesPatterns(file, config.includePatterns);\n\n if (matchesQuery || matchesInclude) {\n const fullPath = path.join(cwd, file);\n const content = readFileSafe(fullPath);\n\n if (content !== null) {\n chunks.push({\n path: file,\n content,\n language: path.extname(file).slice(1) || undefined,\n });\n }\n\n // Limit number of files returned\n if (chunks.length >= 20) {\n break;\n }\n }\n }\n\n logger.info({ fileCount: chunks.length, query }, 'Context response prepared');\n return chunks;\n });\n\n // Handler for incoming tasks\n bridge.onTaskReceived(async (task: TaskRequest, peerId: string) => {\n logger.info({ taskId: task.id, description: task.description, peerId }, 'Task received');\n\n // Check for file operations in task data\n const taskData = task.data as Record<string, unknown> | undefined;\n\n // Handle file write action\n if (taskData?.action === 'write_file') {\n const filePath = taskData.path as string;\n const content = taskData.content as string;\n\n if (!filePath || content === undefined) {\n return {\n success: false,\n data: { error: 'write_file requires path and content' },\n };\n }\n\n // Resolve path relative to cwd\n const fullPath = path.isAbsolute(filePath) ? filePath : path.join(cwd, filePath);\n\n // Security: ensure path is within cwd\n const resolvedPath = path.resolve(fullPath);\n const resolvedCwd = path.resolve(cwd);\n if (!resolvedPath.startsWith(resolvedCwd)) {\n return {\n success: false,\n data: { error: 'Cannot write files outside project directory' },\n };\n }\n\n try {\n // Ensure parent directory exists\n const parentDir = path.dirname(resolvedPath);\n if (!fs.existsSync(parentDir)) {\n fs.mkdirSync(parentDir, { recursive: true });\n }\n\n fs.writeFileSync(resolvedPath, content, 'utf-8');\n logger.info({ path: filePath }, 'File written successfully');\n\n return {\n success: true,\n data: {\n action: 'write_file',\n path: filePath,\n bytesWritten: Buffer.byteLength(content, 'utf-8'),\n },\n };\n } catch (err) {\n logger.error({ error: (err as Error).message, path: filePath }, 'Failed to write file');\n return {\n success: false,\n data: { error: `Failed to write file: ${(err as Error).message}` },\n };\n }\n }\n\n // Handle file read action\n if (taskData?.action === 'read_file') {\n const filePath = taskData.path as string;\n\n if (!filePath) {\n return {\n success: false,\n data: { error: 'read_file requires path' },\n };\n }\n\n const fullPath = path.isAbsolute(filePath) ? filePath : path.join(cwd, filePath);\n const content = readFileSafe(fullPath);\n\n if (content === null) {\n return {\n success: false,\n data: { error: `Cannot read file: ${filePath}` },\n };\n }\n\n return {\n success: true,\n data: {\n action: 'read_file',\n path: filePath,\n content,\n },\n };\n }\n\n // Handle delete file action\n if (taskData?.action === 'delete_file') {\n const filePath = taskData.path as string;\n\n if (!filePath) {\n return {\n success: false,\n data: { error: 'delete_file requires path' },\n };\n }\n\n const fullPath = path.isAbsolute(filePath) ? filePath : path.join(cwd, filePath);\n\n // Security: ensure path is within cwd\n const resolvedPath = path.resolve(fullPath);\n const resolvedCwd = path.resolve(cwd);\n if (!resolvedPath.startsWith(resolvedCwd)) {\n return {\n success: false,\n data: { error: 'Cannot delete files outside project directory' },\n };\n }\n\n try {\n if (!fs.existsSync(resolvedPath)) {\n return {\n success: false,\n data: { error: `File not found: ${filePath}` },\n };\n }\n\n fs.unlinkSync(resolvedPath);\n logger.info({ path: filePath }, 'File deleted successfully');\n\n return {\n success: true,\n data: {\n action: 'delete_file',\n path: filePath,\n },\n };\n } catch (err) {\n logger.error({ error: (err as Error).message, path: filePath }, 'Failed to delete file');\n return {\n success: false,\n data: { error: `Failed to delete file: ${(err as Error).message}` },\n };\n }\n }\n\n // Default: Get project info for the response\n const projectInfo: Record<string, unknown> = {\n cwd,\n platform: process.platform,\n nodeVersion: process.version,\n };\n\n // Try to read package.json for project details\n const pkgPath = path.join(cwd, 'package.json');\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));\n projectInfo.name = pkg.name;\n projectInfo.version = pkg.version;\n projectInfo.description = pkg.description;\n projectInfo.dependencies = Object.keys(pkg.dependencies || {});\n projectInfo.devDependencies = Object.keys(pkg.devDependencies || {});\n } catch {\n // Ignore parse errors\n }\n }\n\n // List top-level files and directories\n try {\n const entries = fs.readdirSync(cwd, { withFileTypes: true });\n projectInfo.structure = entries\n .filter(e => !e.name.startsWith('.') && e.name !== 'node_modules')\n .map(e => ({\n name: e.name,\n type: e.isDirectory() ? 'directory' : 'file',\n }));\n } catch {\n // Ignore errors\n }\n\n // Get source files summary\n const allFiles = getFilesRecursively(cwd);\n const sourceFiles = allFiles.filter(f =>\n matchesPatterns(f, config.includePatterns) &&\n !matchesPatterns(f, config.excludePatterns)\n );\n projectInfo.sourceFileCount = sourceFiles.length;\n projectInfo.sourceFiles = sourceFiles.slice(0, 50); // First 50 files\n\n return {\n success: true,\n data: {\n message: `Task received and analyzed: ${task.description}`,\n scope: task.scope,\n projectInfo,\n },\n };\n });\n\n // Handler for incoming context sync\n bridge.onContextReceived((context, peerId) => {\n logger.info(\n {\n peerId,\n fileCount: context.files?.length || 0,\n summary: context.summary\n },\n 'Context received from peer'\n );\n\n if (context.files) {\n for (const file of context.files) {\n console.log(` 📄 Received: ${file.path} (${file.content?.length || 0} chars)`);\n }\n }\n if (context.summary) {\n console.log(` 📝 Summary: ${context.summary}`);\n }\n });\n\n logger.info('Handlers registered for context requests, tasks, and context sync');\n console.log(' Handlers: enabled (file reading & task processing)');\n}\n\n/**\n * Build bridge configuration from CLI options and config file\n */\nfunction buildBridgeConfig(\n options: StartCommandOptions,\n globalOptions: GlobalOptions\n): BridgeConfig {\n // Load config file first\n const fileConfig = loadConfigSync(globalOptions.config);\n\n // Detect environment if --auto is specified\n let envConfig: Partial<BridgeConfig> = {};\n if (options.auto) {\n const env = detectEnvironment();\n const defaultEnvConfig = getDefaultConfig(env);\n logger.info({ environment: env.type, isContainer: env.isContainer }, 'Auto-detected environment');\n\n // Map the environment defaults to BridgeConfig format\n envConfig = {\n mode: defaultEnvConfig.mode as BridgeMode,\n instanceName: defaultEnvConfig.instanceName,\n listen: defaultEnvConfig.listen,\n connect: defaultEnvConfig.connect,\n };\n }\n\n // CLI options override everything\n const cliConfig: Partial<BridgeConfig> = {};\n\n if (options.port) {\n cliConfig.listen = {\n ...cliConfig.listen,\n port: parseInt(options.port, 10),\n host: options.host ?? '0.0.0.0',\n };\n }\n\n if (options.host && !cliConfig.listen) {\n cliConfig.listen = {\n port: fileConfig.listen.port,\n host: options.host,\n };\n }\n\n if (options.connect) {\n cliConfig.connect = {\n url: options.connect,\n };\n }\n\n // Determine mode based on configuration\n let mode: BridgeMode = 'peer';\n const hasListen = cliConfig.listen || envConfig.listen || fileConfig.listen;\n const hasConnect = cliConfig.connect || envConfig.connect || fileConfig.connect;\n\n if (hasListen && !hasConnect) {\n mode = 'host';\n } else if (hasConnect && !hasListen) {\n mode = 'client';\n }\n\n // Build final config with priority: CLI > env auto-detect > file config > defaults\n const finalConfig: BridgeConfig = {\n mode: cliConfig.mode ?? envConfig.mode ?? fileConfig.mode ?? mode,\n instanceName:\n cliConfig.instanceName ??\n envConfig.instanceName ??\n fileConfig.instanceName ??\n `bridge-${process.pid}`,\n listen: {\n port: cliConfig.listen?.port ?? envConfig.listen?.port ?? fileConfig.listen.port,\n host: cliConfig.listen?.host ?? envConfig.listen?.host ?? fileConfig.listen.host,\n },\n taskTimeout: fileConfig.interaction.taskTimeout,\n contextSharing: {\n autoSync: fileConfig.contextSharing.autoSync,\n syncInterval: fileConfig.contextSharing.syncInterval,\n },\n };\n\n // Add connect config if present\n const connectUrl = cliConfig.connect?.url ?? envConfig.connect?.url ?? fileConfig.connect?.url;\n if (connectUrl) {\n finalConfig.connect = {\n url: connectUrl,\n };\n }\n\n return finalConfig;\n}\n\n/**\n * Start the bridge server\n */\nasync function startBridge(\n options: StartCommandOptions,\n globalOptions: GlobalOptions\n): Promise<void> {\n // Check if already running\n const { running, pid } = isAlreadyRunning();\n if (running) {\n console.error(`Bridge is already running (PID: ${pid})`);\n process.exit(1);\n }\n\n // Build configuration\n const config = buildBridgeConfig(options, globalOptions);\n\n // Log startup info\n console.log('Starting Claude Code Bridge...');\n console.log(` Instance: ${config.instanceName}`);\n console.log(` Mode: ${config.mode}`);\n\n if (config.listen) {\n console.log(` Listening: ${config.listen.host}:${config.listen.port}`);\n }\n\n if (config.connect) {\n console.log(` Connecting to: ${config.connect.url}`);\n }\n\n // Handle daemon mode\n if (options.daemon) {\n // For daemon mode, we would fork the process\n // For now, just write PID and continue (simplified implementation)\n console.log(' Running in daemon mode');\n writePidFile(process.pid);\n }\n\n // Create and start bridge\n const bridge = new Bridge(config);\n\n // Set up graceful shutdown handling\n setupGracefulShutdown({\n cleanup: async () => {\n logger.info('Stopping bridge...');\n await bridge.stop();\n logger.info('Bridge stopped');\n },\n afterCleanup: options.daemon ? removePidFile : undefined,\n verbose: true,\n timeout: 10000,\n });\n\n // Handle unhandled promise rejections\n handleUnhandledRejections({\n exit: false,\n logger: (msg, err) => logger.error({ error: err.message }, msg),\n });\n\n // Load config for handler patterns\n const fileConfig = loadConfigSync(globalOptions.config);\n\n try {\n await bridge.start();\n\n // Register handlers if --with-handlers is enabled\n if (options.withHandlers) {\n registerHandlers(bridge, {\n includePatterns: fileConfig.contextSharing.includePatterns,\n excludePatterns: fileConfig.contextSharing.excludePatterns,\n });\n }\n\n // Write PID file if running in daemon mode\n if (options.daemon) {\n writePidFile(process.pid);\n }\n\n console.log('Bridge started successfully.');\n console.log(`Connected peers: ${bridge.getPeerCount()}`);\n\n // Log connection info for users\n if (config.listen) {\n console.log(`\\nTo connect from another bridge:`);\n console.log(` claude-bridge connect ws://localhost:${config.listen.port}`);\n }\n\n // Keep the process running\n if (!options.daemon) {\n console.log('\\nPress Ctrl+C to stop.');\n }\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to start bridge');\n console.error(`Failed to start bridge: ${(error as Error).message}`);\n if (options.daemon) {\n removePidFile();\n }\n process.exit(1);\n }\n}\n\n/**\n * Create the start command\n */\nexport function createStartCommand(): Command {\n const command = new Command('start');\n\n command\n .description('Start the bridge server')\n .option('-p, --port <port>', 'Port to listen on (default: 8765 in container, 8766 native)')\n .option('-h, --host <host>', 'Host to bind to (default: 0.0.0.0)')\n .option('-c, --connect <url>', 'URL to connect to on startup (e.g., ws://localhost:8765)')\n .option('-a, --auto', 'Auto-detect environment and configure')\n .option('-d, --daemon', 'Run in background')\n .option('--with-handlers', 'Enable file reading and task handling capabilities')\n .action(async (options: StartCommandOptions) => {\n // Get global options from parent command\n const globalOptions = command.parent?.opts() as GlobalOptions;\n await startBridge(options, globalOptions);\n });\n\n return command;\n}\n\n/**\n * Export the command for use in CLI\n */\nexport { createStartCommand as startCommand };\n","/**\n * CLI output formatting utilities\n *\n * Provides helpers for colored output, table formatting, progress spinners,\n * and option parsing/validation.\n */\n\n/**\n * ANSI color codes for terminal output\n */\nexport const colors = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n\n // Foreground colors\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n gray: '\\x1b[90m',\n} as const;\n\n/**\n * Check if terminal supports colors\n */\nexport function supportsColor(): boolean {\n // Disable colors if NO_COLOR env var is set\n if (process.env.NO_COLOR !== undefined) {\n return false;\n }\n\n // Enable colors if FORCE_COLOR is set\n if (process.env.FORCE_COLOR !== undefined) {\n return true;\n }\n\n // Check if stdout is a TTY\n if (typeof process.stdout.isTTY !== 'undefined' && process.stdout.isTTY) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Apply color to text (only if terminal supports it)\n */\nexport function colorize(text: string, color: keyof typeof colors): string {\n if (!supportsColor()) {\n return text;\n }\n return `${colors[color]}${text}${colors.reset}`;\n}\n\n/**\n * Print success message (green)\n */\nexport function success(message: string): void {\n console.log(colorize('✓ ' + message, 'green'));\n}\n\n/**\n * Print error message (red)\n */\nexport function error(message: string): void {\n console.error(colorize('✗ ' + message, 'red'));\n}\n\n/**\n * Print warning message (yellow)\n */\nexport function warning(message: string): void {\n console.log(colorize('⚠ ' + message, 'yellow'));\n}\n\n/**\n * Print info message (blue)\n */\nexport function info(message: string): void {\n console.log(colorize('ℹ ' + message, 'blue'));\n}\n\n/**\n * Print debug message (gray)\n */\nexport function debug(message: string): void {\n console.log(colorize('⋯ ' + message, 'gray'));\n}\n\n/**\n * Table column configuration\n */\nexport interface TableColumn {\n title: string;\n width: number;\n align?: 'left' | 'right' | 'center';\n}\n\n/**\n * Table row data (key-value pairs matching column titles)\n */\nexport type TableRow = Record<string, string | number | undefined>;\n\n/**\n * Pad a string to a specific width with alignment\n */\nexport function padToWidth(\n text: string,\n width: number,\n align: 'left' | 'right' | 'center' = 'left'\n): string {\n const str = String(text).slice(0, width);\n const padding = width - str.length;\n\n if (align === 'right') {\n return ' '.repeat(padding) + str;\n } else if (align === 'center') {\n const leftPad = Math.floor(padding / 2);\n const rightPad = padding - leftPad;\n return ' '.repeat(leftPad) + str + ' '.repeat(rightPad);\n } else {\n return str + ' '.repeat(padding);\n }\n}\n\n/**\n * Print a formatted table\n */\nexport function printTable(\n columns: TableColumn[],\n rows: TableRow[],\n options: { indent?: number; borderStyle?: 'simple' | 'none' } = {}\n): void {\n const indent = ' '.repeat(options.indent ?? 0);\n const borderStyle = options.borderStyle ?? 'simple';\n\n // Print header\n const headerRow = columns\n .map((col) => padToWidth(col.title, col.width, col.align))\n .join(' ');\n console.log(indent + colorize(headerRow, 'bold'));\n\n // Print separator\n if (borderStyle === 'simple') {\n const separator = columns\n .map((col) => '-'.repeat(col.width))\n .join(' ');\n console.log(indent + separator);\n }\n\n // Print rows\n for (const row of rows) {\n const rowText = columns\n .map((col) => {\n // Find matching key case-insensitively\n const key = Object.keys(row).find(\n (k) => k.toLowerCase() === col.title.toLowerCase()\n );\n const value = key ? String(row[key] ?? '') : '';\n return padToWidth(value, col.width, col.align);\n })\n .join(' ');\n console.log(indent + rowText);\n }\n}\n\n/**\n * Spinner frames for progress indication\n */\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\n/**\n * Progress spinner for long operations\n */\nexport class Spinner {\n private message: string;\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private frameIndex = 0;\n private stream = process.stdout;\n\n constructor(message: string) {\n this.message = message;\n }\n\n /**\n * Start the spinner animation\n */\n start(): void {\n if (!supportsColor() || !this.stream.isTTY) {\n // Non-TTY: just print the message once\n console.log(`... ${this.message}`);\n return;\n }\n\n // Hide cursor\n this.stream.write('\\x1b[?25l');\n\n this.intervalId = setInterval(() => {\n const frame = SPINNER_FRAMES[this.frameIndex];\n this.stream.write(\n `\\r${colorize(frame, 'cyan')} ${this.message}`\n );\n this.frameIndex = (this.frameIndex + 1) % SPINNER_FRAMES.length;\n }, 80);\n }\n\n /**\n * Update the spinner message\n */\n update(message: string): void {\n this.message = message;\n }\n\n /**\n * Stop the spinner with a success message\n */\n succeed(message?: string): void {\n this.stop();\n success(message ?? this.message);\n }\n\n /**\n * Stop the spinner with an error message\n */\n fail(message?: string): void {\n this.stop();\n error(message ?? this.message);\n }\n\n /**\n * Stop the spinner with a warning message\n */\n warn(message?: string): void {\n this.stop();\n warning(message ?? this.message);\n }\n\n /**\n * Stop the spinner (no message)\n */\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n\n if (supportsColor() && this.stream.isTTY) {\n // Clear line and show cursor\n this.stream.write('\\r\\x1b[K');\n this.stream.write('\\x1b[?25h');\n }\n }\n}\n\n/**\n * Create and start a new spinner\n */\nexport function spinner(message: string): Spinner {\n const s = new Spinner(message);\n s.start();\n return s;\n}\n\n/**\n * Parsed start command options\n */\nexport interface ParsedStartOptions {\n listen?: {\n port: number;\n host: string;\n };\n connect?: {\n url: string;\n };\n autoDetect: boolean;\n daemon: boolean;\n}\n\n/**\n * Parse and validate start command options\n */\nexport function parseStartOptions(options: {\n port?: string;\n host?: string;\n connect?: string;\n auto?: boolean;\n daemon?: boolean;\n}): ParsedStartOptions {\n const result: ParsedStartOptions = {\n autoDetect: options.auto ?? false,\n daemon: options.daemon ?? false,\n };\n\n // Parse port\n if (options.port) {\n const port = parseInt(options.port, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n throw new Error(`Invalid port: ${options.port}. Must be between 1 and 65535.`);\n }\n result.listen = {\n port,\n host: options.host ?? '0.0.0.0',\n };\n } else if (options.host) {\n // Host specified without port, use default port\n result.listen = {\n port: 8765,\n host: options.host,\n };\n }\n\n // Parse connect URL\n if (options.connect) {\n validateWebSocketUrl(options.connect);\n result.connect = {\n url: options.connect,\n };\n }\n\n return result;\n}\n\n/**\n * Validate a WebSocket URL\n */\nexport function validateWebSocketUrl(url: string): void {\n if (!url.startsWith('ws://') && !url.startsWith('wss://')) {\n throw new Error(\n `Invalid URL protocol. Expected ws:// or wss://, got: ${url}`\n );\n }\n\n try {\n const parsed = new URL(url);\n if (!parsed.hostname) {\n throw new Error('URL must include a hostname');\n }\n } catch (e) {\n if (e instanceof Error && e.message.includes('Invalid URL')) {\n throw new Error(`Invalid URL format: ${url}`);\n }\n throw e;\n }\n}\n\n/**\n * Parsed connect command options\n */\nexport interface ParsedConnectOptions {\n url: string;\n}\n\n/**\n * Parse and validate connect command options\n */\nexport function parseConnectOptions(options: {\n url?: string;\n}): ParsedConnectOptions {\n if (!options.url) {\n throw new Error('URL is required');\n }\n\n validateWebSocketUrl(options.url);\n\n return {\n url: options.url,\n };\n}\n\n/**\n * Format duration in human-readable form\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n if (ms < 60000) {\n return `${(ms / 1000).toFixed(1)}s`;\n }\n if (ms < 3600000) {\n const minutes = Math.floor(ms / 60000);\n const seconds = Math.round((ms % 60000) / 1000);\n return `${minutes}m ${seconds}s`;\n }\n const hours = Math.floor(ms / 3600000);\n const minutes = Math.round((ms % 3600000) / 60000);\n return `${hours}h ${minutes}m`;\n}\n\n/**\n * Format bytes in human-readable form\n */\nexport function formatBytes(bytes: number): string {\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n let unitIndex = 0;\n let value = bytes;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex++;\n }\n\n return `${value.toFixed(unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`;\n}\n\n/**\n * Shutdown handler type\n */\nexport type ShutdownHandler = (signal: string) => Promise<void>;\n\n/**\n * Options for setting up graceful shutdown\n */\nexport interface GracefulShutdownOptions {\n /**\n * Cleanup function to call on shutdown\n */\n cleanup: () => Promise<void>;\n\n /**\n * Additional cleanup to call after main cleanup (e.g., removing PID file)\n */\n afterCleanup?: () => void;\n\n /**\n * Whether to show shutdown messages\n * @default true\n */\n verbose?: boolean;\n\n /**\n * Timeout in milliseconds before forcing exit\n * @default 10000\n */\n timeout?: number;\n}\n\n/**\n * Set up graceful shutdown handlers for SIGTERM and SIGINT\n *\n * Handles process signals to ensure clean shutdown of bridges and connections.\n * - SIGTERM: Sent by `kill` command or process managers\n * - SIGINT: Sent by Ctrl+C in terminal\n *\n * @param options Shutdown configuration options\n * @returns Function to remove the handlers (for testing)\n */\nexport function setupGracefulShutdown(options: GracefulShutdownOptions): () => void {\n const {\n cleanup,\n afterCleanup,\n verbose = true,\n timeout = 10000,\n } = options;\n\n let isShuttingDown = false;\n\n const handler: ShutdownHandler = async (signal: string) => {\n // Prevent multiple shutdown attempts\n if (isShuttingDown) {\n if (verbose) {\n console.log('Shutdown already in progress...');\n }\n return;\n }\n isShuttingDown = true;\n\n if (verbose) {\n console.log(`\\nReceived ${signal}, shutting down gracefully...`);\n }\n\n // Set up force exit timeout\n const forceExitTimeout = setTimeout(() => {\n if (verbose) {\n console.error('Shutdown timeout - forcing exit');\n }\n process.exit(1);\n }, timeout);\n\n try {\n await cleanup();\n\n if (afterCleanup) {\n afterCleanup();\n }\n\n clearTimeout(forceExitTimeout);\n\n if (verbose) {\n console.log('Shutdown complete.');\n }\n process.exit(0);\n } catch (error) {\n clearTimeout(forceExitTimeout);\n if (verbose) {\n console.error(`Error during shutdown: ${(error as Error).message}`);\n }\n process.exit(1);\n }\n };\n\n // Register handlers\n const sigintHandler = () => handler('SIGINT');\n const sigtermHandler = () => handler('SIGTERM');\n\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n // Return cleanup function\n return () => {\n process.off('SIGINT', sigintHandler);\n process.off('SIGTERM', sigtermHandler);\n };\n}\n\n/**\n * Handle unhandled promise rejections\n *\n * Logs unhandled rejections and optionally exits the process.\n *\n * @param options Configuration options\n */\nexport function handleUnhandledRejections(options: {\n exit?: boolean;\n logger?: (message: string, error: Error) => void;\n} = {}): void {\n const { exit = false, logger = console.error } = options;\n\n process.on('unhandledRejection', (reason, promise) => {\n const error = reason instanceof Error ? reason : new Error(String(reason));\n logger('Unhandled promise rejection:', error);\n\n if (exit) {\n process.exit(1);\n }\n });\n}\n","/**\n * CLI stop command - Stop the running bridge\n *\n * Reads the PID from ~/.claude-bridge/bridge.pid and sends SIGTERM\n * to gracefully stop the running bridge process.\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { createLogger } from '../../utils/logger.js';\n\nconst logger = createLogger('cli:stop');\n\n/**\n * Get the PID file path\n */\nfunction getPidFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'bridge.pid');\n}\n\n/**\n * Remove PID file\n */\nfunction removePidFile(): void {\n const pidFile = getPidFilePath();\n if (fs.existsSync(pidFile)) {\n fs.unlinkSync(pidFile);\n }\n}\n\n/**\n * Read PID from file\n * Returns null if file doesn't exist or is invalid\n */\nfunction readPidFile(): number | null {\n const pidFile = getPidFilePath();\n if (!fs.existsSync(pidFile)) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(pidFile, 'utf-8').trim();\n const pid = parseInt(content, 10);\n if (isNaN(pid) || pid <= 0) {\n logger.warn({ content }, 'Invalid PID file content');\n return null;\n }\n return pid;\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to read PID file');\n return null;\n }\n}\n\n/**\n * Check if a process is running\n */\nfunction isProcessRunning(pid: number): boolean {\n try {\n // Signal 0 checks if the process exists without sending a signal\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Wait for a process to exit with timeout\n */\nasync function waitForProcessExit(\n pid: number,\n timeoutMs: number = 5000\n): Promise<boolean> {\n const startTime = Date.now();\n const checkInterval = 100;\n\n while (Date.now() - startTime < timeoutMs) {\n if (!isProcessRunning(pid)) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, checkInterval));\n }\n\n return false;\n}\n\n/**\n * Stop the bridge process\n */\nasync function stopBridge(): Promise<void> {\n const pid = readPidFile();\n\n if (pid === null) {\n console.log('Bridge is not running (no PID file found).');\n return;\n }\n\n // Check if process is actually running\n if (!isProcessRunning(pid)) {\n console.log(`Bridge is not running (stale PID file, process ${pid} not found).`);\n // Clean up stale PID file\n removePidFile();\n return;\n }\n\n console.log(`Stopping bridge (PID: ${pid})...`);\n\n try {\n // Send SIGTERM for graceful shutdown\n process.kill(pid, 'SIGTERM');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ESRCH') {\n // Process doesn't exist\n console.log('Bridge process not found.');\n removePidFile();\n return;\n }\n if ((error as NodeJS.ErrnoException).code === 'EPERM') {\n console.error(`Permission denied: cannot stop bridge (PID: ${pid}).`);\n console.error('Try running with elevated privileges.');\n process.exit(1);\n }\n throw error;\n }\n\n // Wait for process to exit\n const exited = await waitForProcessExit(pid);\n\n if (exited) {\n console.log('Bridge stopped successfully.');\n // Clean up PID file if the process didn't do it\n removePidFile();\n } else {\n console.log('Bridge is still shutting down. Check status with: claude-bridge status');\n // Optionally could try SIGKILL here, but we'll leave that to the user\n console.log(`To force stop: kill -9 ${pid}`);\n }\n}\n\n/**\n * Create the stop command\n */\nexport function createStopCommand(): Command {\n const command = new Command('stop');\n\n command\n .description('Stop the running bridge')\n .action(async () => {\n try {\n await stopBridge();\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to stop bridge');\n console.error(`Failed to stop bridge: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createStopCommand as stopCommand };\n","/**\n * CLI status command - Show bridge status and connected peers\n *\n * Displays whether the bridge is running, what port it's on,\n * and lists connected peers in a formatted table.\n *\n * Options:\n * --port Check status for a specific port\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { createLogger } from '../../utils/logger.js';\n\nconst logger = createLogger('cli:status');\n\n/**\n * Options for the status command\n */\nexport interface StatusCommandOptions {\n port?: string;\n}\n\n/**\n * Bridge status information\n */\nexport interface BridgeStatus {\n running: boolean;\n pid?: number;\n port?: number;\n peers?: PeerStatus[];\n}\n\n/**\n * Peer status information\n */\nexport interface PeerStatus {\n id: string;\n name: string;\n connectedAt: string;\n lastActivity: string;\n}\n\n/**\n * Get the PID file path\n */\nfunction getPidFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'bridge.pid');\n}\n\n/**\n * Get the status file path (where bridge writes current status)\n */\nfunction getStatusFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'status.json');\n}\n\n/**\n * Read PID from file\n */\nfunction readPidFile(): number | null {\n const pidFile = getPidFilePath();\n if (!fs.existsSync(pidFile)) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(pidFile, 'utf-8').trim();\n const pid = parseInt(content, 10);\n if (isNaN(pid) || pid <= 0) {\n return null;\n }\n return pid;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a process is running\n */\nfunction isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read status file written by the bridge\n */\nfunction readStatusFile(): { port?: number; peers?: PeerStatus[] } | null {\n const statusFile = getStatusFilePath();\n if (!fs.existsSync(statusFile)) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(statusFile, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Format a date for display\n */\nfunction formatDate(dateStr: string): string {\n try {\n const date = new Date(dateStr);\n return date.toLocaleString();\n } catch {\n return dateStr;\n }\n}\n\n/**\n * Pad a string to a specific width\n */\nfunction padRight(str: string, width: number): string {\n return str.padEnd(width);\n}\n\n/**\n * Print peer table\n */\nfunction printPeerTable(peers: PeerStatus[]): void {\n if (peers.length === 0) {\n console.log(' No peers connected.');\n return;\n }\n\n // Column headers and widths\n const cols = {\n id: { title: 'ID', width: 38 },\n name: { title: 'Name', width: 20 },\n connected: { title: 'Connected', width: 22 },\n lastActivity: { title: 'Last Activity', width: 22 },\n };\n\n // Print header\n console.log('');\n console.log(\n ' ' +\n padRight(cols.id.title, cols.id.width) +\n padRight(cols.name.title, cols.name.width) +\n padRight(cols.connected.title, cols.connected.width) +\n padRight(cols.lastActivity.title, cols.lastActivity.width)\n );\n\n // Print separator\n const separator =\n ' ' +\n '-'.repeat(cols.id.width - 1) +\n ' ' +\n '-'.repeat(cols.name.width - 1) +\n ' ' +\n '-'.repeat(cols.connected.width - 1) +\n ' ' +\n '-'.repeat(cols.lastActivity.width - 1);\n console.log(separator);\n\n // Print rows\n for (const peer of peers) {\n const row =\n ' ' +\n padRight(peer.id, cols.id.width) +\n padRight(peer.name.slice(0, cols.name.width - 1), cols.name.width) +\n padRight(formatDate(peer.connectedAt), cols.connected.width) +\n padRight(formatDate(peer.lastActivity), cols.lastActivity.width);\n console.log(row);\n }\n\n console.log('');\n}\n\n/**\n * Get bridge status\n */\nfunction getBridgeStatus(): BridgeStatus {\n const pid = readPidFile();\n\n if (pid === null) {\n return { running: false };\n }\n\n if (!isProcessRunning(pid)) {\n // PID file exists but process is not running\n return { running: false };\n }\n\n // Process is running, try to get more details\n const statusInfo = readStatusFile();\n\n return {\n running: true,\n pid,\n port: statusInfo?.port,\n peers: statusInfo?.peers,\n };\n}\n\n/**\n * Show bridge status\n */\nfunction showStatus(options: StatusCommandOptions): void {\n console.log('Claude Code Bridge Status');\n console.log('='.repeat(26));\n console.log('');\n\n const status = getBridgeStatus();\n\n if (!status.running) {\n console.log('Status: stopped');\n console.log('');\n console.log('To start the bridge:');\n console.log(' claude-bridge start');\n return;\n }\n\n console.log('Status: running');\n console.log(`PID: ${status.pid}`);\n\n if (status.port !== undefined) {\n console.log(`Port: ${status.port}`);\n }\n\n console.log('');\n console.log('Connected Peers:');\n\n if (status.peers) {\n printPeerTable(status.peers);\n } else {\n console.log(' Unable to retrieve peer information.');\n console.log(' (Status file not found or unreadable)');\n }\n\n console.log('To stop the bridge:');\n console.log(' claude-bridge stop');\n}\n\n/**\n * Create the status command\n */\nexport function createStatusCommand(): Command {\n const command = new Command('status');\n\n command\n .description('Show bridge status and connected peers')\n .option('-p, --port <port>', 'Check status for a specific port')\n .action((options: StatusCommandOptions) => {\n try {\n showStatus(options);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to get status');\n console.error(`Failed to get status: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createStatusCommand as statusCommand };\n","/**\n * CLI connect command - Connect to a remote bridge\n *\n * Takes a WebSocket URL and initiates a connection to a remote bridge.\n * This is a one-time connection test that verifies connectivity.\n *\n * Usage:\n * claude-bridge connect ws://localhost:8765\n */\n\nimport { Command } from 'commander';\nimport { createLogger } from '../../utils/logger.js';\nimport { WebSocketTransport } from '../../transport/websocket.js';\nimport { ConnectionState } from '../../transport/interface.js';\n\nconst logger = createLogger('cli:connect');\n\n/**\n * Validate WebSocket URL format\n * Returns true if valid, throws Error if invalid\n */\nexport function validateWebSocketUrl(url: string): boolean {\n // Check for ws:// or wss:// protocol\n if (!url.startsWith('ws://') && !url.startsWith('wss://')) {\n throw new Error(`Invalid URL protocol. Expected ws:// or wss://, got: ${url}`);\n }\n\n try {\n const parsed = new URL(url);\n\n // Ensure we have a valid hostname\n if (!parsed.hostname) {\n throw new Error('URL must include a hostname');\n }\n\n // Ensure we have a port (for WebSocket connections)\n if (!parsed.port) {\n // Default ports\n const defaultPort = parsed.protocol === 'wss:' ? '443' : '80';\n logger.debug(`No port specified, will use default: ${defaultPort}`);\n }\n\n return true;\n } catch (error) {\n if (error instanceof Error && error.message.includes('Invalid URL')) {\n throw new Error(`Invalid URL format: ${url}`);\n }\n throw error;\n }\n}\n\n/**\n * Connect to a remote bridge\n */\nasync function connectToBridge(url: string): Promise<void> {\n // Validate URL format\n try {\n validateWebSocketUrl(url);\n } catch (error) {\n console.error(`Error: ${(error as Error).message}`);\n process.exit(1);\n }\n\n console.log(`Connecting to bridge at ${url}...`);\n\n const transport = new WebSocketTransport();\n\n // Set up connection timeout\n const timeoutMs = 10000;\n const timeout = setTimeout(() => {\n console.error(`Error: Connection timeout after ${timeoutMs / 1000} seconds`);\n transport.disconnect().catch(() => {});\n process.exit(1);\n }, timeoutMs);\n\n try {\n // Attempt connection\n await transport.connect({\n url,\n reconnect: false, // Don't auto-reconnect for this test\n });\n\n clearTimeout(timeout);\n\n if (transport.getState() === ConnectionState.CONNECTED) {\n console.log('Successfully connected to bridge!');\n console.log('');\n console.log('Connection details:');\n console.log(` URL: ${url}`);\n console.log(` State: ${ConnectionState[transport.getState()]}`);\n console.log('');\n console.log('To start a bridge that auto-connects on startup:');\n console.log(` claude-bridge start --connect ${url}`);\n } else {\n console.error(`Connection failed. State: ${ConnectionState[transport.getState()]}`);\n process.exit(1);\n }\n\n // Clean up - disconnect after successful test\n await transport.disconnect();\n console.log('\\nConnection test complete. Disconnected.');\n } catch (error) {\n clearTimeout(timeout);\n const errorMessage = (error as Error).message;\n console.error(`Error: Failed to connect - ${errorMessage}`);\n\n // Provide helpful suggestions\n if (errorMessage.includes('ECONNREFUSED')) {\n console.log('');\n console.log('Suggestions:');\n console.log(' - Ensure a bridge is running at the specified address');\n console.log(' - Check the port number is correct');\n console.log(' - Verify no firewall is blocking the connection');\n } else if (errorMessage.includes('ENOTFOUND')) {\n console.log('');\n console.log('Suggestions:');\n console.log(' - Check the hostname is correct');\n console.log(' - Ensure DNS resolution is working');\n }\n\n process.exit(1);\n }\n}\n\n/**\n * Create the connect command\n */\nexport function createConnectCommand(): Command {\n const command = new Command('connect');\n\n command\n .description('Connect to a remote bridge')\n .argument('<url>', 'WebSocket URL to connect to (e.g., ws://localhost:8765)')\n .action(async (url: string) => {\n try {\n await connectToBridge(url);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Connect command failed');\n console.error(`Error: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createConnectCommand as connectCommand };\n","/**\n * CLI discover command - Discover bridges on local network\n *\n * Finds running Docker containers with bridge labels and\n * lists Docksal/DDEV/Lando projects with bridges.\n */\n\nimport { Command } from 'commander';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n type DiscoveredPeer,\n discoverDockerPeers,\n discoverDocksalProjects,\n discoverDdevProjects,\n discoverLandoProjects,\n} from '../../transport/discovery.js';\n\nconst logger = createLogger('cli:discover');\n\n/**\n * Print discovered peers table\n */\nfunction printPeersTable(peers: DiscoveredPeer[]): void {\n if (peers.length === 0) {\n console.log('No bridges found.');\n console.log('');\n console.log('Suggestions:');\n console.log(' - Start a bridge: claude-bridge start');\n console.log(' - Add bridge labels to Docker containers');\n console.log(' - Install bridge addon in your Docksal/DDEV project');\n return;\n }\n\n // Column widths\n const cols = {\n name: { title: 'Name', width: 25 },\n source: { title: 'Source', width: 12 },\n url: { title: 'URL', width: 35 },\n status: { title: 'Status', width: 12 },\n };\n\n // Print header\n console.log(\n cols.name.title.padEnd(cols.name.width) +\n cols.source.title.padEnd(cols.source.width) +\n cols.url.title.padEnd(cols.url.width) +\n cols.status.title.padEnd(cols.status.width)\n );\n\n // Print separator\n console.log(\n '-'.repeat(cols.name.width - 1) +\n ' ' +\n '-'.repeat(cols.source.width - 1) +\n ' ' +\n '-'.repeat(cols.url.width - 1) +\n ' ' +\n '-'.repeat(cols.status.width - 1)\n );\n\n // Print rows\n for (const peer of peers) {\n const row =\n peer.name.slice(0, cols.name.width - 1).padEnd(cols.name.width) +\n peer.source.padEnd(cols.source.width) +\n peer.url.slice(0, cols.url.width - 1).padEnd(cols.url.width) +\n (peer.status || 'unknown').padEnd(cols.status.width);\n console.log(row);\n }\n\n console.log('');\n console.log('To connect to a bridge:');\n console.log(' claude-bridge connect <url>');\n}\n\n/**\n * Discover all local bridges\n */\nasync function discoverBridges(): Promise<void> {\n console.log('Discovering bridges on local network...\\n');\n\n const allPeers: DiscoveredPeer[] = [];\n\n // Discover from all sources\n const dockerPeers = discoverDockerPeers();\n allPeers.push(...dockerPeers);\n logger.debug({ count: dockerPeers.length }, 'Docker peers discovered');\n\n const docksalPeers = discoverDocksalProjects();\n allPeers.push(...docksalPeers);\n logger.debug({ count: docksalPeers.length }, 'Docksal peers discovered');\n\n const ddevPeers = discoverDdevProjects();\n allPeers.push(...ddevPeers);\n logger.debug({ count: ddevPeers.length }, 'DDEV peers discovered');\n\n const landoPeers = discoverLandoProjects();\n allPeers.push(...landoPeers);\n logger.debug({ count: landoPeers.length }, 'Lando peers discovered');\n\n printPeersTable(allPeers);\n}\n\n/**\n * Create the discover command\n */\nexport function createDiscoverCommand(): Command {\n const command = new Command('discover');\n\n command\n .description('Discover bridges on local network')\n .action(async () => {\n try {\n await discoverBridges();\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Discover command failed');\n console.error(`Error: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createDiscoverCommand as discoverCommand };\n","/**\n * CLI info command - Show environment and configuration info\n *\n * Displays information about the current environment, detected\n * container type, network configuration, and loaded config values.\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { createLogger } from '../../utils/logger.js';\nimport { loadConfigSync, DEFAULT_CONFIG } from '../../utils/config.js';\nimport {\n detectEnvironment,\n getHostGateway,\n getDefaultConfig,\n} from '../../environment/detect.js';\nimport type { GlobalOptions } from '../index.js';\n\nconst logger = createLogger('cli:info');\n\n/**\n * Get the config file path that would be loaded\n */\nfunction getConfigFilePath(): string | null {\n // Check project local config first\n const localConfig = path.join(process.cwd(), '.claude-bridge.yml');\n if (fs.existsSync(localConfig)) {\n return localConfig;\n }\n\n // Check home directory\n const homeConfig = path.join(os.homedir(), '.claude-bridge', 'config.yml');\n if (fs.existsSync(homeConfig)) {\n return homeConfig;\n }\n\n return null;\n}\n\n/**\n * Format a value for display (handle undefined, objects, etc.)\n */\nfunction formatValue(value: unknown): string {\n if (value === undefined) {\n return '(not set)';\n }\n if (value === null) {\n return '(null)';\n }\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n return String(value);\n}\n\n/**\n * Print a section header\n */\nfunction printSection(title: string): void {\n console.log('');\n console.log(title);\n console.log('-'.repeat(title.length));\n}\n\n/**\n * Print a key-value pair\n */\nfunction printKeyValue(key: string, value: unknown, indent: number = 0): void {\n const prefix = ' '.repeat(indent);\n console.log(`${prefix}${key}: ${formatValue(value)}`);\n}\n\n/**\n * Show environment and configuration info\n */\nfunction showInfo(globalOptions: GlobalOptions): void {\n console.log('Claude Code Bridge - Environment Information');\n console.log('='.repeat(45));\n\n // Environment Detection\n printSection('Environment');\n const env = detectEnvironment();\n printKeyValue('Type', env.type);\n printKeyValue('Platform', env.platform);\n printKeyValue('Is Container', env.isContainer);\n printKeyValue('Project Name', env.projectName);\n printKeyValue('Project Root', env.projectRoot);\n\n // Network Configuration\n printSection('Network');\n const hostGateway = getHostGateway();\n const envDefaults = getDefaultConfig(env);\n const listenPort = envDefaults.listen?.port ?? 8765;\n const listenHost = envDefaults.listen?.host ?? '0.0.0.0';\n printKeyValue('Host Gateway', hostGateway);\n printKeyValue('Recommended Port', listenPort);\n printKeyValue('Default Host', listenHost);\n\n if (env.isContainer) {\n console.log('');\n console.log(' Note: To connect from host machine:');\n console.log(` ws://localhost:${listenPort}`);\n console.log('');\n console.log(' To connect to host from this container:');\n console.log(` ws://${hostGateway}:8766`);\n }\n\n // Configuration\n printSection('Configuration');\n const configPath = globalOptions.config || getConfigFilePath();\n printKeyValue('Config File', configPath || '(using defaults)');\n\n const config = loadConfigSync(globalOptions.config);\n\n console.log('');\n console.log(' Current Settings:');\n printKeyValue('Mode', config.mode, 2);\n printKeyValue('Instance Name', config.instanceName, 2);\n\n console.log('');\n console.log(' Listen:');\n printKeyValue('Port', config.listen.port, 2);\n printKeyValue('Host', config.listen.host, 2);\n\n console.log('');\n console.log(' Connect:');\n printKeyValue('URL', config.connect?.url, 2);\n\n console.log('');\n console.log(' Context Sharing:');\n printKeyValue('Auto Sync', config.contextSharing.autoSync, 2);\n printKeyValue('Sync Interval', `${config.contextSharing.syncInterval}ms`, 2);\n printKeyValue('Max Chunk Tokens', config.contextSharing.maxChunkTokens, 2);\n\n if (config.contextSharing.includePatterns.length > 0) {\n console.log(' Include Patterns:');\n for (const pattern of config.contextSharing.includePatterns) {\n console.log(` - ${pattern}`);\n }\n }\n\n if (config.contextSharing.excludePatterns.length > 0) {\n console.log(' Exclude Patterns:');\n for (const pattern of config.contextSharing.excludePatterns) {\n console.log(` - ${pattern}`);\n }\n }\n\n console.log('');\n console.log(' Interaction:');\n printKeyValue('Require Confirmation', config.interaction.requireConfirmation, 2);\n printKeyValue('Notify On Activity', config.interaction.notifyOnActivity, 2);\n printKeyValue('Task Timeout', `${config.interaction.taskTimeout}ms`, 2);\n\n // System Info\n printSection('System');\n printKeyValue('Node Version', process.version);\n printKeyValue('OS', `${os.type()} ${os.release()}`);\n printKeyValue('Arch', os.arch());\n printKeyValue('Home Directory', os.homedir());\n printKeyValue('Working Directory', process.cwd());\n\n // Environment Variables (relevant ones)\n printSection('Environment Variables');\n const relevantEnvVars = [\n 'DOCKSAL_STACK',\n 'DOCKSAL_PROJECT',\n 'IS_DDEV_PROJECT',\n 'DDEV_PROJECT',\n 'LANDO',\n 'LANDO_APP_NAME',\n 'LOG_LEVEL',\n ];\n\n let hasEnvVars = false;\n for (const varName of relevantEnvVars) {\n const value = process.env[varName];\n if (value !== undefined) {\n printKeyValue(varName, value);\n hasEnvVars = true;\n }\n }\n\n if (!hasEnvVars) {\n console.log(' (no relevant environment variables set)');\n }\n\n console.log('');\n}\n\n/**\n * Create the info command\n */\nexport function createInfoCommand(): Command {\n const command = new Command('info');\n\n command\n .description('Show environment and configuration info')\n .action(() => {\n try {\n // Get global options from parent command\n const globalOptions = command.parent?.opts() as GlobalOptions ?? {};\n showInfo(globalOptions);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Info command failed');\n console.error(`Error: ${(error as Error).message}`);\n process.exit(1);\n }\n });\n\n return command;\n}\n\n/**\n * Export for use in CLI\n */\nexport { createInfoCommand as infoCommand };\n"],"mappings":"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","names":["Command","logger","Command","fs","path","os","logger","getPidFilePath","removePidFile","resolve","Command","Command","fs","path","os","logger","getPidFilePath","readPidFile","isProcessRunning","Command","Command","logger","Command","Command","logger","Command","Command","fs","path","os","logger","Command","logger","Command"]}
package/dist/index.js CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  safeValidateMessage,
38
38
  serializeMessage,
39
39
  validateMessage
40
- } from "./chunk-IMMNNIX7.js";
40
+ } from "./chunk-VUR4SHJR.js";
41
41
 
42
42
  // src/bridge/context.ts
43
43
  import { readdirSync, readFileSync, statSync, realpathSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@willjackson/claude-code-bridge",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Bidirectional communication system for Claude Code instances across environments",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",