@willjackson/claude-code-bridge 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +9 -0
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -466,6 +466,15 @@ async function startBridge(options, globalOptions) {
|
|
|
466
466
|
if (!process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {
|
|
467
467
|
const { running, pid } = isAlreadyRunning();
|
|
468
468
|
if (running) {
|
|
469
|
+
if (options.launchClaude) {
|
|
470
|
+
console.log(`Bridge already running (PID: ${pid}), launching Claude Code...`);
|
|
471
|
+
const { spawnSync } = await import("child_process");
|
|
472
|
+
const result = spawnSync("claude", [], {
|
|
473
|
+
stdio: "inherit",
|
|
474
|
+
shell: true
|
|
475
|
+
});
|
|
476
|
+
process.exit(result.status ?? 0);
|
|
477
|
+
}
|
|
469
478
|
console.error(`Bridge is already running (PID: ${pid})`);
|
|
470
479
|
process.exit(1);
|
|
471
480
|
}
|
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/info.ts","../src/cli/commands/mcp-server.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 * info Show system 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 { createInfoCommand } from './commands/info.js';\nimport { createMcpServerCommand } from './commands/mcp-server.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(createInfoCommand());\n program.addCommand(createMcpServerCommand());\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)\n * --host, -h Host to bind to (default: 0.0.0.0)\n * --connect, -c URL to connect to on startup\n * --daemon, -d Run in background\n * --with-handlers Enable file reading and task handling capabilities\n * --launch-claude Start bridge daemon and launch Claude Code\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { spawn } from 'child_process';\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 { 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 daemon?: boolean;\n withHandlers?: boolean;\n launchClaude?: 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 // Handle list directory action\n if (taskData?.action === 'list_directory') {\n const dirPath = taskData.path as string;\n\n if (!dirPath) {\n return {\n success: false,\n data: { error: 'list_directory requires path' },\n };\n }\n\n const fullPath = path.isAbsolute(dirPath) ? dirPath : path.join(cwd, dirPath);\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 list directories outside project directory' },\n };\n }\n\n try {\n if (!fs.existsSync(resolvedPath)) {\n return {\n success: false,\n data: { error: `Directory not found: ${dirPath}` },\n };\n }\n\n const stats = fs.statSync(resolvedPath);\n if (!stats.isDirectory()) {\n return {\n success: false,\n data: { error: `Not a directory: ${dirPath}` },\n };\n }\n\n const entries = fs.readdirSync(resolvedPath, { withFileTypes: true });\n const listing = entries.map(entry => ({\n name: entry.name,\n type: entry.isDirectory() ? 'directory' : 'file',\n }));\n\n logger.info({ path: dirPath, count: listing.length }, 'Directory listed successfully');\n\n return {\n success: true,\n data: {\n action: 'list_directory',\n path: dirPath,\n entries: listing,\n },\n };\n } catch (err) {\n logger.error({ error: (err as Error).message, path: dirPath }, 'Failed to list directory');\n return {\n success: false,\n data: { error: `Failed to list directory: ${(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 // 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 || fileConfig.listen;\n const hasConnect = cliConfig.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 > file config > defaults\n const finalConfig: BridgeConfig = {\n mode: cliConfig.mode ?? fileConfig.mode ?? mode,\n instanceName: cliConfig.instanceName ?? fileConfig.instanceName ?? `bridge-${process.pid}`,\n listen: {\n port: cliConfig.listen?.port ?? fileConfig.listen.port,\n host: cliConfig.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 ?? 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 (skip check if we're the daemon child)\n if (!process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\n const { running, pid } = isAlreadyRunning();\n if (running) {\n console.error(`Bridge is already running (PID: ${pid})`);\n process.exit(1);\n }\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 - spawn detached child process\n if (options.daemon && !process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\n const logFile = path.join(os.homedir(), '.claude-bridge', 'bridge.log');\n ensureBridgeDir();\n\n // Build args for child process (exclude --daemon to prevent infinite loop)\n const args = process.argv.slice(2).filter(arg => arg !== '-d' && arg !== '--daemon');\n\n // Spawn detached child process\n const out = fs.openSync(logFile, 'a');\n const err = fs.openSync(logFile, 'a');\n\n const child = spawn(process.execPath, [process.argv[1], ...args], {\n detached: true,\n stdio: ['ignore', out, err],\n env: { ...process.env, CLAUDE_BRIDGE_DAEMON_CHILD: '1' },\n });\n\n child.unref();\n\n // Write child PID to file\n writePidFile(child.pid!);\n\n console.log(` Running in background (PID: ${child.pid})`);\n console.log(` Log file: ${logFile}`);\n console.log(` Use 'claude-bridge status' to check status`);\n console.log(` Use 'claude-bridge stop' to stop the bridge`);\n\n // Launch Claude Code if requested\n if (options.launchClaude) {\n console.log('\\nLaunching Claude Code...');\n\n // Give the daemon a moment to start\n await new Promise(resolve => setTimeout(resolve, 500));\n\n // Launch claude in the foreground (replaces this process)\n const { spawnSync } = await import('child_process');\n const result = spawnSync('claude', [], {\n stdio: 'inherit',\n shell: true,\n });\n\n process.exit(result.status ?? 0);\n }\n\n // Parent exits immediately\n process.exit(0);\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: process.env.CLAUDE_BRIDGE_DAEMON_CHILD ? 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 as daemon child (parent already wrote it, but update to confirm startup)\n if (process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\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 (!process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\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 (process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\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)')\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('-d, --daemon', 'Run in background')\n .option('--with-handlers', 'Enable file reading and task handling capabilities')\n .option('--launch-claude', 'Start bridge daemon and launch Claude Code')\n .action(async (options: StartCommandOptions) => {\n // --launch-claude implies --daemon\n if (options.launchClaude) {\n options.daemon = true;\n }\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 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 daemon?: boolean;\n}): ParsedStartOptions {\n const result: ParsedStartOptions = {\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 info command - Show system and configuration info\n *\n * Displays information about the current system, network configuration,\n * 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 } from '../../utils/config.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 system and configuration info\n */\nfunction showInfo(globalOptions: GlobalOptions): void {\n console.log('Claude Code Bridge - System Information');\n console.log('='.repeat(40));\n\n // System Info\n printSection('System');\n printKeyValue('Node Version', process.version);\n printKeyValue('OS', `${os.type()} ${os.release()}`);\n printKeyValue('Platform', process.platform);\n printKeyValue('Arch', os.arch());\n printKeyValue('Home Directory', os.homedir());\n printKeyValue('Working Directory', process.cwd());\n\n // Network\n printSection('Network');\n const interfaces = os.networkInterfaces();\n for (const [name, addrs] of Object.entries(interfaces)) {\n if (addrs) {\n for (const addr of addrs) {\n if (addr.family === 'IPv4' && !addr.internal) {\n printKeyValue(name, addr.address);\n }\n }\n }\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 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 system 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","/**\n * CLI mcp-server command - Start the MCP server for Claude Code integration\n *\n * Options:\n * --connect, -c Bridge WebSocket URL to connect to (default: ws://localhost:8766)\n * --name MCP server name (default: claude-bridge)\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { spawn } from 'child_process';\nimport { createLogger } from '../../utils/logger.js';\nimport { BridgeMcpServer, type McpServerConfig } from '../../mcp/server.js';\nimport { setupGracefulShutdown, handleUnhandledRejections } from '../utils.js';\nimport type { GlobalOptions } from '../index.js';\n\nconst logger = createLogger('cli:mcp-server');\n\n/**\n * Options for the mcp-server command\n */\nexport interface McpServerCommandOptions {\n connect?: string;\n name?: string;\n}\n\n/**\n * Default bridge daemon port\n */\nconst DEFAULT_DAEMON_PORT = 8766;\n\n/**\n * Get the status file path\n */\nfunction getStatusFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'status.json');\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 * Check if bridge daemon is running\n */\nfunction isDaemonRunning(): { running: boolean; pid?: number; port?: number } {\n const pidFile = getPidFilePath();\n\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\n // Try to read port from status file\n const statusFile = getStatusFilePath();\n if (fs.existsSync(statusFile)) {\n const status = JSON.parse(fs.readFileSync(statusFile, 'utf-8'));\n return { running: true, pid, port: status.port };\n }\n\n return { running: true, pid };\n } catch {\n // Process doesn't exist or status file invalid\n return { running: false };\n }\n}\n\n/**\n * Wait for daemon to be ready\n */\nasync function waitForDaemon(port: number, timeoutMs: number): Promise<void> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeoutMs) {\n const { running, port: runningPort } = isDaemonRunning();\n if (running && (runningPort === port || runningPort === undefined)) {\n // Give it a moment to be fully ready\n await new Promise(resolve => setTimeout(resolve, 500));\n return;\n }\n await new Promise(resolve => setTimeout(resolve, 200));\n }\n\n throw new Error(`Daemon did not start within ${timeoutMs}ms`);\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 * Start bridge daemon if not running\n */\nasync function ensureDaemonRunning(port: number): Promise<number> {\n const { running, pid, port: runningPort } = isDaemonRunning();\n\n if (running) {\n const effectivePort = runningPort ?? port;\n console.error(`[MCP] Bridge daemon already running (PID: ${pid}, port: ${effectivePort})`);\n return effectivePort;\n }\n\n console.error('[MCP] Starting bridge daemon...');\n ensureBridgeDir();\n\n const logFile = path.join(os.homedir(), '.claude-bridge', 'bridge.log');\n\n // Spawn daemon process\n const out = fs.openSync(logFile, 'a');\n const err = fs.openSync(logFile, 'a');\n\n // Find the CLI entry point\n // When running from npx or installed globally, process.argv[1] is the CLI script\n const cliPath = process.argv[1];\n\n const child = spawn(process.execPath, [cliPath, 'start', '--daemon', '--port', String(port)], {\n detached: true,\n stdio: ['ignore', out, err],\n });\n\n child.unref();\n\n console.error(`[MCP] Daemon starting (PID: ${child.pid})`);\n\n // Wait for daemon to be ready\n try {\n await waitForDaemon(port, 5000);\n console.error(`[MCP] Daemon ready on port ${port}`);\n return port;\n } catch (error) {\n console.error(`[MCP] Warning: Could not verify daemon is ready: ${(error as Error).message}`);\n // Continue anyway, the bridge connection will fail if daemon isn't running\n return port;\n }\n}\n\n/**\n * Start the MCP server\n */\nasync function startMcpServer(\n options: McpServerCommandOptions,\n _globalOptions: GlobalOptions\n): Promise<void> {\n // Parse connection URL\n let bridgeUrl = options.connect ?? `ws://localhost:${DEFAULT_DAEMON_PORT}`;\n\n // If no explicit URL provided, try to auto-start daemon\n if (!options.connect) {\n try {\n const port = await ensureDaemonRunning(DEFAULT_DAEMON_PORT);\n bridgeUrl = `ws://localhost:${port}`;\n } catch (error) {\n console.error(`[MCP] Warning: Could not ensure daemon is running: ${(error as Error).message}`);\n }\n }\n\n // Build MCP server config\n const config: McpServerConfig = {\n bridgeUrl,\n name: options.name ?? 'claude-bridge',\n version: '0.4.0',\n instanceName: `mcp-server-${process.pid}`,\n taskTimeout: 60000,\n };\n\n // Create and start MCP server\n const server = new BridgeMcpServer(config);\n\n // Set up graceful shutdown handling\n setupGracefulShutdown({\n cleanup: async () => {\n console.error('[MCP] Shutting down...');\n await server.stop();\n },\n verbose: false,\n timeout: 5000,\n });\n\n // Handle unhandled promise rejections\n handleUnhandledRejections({\n exit: true,\n logger: (msg, err) => {\n console.error(`[MCP] ${msg}: ${err.message}`);\n logger.error({ error: err.message }, msg);\n },\n });\n\n try {\n await server.start();\n // Server is now running and listening on stdio\n // It will keep running until interrupted\n } catch (error) {\n console.error(`[MCP] Failed to start MCP server: ${(error as Error).message}`);\n process.exit(1);\n }\n}\n\n/**\n * Create the mcp-server command\n */\nexport function createMcpServerCommand(): Command {\n const command = new Command('mcp-server');\n\n command\n .description('Start the MCP server for Claude Code integration')\n .option('-c, --connect <url>', `Bridge WebSocket URL (default: ws://localhost:${DEFAULT_DAEMON_PORT})`)\n .option('--name <name>', 'MCP server name (default: claude-bridge)')\n .action(async (options: McpServerCommandOptions) => {\n // Get global options from parent command\n const globalOptions = command.parent?.opts() as GlobalOptions;\n await startMcpServer(options, globalOptions);\n });\n\n return command;\n}\n\n/**\n * Export the command for use in CLI\n */\nexport { createMcpServerCommand as mcpServerCommand };\n"],"mappings":"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","names":["Command","logger","resolve","Command","fs","path","os","logger","getPidFilePath","removePidFile","resolve","Command","Command","fs","path","os","logger","getPidFilePath","readPidFile","isProcessRunning","Command","Command","logger","Command","Command","fs","path","os","logger","Command","Command","fs","path","os","spawn","logger","getStatusFilePath","getPidFilePath","resolve","ensureBridgeDir","spawn","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/info.ts","../src/cli/commands/mcp-server.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 * info Show system 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 { createInfoCommand } from './commands/info.js';\nimport { createMcpServerCommand } from './commands/mcp-server.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(createInfoCommand());\n program.addCommand(createMcpServerCommand());\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)\n * --host, -h Host to bind to (default: 0.0.0.0)\n * --connect, -c URL to connect to on startup\n * --daemon, -d Run in background\n * --with-handlers Enable file reading and task handling capabilities\n * --launch-claude Start bridge daemon and launch Claude Code\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { spawn } from 'child_process';\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 { 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 daemon?: boolean;\n withHandlers?: boolean;\n launchClaude?: 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 // Handle list directory action\n if (taskData?.action === 'list_directory') {\n const dirPath = taskData.path as string;\n\n if (!dirPath) {\n return {\n success: false,\n data: { error: 'list_directory requires path' },\n };\n }\n\n const fullPath = path.isAbsolute(dirPath) ? dirPath : path.join(cwd, dirPath);\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 list directories outside project directory' },\n };\n }\n\n try {\n if (!fs.existsSync(resolvedPath)) {\n return {\n success: false,\n data: { error: `Directory not found: ${dirPath}` },\n };\n }\n\n const stats = fs.statSync(resolvedPath);\n if (!stats.isDirectory()) {\n return {\n success: false,\n data: { error: `Not a directory: ${dirPath}` },\n };\n }\n\n const entries = fs.readdirSync(resolvedPath, { withFileTypes: true });\n const listing = entries.map(entry => ({\n name: entry.name,\n type: entry.isDirectory() ? 'directory' : 'file',\n }));\n\n logger.info({ path: dirPath, count: listing.length }, 'Directory listed successfully');\n\n return {\n success: true,\n data: {\n action: 'list_directory',\n path: dirPath,\n entries: listing,\n },\n };\n } catch (err) {\n logger.error({ error: (err as Error).message, path: dirPath }, 'Failed to list directory');\n return {\n success: false,\n data: { error: `Failed to list directory: ${(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 // 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 || fileConfig.listen;\n const hasConnect = cliConfig.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 > file config > defaults\n const finalConfig: BridgeConfig = {\n mode: cliConfig.mode ?? fileConfig.mode ?? mode,\n instanceName: cliConfig.instanceName ?? fileConfig.instanceName ?? `bridge-${process.pid}`,\n listen: {\n port: cliConfig.listen?.port ?? fileConfig.listen.port,\n host: cliConfig.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 ?? 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 (skip check if we're the daemon child)\n if (!process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\n const { running, pid } = isAlreadyRunning();\n if (running) {\n // If --launch-claude is set, just launch Claude Code and attach to existing bridge\n if (options.launchClaude) {\n console.log(`Bridge already running (PID: ${pid}), launching Claude Code...`);\n const { spawnSync } = await import('child_process');\n const result = spawnSync('claude', [], {\n stdio: 'inherit',\n shell: true,\n });\n process.exit(result.status ?? 0);\n }\n console.error(`Bridge is already running (PID: ${pid})`);\n process.exit(1);\n }\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 - spawn detached child process\n if (options.daemon && !process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\n const logFile = path.join(os.homedir(), '.claude-bridge', 'bridge.log');\n ensureBridgeDir();\n\n // Build args for child process (exclude --daemon to prevent infinite loop)\n const args = process.argv.slice(2).filter(arg => arg !== '-d' && arg !== '--daemon');\n\n // Spawn detached child process\n const out = fs.openSync(logFile, 'a');\n const err = fs.openSync(logFile, 'a');\n\n const child = spawn(process.execPath, [process.argv[1], ...args], {\n detached: true,\n stdio: ['ignore', out, err],\n env: { ...process.env, CLAUDE_BRIDGE_DAEMON_CHILD: '1' },\n });\n\n child.unref();\n\n // Write child PID to file\n writePidFile(child.pid!);\n\n console.log(` Running in background (PID: ${child.pid})`);\n console.log(` Log file: ${logFile}`);\n console.log(` Use 'claude-bridge status' to check status`);\n console.log(` Use 'claude-bridge stop' to stop the bridge`);\n\n // Launch Claude Code if requested\n if (options.launchClaude) {\n console.log('\\nLaunching Claude Code...');\n\n // Give the daemon a moment to start\n await new Promise(resolve => setTimeout(resolve, 500));\n\n // Launch claude in the foreground (replaces this process)\n const { spawnSync } = await import('child_process');\n const result = spawnSync('claude', [], {\n stdio: 'inherit',\n shell: true,\n });\n\n process.exit(result.status ?? 0);\n }\n\n // Parent exits immediately\n process.exit(0);\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: process.env.CLAUDE_BRIDGE_DAEMON_CHILD ? 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 as daemon child (parent already wrote it, but update to confirm startup)\n if (process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\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 (!process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\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 (process.env.CLAUDE_BRIDGE_DAEMON_CHILD) {\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)')\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('-d, --daemon', 'Run in background')\n .option('--with-handlers', 'Enable file reading and task handling capabilities')\n .option('--launch-claude', 'Start bridge daemon and launch Claude Code')\n .action(async (options: StartCommandOptions) => {\n // --launch-claude implies --daemon\n if (options.launchClaude) {\n options.daemon = true;\n }\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 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 daemon?: boolean;\n}): ParsedStartOptions {\n const result: ParsedStartOptions = {\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 info command - Show system and configuration info\n *\n * Displays information about the current system, network configuration,\n * 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 } from '../../utils/config.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 system and configuration info\n */\nfunction showInfo(globalOptions: GlobalOptions): void {\n console.log('Claude Code Bridge - System Information');\n console.log('='.repeat(40));\n\n // System Info\n printSection('System');\n printKeyValue('Node Version', process.version);\n printKeyValue('OS', `${os.type()} ${os.release()}`);\n printKeyValue('Platform', process.platform);\n printKeyValue('Arch', os.arch());\n printKeyValue('Home Directory', os.homedir());\n printKeyValue('Working Directory', process.cwd());\n\n // Network\n printSection('Network');\n const interfaces = os.networkInterfaces();\n for (const [name, addrs] of Object.entries(interfaces)) {\n if (addrs) {\n for (const addr of addrs) {\n if (addr.family === 'IPv4' && !addr.internal) {\n printKeyValue(name, addr.address);\n }\n }\n }\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 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 system 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","/**\n * CLI mcp-server command - Start the MCP server for Claude Code integration\n *\n * Options:\n * --connect, -c Bridge WebSocket URL to connect to (default: ws://localhost:8766)\n * --name MCP server name (default: claude-bridge)\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { spawn } from 'child_process';\nimport { createLogger } from '../../utils/logger.js';\nimport { BridgeMcpServer, type McpServerConfig } from '../../mcp/server.js';\nimport { setupGracefulShutdown, handleUnhandledRejections } from '../utils.js';\nimport type { GlobalOptions } from '../index.js';\n\nconst logger = createLogger('cli:mcp-server');\n\n/**\n * Options for the mcp-server command\n */\nexport interface McpServerCommandOptions {\n connect?: string;\n name?: string;\n}\n\n/**\n * Default bridge daemon port\n */\nconst DEFAULT_DAEMON_PORT = 8766;\n\n/**\n * Get the status file path\n */\nfunction getStatusFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'status.json');\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 * Check if bridge daemon is running\n */\nfunction isDaemonRunning(): { running: boolean; pid?: number; port?: number } {\n const pidFile = getPidFilePath();\n\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\n // Try to read port from status file\n const statusFile = getStatusFilePath();\n if (fs.existsSync(statusFile)) {\n const status = JSON.parse(fs.readFileSync(statusFile, 'utf-8'));\n return { running: true, pid, port: status.port };\n }\n\n return { running: true, pid };\n } catch {\n // Process doesn't exist or status file invalid\n return { running: false };\n }\n}\n\n/**\n * Wait for daemon to be ready\n */\nasync function waitForDaemon(port: number, timeoutMs: number): Promise<void> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeoutMs) {\n const { running, port: runningPort } = isDaemonRunning();\n if (running && (runningPort === port || runningPort === undefined)) {\n // Give it a moment to be fully ready\n await new Promise(resolve => setTimeout(resolve, 500));\n return;\n }\n await new Promise(resolve => setTimeout(resolve, 200));\n }\n\n throw new Error(`Daemon did not start within ${timeoutMs}ms`);\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 * Start bridge daemon if not running\n */\nasync function ensureDaemonRunning(port: number): Promise<number> {\n const { running, pid, port: runningPort } = isDaemonRunning();\n\n if (running) {\n const effectivePort = runningPort ?? port;\n console.error(`[MCP] Bridge daemon already running (PID: ${pid}, port: ${effectivePort})`);\n return effectivePort;\n }\n\n console.error('[MCP] Starting bridge daemon...');\n ensureBridgeDir();\n\n const logFile = path.join(os.homedir(), '.claude-bridge', 'bridge.log');\n\n // Spawn daemon process\n const out = fs.openSync(logFile, 'a');\n const err = fs.openSync(logFile, 'a');\n\n // Find the CLI entry point\n // When running from npx or installed globally, process.argv[1] is the CLI script\n const cliPath = process.argv[1];\n\n const child = spawn(process.execPath, [cliPath, 'start', '--daemon', '--port', String(port)], {\n detached: true,\n stdio: ['ignore', out, err],\n });\n\n child.unref();\n\n console.error(`[MCP] Daemon starting (PID: ${child.pid})`);\n\n // Wait for daemon to be ready\n try {\n await waitForDaemon(port, 5000);\n console.error(`[MCP] Daemon ready on port ${port}`);\n return port;\n } catch (error) {\n console.error(`[MCP] Warning: Could not verify daemon is ready: ${(error as Error).message}`);\n // Continue anyway, the bridge connection will fail if daemon isn't running\n return port;\n }\n}\n\n/**\n * Start the MCP server\n */\nasync function startMcpServer(\n options: McpServerCommandOptions,\n _globalOptions: GlobalOptions\n): Promise<void> {\n // Parse connection URL\n let bridgeUrl = options.connect ?? `ws://localhost:${DEFAULT_DAEMON_PORT}`;\n\n // If no explicit URL provided, try to auto-start daemon\n if (!options.connect) {\n try {\n const port = await ensureDaemonRunning(DEFAULT_DAEMON_PORT);\n bridgeUrl = `ws://localhost:${port}`;\n } catch (error) {\n console.error(`[MCP] Warning: Could not ensure daemon is running: ${(error as Error).message}`);\n }\n }\n\n // Build MCP server config\n const config: McpServerConfig = {\n bridgeUrl,\n name: options.name ?? 'claude-bridge',\n version: '0.4.0',\n instanceName: `mcp-server-${process.pid}`,\n taskTimeout: 60000,\n };\n\n // Create and start MCP server\n const server = new BridgeMcpServer(config);\n\n // Set up graceful shutdown handling\n setupGracefulShutdown({\n cleanup: async () => {\n console.error('[MCP] Shutting down...');\n await server.stop();\n },\n verbose: false,\n timeout: 5000,\n });\n\n // Handle unhandled promise rejections\n handleUnhandledRejections({\n exit: true,\n logger: (msg, err) => {\n console.error(`[MCP] ${msg}: ${err.message}`);\n logger.error({ error: err.message }, msg);\n },\n });\n\n try {\n await server.start();\n // Server is now running and listening on stdio\n // It will keep running until interrupted\n } catch (error) {\n console.error(`[MCP] Failed to start MCP server: ${(error as Error).message}`);\n process.exit(1);\n }\n}\n\n/**\n * Create the mcp-server command\n */\nexport function createMcpServerCommand(): Command {\n const command = new Command('mcp-server');\n\n command\n .description('Start the MCP server for Claude Code integration')\n .option('-c, --connect <url>', `Bridge WebSocket URL (default: ws://localhost:${DEFAULT_DAEMON_PORT})`)\n .option('--name <name>', 'MCP server name (default: claude-bridge)')\n .action(async (options: McpServerCommandOptions) => {\n // Get global options from parent command\n const globalOptions = command.parent?.opts() as GlobalOptions;\n await startMcpServer(options, globalOptions);\n });\n\n return command;\n}\n\n/**\n * Export the command for use in CLI\n */\nexport { createMcpServerCommand as mcpServerCommand };\n"],"mappings":"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","names":["Command","logger","resolve","Command","fs","path","os","logger","getPidFilePath","removePidFile","resolve","Command","Command","fs","path","os","logger","getPidFilePath","readPidFile","isProcessRunning","Command","Command","logger","Command","Command","fs","path","os","logger","Command","Command","fs","path","os","spawn","logger","getStatusFilePath","getPidFilePath","resolve","ensureBridgeDir","spawn","Command","logger","Command"]}
|