@tongil_kim/clautunnel 1.3.4 → 1.3.6

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/index.js CHANGED
@@ -2739,14 +2739,24 @@ var MobileServerManager = class {
2739
2739
  }
2740
2740
  installDependencies() {
2741
2741
  const nodeModulesPath = join5(this.mobileProjectPath, "node_modules");
2742
- if (existsSync4(nodeModulesPath)) return true;
2742
+ const repoRoot = join5(this.mobileProjectPath, "..", "..");
2743
+ const sharedDistPath = join5(repoRoot, "packages", "shared", "dist", "index.js");
2744
+ if (existsSync4(nodeModulesPath) && existsSync4(sharedDistPath)) return true;
2743
2745
  try {
2744
2746
  execSync2("pnpm install", {
2745
- cwd: this.mobileProjectPath,
2747
+ cwd: repoRoot,
2746
2748
  stdio: "pipe",
2747
2749
  timeout: 12e4
2748
2750
  // 2 minute timeout
2749
2751
  });
2752
+ const sharedDir = join5(repoRoot, "packages", "shared");
2753
+ if (existsSync4(join5(sharedDir, "tsconfig.json"))) {
2754
+ execSync2("pnpm build", {
2755
+ cwd: sharedDir,
2756
+ stdio: "pipe",
2757
+ timeout: 3e4
2758
+ });
2759
+ }
2750
2760
  return true;
2751
2761
  } catch {
2752
2762
  return false;
@@ -2873,7 +2883,8 @@ var MobileServerManager = class {
2873
2883
  await this.stop();
2874
2884
  return { started: false, error: "Failed to start Expo server" };
2875
2885
  }
2876
- const expoUrl = `exp+${tunnelUrl}`;
2886
+ const host = tunnelUrl.replace(/^https?:\/\//, "");
2887
+ const expoUrl = `exp://${host}:443`;
2877
2888
  console.log("");
2878
2889
  console.log(" Scan with Expo Go:");
2879
2890
  qrcode.generate(expoUrl, { small: true }, (code) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../packages/shared/dist/types/message.js","../../../packages/shared/dist/types/session.js","../../../packages/shared/dist/types/machine.js","../../../packages/shared/dist/types/presence.js","../../../packages/shared/src/types/index.ts","../../../packages/shared/src/constants/events.ts","../../../packages/shared/src/constants/index.ts","../../../packages/shared/src/index.ts","../src/index.ts","../src/utils/config.ts","../src/utils/logger.ts","../src/realtime/client.ts","../src/realtime/utils.ts","../src/daemon/session.ts","../src/daemon/machine.ts","../src/daemon/daemon.ts","../src/daemon/sdk-session.ts","../src/daemon/config-manager.ts","../src/commands/start.ts","../src/realtime/machine-client.ts","../src/utils/spinner.ts","../src/utils/supabase.ts","../src/utils/sleep-prevention.ts","../src/mobile/mobile-server.ts","../src/commands/stop.ts","../src/commands/status.ts","../src/commands/login.ts","../src/utils/prompt.ts","../src/commands/logout.ts","../src/commands/signup.ts","../src/commands/setup.ts","../src/commands/mobile-setup.ts"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=message.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=session.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=machine.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=presence.js.map","export * from './message.js';\nexport * from './session.js';\nexport * from './machine.js';\nexport * from './presence.js';\n","export const REALTIME_CHANNELS = {\n sessionOutput: (sessionId: string) => `session:${sessionId}:output`,\n sessionInput: (sessionId: string) => `session:${sessionId}:input`,\n sessionPresence: (sessionId: string) => `session:${sessionId}:presence`,\n machinePresence: (machineId: string) => `machine:${machineId}:presence`,\n machineInput: (machineId: string) => `machine:${machineId}:input`,\n machineOutput: (machineId: string) => `machine:${machineId}:output`,\n} as const;\n","export * from './events.js';\n","// Types\nexport * from './types/index.js';\n\n// Constants\nexport * from './constants/index.js';\n","#!/usr/bin/env node\n\nimport { config } from 'dotenv';\nimport { resolve, dirname } from 'path';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\n\n// ESM equivalent of __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Load .env from CLI package root (quiet mode to suppress dotenvx tips)\nconfig({ path: resolve(__dirname, '../.env'), quiet: true });\n\n// Read version from package.json\nconst packageJson = JSON.parse(\n readFileSync(resolve(__dirname, '../package.json'), 'utf-8')\n);\nconst version = packageJson.version || '0.0.0';\n\n// Library exports\nexport { Config, getConfig } from './utils/config.js';\nexport { Logger, getLogger } from './utils/logger.js';\nexport { RealtimeClient } from './realtime/client.js';\nexport { SessionManager } from './daemon/session.js';\nexport { MachineManager } from './daemon/machine.js';\nexport { Daemon } from './daemon/daemon.js';\n\n// CLI entry point\nimport { Command } from 'commander';\nimport { createStartCommand } from './commands/start.js';\nimport { createStopCommand } from './commands/stop.js';\nimport { createStatusCommand } from './commands/status.js';\nimport { createLoginCommand } from './commands/login.js';\nimport { createLogoutCommand } from './commands/logout.js';\nimport { createSignupCommand } from './commands/signup.js';\nimport { createSetupCommand } from './commands/setup.js';\nimport { createMobileSetupCommand } from './commands/mobile-setup.js';\n\nconst program = new Command();\n\nprogram\n .name('clautunnel')\n .description('Remote control for Claude Code CLI')\n .version(version);\n\nprogram.addCommand(createSetupCommand());\nprogram.addCommand(createStartCommand());\nprogram.addCommand(createStopCommand());\nprogram.addCommand(createStatusCommand());\nprogram.addCommand(createLoginCommand());\nprogram.addCommand(createLogoutCommand());\nprogram.addCommand(createSignupCommand());\nprogram.addCommand(createMobileSetupCommand());\n\n// Only parse when run directly (not when imported as library)\nif (process.argv[1]?.includes('clautunnel') || process.argv[1]?.endsWith('/index.js') || process.argv[1]?.endsWith('/index.ts')) {\n program.parse();\n}\n","import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nexport class ConfigurationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ConfigurationError';\n }\n}\n\ninterface ConfigData {\n machineId?: string;\n sessionTokens?: {\n accessToken: string;\n refreshToken: string;\n };\n supabaseUrl?: string;\n supabaseAnonKey?: string;\n mobileProjectPath?: string;\n}\n\nexport class Config {\n private configDir: string;\n private configFile: string;\n private data: ConfigData;\n\n constructor(configDir?: string) {\n this.configDir = configDir ?? join(homedir(), '.clautunnel');\n this.configFile = join(this.configDir, 'config.json');\n if (!configDir) {\n this.migrateFromLegacy();\n }\n this.data = this.loadConfig();\n }\n\n private migrateFromLegacy(): void {\n const legacyDir = join(homedir(), '.termbridge');\n if (existsSync(legacyDir) && !existsSync(this.configDir)) {\n renameSync(legacyDir, this.configDir);\n console.log(`Migrated config from ~/.termbridge to ~/.clautunnel`);\n }\n }\n\n private loadConfig(): ConfigData {\n if (existsSync(this.configFile)) {\n try {\n return JSON.parse(readFileSync(this.configFile, 'utf-8'));\n } catch {\n return {};\n }\n }\n return {};\n }\n\n private saveConfig(): void {\n if (!existsSync(this.configDir)) {\n mkdirSync(this.configDir, { recursive: true });\n }\n writeFileSync(this.configFile, JSON.stringify(this.data, null, 2));\n }\n\n getSupabaseUrl(): string {\n // Prefer env var over config file\n const url = process.env['SUPABASE_URL'] || this.data.supabaseUrl;\n if (!url) {\n throw new Error('SUPABASE_URL environment variable is not set');\n }\n\n // Validate URL format\n try {\n new URL(url);\n } catch {\n throw new Error('SUPABASE_URL must be a valid URL');\n }\n\n return url;\n }\n\n getSupabaseAnonKey(): string {\n // Prefer env var over config file\n const key = process.env['SUPABASE_ANON_KEY'] || this.data.supabaseAnonKey;\n if (!key) {\n throw new Error('SUPABASE_ANON_KEY environment variable is not set');\n }\n return key;\n }\n\n setSupabaseCredentials(credentials: { url: string; anonKey: string }): void {\n this.data.supabaseUrl = credentials.url;\n this.data.supabaseAnonKey = credentials.anonKey;\n this.saveConfig();\n }\n\n isConfigured(): boolean {\n const hasEnvVars = !!(process.env['SUPABASE_URL'] && process.env['SUPABASE_ANON_KEY']);\n const hasConfigFile = !!(this.data.supabaseUrl && this.data.supabaseAnonKey);\n return hasEnvVars || hasConfigFile;\n }\n\n requireConfiguration(): void {\n if (!this.isConfigured()) {\n throw new ConfigurationError(\n 'ClauTunnel is not configured.\\n\\n' +\n 'Run \"clautunnel setup\" to configure your Supabase credentials.\\n\\n' +\n 'Or set environment variables in your shell profile (~/.zshrc or ~/.bashrc):\\n' +\n ' export SUPABASE_URL=https://<project-id>.supabase.co\\n' +\n ' export SUPABASE_ANON_KEY=<your-anon-key>'\n );\n }\n }\n\n getMachineId(): string | undefined {\n return this.data.machineId;\n }\n\n setMachineId(machineId: string): void {\n this.data.machineId = machineId;\n this.saveConfig();\n }\n\n getSessionTokens(): ConfigData['sessionTokens'] | undefined {\n return this.data.sessionTokens;\n }\n\n setSessionTokens(tokens: ConfigData['sessionTokens']): void {\n this.data.sessionTokens = tokens;\n this.saveConfig();\n }\n\n // Alias for setSessionTokens\n setSession(tokens: { accessToken: string; refreshToken: string }): void {\n this.setSessionTokens(tokens);\n }\n\n clearSessionTokens(): void {\n delete this.data.sessionTokens;\n this.saveConfig();\n }\n\n getMobileProjectPath(): string | undefined {\n return this.data.mobileProjectPath;\n }\n\n setMobileProjectPath(path: string): void {\n this.data.mobileProjectPath = path;\n this.saveConfig();\n }\n}\n\n// Default singleton instance\nlet defaultConfig: Config | null = null;\n\nexport function getConfig(): Config {\n if (!defaultConfig) {\n defaultConfig = new Config();\n }\n return defaultConfig;\n}\n","type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport class Logger {\n private silent: boolean;\n private debugEnabled: boolean;\n\n constructor() {\n this.silent = process.env['SILENT'] === 'true';\n this.debugEnabled = process.env['DEBUG'] === 'true';\n }\n\n private formatTimestamp(): string {\n const now = new Date();\n return now.toTimeString().split(' ')[0] ?? now.toISOString();\n }\n\n private formatMessage(level: LogLevel, message: string, data?: object): string {\n const timestamp = this.formatTimestamp();\n const levelStr = level.toUpperCase().padEnd(5);\n let formatted = `[${timestamp}] [${levelStr}] ${message}`;\n\n if (data) {\n formatted += ` ${JSON.stringify(data)}`;\n }\n\n return formatted;\n }\n\n debug(message: string, data?: object): void {\n if (this.silent || !this.debugEnabled) return;\n console.log(this.formatMessage('debug', message, data));\n }\n\n info(message: string, data?: object): void {\n if (this.silent) return;\n console.log(this.formatMessage('info', message, data));\n }\n\n warn(message: string, data?: object): void {\n if (this.silent) return;\n console.warn(this.formatMessage('warn', message, data));\n }\n\n error(message: string, data?: object): void {\n if (this.silent) return;\n console.error(this.formatMessage('error', message, data));\n }\n}\n\n// Default singleton instance\nlet defaultLogger: Logger | null = null;\n\nexport function getLogger(): Logger {\n if (!defaultLogger) {\n defaultLogger = new Logger();\n }\n return defaultLogger;\n}\n","import { EventEmitter } from 'events';\nimport type { SupabaseClient, RealtimeChannel } from '@supabase/supabase-js';\nimport type {\n RealtimeMessage,\n ModelInfo,\n PermissionMode,\n SlashCommand,\n InteractiveCommandData,\n InteractiveCommandType,\n InteractiveResult,\n PresencePayload,\n UserQuestionData,\n PermissionRequestData,\n ToolUseData,\n} from 'clautunnel-shared';\nimport { REALTIME_CHANNELS } from 'clautunnel-shared';\nimport { subscribeWithTimeout } from './utils.js';\n\nexport interface RealtimeClientOptions {\n supabase: SupabaseClient;\n sessionId: string;\n}\n\nexport class RealtimeClient extends EventEmitter {\n private supabase: SupabaseClient;\n private sessionId: string;\n private outputChannel: RealtimeChannel | null = null;\n private inputChannel: RealtimeChannel | null = null;\n private presenceChannel: RealtimeChannel | null = null;\n private seq: number = 0;\n private realtimeEnabled: boolean = false;\n\n constructor(options: RealtimeClientOptions) {\n super();\n this.supabase = options.supabase;\n this.sessionId = options.sessionId;\n }\n\n async connect(): Promise<void> {\n // Subscribe to output channel (CLI broadcasts to mobile)\n const outputChannelName = REALTIME_CHANNELS.sessionOutput(this.sessionId);\n this.outputChannel = this.supabase.channel(outputChannelName);\n\n // Subscribe to input channel (mobile sends to CLI)\n const inputChannelName = REALTIME_CHANNELS.sessionInput(this.sessionId);\n this.inputChannel = this.supabase.channel(inputChannelName);\n\n this.inputChannel.on('broadcast', { event: 'input' }, (payload) => {\n this.emit('input', payload.payload as RealtimeMessage);\n });\n\n const results = await Promise.all([\n subscribeWithTimeout(this.outputChannel, 'output'),\n subscribeWithTimeout(this.inputChannel, 'input'),\n ]);\n\n // Only enable realtime if both channels subscribed successfully\n this.realtimeEnabled = results.every((success) => success);\n\n // Set up presence channel to track CLI online status\n if (this.realtimeEnabled) {\n const presenceChannelName = REALTIME_CHANNELS.sessionPresence(this.sessionId);\n this.presenceChannel = this.supabase.channel(presenceChannelName);\n\n // Subscribe and track presence - re-track on every SUBSCRIBED (handles reconnection)\n this.presenceChannel.subscribe(async (status, err) => {\n if (status === 'SUBSCRIBED' && this.presenceChannel) {\n try {\n const payload: PresencePayload = {\n type: 'cli',\n online_at: new Date().toISOString(),\n };\n await this.presenceChannel.track(payload);\n } catch (trackError) {\n // Presence tracking is non-critical - log and continue\n console.warn('[WARN] Failed to track presence:', trackError);\n }\n } else if (status === 'CHANNEL_ERROR') {\n // Presence is non-critical - log and continue\n console.warn('[WARN] Presence channel error:', err?.message || 'Unknown error');\n }\n });\n }\n\n this.emit('connected');\n }\n\n async disconnect(): Promise<void> {\n // Untrack presence before disconnecting\n if (this.presenceChannel) {\n await this.presenceChannel.untrack();\n await this.supabase.removeChannel(this.presenceChannel);\n this.presenceChannel = null;\n }\n\n if (this.outputChannel) {\n await this.supabase.removeChannel(this.outputChannel);\n this.outputChannel = null;\n }\n\n if (this.inputChannel) {\n await this.supabase.removeChannel(this.inputChannel);\n this.inputChannel = null;\n }\n\n this.emit('disconnected');\n }\n\n async broadcast(content: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n const message: RealtimeMessage = {\n type: 'output',\n content,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n // Persist message to database for history\n try {\n const { error } = await this.supabase.from('messages').insert({\n session_id: this.sessionId,\n type: message.type,\n content: message.content,\n seq: message.seq,\n });\n if (error) {\n console.warn('[WARN] Failed to persist message:', error.message);\n }\n } catch (error) {\n // Log but don't fail - message persistence is secondary to realtime\n console.warn('[WARN] Failed to persist message:', error);\n }\n\n // Skip realtime broadcasting if not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n try {\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n } catch (error) {\n throw error;\n }\n\n this.emit('broadcast', message);\n }\n\n async broadcastMode(mode: PermissionMode): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'mode',\n permissionMode: mode,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastCommands(commands: SlashCommand[]): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'commands',\n commands,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastModel(model: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'model',\n model,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastModels(models: ModelInfo[]): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'models',\n availableModels: models,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastSystem(content: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n const message: RealtimeMessage = {\n type: 'system',\n content,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n // Persist message to database for history\n try {\n const { error } = await this.supabase.from('messages').insert({\n session_id: this.sessionId,\n type: message.type,\n content: message.content,\n seq: message.seq,\n });\n if (error) {\n console.warn('[WARN] Failed to persist system message:', error.message);\n }\n } catch (error) {\n console.warn('[WARN] Failed to persist system message:', error);\n }\n\n // Skip realtime broadcasting if not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n try {\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n } catch (error) {\n throw error;\n }\n\n this.emit('broadcast', message);\n }\n\n async broadcastInteractiveResponse(data: InteractiveCommandData): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'interactive-response',\n interactiveData: data,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastInteractiveConfirm(\n command: InteractiveCommandType,\n result: InteractiveResult\n ): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'interactive-confirm',\n interactiveCommand: command,\n interactiveResult: result,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastResumeHistory(historySessionId: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'resume-history',\n historySessionId,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastUserQuestion(questionData: UserQuestionData): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'user-question',\n userQuestion: questionData,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastPermissionRequest(requestData: PermissionRequestData): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'permission-request',\n permissionRequest: requestData,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastToolUse(toolUseData: ToolUseData): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n const message: RealtimeMessage = {\n type: 'tool-use',\n toolUseData,\n content: JSON.stringify(toolUseData),\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n // Persist to database for history\n try {\n const { error } = await this.supabase.from('messages').insert({\n session_id: this.sessionId,\n type: message.type,\n content: message.content,\n seq: message.seq,\n });\n if (error) {\n console.warn('[WARN] Failed to persist tool-use message:', error.message);\n }\n } catch (error) {\n console.warn('[WARN] Failed to persist tool-use message:', error);\n }\n\n // Skip realtime broadcasting if not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n try {\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n } catch (error) {\n throw error;\n }\n\n this.emit('broadcast', message);\n }\n\n async broadcastComplete(): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'complete',\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastSessionTitle(title: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'session-title',\n sessionTitle: title,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastQueued(): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'request-queued',\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastError(errorMessage: string, errorCode?: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'error',\n content: errorMessage,\n errorCode: errorCode || 'unknown',\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n getSeq(): number {\n return this.seq;\n }\n\n isConnected(): boolean {\n return this.outputChannel !== null && this.inputChannel !== null;\n }\n\n isRealtimeEnabled(): boolean {\n return this.realtimeEnabled;\n }\n}\n","import type { RealtimeChannel } from '@supabase/supabase-js';\n\nconst DEFAULT_TIMEOUT = 10000;\n\nexport function subscribeWithTimeout(\n channel: RealtimeChannel,\n channelName: string,\n timeout: number = DEFAULT_TIMEOUT\n): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n let lastStatus = 'unknown';\n\n const timer = setTimeout(() => {\n console.warn(\n `[WARN] Realtime subscription timeout for ${channelName} (last status: ${lastStatus}).`\n );\n resolve(false);\n }, timeout);\n\n channel.subscribe((status, err) => {\n lastStatus = status;\n\n if (status === 'SUBSCRIBED') {\n clearTimeout(timer);\n resolve(true);\n } else if (\n status === 'CHANNEL_ERROR' ||\n status === 'CLOSED' ||\n status === 'TIMED_OUT'\n ) {\n clearTimeout(timer);\n console.warn(\n `[WARN] Channel ${channelName} ${status.toLowerCase()}.`\n );\n if (err) {\n console.warn(`[WARN] Error details: ${err.message || err}`);\n }\n resolve(false);\n }\n });\n });\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type { Session, SessionStatus } from 'clautunnel-shared';\n\nexport interface SessionManagerOptions {\n supabase: SupabaseClient;\n}\n\nexport class SessionManager {\n private supabase: SupabaseClient;\n\n constructor(options: SessionManagerOptions) {\n this.supabase = options.supabase;\n }\n\n async createSession(\n machineId: string,\n workingDirectory?: string\n ): Promise<Session> {\n const { data, error } = await this.supabase\n .from('sessions')\n .insert({\n machine_id: machineId,\n status: 'active' as SessionStatus,\n working_directory: workingDirectory,\n started_at: new Date().toISOString(),\n })\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create session: ${error.message}`);\n }\n\n return data as Session;\n }\n\n async endSession(sessionId: string): Promise<void> {\n const { error } = await this.supabase\n .from('sessions')\n .update({\n status: 'ended' as SessionStatus,\n ended_at: new Date().toISOString(),\n })\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to end session: ${error.message}`);\n }\n }\n\n async getSession(sessionId: string): Promise<Session | null> {\n const { data, error } = await this.supabase\n .from('sessions')\n .select()\n .eq('id', sessionId)\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n // Not found\n return null;\n }\n throw new Error(`Failed to get session: ${error.message}`);\n }\n\n return data as Session;\n }\n\n async updateSessionStatus(\n sessionId: string,\n status: SessionStatus\n ): Promise<void> {\n const updates: Partial<Session> = { status };\n\n if (status === 'ended') {\n updates.ended_at = new Date().toISOString();\n }\n\n const { error } = await this.supabase\n .from('sessions')\n .update(updates)\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to update session status: ${error.message}`);\n }\n }\n\n async updateSessionModel(\n sessionId: string,\n model: string\n ): Promise<void> {\n const { error } = await this.supabase\n .from('sessions')\n .update({ model })\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to update session model: ${error.message}`);\n }\n }\n\n async updateSdkSessionId(\n sessionId: string,\n sdkSessionId: string\n ): Promise<void> {\n const { error } = await this.supabase\n .from('sessions')\n .update({ sdk_session_id: sdkSessionId })\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to update SDK session ID: ${error.message}`);\n }\n }\n\n async updateSessionTitle(\n sessionId: string,\n title: string\n ): Promise<void> {\n const { error } = await this.supabase\n .from('sessions')\n .update({ title })\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to update session title: ${error.message}`);\n }\n }\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type { Machine, MachineStatus } from 'clautunnel-shared';\nimport * as os from 'os';\n\nexport interface MachineManagerOptions {\n supabase: SupabaseClient;\n}\n\nexport class MachineManager {\n private supabase: SupabaseClient;\n\n constructor(options: MachineManagerOptions) {\n this.supabase = options.supabase;\n }\n\n async registerMachine(\n userId: string,\n name?: string,\n machineId?: string\n ): Promise<Machine> {\n const hostname = os.hostname();\n const machineName = name || hostname;\n\n // If machineId provided, try to update existing machine\n if (machineId) {\n const existing = await this.getMachine(machineId);\n if (existing) {\n await this.updateMachineStatus(machineId, 'online');\n return existing;\n }\n }\n\n // Check if machine with same user_id and hostname already exists\n const { data: existingByHostname } = await this.supabase\n .from('machines')\n .select()\n .eq('user_id', userId)\n .eq('hostname', hostname)\n .single();\n\n if (existingByHostname) {\n // Update existing machine and return it\n await this.updateMachineStatus(existingByHostname.id, 'online');\n return existingByHostname as Machine;\n }\n\n // Create new machine\n const { data, error } = await this.supabase\n .from('machines')\n .insert({\n user_id: userId,\n name: machineName,\n hostname,\n status: 'online' as MachineStatus,\n last_seen_at: new Date().toISOString(),\n })\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to register machine: ${error.message}`);\n }\n\n return data as Machine;\n }\n\n async getMachine(machineId: string): Promise<Machine | null> {\n const { data, error } = await this.supabase\n .from('machines')\n .select()\n .eq('id', machineId)\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n // Not found\n return null;\n }\n throw new Error(`Failed to get machine: ${error.message}`);\n }\n\n return data as Machine;\n }\n\n async updateMachineStatus(\n machineId: string,\n status: MachineStatus\n ): Promise<void> {\n const { error } = await this.supabase\n .from('machines')\n .update({\n status,\n last_seen_at: new Date().toISOString(),\n })\n .eq('id', machineId);\n\n if (error) {\n throw new Error(`Failed to update machine status: ${error.message}`);\n }\n }\n\n async heartbeat(machineId: string): Promise<void> {\n const { error } = await this.supabase\n .from('machines')\n .update({\n last_seen_at: new Date().toISOString(),\n })\n .eq('id', machineId);\n\n if (error) {\n throw new Error(`Failed to update heartbeat: ${error.message}`);\n }\n }\n\n async listMachines(userId: string): Promise<Machine[]> {\n const { data, error } = await this.supabase\n .from('machines')\n .select()\n .eq('user_id', userId)\n .order('last_seen_at', { ascending: false });\n\n if (error) {\n throw new Error(`Failed to list machines: ${error.message}`);\n }\n\n return data as Machine[];\n }\n}\n","import { EventEmitter } from 'events';\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport { SdkSession } from './sdk-session.js';\nimport { SessionManager } from './session.js';\nimport { MachineManager } from './machine.js';\nimport { ConfigManager } from './config-manager.js';\nimport { RealtimeClient } from '../realtime/client.js';\nimport type { Session, Machine, RealtimeMessage, ImageAttachment, PermissionMode, UserQuestionData, PermissionRequestData, ToolUseData } from 'clautunnel-shared';\n\nexport interface DaemonOptions {\n supabase: SupabaseClient;\n userId: string;\n machineId?: string;\n machineName?: string;\n cwd: string;\n hybrid?: boolean;\n}\n\nexport class Daemon extends EventEmitter {\n private options: DaemonOptions;\n private sdkSession: SdkSession;\n private sessionManager: SessionManager;\n private machineManager: MachineManager;\n private configManager: ConfigManager;\n private realtimeClient: RealtimeClient | null = null;\n private machine: Machine | null = null;\n private session: Session | null = null;\n private running: boolean = false;\n private commandsBroadcast: boolean = false;\n private sdkCommandsBroadcast: boolean = false;\n private titleSet: boolean = false;\n\n constructor(options: DaemonOptions) {\n super();\n this.options = options;\n\n this.sdkSession = new SdkSession({\n cwd: options.cwd,\n });\n\n this.sessionManager = new SessionManager({\n supabase: options.supabase,\n });\n\n this.machineManager = new MachineManager({\n supabase: options.supabase,\n });\n\n this.configManager = new ConfigManager({\n cwd: options.cwd,\n });\n\n // Initialize thinking mode from settings\n const thinkingEnabled = this.configManager.getThinkingMode();\n if (thinkingEnabled) {\n this.sdkSession.setThinkingMode(true);\n }\n }\n\n async start(): Promise<void> {\n if (this.running) {\n throw new Error('Daemon is already running');\n }\n\n // Register machine\n this.machine = await this.machineManager.registerMachine(\n this.options.userId,\n this.options.machineName,\n this.options.machineId\n );\n\n // Create session\n this.session = await this.sessionManager.createSession(\n this.machine.id,\n this.options.cwd\n );\n\n // Initialize realtime client\n this.realtimeClient = new RealtimeClient({\n supabase: this.options.supabase,\n sessionId: this.session.id,\n });\n\n // Wire up SDK session output to broadcast\n this.sdkSession.on('output', async (data: string) => {\n // Hybrid mode: output to local stdout\n if (this.options.hybrid !== false) {\n process.stdout.write(data);\n }\n\n // Emit for external listeners (e.g., start command logging)\n this.emit('mobile-output', data);\n\n // Broadcast to mobile\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcast(data);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n this.sdkSession.on('error', (error: Error) => {\n this.emit('error', error);\n });\n\n // Broadcast commands when they're updated from init message (includes plugins/skills)\n this.sdkSession.on('commands-updated', async () => {\n await this.broadcastCommands();\n });\n\n // Save SDK session ID to Supabase for resume functionality\n this.sdkSession.on('session-started', async (sdkSessionId: string) => {\n if (!this.session) return;\n try {\n await this.sessionManager.updateSdkSessionId(this.session.id, sdkSessionId);\n } catch {\n // Silently handle - non-critical for basic functionality\n }\n });\n\n this.sdkSession.on('complete', async () => {\n // Session query completed, ready for next input\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n> ');\n }\n\n // Broadcast completion to mobile so it knows Claude is done\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastComplete();\n } catch {\n // Silently handle broadcast errors\n }\n }\n\n // Broadcast real SDK commands (including custom skills) after first query completion\n // This updates the fallback commands with the full list from the SDK\n if (!this.sdkCommandsBroadcast && this.realtimeClient) {\n this.sdkCommandsBroadcast = true;\n await this.broadcastCommands();\n }\n });\n\n // Wire up permission mode changes to broadcast\n this.sdkSession.on('permission-mode', async (mode: PermissionMode) => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastMode(mode);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up user questions to broadcast to mobile\n this.sdkSession.on('user-question', async (questionData: UserQuestionData) => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastUserQuestion(questionData);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up request queuing to broadcast to mobile\n this.sdkSession.on('request-queued', async () => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastQueued();\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up permission requests to broadcast to mobile\n this.sdkSession.on('permission-request', async (requestData: PermissionRequestData) => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastPermissionRequest(requestData);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up tool use data to broadcast to mobile (for code diffs)\n this.sdkSession.on('tool-use', async (toolUseData: ToolUseData) => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastToolUse(toolUseData);\n } catch (err) {\n console.warn('[Daemon] Failed to broadcast tool-use:', err);\n }\n }\n });\n\n // Wire up model changes to broadcast and persist\n this.sdkSession.on('model', async (model: string) => {\n // Persist model to database for this session\n if (this.session) {\n try {\n await this.sessionManager.updateSessionModel(this.session.id, model);\n } catch {\n // Silently handle persistence errors\n }\n }\n\n // Broadcast to mobile\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastModel(model);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up input from mobile\n this.realtimeClient.on('input', async (message: RealtimeMessage) => {\n // Broadcast commands on first message from mobile if not already done\n if (!this.commandsBroadcast) {\n this.commandsBroadcast = true;\n await this.broadcastCommands();\n }\n\n // Handle mode change requests\n if (message.type === 'mode-change' && message.permissionMode) {\n this.sdkSession.setPermissionMode(message.permissionMode);\n // Broadcast the new mode back to confirm\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastMode(message.permissionMode);\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle commands request\n if (message.type === 'commands-request') {\n await this.broadcastCommands();\n return;\n }\n\n // Handle model change requests\n if (message.type === 'model-change' && message.model) {\n const previousModel = this.sdkSession.getModel();\n await this.sdkSession.setModel(message.model);\n\n // Output confirmation message if model actually changed\n if (previousModel !== message.model) {\n const modelNames: Record<string, string> = {\n 'default': 'Opus 4.6',\n 'sonnet': 'Sonnet 4.5',\n 'opus': 'Opus 4.6',\n 'haiku': 'Haiku 3.5',\n };\n const displayName = modelNames[message.model] || message.model;\n const confirmationMsg = `[Model switched to ${displayName}]`;\n\n // Output to local terminal\n if (this.options.hybrid !== false) {\n process.stdout.write(`\\n${confirmationMsg}\\n`);\n }\n\n // Broadcast to mobile as system message (appears as separate bubble)\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastSystem(confirmationMsg);\n } catch {\n // Silently handle broadcast errors\n }\n }\n } else {\n // Model didn't change — still broadcast current model so mobile clears loading state\n try {\n await this.realtimeClient?.broadcastModel(this.sdkSession.getModel());\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle models request - send both available models and current model\n if (message.type === 'models-request') {\n await this.broadcastModels();\n // Also broadcast the current model so UI shows the correct selection\n try {\n await this.realtimeClient?.broadcastModel(this.sdkSession.getModel());\n } catch {\n // Silently handle broadcast errors\n }\n return;\n }\n\n // Handle status request - re-broadcast any pending question or permission\n if (message.type === 'status-request') {\n if (this.realtimeClient) {\n try {\n const pendingQuestion = this.sdkSession.getPendingQuestionData();\n if (pendingQuestion) {\n await this.realtimeClient.broadcastUserQuestion(pendingQuestion);\n }\n const pendingPermission = this.sdkSession.getPendingPermissionData();\n if (pendingPermission) {\n await this.realtimeClient.broadcastPermissionRequest(pendingPermission);\n }\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle mobile disconnect notification\n if (message.type === 'mobile-disconnect') {\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[ClauTunnel] Mobile client disconnected.\\n');\n }\n this.emit('mobile-disconnected');\n return;\n }\n\n // Handle interactive command request\n if (message.type === 'interactive-request' && message.interactiveCommand) {\n const data = this.configManager.getInteractiveData(message.interactiveCommand);\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastInteractiveResponse(data);\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle interactive apply\n if (message.type === 'interactive-apply' && message.interactivePayload) {\n const result = this.configManager.applyChange(message.interactivePayload);\n\n // If thinking mode was changed, also update the running SDK session\n if (\n message.interactivePayload.command === 'config' &&\n message.interactivePayload.key === 'alwaysThinkingEnabled'\n ) {\n const enabled = Boolean(message.interactivePayload.value);\n await this.sdkSession.setThinkingMode(enabled);\n }\n\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastInteractiveConfirm(\n message.interactivePayload.command,\n result\n );\n // Also broadcast a system message for confirmation\n const statusText = result.success\n ? `✓ ${result.message}`\n : `✗ ${result.message}`;\n await this.realtimeClient.broadcastSystem(statusText);\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle cancel request from mobile - stop Claude mid-processing\n if (message.type === 'cancel-request') {\n this.sdkSession.cancel();\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[Cancelled]\\n> ');\n }\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastSystem('[Cancelled]');\n await this.realtimeClient.broadcastComplete();\n } catch (error) {\n console.warn('[Daemon] Failed to broadcast cancel:', error);\n }\n }\n return;\n }\n\n // Handle clear request from mobile (doesn't appear in chat)\n if (message.type === 'clear-request') {\n this.sdkSession.clearHistory();\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[Conversation cleared]\\n> ');\n }\n return;\n }\n\n // Handle user answer (response to AskUserQuestion)\n // Use provideAnswer() to stream into the existing query instead of\n // sendPrompt() which would be rejected since isProcessing is true\n if (message.type === 'user-answer' && message.userAnswer) {\n const answerText = Object.values(message.userAnswer.answers).join('\\n');\n this.emit('mobile-input', `(answer) ${answerText}`);\n await this.sdkSession.provideAnswer(answerText, message.userAnswer.answers);\n return;\n }\n\n // Handle permission response from mobile\n if (message.type === 'permission-response' && message.permissionResponse) {\n this.sdkSession.handlePermissionResponse(message.permissionResponse);\n return;\n }\n\n // Handle resume request from mobile (doesn't appear in chat)\n if (message.type === 'resume-request' && message.resumeSessionId) {\n const targetSdkSessionId = message.resumeSessionId;\n this.sdkSession.resumeSession(targetSdkSessionId);\n\n const confirmationMsg = `[Resuming session: ${targetSdkSessionId.slice(0, 8)}...]`;\n if (this.options.hybrid !== false) {\n process.stdout.write(`\\n${confirmationMsg}\\n`);\n }\n\n if (this.realtimeClient) {\n try {\n // Find the Supabase session with this SDK session ID to load its messages\n const { data: sessionData } = await this.options.supabase\n .from('sessions')\n .select('id')\n .eq('sdk_session_id', targetSdkSessionId)\n .single();\n\n if (sessionData) {\n // Tell mobile to load messages from this session\n await this.realtimeClient.broadcastResumeHistory(sessionData.id);\n }\n\n await this.realtimeClient.broadcastSystem(confirmationMsg);\n } catch {\n // Silently handle broadcast errors\n }\n }\n\n // Send a prompt to trigger the resumed session\n await this.sdkSession.sendPrompt('Continue from where we left off.');\n return;\n }\n\n // Remove trailing newline/carriage return for SDK\n const prompt = message.content?.replace(/[\\r\\n]+$/, '') || '';\n const attachments = message.attachments;\n\n // Send if there's text or attachments\n if (prompt.trim() || (attachments && attachments.length > 0)) {\n const trimmedPrompt = prompt.trim();\n\n // Emit mobile input event for logging\n this.emit('mobile-input', trimmedPrompt, attachments);\n\n // Handle /clear typed in chat (legacy support)\n if (trimmedPrompt === '/clear') {\n this.sdkSession.clearHistory();\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastSystem('Conversation cleared');\n } catch {\n // Silently handle broadcast errors\n }\n }\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[Conversation cleared]\\n> ');\n }\n return;\n }\n\n // Auto-set session title from the first user message\n if (!this.titleSet && this.session) {\n this.titleSet = true;\n const title = trimmedPrompt.length > 50\n ? trimmedPrompt.slice(0, 50) + '...'\n : trimmedPrompt;\n this.sessionManager.updateSessionTitle(this.session.id, title).catch(() => {\n // Non-critical - silently handle\n });\n if (this.realtimeClient) {\n this.realtimeClient.broadcastSessionTitle(title).catch(() => {\n // Non-critical - silently handle\n });\n }\n }\n\n await this.sdkSession.sendPrompt(prompt, attachments);\n }\n });\n\n // Connect to realtime\n await this.realtimeClient.connect();\n\n // Broadcast initial permission mode\n try {\n await this.realtimeClient.broadcastMode(this.sdkSession.getPermissionMode());\n } catch {\n // Silently handle broadcast errors\n }\n\n // Broadcast available commands immediately\n await this.broadcastCommands();\n\n // Broadcast available models immediately\n await this.broadcastModels();\n\n // Broadcast current model\n try {\n await this.realtimeClient.broadcastModel(this.sdkSession.getModel());\n } catch {\n // Silently handle broadcast errors\n }\n\n this.running = true;\n this.emit('started', {\n machine: this.machine,\n session: this.session,\n mobileSyncEnabled: this.realtimeClient?.isRealtimeEnabled() ?? false,\n });\n\n // Show initial prompt\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[ClauTunnel] Ready for input.\\n> ');\n }\n }\n\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n this.running = false;\n\n // Cancel any ongoing SDK operation\n this.sdkSession.cancel();\n\n // End session\n if (this.session) {\n await this.sessionManager.endSession(this.session.id);\n }\n\n // Note: We don't set machine status to 'offline' here because other\n // sessions may still be running on the same machine. The machine\n // status is set to 'online' when any session starts.\n\n // Disconnect realtime\n if (this.realtimeClient) {\n await this.realtimeClient.disconnect();\n }\n\n this.emit('stopped');\n }\n\n async sendPrompt(prompt: string, attachments?: ImageAttachment[]): Promise<void> {\n await this.sdkSession.sendPrompt(prompt, attachments);\n }\n\n isRunning(): boolean {\n return this.running;\n }\n\n getSession(): Session | null {\n return this.session;\n }\n\n getMachine(): Machine | null {\n return this.machine;\n }\n\n private async broadcastCommands(): Promise<void> {\n if (!this.realtimeClient) {\n return;\n }\n\n try {\n const commands = await this.sdkSession.getSupportedCommands();\n await this.realtimeClient.broadcastCommands(commands);\n } catch {\n // Silently handle broadcast errors\n }\n }\n\n private async broadcastModels(): Promise<void> {\n if (!this.realtimeClient) {\n return;\n }\n\n try {\n const models = await this.sdkSession.getSupportedModels();\n await this.realtimeClient.broadcastModels(models);\n } catch {\n // Silently handle broadcast errors\n }\n }\n}\n","import { EventEmitter } from 'events';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { unstable_v2_createSession, unstable_v2_resumeSession } from '@anthropic-ai/claude-agent-sdk';\nimport type { SDKSession as V2Session, SDKSessionOptions, SDKMessage, SlashCommand as SDKSlashCommand, CanUseTool, PermissionResult, PermissionUpdate as SDKPermissionUpdate, SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';\nimport type { ImageAttachment, ModelInfo, PermissionMode, SlashCommand, UserQuestionData, UserQuestion, PermissionRequestData, PermissionResponseData, PermissionUpdate, ToolUseData } from 'clautunnel-shared';\nimport { v4 as uuidv4 } from 'uuid';\n\n/** Maximum characters to capture from tool use content */\nconst MAX_TOOL_CONTENT = 10000;\n\n/** Commands unsupported in remote/mobile context */\nconst UNSUPPORTED_COMMANDS = new Set([\n 'keybindings-help', 'help', 'context', 'cost', 'release-notes',\n 'vim', 'mcp', 'agents', 'hooks', 'status',\n]);\n\nexport interface SdkSessionOptions {\n cwd: string;\n allowedTools?: string[];\n permissionMode?: PermissionMode;\n model?: string;\n}\n\ninterface ConversationMessage {\n role: 'user' | 'assistant';\n content: string;\n}\n\n// Pending permission request with resolver\ninterface PendingPermissionRequest {\n resolve: (result: PermissionResult) => void;\n reject: (error: Error) => void;\n signal: AbortSignal;\n}\n\nexport class SdkSession extends EventEmitter {\n private options: SdkSessionOptions;\n private sessionId: string | null = null;\n private isProcessing: boolean = false;\n private currentPermissionMode: PermissionMode;\n private v2Session: V2Session | null = null;\n private streamLoopRunning: boolean = false;\n private cachedCommands: SlashCommand[] | null = null;\n private cachedModels: ModelInfo[] | null = null;\n private currentModel: string = 'opus';\n private conversationHistory: ConversationMessage[] = [];\n private pendingContextTransfer: boolean = false;\n private thinkingEnabled: boolean = false;\n private pendingPermissionRequests: Map<string, PendingPermissionRequest> = new Map();\n // Pending AskUserQuestion answer resolver - resolved by provideAnswer()\n private pendingAnswerResolve: ((answers: Record<string, string>) => void) | null = null;\n // Track pending question/permission data for re-broadcast on status-request\n private pendingQuestionData: UserQuestionData | null = null;\n private pendingPermissionData: PermissionRequestData | null = null;\n // Track current assistant response text for conversation history\n private currentAssistantResponse: string = '';\n // Queued prompt to send after current processing completes (last-one-wins)\n private pendingPrompt: { prompt: string; attachments?: ImageAttachment[] } | null = null;\n\n constructor(options: SdkSessionOptions) {\n super();\n this.options = options;\n this.currentPermissionMode = options.permissionMode || 'default';\n this.currentModel = options.model || 'opus';\n }\n\n /**\n * Handle permission response from mobile\n */\n handlePermissionResponse(response: PermissionResponseData): void {\n const pending = this.pendingPermissionRequests.get(response.requestId);\n if (!pending) {\n console.warn(`[WARN] No pending permission request found for ID: ${response.requestId}`);\n return;\n }\n\n this.pendingPermissionRequests.delete(response.requestId);\n this.pendingPermissionData = null;\n\n if (response.behavior === 'allow') {\n const result: PermissionResult = {\n behavior: 'allow',\n updatedInput: response.updatedInput,\n updatedPermissions: response.updatedPermissions as SDKPermissionUpdate[] | undefined,\n };\n pending.resolve(result);\n } else {\n const result: PermissionResult = {\n behavior: 'deny',\n message: response.message || 'Permission denied by user',\n };\n pending.resolve(result);\n }\n }\n\n /**\n * Create canUseTool callback for SDK\n *\n * AskUserQuestion goes through this path: the subprocess sends a\n * control_request with subtype \"can_use_tool\" and blocks until a\n * control_response is returned. For AskUserQuestion we emit a\n * user-question event, wait for provideAnswer() to resolve the pending\n * promise, and return {behavior:'allow', updatedInput:{questions, answers}}\n * so the subprocess can produce the tool_result and continue.\n */\n private createCanUseTool(): CanUseTool {\n return async (\n toolName: string,\n input: Record<string, unknown>,\n options: {\n signal: AbortSignal;\n suggestions?: SDKPermissionUpdate[];\n blockedPath?: string;\n decisionReason?: string;\n toolUseID: string;\n agentID?: string;\n }\n ): Promise<PermissionResult> => {\n\n // --- AskUserQuestion: route through user-question event -----------\n if (toolName === 'AskUserQuestion') {\n const questionInput = input as {\n questions?: Array<{\n question: string;\n header: string;\n options: Array<{ label: string; description: string }>;\n multiSelect?: boolean;\n }>;\n };\n\n if (questionInput.questions && Array.isArray(questionInput.questions)) {\n const questions: UserQuestion[] = questionInput.questions.map(q => ({\n question: q.question,\n header: q.header,\n options: (q.options || []).map(o => ({\n label: o.label,\n description: o.description,\n })),\n multiSelect: q.multiSelect,\n }));\n\n const questionData: UserQuestionData = {\n toolUseId: options.toolUseID,\n questions,\n };\n\n // Store and broadcast to mobile\n this.pendingQuestionData = questionData;\n this.emit('user-question', questionData);\n\n // Wait for provideAnswer() to supply the answers\n const answers = await new Promise<Record<string, string>>(\n (resolve, reject) => {\n this.pendingAnswerResolve = resolve;\n\n // Clean up if the request is aborted (e.g. session cancelled)\n options.signal.addEventListener('abort', () => {\n this.pendingAnswerResolve = null;\n this.pendingQuestionData = null;\n reject(new Error('Question aborted'));\n });\n }\n );\n\n this.pendingAnswerResolve = null;\n this.pendingQuestionData = null;\n\n // Return updatedInput so the subprocess can build the tool_result\n return {\n behavior: 'allow' as const,\n updatedInput: {\n questions: questionInput.questions,\n answers,\n },\n };\n }\n }\n\n // --- Regular permission request: broadcast to mobile and wait -----\n const requestId = uuidv4();\n\n // Convert SDK permission updates to our type\n const suggestions = options.suggestions?.map((s): PermissionUpdate => {\n // Handle different permission update types\n if (s.type === 'addRules' || s.type === 'replaceRules' || s.type === 'removeRules') {\n return {\n type: s.type,\n rules: s.rules,\n behavior: s.behavior,\n destination: s.destination,\n };\n } else if (s.type === 'setMode') {\n return {\n type: 'setMode',\n mode: s.mode as PermissionMode,\n destination: s.destination,\n };\n } else if (s.type === 'addDirectories' || s.type === 'removeDirectories') {\n return {\n type: s.type,\n directories: s.directories,\n destination: s.destination,\n };\n }\n // Fallback - should never reach here\n return s as PermissionUpdate;\n });\n\n const requestData: PermissionRequestData = {\n requestId,\n toolName,\n toolInput: input,\n toolUseId: options.toolUseID,\n suggestions,\n blockedPath: options.blockedPath,\n decisionReason: options.decisionReason,\n agentId: options.agentID,\n };\n\n // Store and emit event for daemon to broadcast to mobile\n this.pendingPermissionData = requestData;\n this.emit('permission-request', requestData);\n\n // Create promise that will be resolved when mobile responds\n return new Promise<PermissionResult>((resolve, reject) => {\n this.pendingPermissionRequests.set(requestId, {\n resolve,\n reject,\n signal: options.signal,\n });\n\n // Handle abort\n options.signal.addEventListener('abort', () => {\n this.pendingPermissionRequests.delete(requestId);\n this.pendingPermissionData = null;\n reject(new Error('Permission request aborted'));\n });\n });\n };\n }\n\n setPermissionMode(mode: PermissionMode): void {\n this.currentPermissionMode = mode;\n this.emit('permission-mode', mode);\n }\n\n getPermissionMode(): PermissionMode {\n return this.currentPermissionMode;\n }\n\n async setThinkingMode(enabled: boolean): Promise<void> {\n this.thinkingEnabled = enabled;\n this.emit('thinking-mode', enabled);\n }\n\n getThinkingMode(): boolean {\n return this.thinkingEnabled;\n }\n\n /**\n * Build V2 session options from current state\n */\n private buildSessionOptions(): SDKSessionOptions {\n const opts: SDKSessionOptions = {\n // SDK accepts shorthand model names: 'opus' | 'sonnet' | 'haiku'\n // Full model IDs (e.g. 'claude-opus-4-6') are also valid but shorthand is preferred\n model: this.currentModel,\n allowedTools: this.options.allowedTools || ['Read', 'Edit', 'Write', 'Bash', 'Glob', 'Grep'],\n canUseTool: this.createCanUseTool(),\n permissionMode: this.currentPermissionMode,\n };\n return opts;\n }\n\n /**\n * Ensure a V2 session exists, creating one if needed\n */\n private ensureSession(): V2Session {\n if (!this.v2Session) {\n const opts = this.buildSessionOptions();\n\n if (this.sessionId) {\n // Resume existing session\n this.v2Session = unstable_v2_resumeSession(this.sessionId, opts);\n } else {\n // Create new session\n this.v2Session = unstable_v2_createSession(opts);\n }\n\n // Start the background message processing loop\n this.startStreamLoop();\n }\n return this.v2Session;\n }\n\n /**\n * Background loop that processes messages from the V2 session stream.\n * Runs continuously for the lifetime of the session.\n */\n private async startStreamLoop(): Promise<void> {\n if (this.streamLoopRunning || !this.v2Session) return;\n this.streamLoopRunning = true;\n\n try {\n // The V2 stream() returns after each 'result' message.\n // For multi-turn sessions, we need to call stream() again after each result.\n while (this.v2Session && !this.v2Session['closed']) {\n for await (const message of this.v2Session.stream()) {\n this.processMessage(message);\n }\n }\n } catch (error) {\n if ((error as Error).name !== 'AbortError') {\n this.emit('error', error);\n }\n } finally {\n this.streamLoopRunning = false;\n // If the stream loop exits without a 'result' message (e.g. unexpected\n // disconnect or error), ensure isProcessing is reset so subsequent\n // requests are not permanently blocked.\n if (this.isProcessing) {\n this.isProcessing = false;\n this.pendingPrompt = null;\n this.emit('complete');\n }\n }\n }\n\n /**\n * Process a single SDK message from the stream\n */\n private processMessage(message: SDKMessage): void {\n // Handle different message types\n if (message.type === 'system' && 'subtype' in message && message.subtype === 'init') {\n // Capture session ID for resuming\n this.sessionId = message.session_id;\n this.emit('session-started', this.sessionId);\n\n // Emit permission mode if present\n if ('permissionMode' in message) {\n this.emit('permission-mode', message.permissionMode);\n }\n\n // Capture slash commands from init message (includes plugins/skills)\n if ('slash_commands' in message && Array.isArray(message.slash_commands)) {\n this.cachedCommands = message.slash_commands.map((cmd: unknown) => {\n if (typeof cmd === 'string') {\n return { name: cmd, description: '', argumentHint: '' };\n } else if (typeof cmd === 'object' && cmd !== null) {\n const cmdObj = cmd as SDKSlashCommand;\n return {\n name: cmdObj.name || '',\n description: cmdObj.description || '',\n argumentHint: cmdObj.argumentHint || '',\n };\n }\n return { name: String(cmd), description: '', argumentHint: '' };\n });\n this.emit('commands-updated', this.cachedCommands);\n }\n } else if (message.type === 'assistant') {\n // Assistant text output and tool use\n if (message.message?.content) {\n for (const block of message.message.content) {\n if ('type' in block && block.type === 'text' && 'text' in block) {\n this.emit('output', block.text);\n this.currentAssistantResponse += block.text;\n } else if ('type' in block && block.type === 'tool_use' && 'name' in block) {\n // AskUserQuestion tool_use blocks are handled via the canUseTool\n // callback (which emits 'user-question' and waits for the answer).\n const toolName = (block as any).name as string;\n if (toolName !== 'AskUserQuestion') {\n const input = (block as any).input || {};\n let toolUseData: ToolUseData;\n\n if (toolName === 'Edit' && input.file_path && input.old_string !== undefined) {\n toolUseData = {\n action: 'Edit',\n filePath: input.file_path,\n oldString: String(input.old_string).slice(0, MAX_TOOL_CONTENT),\n newString: String(input.new_string || '').slice(0, MAX_TOOL_CONTENT),\n };\n } else if (toolName === 'Write' && input.file_path) {\n toolUseData = {\n action: 'Write',\n filePath: input.file_path,\n content: String(input.content || '').slice(0, MAX_TOOL_CONTENT),\n };\n } else {\n toolUseData = {\n action: toolName,\n toolName,\n input,\n };\n }\n\n this.emit('tool-use', toolUseData);\n }\n }\n }\n }\n } else if (message.type === 'result') {\n // Emit result text if no assistant output was captured (e.g. slash commands like /context)\n if (!this.currentAssistantResponse.trim() && 'result' in message && message.result) {\n const resultText = String(message.result);\n this.emit('output', resultText);\n this.currentAssistantResponse = resultText;\n }\n // Final result - track assistant response in history\n if (this.currentAssistantResponse.trim()) {\n this.conversationHistory.push({ role: 'assistant', content: this.currentAssistantResponse.trim() });\n }\n\n this.currentAssistantResponse = '';\n this.isProcessing = false;\n\n // Auto-send queued message if one is pending\n const queued = this.pendingPrompt;\n if (queued) {\n this.pendingPrompt = null;\n // Don't emit 'complete' — mobile isTyping stays true seamlessly\n this.sendPrompt(queued.prompt, queued.attachments);\n } else {\n this.emit('complete');\n }\n } else if (message.type === 'tool_progress') {\n // Tool progress (tool being used)\n if ('tool_name' in message) {\n this.emit('output', `\\n[Using tool: ${message.tool_name}]\\n`);\n }\n } else if (message.type === 'tool_use_summary') {\n // Tool use summary\n if ('tool_name' in message) {\n this.emit('output', `[Tool ${message.tool_name} completed]\\n`);\n }\n }\n }\n\n async sendPrompt(prompt: string, attachments?: ImageAttachment[]): Promise<void> {\n if (this.isProcessing) {\n // Queue the message instead of rejecting — last one wins\n this.pendingPrompt = { prompt, attachments };\n this.emit('request-queued');\n return;\n }\n\n this.isProcessing = true;\n this.currentAssistantResponse = '';\n\n // Track user message in conversation history\n if (prompt.trim()) {\n this.conversationHistory.push({ role: 'user', content: prompt });\n }\n\n try {\n // Build the prompt text, including context if transferring to new session\n let finalPrompt = prompt;\n if (this.pendingContextTransfer && this.conversationHistory.length > 1) {\n // Build context from previous conversation (excluding current message)\n const previousHistory = this.conversationHistory.slice(0, -1);\n const contextLines = previousHistory.map(msg =>\n `${msg.role === 'user' ? 'User' : 'Assistant'}: ${msg.content}`\n );\n const contextPrefix = `[Previous conversation context - you switched to a new model]\\n${contextLines.join('\\n')}\\n\\n[Continue with new message]\\n`;\n finalPrompt = contextPrefix + prompt;\n this.pendingContextTransfer = false;\n }\n\n // Ensure we have a V2 session\n const session = this.ensureSession();\n\n // Build message content\n const contentBlocks: Array<{ type: string; text?: string; source?: { type: string; media_type: string; data: string } }> = [];\n\n // Add images if present\n if (attachments && attachments.length > 0) {\n for (const attachment of attachments) {\n contentBlocks.push({\n type: 'image',\n source: {\n type: 'base64',\n media_type: attachment.mediaType,\n data: attachment.data,\n },\n });\n }\n }\n\n // Add text\n if (finalPrompt.trim()) {\n contentBlocks.push({\n type: 'text',\n text: finalPrompt,\n });\n }\n\n // Build and send the user message via V2 session.send()\n const userMessage: SDKUserMessage = {\n type: 'user' as const,\n message: {\n role: 'user' as const,\n content: contentBlocks.length > 0 ? contentBlocks : [{ type: 'text' as const, text: finalPrompt }],\n },\n parent_tool_use_id: null,\n session_id: this.sessionId || '',\n };\n\n await session.send(userMessage);\n } catch (error) {\n if ((error as Error).name === 'AbortError') {\n this.emit('output', '\\n[Cancelled]\\n');\n } else {\n this.emit('error', error);\n this.emit('output', `\\n[Error: ${(error as Error).message}]\\n`);\n }\n this.isProcessing = false;\n }\n }\n\n /**\n * Provide an answer to a pending AskUserQuestion.\n *\n * AskUserQuestion flows through the canUseTool callback which blocks\n * waiting for a Promise to resolve. This method resolves that Promise\n * with the user's answers, which causes canUseTool to return\n * {behavior:'allow', updatedInput:{questions, answers}} → the SDK\n * sends the control_response back to the subprocess → it unblocks and\n * builds the tool_result for the Claude API.\n */\n async provideAnswer(answerText: string, answers?: Record<string, string>): Promise<void> {\n // Track in conversation history\n if (answerText.trim()) {\n this.conversationHistory.push({ role: 'user', content: answerText });\n }\n\n if (this.pendingAnswerResolve) {\n // Resolve the pending canUseTool callback with the answers\n const resolvedAnswers = answers || { result: answerText };\n this.pendingAnswerResolve(resolvedAnswers);\n this.pendingAnswerResolve = null;\n return;\n }\n\n // No pending question - fall back to sendPrompt\n await this.sendPrompt(answerText);\n }\n\n cancel(): void {\n this.pendingAnswerResolve = null;\n this.pendingQuestionData = null;\n this.pendingPermissionData = null;\n this.pendingPermissionRequests.clear();\n if (this.v2Session) {\n this.v2Session.close();\n this.v2Session = null;\n this.streamLoopRunning = false;\n }\n this.isProcessing = false;\n this.pendingPrompt = null;\n }\n\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n /**\n * Resume a different session by setting its ID.\n * The next sendPrompt call will use this session ID.\n */\n resumeSession(sessionId: string): void {\n // Close existing session if any\n if (this.v2Session) {\n this.v2Session.close();\n this.v2Session = null;\n this.streamLoopRunning = false;\n }\n this.sessionId = sessionId;\n this.isProcessing = false;\n this.pendingPrompt = null;\n this.conversationHistory = []; // Clear local history since we're resuming a different session\n this.emit('session-resumed', sessionId);\n }\n\n isActive(): boolean {\n return this.isProcessing;\n }\n\n getPendingQuestionData(): UserQuestionData | null {\n return this.pendingQuestionData;\n }\n\n getPendingPermissionData(): PermissionRequestData | null {\n return this.pendingPermissionData;\n }\n\n async setModel(model: string): Promise<void> {\n if (model === this.currentModel) return;\n\n this.currentModel = model;\n\n // Close existing session - a new one will be created with the new model on next sendPrompt()\n if (this.v2Session) {\n this.v2Session.close();\n this.v2Session = null;\n this.streamLoopRunning = false;\n this.sessionId = null;\n this.isProcessing = false;\n this.pendingPrompt = null;\n this.pendingContextTransfer = true;\n } else if (this.sessionId) {\n this.sessionId = null;\n this.pendingContextTransfer = true;\n }\n\n this.emit('model', model);\n }\n\n getModel(): string {\n return this.currentModel;\n }\n\n getConversationHistory(): ConversationMessage[] {\n return [...this.conversationHistory];\n }\n\n clearHistory(): void {\n this.conversationHistory = [];\n // Close existing session and force a fresh one on next prompt\n if (this.v2Session) {\n this.v2Session.close();\n this.v2Session = null;\n this.streamLoopRunning = false;\n }\n this.sessionId = null;\n this.isProcessing = false;\n this.pendingPrompt = null;\n }\n\n async getSupportedModels(): Promise<ModelInfo[]> {\n // Fallback models matching SDK response format\n const coreModels: ModelInfo[] = [\n { value: 'opus', displayName: 'Opus 4.6', description: 'Opus 4.6 · Most capable for complex work' },\n { value: 'haiku', displayName: 'Haiku 4.5', description: 'Haiku 4.5 · Fastest for quick answers' },\n { value: 'sonnet', displayName: 'Sonnet 4.5', description: 'Sonnet 4.5 · Best for everyday tasks' },\n ];\n\n // Return cached SDK models if available\n if (this.cachedModels) {\n return this.cachedModels;\n }\n\n return coreModels;\n }\n\n /**\n * Scan file system for custom commands/skills\n * Commands are in ~/.claude/commands/ and .claude/commands/\n * Subdirectories create namespaced commands (e.g., gsd/add-phase.md -> gsd:add-phase)\n */\n private scanCustomCommands(): SlashCommand[] {\n const commands: SlashCommand[] = [];\n const homeDir = os.homedir();\n\n // Directories to scan\n const dirs = [\n path.join(homeDir, '.claude', 'commands'), // Personal commands\n path.join(this.options.cwd, '.claude', 'commands'), // Project commands\n ];\n\n for (const dir of dirs) {\n if (!fs.existsSync(dir)) continue;\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n // Namespaced commands (e.g., gsd/)\n const namespace = entry.name;\n const subDir = path.join(dir, namespace);\n const subEntries = fs.readdirSync(subDir);\n\n for (const file of subEntries) {\n if (file.endsWith('.md')) {\n const name = `${namespace}:${file.replace('.md', '')}`;\n const description = this.extractDescription(path.join(subDir, file));\n commands.push({ name, description, argumentHint: '' });\n }\n }\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n // Top-level commands\n const name = entry.name.replace('.md', '');\n const description = this.extractDescription(path.join(dir, entry.name));\n commands.push({ name, description, argumentHint: '' });\n }\n }\n } catch {\n // Ignore errors scanning directories\n }\n }\n\n return commands;\n }\n\n /**\n * Extract description from markdown file (first line or frontmatter)\n */\n private extractDescription(filePath: string): string {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n // Check for frontmatter description\n if (lines[0] === '---') {\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (!line) continue;\n if (line === '---') break;\n if (line.startsWith('description:')) {\n return line.replace('description:', '').trim().replace(/^[\"']|[\"']$/g, '');\n }\n }\n }\n\n // Use first heading or first line as description\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith('# ')) {\n return trimmed.replace('# ', '');\n }\n if (trimmed && !trimmed.startsWith('---')) {\n return trimmed.slice(0, 100);\n }\n }\n } catch {\n // Ignore errors\n }\n return '';\n }\n\n async getSupportedCommands(): Promise<SlashCommand[]> {\n // Fallback commands - known Claude Code built-in commands\n const fallbackCommands: SlashCommand[] = [\n // Session management\n { name: 'help', description: 'Show all commands and custom slash commands', argumentHint: '' },\n { name: 'clear', description: 'Clear the conversation history', argumentHint: '' },\n { name: 'compact', description: 'Compress conversation by summarizing older messages', argumentHint: '' },\n { name: 'resume', description: 'Resume a previous conversation', argumentHint: '<session-id>' },\n { name: 'rewind', description: 'Go back to a previous message in the session', argumentHint: '' },\n { name: 'context', description: 'Check context and excluded skills', argumentHint: '' },\n // Configuration\n { name: 'config', description: 'Configure Claude Code settings interactively', argumentHint: '' },\n { name: 'permissions', description: 'View or update tool permissions', argumentHint: '' },\n { name: 'allowed-tools', description: 'Configure tool permissions interactively', argumentHint: '' },\n { name: 'model', description: 'Change the AI model', argumentHint: '' },\n { name: 'vim', description: 'Enable vim-style editing mode', argumentHint: '' },\n // Integrations\n { name: 'hooks', description: 'Configure hooks', argumentHint: '' },\n { name: 'mcp', description: 'Manage MCP servers', argumentHint: '' },\n { name: 'agents', description: 'Manage subagents (create, edit, list)', argumentHint: '' },\n { name: 'terminal-setup', description: 'Install terminal shortcuts for iTerm2/VS Code', argumentHint: '' },\n { name: 'install-github-app', description: 'Set up GitHub Actions integration', argumentHint: '' },\n { name: 'ide', description: 'Open in IDE or configure IDE integration', argumentHint: '' },\n // Project\n { name: 'init', description: 'Initialize Claude Code and generate CLAUDE.md', argumentHint: '' },\n { name: 'memory', description: 'Edit CLAUDE.md memory file', argumentHint: '' },\n { name: 'add-dir', description: 'Add a directory to the context', argumentHint: '<path>' },\n // Git & Code Review\n { name: 'commit', description: 'Commit changes to git with a generated message', argumentHint: '' },\n { name: 'review', description: 'Review code changes', argumentHint: '' },\n { name: 'review-pr', description: 'Review a GitHub pull request', argumentHint: '<pr-url>' },\n { name: 'pr-comments', description: 'Get comments from a GitHub pull request', argumentHint: '' },\n { name: 'release-notes', description: 'Generate release notes', argumentHint: '' },\n { name: 'security-review', description: 'Perform a security review', argumentHint: '' },\n // Account & System\n { name: 'login', description: 'Log in to your Anthropic account', argumentHint: '' },\n { name: 'logout', description: 'Log out of your Anthropic account', argumentHint: '' },\n { name: 'doctor', description: 'Check Claude Code health and configuration', argumentHint: '' },\n { name: 'bug', description: 'Report a bug to Anthropic', argumentHint: '' },\n { name: 'cost', description: 'Show token usage and cost', argumentHint: '' },\n { name: 'status', description: 'Show current session status', argumentHint: '' },\n ];\n\n // Get custom commands from file system (includes gsd:* etc.)\n const customCommands = this.scanCustomCommands();\n\n // Start with all commands\n let allCommands: SlashCommand[] = [...customCommands];\n\n // Add cached commands from init message\n if (this.cachedCommands && this.cachedCommands.length > 0) {\n const existingNames = new Set(allCommands.map(c => c.name));\n const newCached = this.cachedCommands.filter(c => !existingNames.has(c.name));\n allCommands = [...allCommands, ...newCached];\n }\n\n // Add fallback commands\n const existingNames = new Set(allCommands.map(c => c.name));\n const uniqueFallbacks = fallbackCommands.filter(c => !existingNames.has(c.name));\n allCommands = [...allCommands, ...uniqueFallbacks];\n\n allCommands = allCommands.filter(c => !UNSUPPORTED_COMMANDS.has(c.name));\n\n return allCommands;\n }\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport type {\n InteractiveCommandType,\n InteractiveCommandData,\n InteractiveApplyPayload,\n InteractiveResult,\n InteractiveOption,\n} from 'clautunnel-shared';\n\ninterface ClaudeSettings {\n preferences?: {\n verboseMode?: boolean;\n theme?: string;\n autoCompact?: boolean;\n };\n permissions?: {\n mode?: string;\n allowedTools?: string[];\n allow?: string[];\n };\n vim?: boolean;\n alwaysThinkingEnabled?: boolean;\n}\n\nexport interface ConfigManagerOptions {\n cwd?: string;\n homeDir?: string;\n}\n\nexport class ConfigManager {\n private claudeDir: string;\n private cwd: string;\n\n constructor(options: ConfigManagerOptions = {}) {\n const home = options.homeDir || homedir();\n this.claudeDir = join(home, '.claude');\n this.cwd = options.cwd || process.cwd();\n }\n\n private getGlobalSettingsPath(): string {\n return join(this.claudeDir, 'settings.json');\n }\n\n private getLocalSettingsPath(): string {\n return join(this.claudeDir, 'settings.local.json');\n }\n\n private getProjectSettingsPath(): string {\n return join(this.cwd, '.claude', 'settings.json');\n }\n\n private readSettingsFile(path: string): ClaudeSettings | null {\n try {\n if (existsSync(path)) {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content);\n }\n } catch {\n // Silently ignore read errors\n }\n return null;\n }\n\n private writeSettingsFile(path: string, settings: ClaudeSettings): boolean {\n try {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(path, JSON.stringify(settings, null, 2));\n return true;\n } catch {\n return false;\n }\n }\n\n private getMergedSettings(): ClaudeSettings {\n const global = this.readSettingsFile(this.getGlobalSettingsPath()) || {};\n const local = this.readSettingsFile(this.getLocalSettingsPath()) || {};\n const project = this.readSettingsFile(this.getProjectSettingsPath()) || {};\n\n // Merge settings with project > local > global precedence\n return {\n ...global,\n ...local,\n ...project,\n preferences: {\n ...global.preferences,\n ...local.preferences,\n ...project.preferences,\n },\n permissions: {\n ...global.permissions,\n ...local.permissions,\n ...project.permissions,\n },\n };\n }\n\n /**\n * Get the current thinking mode setting from merged settings\n */\n getThinkingMode(): boolean {\n const settings = this.getMergedSettings();\n return settings.alwaysThinkingEnabled ?? false;\n }\n\n getInteractiveData(command: InteractiveCommandType): InteractiveCommandData {\n const settings = this.getMergedSettings();\n\n switch (command) {\n case 'config':\n return this.getConfigData(settings);\n case 'permissions':\n return this.getPermissionsData(settings);\n case 'vim':\n return this.getVimData(settings);\n case 'allowed-tools':\n return this.getAllowedToolsData(settings);\n default:\n return {\n command,\n uiType: 'select',\n title: `${command} Settings`,\n description: 'This command is not yet supported in mobile.',\n options: [],\n };\n }\n }\n\n private getConfigData(settings: ClaudeSettings): InteractiveCommandData {\n const options: InteractiveOption[] = [\n {\n id: 'alwaysThinkingEnabled',\n label: 'Thinking Mode',\n description: 'Enable extended thinking for complex tasks',\n value: settings.alwaysThinkingEnabled || false,\n selected: settings.alwaysThinkingEnabled || false,\n },\n {\n id: 'autoCompact',\n label: 'Auto-Compact',\n description: 'Automatically compact conversation when context is full',\n value: settings.preferences?.autoCompact ?? true,\n selected: settings.preferences?.autoCompact ?? true,\n },\n ];\n\n return {\n command: 'config',\n uiType: 'nested',\n title: 'Configuration',\n description: 'Claude Code preferences and settings',\n options,\n };\n }\n\n private getPermissionsData(settings: ClaudeSettings): InteractiveCommandData {\n const currentMode = settings.permissions?.mode || 'default';\n const options: InteractiveOption[] = [\n {\n id: 'default',\n label: 'Default',\n description: 'Ask before making changes to files',\n value: 'default',\n selected: currentMode === 'default',\n },\n {\n id: 'acceptEdits',\n label: 'Auto-approve Edits',\n description: 'Automatically approve file edits',\n value: 'acceptEdits',\n selected: currentMode === 'acceptEdits',\n },\n {\n id: 'plan',\n label: 'Plan Mode',\n description: 'Only plan changes without executing',\n value: 'plan',\n selected: currentMode === 'plan',\n },\n {\n id: 'bypassPermissions',\n label: 'Yolo Mode',\n description: 'Bypass all permission prompts',\n value: 'bypassPermissions',\n selected: currentMode === 'bypassPermissions',\n },\n ];\n\n return {\n command: 'permissions',\n uiType: 'select',\n title: 'Permission Mode',\n description: 'Select how Claude handles file edits',\n options,\n currentValue: currentMode,\n };\n }\n\n private getVimData(settings: ClaudeSettings): InteractiveCommandData {\n const enabled = settings.vim ?? false;\n\n return {\n command: 'vim',\n uiType: 'toggle',\n title: 'Vim Mode',\n description: 'Enable vim keybindings in the editor',\n options: [\n {\n id: 'vim-enabled',\n label: 'Vim Mode',\n description: enabled ? 'Currently enabled' : 'Currently disabled',\n value: enabled,\n selected: enabled,\n },\n ],\n currentValue: enabled,\n };\n }\n\n private getAllowedToolsData(settings: ClaudeSettings): InteractiveCommandData {\n const allowedTools = settings.permissions?.allowedTools || [];\n const allTools = [\n { id: 'Bash', label: 'Bash', description: 'Execute shell commands' },\n { id: 'Read', label: 'Read', description: 'Read file contents' },\n { id: 'Write', label: 'Write', description: 'Write to files' },\n { id: 'Edit', label: 'Edit', description: 'Edit file contents' },\n { id: 'Glob', label: 'Glob', description: 'Search for files' },\n { id: 'Grep', label: 'Grep', description: 'Search file contents' },\n { id: 'WebFetch', label: 'WebFetch', description: 'Fetch web content' },\n { id: 'WebSearch', label: 'WebSearch', description: 'Search the web' },\n ];\n\n const options: InteractiveOption[] = allTools.map((tool) => ({\n ...tool,\n value: tool.id,\n selected: allowedTools.includes(tool.id),\n }));\n\n return {\n command: 'allowed-tools',\n uiType: 'multi-select',\n title: 'Allowed Tools',\n description: 'Select which tools Claude can use',\n options,\n currentValue: allowedTools,\n };\n }\n\n applyChange(payload: InteractiveApplyPayload): InteractiveResult {\n const globalPath = this.getGlobalSettingsPath();\n const settings = this.readSettingsFile(globalPath) || {};\n\n try {\n switch (payload.command) {\n case 'config':\n return this.applyConfigChange(settings, globalPath, payload);\n case 'permissions':\n return this.applyPermissionsChange(settings, globalPath, payload);\n case 'vim':\n return this.applyVimChange(settings, globalPath, payload);\n case 'allowed-tools':\n return this.applyAllowedToolsChange(settings, globalPath, payload);\n default:\n return {\n success: false,\n message: `Unknown command: ${payload.command}`,\n };\n }\n } catch (error) {\n return {\n success: false,\n message: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n private applyConfigChange(\n settings: ClaudeSettings,\n path: string,\n payload: InteractiveApplyPayload\n ): InteractiveResult {\n if (!settings.preferences) {\n settings.preferences = {};\n }\n\n switch (payload.key) {\n case 'theme':\n settings.preferences.theme = payload.value as string;\n break;\n case 'alwaysThinkingEnabled':\n // alwaysThinkingEnabled is at root level, not in preferences\n settings.alwaysThinkingEnabled = payload.value as boolean;\n break;\n case 'autoCompact':\n settings.preferences.autoCompact = payload.value as boolean;\n break;\n case 'verbose':\n settings.preferences.verboseMode = payload.value as boolean;\n break;\n default:\n return { success: false, message: `Unknown config key: ${payload.key}` };\n }\n\n if (this.writeSettingsFile(path, settings)) {\n return { success: true, message: `Config ${payload.key} updated` };\n }\n return { success: false, message: 'Failed to write settings file' };\n }\n\n private applyPermissionsChange(\n settings: ClaudeSettings,\n path: string,\n payload: InteractiveApplyPayload\n ): InteractiveResult {\n if (!settings.permissions) {\n settings.permissions = {};\n }\n\n settings.permissions.mode = payload.value as string;\n\n if (this.writeSettingsFile(path, settings)) {\n return { success: true, message: `Permission mode set to ${payload.value}` };\n }\n return { success: false, message: 'Failed to write settings file' };\n }\n\n private applyVimChange(\n settings: ClaudeSettings,\n path: string,\n payload: InteractiveApplyPayload\n ): InteractiveResult {\n if (payload.action === 'toggle') {\n settings.vim = !settings.vim;\n } else {\n settings.vim = payload.value as boolean;\n }\n\n if (this.writeSettingsFile(path, settings)) {\n return { success: true, message: `Vim mode ${settings.vim ? 'enabled' : 'disabled'}` };\n }\n return { success: false, message: 'Failed to write settings file' };\n }\n\n private applyAllowedToolsChange(\n settings: ClaudeSettings,\n path: string,\n payload: InteractiveApplyPayload\n ): InteractiveResult {\n if (!settings.permissions) {\n settings.permissions = {};\n }\n if (!settings.permissions.allowedTools) {\n settings.permissions.allowedTools = [];\n }\n\n const toolId = payload.value as string;\n\n switch (payload.action) {\n case 'add':\n if (!settings.permissions.allowedTools.includes(toolId)) {\n settings.permissions.allowedTools.push(toolId);\n }\n break;\n case 'remove':\n settings.permissions.allowedTools = settings.permissions.allowedTools.filter(\n (t) => t !== toolId\n );\n break;\n case 'set':\n settings.permissions.allowedTools = payload.value as string[];\n break;\n case 'toggle':\n if (settings.permissions.allowedTools.includes(toolId)) {\n settings.permissions.allowedTools = settings.permissions.allowedTools.filter(\n (t) => t !== toolId\n );\n } else {\n settings.permissions.allowedTools.push(toolId);\n }\n break;\n }\n\n if (this.writeSettingsFile(path, settings)) {\n return { success: true, message: 'Allowed tools updated' };\n }\n return { success: false, message: 'Failed to write settings file' };\n }\n}\n","import { Command } from 'commander';\nimport WebSocket from 'ws';\nimport { Daemon } from '../daemon/daemon.js';\nimport { MachineManager } from '../daemon/machine.js';\nimport { MachineRealtimeClient } from '../realtime/machine-client.js';\nimport { Config, ConfigurationError } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { Spinner } from '../utils/spinner.js';\nimport { createSupabaseClient, restoreSession } from '../utils/supabase.js';\nimport {\n promptYesNo,\n enableSleepPrevention,\n startCaffeinate,\n cleanup as cleanupSleep,\n isMacOS,\n checkFullDiskAccess,\n getFullDiskAccessStatus,\n getTerminalAppName,\n openFullDiskAccessSettings,\n type SleepPreventionState,\n type FullDiskAccessStatus,\n} from '../utils/sleep-prevention.js';\nimport { MobileServerManager } from '../mobile/mobile-server.js';\nimport type { MachineCommand } from 'clautunnel-shared';\n\n// Polyfill WebSocket for Node.js (Supabase Realtime needs this)\nif (typeof globalThis.WebSocket === 'undefined') {\n // @ts-expect-error WebSocket polyfill for Node.js\n globalThis.WebSocket = WebSocket;\n}\n\nexport interface StartOptions {\n name?: string;\n preventSleep?: boolean;\n mobile?: boolean;\n}\n\nexport function createStartCommand(): Command {\n const command = new Command('start');\n\n command\n .description('Start ClauTunnel and listen for session requests from mobile app')\n .option('-n, --name <name>', 'Machine name')\n .option('--prevent-sleep', 'Auto-enable sleep prevention (skip prompt)')\n .option('--no-mobile', 'Skip mobile server startup')\n .action(async (options: StartOptions) => {\n const config = new Config();\n const logger = new Logger();\n const spinner = new Spinner('Starting ClauTunnel...');\n\n const daemons: Map<string, Daemon> = new Map(); // sessionId -> Daemon\n let machineClient: MachineRealtimeClient | null = null;\n\n try {\n config.requireConfiguration();\n\n spinner.start();\n\n const supabase = createSupabaseClient(\n config.getSupabaseUrl(),\n config.getSupabaseAnonKey(),\n { realtime: true }\n );\n\n // Restore session from stored tokens\n spinner.update('Authenticating...');\n\n const session = await restoreSession(supabase, config);\n if (!session) {\n spinner.fail('Not authenticated');\n logger.error(\n 'Run \"clautunnel login\" or \"clautunnel signup\" first.'\n );\n process.exit(1);\n }\n\n const { user } = session;\n spinner.update(`Authenticated as ${user.email}...`);\n\n // Check Full Disk Access (macOS only)\n let fdaStatus: FullDiskAccessStatus | null = null;\n\n if (isMacOS()) {\n spinner.stop();\n\n const terminalApp = getTerminalAppName();\n let fdaEnabled = checkFullDiskAccess();\n fdaStatus = getFullDiskAccessStatus(fdaEnabled, terminalApp);\n\n if (fdaStatus.enabled) {\n logger.info(`✓ Full Disk Access: ${fdaStatus.label}`);\n } else {\n logger.warn(`⚠ Full Disk Access: ${fdaStatus.label}`);\n logger.warn('');\n for (const line of fdaStatus.warning!.split('\\n')) {\n logger.warn(` ${line}`);\n }\n logger.warn('');\n\n const openSettings = await promptYesNo(\n 'Open Full Disk Access settings? [Y/n]: '\n );\n\n if (openSettings) {\n openFullDiskAccessSettings();\n logger.info('');\n await promptYesNo(\n 'Press Enter after enabling Full Disk Access (or Enter to skip): '\n );\n\n // Recheck FDA status\n fdaEnabled = checkFullDiskAccess();\n fdaStatus = getFullDiskAccessStatus(fdaEnabled, terminalApp);\n\n if (fdaStatus.enabled) {\n logger.info('✓ Full Disk Access: Enabled');\n } else {\n logger.warn('Full Disk Access still not enabled. Continuing without it.');\n }\n }\n\n logger.info('');\n }\n\n spinner.start();\n }\n\n // Handle sleep prevention (macOS only)\n const sleepState: SleepPreventionState = {\n caffeinateProcess: null,\n pmsetEnabled: false,\n };\n\n if (isMacOS()) {\n spinner.stop();\n\n // Auto-enable if --prevent-sleep flag is used, otherwise ask\n const enableSleep =\n options.preventSleep ||\n (await promptYesNo(\n 'Prevent sleep when lid is closed? (keeps clautunnel running) [y/N]: '\n ));\n\n if (enableSleep) {\n logger.info('');\n logger.info('Enabling sleep prevention...');\n if (!options.preventSleep) {\n logger.info('This requires sudo password (auto-restored on exit)');\n logger.info('');\n }\n\n sleepState.pmsetEnabled = enableSleepPrevention();\n if (sleepState.pmsetEnabled) {\n logger.info('✓ Lid-closed mode enabled');\n } else {\n logger.warn('Failed to enable lid-closed mode. Using basic mode.');\n }\n\n // Start caffeinate to prevent idle sleep\n sleepState.caffeinateProcess = startCaffeinate();\n\n sleepState.caffeinateProcess.on('error', () => {\n logger.warn('Failed to start caffeinate');\n });\n\n logger.info('');\n }\n\n spinner.start();\n }\n\n // Mobile server\n let mobileServer: MobileServerManager | null = null;\n\n if (options.mobile !== false) {\n const mobileProjectPath = config.getMobileProjectPath();\n mobileServer = new MobileServerManager({\n mobileProjectPath,\n supabaseUrl: config.getSupabaseUrl(),\n supabaseAnonKey: config.getSupabaseAnonKey(),\n onProgress: (msg) => spinner.update(msg),\n });\n\n const result = await mobileServer.start();\n spinner.stop();\n\n if (result.started) {\n logger.info('');\n logger.info(` Tunnel: ${result.tunnelUrl}`);\n logger.info('');\n } else {\n logger.error(`Mobile server failed: ${result.error}`);\n process.exit(1);\n }\n\n spinner.start();\n }\n\n // Cleanup helper\n const cleanup = async () => {\n if (mobileServer) {\n try {\n await mobileServer.stop();\n } catch {\n // Best-effort cleanup\n }\n }\n if (sleepState.pmsetEnabled) {\n console.log('Restoring sleep settings...');\n }\n cleanupSleep(sleepState);\n };\n\n // Handle process signals\n let isShuttingDown = false;\n\n const gracefulShutdown = async (signal: string) => {\n if (isShuttingDown) {\n console.log('\\nForce exiting...');\n process.exit(1);\n }\n isShuttingDown = true;\n console.log(`\\n[${signal}] Shutting down gracefully...`);\n try {\n for (const [sessionId, d] of daemons) {\n try {\n await d.stop();\n } catch {\n // Continue stopping other daemons\n }\n daemons.delete(sessionId);\n }\n if (machineClient) {\n await machineClient.disconnect();\n machineClient = null;\n }\n console.log('[Cleanup] All sessions ended in database');\n await cleanup();\n } catch (error) {\n console.error('[Cleanup] Error during shutdown:', error);\n }\n process.exit(0);\n };\n\n process.on('SIGINT', () => {\n gracefulShutdown('SIGINT').catch(console.error);\n });\n\n process.on('SIGTERM', () => {\n gracefulShutdown('SIGTERM').catch(console.error);\n });\n\n spinner.update('Registering machine...');\n\n // Register machine\n const machineManager = new MachineManager({ supabase });\n const machine = await machineManager.registerMachine(\n user.id,\n options.name,\n config.getMachineId()\n );\n\n // Save machine ID for future use\n config.setMachineId(machine.id);\n\n spinner.update('Connecting to realtime...');\n\n // Create machine-level realtime client\n machineClient = new MachineRealtimeClient({\n supabase,\n machineId: machine.id,\n });\n\n const connected = await machineClient.connect();\n\n spinner.stop();\n\n if (!connected) {\n logger.error('Failed to connect to Supabase Realtime.');\n logger.error('');\n logger.error('This may be a temporary issue. Try the following:');\n logger.error(' 1. Open a new terminal and run \"clautunnel start\" again');\n logger.error(' 2. Check your network connection');\n logger.error(' 3. Try \"clautunnel login\" to refresh your session');\n process.exit(1);\n }\n\n logger.info('');\n logger.info('✓ ClauTunnel is ready!');\n logger.info(` Machine: ${machine.name}`);\n if (fdaStatus) {\n if (fdaStatus.enabled) {\n logger.info(` Full Disk Access: ${fdaStatus.label}`);\n } else {\n logger.warn(` Full Disk Access: ${fdaStatus.label}`);\n }\n }\n if (sleepState.caffeinateProcess) {\n logger.info(\n ` Sleep prevention: ${sleepState.pmsetEnabled ? 'Lid-closed mode' : 'Basic mode'}`\n );\n }\n if (mobileServer) {\n logger.info(' Mobile server: Running');\n }\n logger.info('');\n logger.info('Open the mobile app to start a session.');\n logger.info('Press Ctrl+C to stop.');\n logger.info('');\n\n // Handle incoming commands from mobile\n machineClient.on('command', async (cmd: MachineCommand) => {\n if (cmd.type === 'start-session') {\n logger.info('Starting session (requested from mobile)...');\n\n try {\n const newDaemon = new Daemon({\n supabase,\n userId: user.id,\n machineId: machine.id,\n machineName: options.name,\n cwd: process.cwd(),\n hybrid: false,\n });\n\n newDaemon.on('started', async ({ session }) => {\n daemons.set(session.id, newDaemon);\n\n logger.info(` Session: ${session.id.slice(0, 8)}...`);\n logger.info(' Mobile sync: Enabled');\n logger.info(` Active sessions: ${daemons.size}`);\n logger.info('');\n\n await machineClient?.broadcastSessionStarted(\n session.id,\n process.cwd()\n );\n });\n\n newDaemon.on('error', (error: Error) => {\n logger.error(`Session error: ${error.message}`);\n });\n\n newDaemon.on('mobile-input', (prompt: string, attachments?: unknown[]) => {\n const hasImages = attachments && attachments.length > 0;\n const imageInfo = hasImages ? ` [+${attachments.length} image${attachments.length > 1 ? 's' : ''}]` : '';\n logger.info(`[Mobile] ${prompt}${imageInfo}`);\n });\n\n newDaemon.on('mobile-output', (data: string) => {\n const trimmed = data.trim();\n if (trimmed) {\n logger.info(`[Claude] ${trimmed}`);\n }\n });\n\n newDaemon.on('mobile-disconnected', async () => {\n logger.info('Mobile disconnected. Ending session...');\n try {\n await newDaemon.stop();\n } catch {\n // Silently handle stop errors - stopped handler handles the rest\n }\n });\n\n newDaemon.on('stopped', async () => {\n const sessionId = newDaemon.getSession()?.id;\n if (sessionId) {\n daemons.delete(sessionId);\n await machineClient?.broadcastSessionEnded(sessionId);\n }\n\n logger.info('Session ended.');\n logger.info(` Active sessions: ${daemons.size}`);\n logger.info('');\n if (daemons.size === 0) {\n logger.info('Waiting for next session request...');\n logger.info('');\n }\n });\n\n await newDaemon.start();\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n logger.error(`Failed to start session: ${errorMessage}`);\n await machineClient?.broadcastError(errorMessage);\n }\n }\n\n if (cmd.type === 'stop-session' && cmd.sessionId) {\n const targetDaemon = daemons.get(cmd.sessionId);\n if (targetDaemon) {\n logger.info(`Stopping session ${cmd.sessionId.slice(0, 8)}... (requested from mobile)`);\n try {\n await targetDaemon.stop();\n } catch {\n // Silently handle stop errors\n }\n }\n }\n });\n } catch (error) {\n if (error instanceof ConfigurationError) {\n spinner.stop();\n logger.error(error.message);\n process.exit(1);\n }\n spinner.fail('Failed to start');\n logger.error(\n `${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { EventEmitter } from 'events';\nimport type { SupabaseClient, RealtimeChannel } from '@supabase/supabase-js';\nimport type { MachineCommand, PresencePayload } from 'clautunnel-shared';\nimport { REALTIME_CHANNELS } from 'clautunnel-shared';\nimport { subscribeWithTimeout } from './utils.js';\n\nexport interface MachineRealtimeClientOptions {\n supabase: SupabaseClient;\n machineId: string;\n}\n\nexport class MachineRealtimeClient extends EventEmitter {\n private supabase: SupabaseClient;\n private machineId: string;\n private inputChannel: RealtimeChannel | null = null;\n private outputChannel: RealtimeChannel | null = null;\n private presenceChannel: RealtimeChannel | null = null;\n\n constructor(options: MachineRealtimeClientOptions) {\n super();\n this.supabase = options.supabase;\n this.machineId = options.machineId;\n }\n\n async connect(): Promise<boolean> {\n // Subscribe to input channel (receives commands from mobile)\n const inputChannelName = REALTIME_CHANNELS.machineInput(this.machineId);\n this.inputChannel = this.supabase.channel(inputChannelName);\n\n this.inputChannel.on('broadcast', { event: 'machine-command' }, (payload) => {\n this.emit('command', payload.payload as MachineCommand);\n });\n\n // Subscribe to output channel (sends responses to mobile)\n const outputChannelName = REALTIME_CHANNELS.machineOutput(this.machineId);\n this.outputChannel = this.supabase.channel(outputChannelName);\n\n const results = await Promise.all([\n subscribeWithTimeout(this.inputChannel, 'machine-input'),\n subscribeWithTimeout(this.outputChannel, 'machine-output'),\n ]);\n\n const connected = results.every((success) => success);\n\n // Set up presence channel to track listener online status\n if (connected) {\n const presenceChannelName = REALTIME_CHANNELS.machinePresence(this.machineId);\n this.presenceChannel = this.supabase.channel(presenceChannelName);\n\n this.presenceChannel.subscribe(async (status) => {\n if (status === 'SUBSCRIBED' && this.presenceChannel) {\n try {\n const payload: PresencePayload = {\n type: 'cli',\n online_at: new Date().toISOString(),\n };\n await this.presenceChannel.track(payload);\n } catch (trackError) {\n console.warn('[WARN] Failed to track machine presence:', trackError);\n }\n }\n });\n }\n\n return connected;\n }\n\n async broadcastSessionStarted(sessionId: string, workingDirectory: string): Promise<void> {\n if (!this.outputChannel) return;\n\n const command: MachineCommand = {\n type: 'session-started',\n sessionId,\n workingDirectory,\n timestamp: Date.now(),\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'machine-command',\n payload: command,\n });\n }\n\n async broadcastSessionEnded(sessionId: string): Promise<void> {\n if (!this.outputChannel) return;\n\n const command: MachineCommand = {\n type: 'session-ended',\n sessionId,\n timestamp: Date.now(),\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'machine-command',\n payload: command,\n });\n }\n\n async broadcastError(error: string): Promise<void> {\n if (!this.outputChannel) return;\n\n const command: MachineCommand = {\n type: 'start-session-error',\n error,\n timestamp: Date.now(),\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'machine-command',\n payload: command,\n });\n }\n\n async disconnect(): Promise<void> {\n if (this.presenceChannel) {\n await this.presenceChannel.untrack();\n await this.supabase.removeChannel(this.presenceChannel);\n this.presenceChannel = null;\n }\n\n if (this.inputChannel) {\n await this.supabase.removeChannel(this.inputChannel);\n this.inputChannel = null;\n }\n\n if (this.outputChannel) {\n await this.supabase.removeChannel(this.outputChannel);\n this.outputChannel = null;\n }\n\n this.emit('disconnected');\n }\n}\n","export class Spinner {\n private frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n private currentFrame = 0;\n private interval: NodeJS.Timeout | null = null;\n private message: string;\n private stream: NodeJS.WriteStream;\n\n constructor(message: string, stream: NodeJS.WriteStream = process.stdout) {\n this.message = message;\n this.stream = stream;\n }\n\n start(): void {\n if (this.interval) {\n return;\n }\n\n // Hide cursor\n this.stream.write('\\x1B[?25l');\n\n this.interval = setInterval(() => {\n const frame = this.frames[this.currentFrame];\n this.stream.write(`\\r${frame} ${this.message}`);\n this.currentFrame = (this.currentFrame + 1) % this.frames.length;\n }, 80);\n }\n\n update(message: string): void {\n this.message = message;\n }\n\n stop(): void {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n\n // Clear the line and show cursor\n this.stream.write('\\r\\x1B[K');\n this.stream.write('\\x1B[?25h');\n }\n\n succeed(message: string): void {\n this.stop();\n this.stream.write(`\\r✓ ${message}\\n`);\n }\n\n fail(message: string): void {\n this.stop();\n this.stream.write(`\\r✗ ${message}\\n`);\n }\n}\n","import { createClient, type SupabaseClient } from '@supabase/supabase-js';\n\nexport interface CreateSupabaseClientOptions {\n realtime?: boolean;\n}\n\nexport function createSupabaseClient(\n url: string,\n anonKey: string,\n options?: CreateSupabaseClientOptions\n): SupabaseClient {\n const clientOptions = options?.realtime\n ? {\n realtime: {\n params: { eventsPerSecond: 10 },\n timeout: 30000,\n },\n }\n : undefined;\n\n return createClient(url, anonKey, clientOptions);\n}\n\nexport interface SessionTokenStore {\n getSessionTokens(): { accessToken: string; refreshToken: string } | null;\n clearSessionTokens(): void;\n}\n\nexport async function restoreSession(\n supabase: SupabaseClient,\n config: SessionTokenStore\n): Promise<{ user: any } | null> {\n const sessionTokens = config.getSessionTokens();\n if (!sessionTokens) {\n return null;\n }\n\n const { error: sessionError } = await supabase.auth.setSession({\n access_token: sessionTokens.accessToken,\n refresh_token: sessionTokens.refreshToken,\n });\n\n if (sessionError) {\n config.clearSessionTokens();\n return null;\n }\n\n const {\n data: { user },\n error: authError,\n } = await supabase.auth.getUser();\n\n if (authError || !user) {\n return null;\n }\n\n return { user };\n}\n","import { spawn, execSync, type ChildProcess } from 'child_process';\nimport * as readline from 'readline';\nimport { readdirSync } from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nexport interface SleepPreventionState {\n caffeinateProcess: ChildProcess | null;\n pmsetEnabled: boolean;\n}\n\nexport async function promptYesNo(question: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');\n });\n });\n}\n\nexport function enableSleepPrevention(): boolean {\n try {\n execSync('sudo pmset -a disablesleep 1', { stdio: 'inherit' });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function disableSleepPrevention(): void {\n try {\n execSync('sudo pmset -a disablesleep 0', { stdio: 'inherit' });\n } catch {\n // Ignore errors on cleanup\n }\n}\n\nexport function startCaffeinate(): ChildProcess {\n const process = spawn('caffeinate', ['-i', '-s'], {\n stdio: 'ignore',\n detached: false,\n });\n\n return process;\n}\n\nexport function stopCaffeinate(process: ChildProcess | null): void {\n if (process) {\n process.kill();\n }\n}\n\nexport function cleanup(state: SleepPreventionState): void {\n stopCaffeinate(state.caffeinateProcess);\n if (state.pmsetEnabled) {\n disableSleepPrevention();\n }\n}\n\nexport function isMacOS(): boolean {\n return process.platform === 'darwin';\n}\n\nexport interface FullDiskAccessStatus {\n enabled: boolean;\n label: string;\n warning?: string;\n}\n\n/**\n * Checks if Full Disk Access is granted on macOS by attempting to read\n * a TCC-protected directory. Returns true on non-macOS platforms.\n */\nexport function checkFullDiskAccess(): boolean {\n if (!isMacOS()) return true;\n\n try {\n const safariDir = path.join(os.homedir(), 'Library', 'Safari');\n readdirSync(safariDir);\n return true;\n } catch {\n return false;\n }\n}\n\nconst TERM_PROGRAM_MAP: Record<string, string> = {\n vscode: 'Visual Studio Code',\n Apple_Terminal: 'Terminal',\n 'iTerm.app': 'iTerm2',\n WarpTerminal: 'Warp',\n Hyper: 'Hyper',\n};\n\n/**\n * Detects the terminal application name from the TERM_PROGRAM environment variable.\n */\nexport function getTerminalAppName(): string {\n const termProgram = process.env.TERM_PROGRAM;\n if (termProgram && TERM_PROGRAM_MAP[termProgram]) {\n return TERM_PROGRAM_MAP[termProgram];\n }\n return 'your terminal app';\n}\n\n/**\n * Opens macOS System Settings to the Full Disk Access pane.\n * Returns true on success, false on failure or non-macOS platforms.\n */\nexport function openFullDiskAccessSettings(): boolean {\n if (!isMacOS()) return false;\n\n try {\n execSync(\n 'open \"x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles\"'\n );\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Returns a structured status object with label and optional warning message\n * describing the Full Disk Access state and its implications for remote usage.\n */\nexport function getFullDiskAccessStatus(enabled: boolean, terminalApp?: string): FullDiskAccessStatus {\n if (enabled) {\n return {\n enabled: true,\n label: 'Enabled',\n };\n }\n\n const appName = terminalApp || 'your terminal app';\n\n return {\n enabled: false,\n label: 'Not enabled',\n warning: [\n 'Without Full Disk Access, macOS may show permission dialogs',\n 'when Claude tries to access certain files or directories.',\n 'These dialogs are only visible on this machine\\'s screen —',\n 'you won\\'t be able to see or approve them from the mobile app,',\n 'which will cause Claude\\'s operations to silently hang.',\n '',\n 'To enable:',\n ` 1. Open System Settings → Privacy & Security → Full Disk Access`,\n ` 2. Toggle ON \"${appName}\" in the list`,\n ' 3. Restart your terminal and run \"clautunnel start\" again',\n ].join('\\n'),\n };\n}\n","import { spawn, execSync, type ChildProcess } from 'child_process';\nimport {\n existsSync,\n mkdirSync,\n writeFileSync,\n createWriteStream,\n type WriteStream,\n} from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { get } from 'http';\nimport qrcode from 'qrcode-terminal';\n\nconst REPO_URL = 'https://github.com/TongilKim/ClauTunnel.git';\nconst DEFAULT_MOBILE_DIR = join(homedir(), '.clautunnel', 'mobile');\n\nexport interface MobileServerOptions {\n mobileProjectPath?: string;\n supabaseUrl: string;\n supabaseAnonKey: string;\n expoPort?: number;\n logDir?: string;\n onProgress?: (message: string) => void;\n}\n\nexport interface MobileServerResult {\n started: boolean;\n tunnelUrl?: string;\n error?: string;\n}\n\ninterface PrerequisiteResult {\n ready: boolean;\n issues: string[];\n needsInstall: boolean;\n}\n\nexport class MobileServerManager {\n private options: MobileServerOptions;\n private mobileProjectPath: string;\n private logDir: string;\n private expoPort: number;\n private ngrokProcess: ChildProcess | null = null;\n private expoProcess: ChildProcess | null = null;\n private ngrokLogStream: WriteStream | null = null;\n private expoLogStream: WriteStream | null = null;\n private tunnelUrl: string | null = null;\n private onProgress: (message: string) => void;\n private hasCustomPath: boolean;\n\n constructor(options: MobileServerOptions) {\n this.options = options;\n this.hasCustomPath = options.mobileProjectPath !== undefined;\n this.mobileProjectPath = options.mobileProjectPath ?? DEFAULT_MOBILE_DIR;\n this.expoPort = options.expoPort ?? 8081;\n this.logDir = options.logDir ?? join(homedir(), '.clautunnel', 'logs');\n this.onProgress = options.onProgress ?? (() => {});\n }\n\n getMobileProjectPath(): string {\n return this.mobileProjectPath;\n }\n\n checkPrerequisites(): PrerequisiteResult {\n const issues: string[] = [];\n let needsInstall = false;\n\n // Path check is skipped here — ensureMobileProject handles it\n\n // Check ngrok\n try {\n execSync('which ngrok', { stdio: 'pipe' });\n } catch {\n issues.push(\n 'ngrok is not installed.\\n' +\n ' Install: brew install ngrok\\n' +\n ' Sign up: https://ngrok.com\\n' +\n ' Auth: ngrok config add-authtoken <your-token>'\n );\n }\n\n // Check node_modules\n const nodeModulesPath = join(this.mobileProjectPath, 'node_modules');\n if (!existsSync(nodeModulesPath)) {\n needsInstall = true;\n }\n\n return { ready: issues.length === 0, issues, needsInstall };\n }\n\n ensureMobileProject(): { ready: boolean; cloned: boolean; error?: string } {\n // Check if apps/mobile subdir exists (handles both custom path and cloned repo)\n const packageJson = join(this.mobileProjectPath, 'package.json');\n if (existsSync(packageJson)) {\n return { ready: true, cloned: false };\n }\n\n // If custom path was provided and doesn't exist, don't auto-clone\n if (this.hasCustomPath) {\n return {\n ready: false,\n cloned: false,\n error: `Mobile project path not found: ${this.mobileProjectPath}`,\n };\n }\n\n // Auto-clone to default location\n try {\n // Check git is installed\n execSync('which git', { stdio: 'pipe' });\n } catch {\n return {\n ready: false,\n cloned: false,\n error: 'git is required to download the mobile app.\\n' +\n ' Install: https://git-scm.com/downloads\\n' +\n ' macOS: xcode-select --install',\n };\n }\n\n try {\n // Clone only the apps/mobile directory using sparse checkout\n const clautunnelDir = join(homedir(), '.clautunnel');\n if (!existsSync(clautunnelDir)) {\n mkdirSync(clautunnelDir, { recursive: true });\n }\n\n // Clone with depth 1 and sparse checkout for apps/mobile only\n const repoDir = join(clautunnelDir, 'repo');\n if (existsSync(repoDir)) {\n // Pull latest\n execSync('git pull --ff-only', {\n cwd: repoDir,\n stdio: 'pipe',\n timeout: 60000,\n });\n } else {\n execSync(\n `git clone --depth 1 --filter=blob:none --sparse \"${REPO_URL}\" repo`,\n {\n cwd: clautunnelDir,\n stdio: 'pipe',\n timeout: 60000,\n }\n );\n execSync('git sparse-checkout set apps/mobile packages/shared', {\n cwd: repoDir,\n stdio: 'pipe',\n timeout: 30000,\n });\n }\n\n // Point mobileProjectPath to the cloned apps/mobile\n this.mobileProjectPath = join(repoDir, 'apps', 'mobile');\n\n if (!existsSync(join(this.mobileProjectPath, 'package.json'))) {\n return { ready: false, cloned: false, error: 'Clone succeeded but apps/mobile not found' };\n }\n\n return { ready: true, cloned: true };\n } catch (error) {\n return {\n ready: false,\n cloned: false,\n error: `Failed to clone mobile project: ${error instanceof Error ? error.message : 'Unknown error'}`,\n };\n }\n }\n\n ensureEnvFile(): void {\n const envPath = join(this.mobileProjectPath, '.env');\n const envContent = [\n `EXPO_PUBLIC_SUPABASE_URL=${this.options.supabaseUrl}`,\n `EXPO_PUBLIC_SUPABASE_ANON_KEY=${this.options.supabaseAnonKey}`,\n '',\n ].join('\\n');\n writeFileSync(envPath, envContent);\n }\n\n installDependencies(): boolean {\n const nodeModulesPath = join(this.mobileProjectPath, 'node_modules');\n if (existsSync(nodeModulesPath)) return true;\n\n try {\n execSync('pnpm install', {\n cwd: this.mobileProjectPath,\n stdio: 'pipe',\n timeout: 120000, // 2 minute timeout\n });\n return true;\n } catch {\n return false;\n }\n }\n\n async startNgrok(): Promise<string | null> {\n this.ensureLogDir();\n\n this.ngrokLogStream = createWriteStream(join(this.logDir, 'ngrok.log'));\n\n this.ngrokProcess = spawn('ngrok', ['http', String(this.expoPort)], {\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: false,\n });\n\n // Redirect output to log file\n this.ngrokProcess.stdout?.pipe(this.ngrokLogStream);\n this.ngrokProcess.stderr?.pipe(this.ngrokLogStream);\n\n this.ngrokProcess.on('error', () => {\n // Silently handle spawn errors\n });\n\n // Poll for tunnel URL\n for (let i = 0; i < 10; i++) {\n await this.sleep(1000);\n const url = await this.getNgrokTunnelUrl();\n if (url) {\n this.tunnelUrl = url;\n return url;\n }\n }\n\n // Failed to get tunnel URL\n this.killProcess(this.ngrokProcess);\n this.ngrokProcess = null;\n return null;\n }\n\n async startExpo(tunnelUrl: string): Promise<boolean> {\n this.ensureLogDir();\n\n this.expoLogStream = createWriteStream(join(this.logDir, 'expo.log'));\n\n this.expoProcess = spawn('npx', ['expo', 'start', '--port', String(this.expoPort)], {\n cwd: this.mobileProjectPath,\n env: {\n ...process.env,\n EXPO_PACKAGER_PROXY_URL: tunnelUrl,\n },\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: false,\n });\n\n this.expoProcess.on('error', () => {\n // Silently handle spawn errors\n });\n\n // Wait for Expo to be ready, print QR code if available\n return new Promise<boolean>((resolve) => {\n let ready = false;\n let resolved = false;\n let qrActive = false;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n this.expoProcess?.stdout?.pipe(this.expoLogStream!);\n this.expoProcess?.stderr?.pipe(this.expoLogStream!);\n resolve(false);\n }\n }, 60000); // 60 second timeout\n\n this.expoProcess?.stdout?.on('data', (data: Buffer) => {\n const text = data.toString();\n const lines = text.split('\\n');\n\n for (const line of lines) {\n if (ready) {\n this.expoLogStream?.write(line + '\\n');\n continue;\n }\n\n // Print QR code lines to terminal\n if (this.isQrCodeLine(line)) {\n qrActive = true;\n process.stdout.write(line + '\\n');\n } else if (qrActive && !this.isExpoReadyLine(line) && line.trim()) {\n // Lines between QR code blocks (spacing, URL info)\n process.stdout.write(line + '\\n');\n } else if (this.isExpoReadyLine(line)) {\n // Expo is ready — this is our success signal\n process.stdout.write(line + '\\n');\n ready = true;\n\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n // Redirect remaining output to log\n this.expoProcess?.stdout?.pipe(this.expoLogStream!);\n this.expoProcess?.stderr?.pipe(this.expoLogStream!);\n resolve(true);\n }\n } else {\n // Pre-ready output goes to log\n this.expoLogStream?.write(line + '\\n');\n }\n }\n });\n\n this.expoProcess?.stderr?.pipe(this.expoLogStream!);\n\n this.expoProcess?.on('exit', () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve(false);\n }\n });\n });\n }\n\n async start(): Promise<MobileServerResult> {\n // Step 1: Ensure mobile project exists (auto-clone if needed)\n this.onProgress('Checking mobile project...');\n const projectResult = this.ensureMobileProject();\n if (!projectResult.ready) {\n return { started: false, error: projectResult.error };\n }\n if (projectResult.cloned) {\n this.onProgress('Mobile project cloned to ~/.clautunnel/repo/apps/mobile');\n }\n\n // Step 2: Check prerequisites (ngrok, etc.)\n this.onProgress('Checking prerequisites...');\n const prereqs = this.checkPrerequisites();\n if (!prereqs.ready) {\n return { started: false, error: prereqs.issues.join('; ') };\n }\n\n // Step 3: Install dependencies if needed\n if (prereqs.needsInstall) {\n this.onProgress('Installing dependencies (this may take a minute)...');\n const installed = this.installDependencies();\n if (!installed) {\n return { started: false, error: 'Failed to install mobile dependencies' };\n }\n }\n\n // Step 4: Sync .env file\n this.onProgress('Syncing credentials...');\n this.ensureEnvFile();\n\n // Step 5: Start ngrok tunnel\n this.onProgress('Starting ngrok tunnel...');\n const tunnelUrl = await this.startNgrok();\n if (!tunnelUrl) {\n return { started: false, error: 'Failed to start ngrok tunnel' };\n }\n\n // Step 6: Start Expo server\n this.onProgress('Starting Expo server...');\n const expoStarted = await this.startExpo(tunnelUrl);\n if (!expoStarted) {\n // Expo failed, kill ngrok too\n await this.stop();\n return { started: false, error: 'Failed to start Expo server' };\n }\n\n // Step 7: Show QR code for Expo Go\n const expoUrl = `exp+${tunnelUrl}`;\n console.log('');\n console.log(' Scan with Expo Go:');\n qrcode.generate(expoUrl, { small: true }, (code: string) => {\n // Indent each line for alignment\n for (const line of code.split('\\n')) {\n console.log(` ${line}`);\n }\n });\n console.log(` ${expoUrl}`);\n console.log('');\n\n return { started: true, tunnelUrl };\n }\n\n async stop(): Promise<void> {\n if (this.expoProcess) {\n this.killProcess(this.expoProcess);\n this.expoProcess = null;\n }\n\n if (this.ngrokProcess) {\n this.killProcess(this.ngrokProcess);\n this.ngrokProcess = null;\n }\n\n if (this.expoLogStream) {\n this.expoLogStream.end();\n this.expoLogStream = null;\n }\n\n if (this.ngrokLogStream) {\n this.ngrokLogStream.end();\n this.ngrokLogStream = null;\n }\n\n this.tunnelUrl = null;\n }\n\n getTunnelUrl(): string | null {\n return this.tunnelUrl;\n }\n\n private isQrCodeLine(line: string): boolean {\n return line.includes('\\u2588') || line.includes('\\u2584') || line.includes('\\u2580');\n }\n\n private isExpoReadyLine(line: string): boolean {\n return line.includes('Metro waiting on') || line.includes('Logs for your project');\n }\n\n private getNgrokTunnelUrl(): Promise<string | null> {\n return new Promise((resolve) => {\n const req = get('http://localhost:4040/api/tunnels', (res) => {\n let data = '';\n res.on('data', (chunk) => (data += chunk));\n res.on('end', () => {\n try {\n const tunnels = JSON.parse(data).tunnels;\n const httpsTunnel = tunnels?.find(\n (t: { proto: string }) => t.proto === 'https'\n );\n resolve(httpsTunnel?.public_url ?? null);\n } catch {\n resolve(null);\n }\n });\n });\n\n req.on('error', () => resolve(null));\n req.setTimeout(2000, () => {\n req.destroy();\n resolve(null);\n });\n });\n }\n\n private killProcess(proc: ChildProcess): void {\n try {\n proc.kill('SIGTERM');\n // Give it 3 seconds before SIGKILL\n setTimeout(() => {\n try {\n proc.kill('SIGKILL');\n } catch {\n // Already dead\n }\n }, 3000);\n } catch {\n // Process already exited\n }\n }\n\n private ensureLogDir(): void {\n if (!existsSync(this.logDir)) {\n mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { Logger } from '../utils/logger.js';\n\nconst PID_FILE = path.join(os.homedir(), '.clautunnel', 'daemon.pid');\n\nexport function createStopCommand(): Command {\n const command = new Command('stop');\n\n command.description('Stop the running daemon').action(async () => {\n const logger = new Logger();\n\n try {\n if (!fs.existsSync(PID_FILE)) {\n logger.info('No daemon is running');\n return;\n }\n\n const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim(), 10);\n\n if (isNaN(pid)) {\n logger.error('Invalid PID file');\n fs.unlinkSync(PID_FILE);\n return;\n }\n\n try {\n // Check if process exists\n process.kill(pid, 0);\n\n // Send SIGTERM\n process.kill(pid, 'SIGTERM');\n logger.info(`Sent stop signal to daemon (PID: ${pid})`);\n\n // Wait for process to exit\n let attempts = 0;\n while (attempts < 10) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n try {\n process.kill(pid, 0);\n attempts++;\n } catch {\n // Process has exited\n break;\n }\n }\n\n if (attempts >= 10) {\n logger.warn('Daemon did not stop gracefully, sending SIGKILL');\n process.kill(pid, 'SIGKILL');\n }\n\n logger.info('Daemon stopped');\n } catch (err: any) {\n if (err.code === 'ESRCH') {\n logger.info('Daemon process not found (already stopped)');\n } else {\n throw err;\n }\n }\n\n // Clean up PID file\n if (fs.existsSync(PID_FILE)) {\n fs.unlinkSync(PID_FILE);\n }\n } catch (error) {\n logger.error(\n `Failed to stop daemon: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { MachineManager } from '../daemon/machine.js';\nimport { createSupabaseClient, restoreSession } from '../utils/supabase.js';\n\nexport function createStatusCommand(): Command {\n const command = new Command('status');\n\n command\n .description('Show connection status')\n .action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n const supabase = createSupabaseClient(\n config.getSupabaseUrl(),\n config.getSupabaseAnonKey()\n );\n\n // Restore session from stored tokens\n const session = await restoreSession(supabase, config);\n if (!session) {\n logger.info('Status: Not authenticated');\n logger.info('Run \"clautunnel login\" to authenticate');\n return;\n }\n\n const { user } = session;\n\n logger.info(`User: ${user.email}`);\n\n const machineId = config.getMachineId();\n if (!machineId) {\n logger.info('Machine: Not registered');\n logger.info('Run \"clautunnel start\" to register this machine');\n return;\n }\n\n const machineManager = new MachineManager({ supabase });\n const machine = await machineManager.getMachine(machineId);\n\n if (!machine) {\n logger.info(`Machine ID: ${machineId} (not found)`);\n return;\n }\n\n logger.info(`Machine: ${machine.name} (${machine.id})`);\n logger.info(`Status: ${machine.status}`);\n logger.info(`Last seen: ${machine.last_seen_at}`);\n } catch (error) {\n logger.error(\n `Failed to get status: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config, ConfigurationError } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { prompt, promptHidden } from '../utils/prompt.js';\nimport { createSupabaseClient } from '../utils/supabase.js';\n\nexport function createLoginCommand(): Command {\n const command = new Command('login');\n\n command.description('Authenticate with ClauTunnel').action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n config.requireConfiguration();\n\n const supabase = createSupabaseClient(\n config.getSupabaseUrl(),\n config.getSupabaseAnonKey()\n );\n\n const email = await prompt('Email: ');\n const password = await promptHidden('Password: ');\n\n if (!email || !password) {\n logger.error('Email and password are required');\n process.exit(1);\n }\n\n const { data, error } = await supabase.auth.signInWithPassword({\n email,\n password,\n });\n\n if (error) {\n logger.error(`Login failed: ${error.message}`);\n process.exit(1);\n }\n\n if (data.user) {\n logger.info(`Logged in as ${data.user.email}`);\n\n // Store session tokens securely\n if (data.session) {\n config.setSession({\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n });\n logger.info('Session saved');\n }\n\n logger.info('');\n logger.info('Next steps:');\n logger.info(' 1. Run \"clautunnel start\" to begin a session');\n logger.info(' 2. Set up the mobile app:');\n logger.info(' https://github.com/TongilKim/ClauTunnel#mobile-app-setup');\n }\n } catch (error) {\n if (error instanceof ConfigurationError) {\n logger.error(error.message);\n process.exit(1);\n }\n logger.error(\n `Login failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import * as readline from 'readline';\n\nexport function prompt(question: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n}\n\nexport function promptHidden(question: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n process.stdout.write(question);\n\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n }\n\n let password = '';\n\n const onData = (char: Buffer) => {\n const c = char.toString();\n\n if (c === '\\n' || c === '\\r') {\n process.stdin.removeListener('data', onData);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(false);\n }\n process.stdout.write('\\n');\n rl.close();\n resolve(password);\n } else if (c === '\\u0003') {\n // Ctrl+C\n process.exit(0);\n } else if (c === '\\u007F' || c === '\\b') {\n // Backspace\n if (password.length > 0) {\n password = password.slice(0, -1);\n }\n } else {\n password += c;\n }\n };\n\n process.stdin.on('data', onData);\n process.stdin.resume();\n });\n}\n","import { Command } from 'commander';\nimport { Config } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\n\nexport function createLogoutCommand(): Command {\n const command = new Command('logout');\n\n command.description('Log out of ClauTunnel').action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n const session = config.getSessionTokens();\n if (!session) {\n logger.info('Not currently logged in.');\n return;\n }\n\n config.clearSessionTokens();\n logger.info('Logged out successfully.');\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config, ConfigurationError } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { prompt, promptHidden } from '../utils/prompt.js';\nimport { createSupabaseClient } from '../utils/supabase.js';\n\nexport function createSignupCommand(): Command {\n const command = new Command('signup');\n\n command.description('Create a new ClauTunnel account').action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n config.requireConfiguration();\n\n const supabase = createSupabaseClient(\n config.getSupabaseUrl(),\n config.getSupabaseAnonKey()\n );\n\n logger.info('Create a new ClauTunnel account');\n logger.info('');\n\n const email = await prompt('Email: ');\n if (!email) {\n logger.error('Email is required');\n process.exit(1);\n }\n\n const password = await promptHidden('Password: ');\n if (!password) {\n logger.error('Password is required');\n process.exit(1);\n }\n\n if (password.length < 6) {\n logger.error('Password must be at least 6 characters');\n process.exit(1);\n }\n\n const confirmPassword = await promptHidden('Confirm Password: ');\n if (password !== confirmPassword) {\n logger.error('Passwords do not match');\n process.exit(1);\n }\n\n const { data, error } = await supabase.auth.signUp({\n email,\n password,\n });\n\n if (error) {\n logger.error(`Signup failed: ${error.message}`);\n process.exit(1);\n }\n\n if (data.user) {\n logger.info('');\n logger.info(`Account created for ${data.user.email}`);\n\n if (data.session) {\n config.setSession({\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n });\n logger.info('Logged in automatically');\n }\n\n logger.info('');\n logger.info('Next steps:');\n logger.info(' 1. Run \"clautunnel start\" to begin a session');\n logger.info(' 2. Set up the mobile app:');\n logger.info(' https://github.com/TongilKim/ClauTunnel#mobile-app-setup');\n }\n } catch (error) {\n if (error instanceof ConfigurationError) {\n logger.error(error.message);\n process.exit(1);\n }\n logger.error(\n `Signup failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { prompt } from '../utils/prompt.js';\n\nexport function createSetupCommand(): Command {\n const command = new Command('setup');\n\n command\n .description('Configure ClauTunnel with Supabase credentials')\n .action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n logger.info('ClauTunnel Setup');\n logger.info('================');\n logger.info('');\n\n // Step 1: Project ID\n logger.info('[Step 1/2] Supabase Project ID');\n logger.info('');\n logger.info(' 1. Go to your Supabase project dashboard');\n logger.info(' 2. Settings > General > Copy \"Project ID\"');\n logger.info('');\n\n const projectId = await prompt('Project ID: ');\n if (!projectId) {\n logger.error('Supabase Project ID is required');\n process.exit(1);\n }\n\n // Check if user accidentally pasted a full URL\n if (projectId.includes('supabase.co') || projectId.startsWith('http')) {\n logger.error('');\n logger.error('Please enter only the Project ID, not the full URL.');\n logger.error('');\n logger.error('Example: abcdefghijklmnop');\n logger.error('NOT: https://abcdefghijklmnop.supabase.co');\n process.exit(1);\n }\n\n // Validate Project ID format (alphanumeric, no spaces/special chars)\n if (!/^[a-zA-Z0-9-]+$/.test(projectId)) {\n logger.error('');\n logger.error('Invalid Project ID format.');\n logger.error('The Project ID should only contain letters, numbers, and hyphens.');\n logger.error('');\n logger.error('You can find it at: Settings > General > Project ID');\n process.exit(1);\n }\n\n const url = `https://${projectId}.supabase.co`;\n logger.info('✓ Project ID saved');\n logger.info('');\n\n // Step 2: Anon Key\n logger.info('[Step 2/2] Supabase Anon Key');\n logger.info('');\n logger.info(' 1. Go to your Supabase project dashboard');\n logger.info(' 2. Settings > API Keys > Legacy anon Tab > Copy anon key');\n logger.info('');\n\n const anonKey = await prompt('Anon Key: ');\n if (!anonKey) {\n logger.error('Supabase Anon Key is required');\n process.exit(1);\n }\n\n config.setSupabaseCredentials({ url, anonKey });\n\n logger.info('');\n logger.info('✓ Configuration saved successfully!');\n logger.info('');\n logger.info('Next steps:');\n logger.info(' - New user? Run \"clautunnel signup\" to create an account');\n logger.info(' - Have account? Run \"clautunnel login\" to authenticate');\n } catch (error) {\n logger.error(\n `Setup failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config, ConfigurationError } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { existsSync, writeFileSync } from 'fs';\nimport { join, resolve } from 'path';\n\nexport function createMobileSetupCommand(): Command {\n const command = new Command('mobile-setup');\n\n command\n .description('Generate mobile app .env file from CLI credentials')\n .action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n config.requireConfiguration();\n\n const supabaseUrl = config.getSupabaseUrl();\n const supabaseAnonKey = config.getSupabaseAnonKey();\n\n // Look for apps/mobile directory relative to cwd\n const mobileDir = resolve(process.cwd(), 'apps', 'mobile');\n if (!existsSync(mobileDir)) {\n logger.error('Could not find apps/mobile directory.');\n logger.error('');\n logger.error('Make sure you run this command from the ClauTunnel project root:');\n logger.error(' cd clautunnel');\n logger.error(' clautunnel mobile-setup');\n process.exit(1);\n }\n\n const envPath = join(mobileDir, '.env');\n\n // Warn if .env already exists\n if (existsSync(envPath)) {\n logger.warn('apps/mobile/.env already exists and will be overwritten.');\n }\n\n const envContent = [\n `EXPO_PUBLIC_SUPABASE_URL=${supabaseUrl}`,\n `EXPO_PUBLIC_SUPABASE_ANON_KEY=${supabaseAnonKey}`,\n '',\n ].join('\\n');\n\n writeFileSync(envPath, envContent);\n\n // Save mobile project path to config for clautunnel start\n config.setMobileProjectPath(mobileDir);\n\n logger.info('');\n logger.info('Mobile app configured successfully!');\n logger.info(` Project: ${mobileDir}`);\n logger.info(` .env: ${envPath}`);\n logger.info('');\n logger.info('The mobile server will start automatically with \"clautunnel start\".');\n logger.info('Use \"clautunnel start --no-mobile\" to skip mobile server.');\n } catch (error) {\n if (error instanceof ConfigurationError) {\n logger.error(error.message);\n process.exit(1);\n }\n logger.error(\n `Mobile setup failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n"],"mappings":"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","names":["resolve","dirname","readFileSync","path","resolve","hostname","EventEmitter","EventEmitter","os","resolve","prompt","existingNames","existsSync","readFileSync","writeFileSync","mkdirSync","join","homedir","path","EventEmitter","prompt","Command","import_clautunnel_shared","EventEmitter","EventEmitter","config","readdirSync","path","os","resolve","process","spawn","execSync","existsSync","mkdirSync","writeFileSync","join","homedir","packageJson","resolve","config","cleanup","session","prompt","Command","fs","path","os","Command","resolve","Command","Command","config","Command","readline","resolve","Command","config","Command","Command","config","Command","Command","config","Command","Command","config","Command","existsSync","writeFileSync","join","Command","config","dirname","resolve","readFileSync","Command"]}
1
+ {"version":3,"sources":["../../../packages/shared/dist/types/message.js","../../../packages/shared/dist/types/session.js","../../../packages/shared/dist/types/machine.js","../../../packages/shared/dist/types/presence.js","../../../packages/shared/src/types/index.ts","../../../packages/shared/src/constants/events.ts","../../../packages/shared/src/constants/index.ts","../../../packages/shared/src/index.ts","../src/index.ts","../src/utils/config.ts","../src/utils/logger.ts","../src/realtime/client.ts","../src/realtime/utils.ts","../src/daemon/session.ts","../src/daemon/machine.ts","../src/daemon/daemon.ts","../src/daemon/sdk-session.ts","../src/daemon/config-manager.ts","../src/commands/start.ts","../src/realtime/machine-client.ts","../src/utils/spinner.ts","../src/utils/supabase.ts","../src/utils/sleep-prevention.ts","../src/mobile/mobile-server.ts","../src/commands/stop.ts","../src/commands/status.ts","../src/commands/login.ts","../src/utils/prompt.ts","../src/commands/logout.ts","../src/commands/signup.ts","../src/commands/setup.ts","../src/commands/mobile-setup.ts"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=message.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=session.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=machine.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=presence.js.map","export * from './message.js';\nexport * from './session.js';\nexport * from './machine.js';\nexport * from './presence.js';\n","export const REALTIME_CHANNELS = {\n sessionOutput: (sessionId: string) => `session:${sessionId}:output`,\n sessionInput: (sessionId: string) => `session:${sessionId}:input`,\n sessionPresence: (sessionId: string) => `session:${sessionId}:presence`,\n machinePresence: (machineId: string) => `machine:${machineId}:presence`,\n machineInput: (machineId: string) => `machine:${machineId}:input`,\n machineOutput: (machineId: string) => `machine:${machineId}:output`,\n} as const;\n","export * from './events.js';\n","// Types\nexport * from './types/index.js';\n\n// Constants\nexport * from './constants/index.js';\n","#!/usr/bin/env node\n\nimport { config } from 'dotenv';\nimport { resolve, dirname } from 'path';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\n\n// ESM equivalent of __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Load .env from CLI package root (quiet mode to suppress dotenvx tips)\nconfig({ path: resolve(__dirname, '../.env'), quiet: true });\n\n// Read version from package.json\nconst packageJson = JSON.parse(\n readFileSync(resolve(__dirname, '../package.json'), 'utf-8')\n);\nconst version = packageJson.version || '0.0.0';\n\n// Library exports\nexport { Config, getConfig } from './utils/config.js';\nexport { Logger, getLogger } from './utils/logger.js';\nexport { RealtimeClient } from './realtime/client.js';\nexport { SessionManager } from './daemon/session.js';\nexport { MachineManager } from './daemon/machine.js';\nexport { Daemon } from './daemon/daemon.js';\n\n// CLI entry point\nimport { Command } from 'commander';\nimport { createStartCommand } from './commands/start.js';\nimport { createStopCommand } from './commands/stop.js';\nimport { createStatusCommand } from './commands/status.js';\nimport { createLoginCommand } from './commands/login.js';\nimport { createLogoutCommand } from './commands/logout.js';\nimport { createSignupCommand } from './commands/signup.js';\nimport { createSetupCommand } from './commands/setup.js';\nimport { createMobileSetupCommand } from './commands/mobile-setup.js';\n\nconst program = new Command();\n\nprogram\n .name('clautunnel')\n .description('Remote control for Claude Code CLI')\n .version(version);\n\nprogram.addCommand(createSetupCommand());\nprogram.addCommand(createStartCommand());\nprogram.addCommand(createStopCommand());\nprogram.addCommand(createStatusCommand());\nprogram.addCommand(createLoginCommand());\nprogram.addCommand(createLogoutCommand());\nprogram.addCommand(createSignupCommand());\nprogram.addCommand(createMobileSetupCommand());\n\n// Only parse when run directly (not when imported as library)\nif (process.argv[1]?.includes('clautunnel') || process.argv[1]?.endsWith('/index.js') || process.argv[1]?.endsWith('/index.ts')) {\n program.parse();\n}\n","import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nexport class ConfigurationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ConfigurationError';\n }\n}\n\ninterface ConfigData {\n machineId?: string;\n sessionTokens?: {\n accessToken: string;\n refreshToken: string;\n };\n supabaseUrl?: string;\n supabaseAnonKey?: string;\n mobileProjectPath?: string;\n}\n\nexport class Config {\n private configDir: string;\n private configFile: string;\n private data: ConfigData;\n\n constructor(configDir?: string) {\n this.configDir = configDir ?? join(homedir(), '.clautunnel');\n this.configFile = join(this.configDir, 'config.json');\n if (!configDir) {\n this.migrateFromLegacy();\n }\n this.data = this.loadConfig();\n }\n\n private migrateFromLegacy(): void {\n const legacyDir = join(homedir(), '.termbridge');\n if (existsSync(legacyDir) && !existsSync(this.configDir)) {\n renameSync(legacyDir, this.configDir);\n console.log(`Migrated config from ~/.termbridge to ~/.clautunnel`);\n }\n }\n\n private loadConfig(): ConfigData {\n if (existsSync(this.configFile)) {\n try {\n return JSON.parse(readFileSync(this.configFile, 'utf-8'));\n } catch {\n return {};\n }\n }\n return {};\n }\n\n private saveConfig(): void {\n if (!existsSync(this.configDir)) {\n mkdirSync(this.configDir, { recursive: true });\n }\n writeFileSync(this.configFile, JSON.stringify(this.data, null, 2));\n }\n\n getSupabaseUrl(): string {\n // Prefer env var over config file\n const url = process.env['SUPABASE_URL'] || this.data.supabaseUrl;\n if (!url) {\n throw new Error('SUPABASE_URL environment variable is not set');\n }\n\n // Validate URL format\n try {\n new URL(url);\n } catch {\n throw new Error('SUPABASE_URL must be a valid URL');\n }\n\n return url;\n }\n\n getSupabaseAnonKey(): string {\n // Prefer env var over config file\n const key = process.env['SUPABASE_ANON_KEY'] || this.data.supabaseAnonKey;\n if (!key) {\n throw new Error('SUPABASE_ANON_KEY environment variable is not set');\n }\n return key;\n }\n\n setSupabaseCredentials(credentials: { url: string; anonKey: string }): void {\n this.data.supabaseUrl = credentials.url;\n this.data.supabaseAnonKey = credentials.anonKey;\n this.saveConfig();\n }\n\n isConfigured(): boolean {\n const hasEnvVars = !!(process.env['SUPABASE_URL'] && process.env['SUPABASE_ANON_KEY']);\n const hasConfigFile = !!(this.data.supabaseUrl && this.data.supabaseAnonKey);\n return hasEnvVars || hasConfigFile;\n }\n\n requireConfiguration(): void {\n if (!this.isConfigured()) {\n throw new ConfigurationError(\n 'ClauTunnel is not configured.\\n\\n' +\n 'Run \"clautunnel setup\" to configure your Supabase credentials.\\n\\n' +\n 'Or set environment variables in your shell profile (~/.zshrc or ~/.bashrc):\\n' +\n ' export SUPABASE_URL=https://<project-id>.supabase.co\\n' +\n ' export SUPABASE_ANON_KEY=<your-anon-key>'\n );\n }\n }\n\n getMachineId(): string | undefined {\n return this.data.machineId;\n }\n\n setMachineId(machineId: string): void {\n this.data.machineId = machineId;\n this.saveConfig();\n }\n\n getSessionTokens(): ConfigData['sessionTokens'] | undefined {\n return this.data.sessionTokens;\n }\n\n setSessionTokens(tokens: ConfigData['sessionTokens']): void {\n this.data.sessionTokens = tokens;\n this.saveConfig();\n }\n\n // Alias for setSessionTokens\n setSession(tokens: { accessToken: string; refreshToken: string }): void {\n this.setSessionTokens(tokens);\n }\n\n clearSessionTokens(): void {\n delete this.data.sessionTokens;\n this.saveConfig();\n }\n\n getMobileProjectPath(): string | undefined {\n return this.data.mobileProjectPath;\n }\n\n setMobileProjectPath(path: string): void {\n this.data.mobileProjectPath = path;\n this.saveConfig();\n }\n}\n\n// Default singleton instance\nlet defaultConfig: Config | null = null;\n\nexport function getConfig(): Config {\n if (!defaultConfig) {\n defaultConfig = new Config();\n }\n return defaultConfig;\n}\n","type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport class Logger {\n private silent: boolean;\n private debugEnabled: boolean;\n\n constructor() {\n this.silent = process.env['SILENT'] === 'true';\n this.debugEnabled = process.env['DEBUG'] === 'true';\n }\n\n private formatTimestamp(): string {\n const now = new Date();\n return now.toTimeString().split(' ')[0] ?? now.toISOString();\n }\n\n private formatMessage(level: LogLevel, message: string, data?: object): string {\n const timestamp = this.formatTimestamp();\n const levelStr = level.toUpperCase().padEnd(5);\n let formatted = `[${timestamp}] [${levelStr}] ${message}`;\n\n if (data) {\n formatted += ` ${JSON.stringify(data)}`;\n }\n\n return formatted;\n }\n\n debug(message: string, data?: object): void {\n if (this.silent || !this.debugEnabled) return;\n console.log(this.formatMessage('debug', message, data));\n }\n\n info(message: string, data?: object): void {\n if (this.silent) return;\n console.log(this.formatMessage('info', message, data));\n }\n\n warn(message: string, data?: object): void {\n if (this.silent) return;\n console.warn(this.formatMessage('warn', message, data));\n }\n\n error(message: string, data?: object): void {\n if (this.silent) return;\n console.error(this.formatMessage('error', message, data));\n }\n}\n\n// Default singleton instance\nlet defaultLogger: Logger | null = null;\n\nexport function getLogger(): Logger {\n if (!defaultLogger) {\n defaultLogger = new Logger();\n }\n return defaultLogger;\n}\n","import { EventEmitter } from 'events';\nimport type { SupabaseClient, RealtimeChannel } from '@supabase/supabase-js';\nimport type {\n RealtimeMessage,\n ModelInfo,\n PermissionMode,\n SlashCommand,\n InteractiveCommandData,\n InteractiveCommandType,\n InteractiveResult,\n PresencePayload,\n UserQuestionData,\n PermissionRequestData,\n ToolUseData,\n} from 'clautunnel-shared';\nimport { REALTIME_CHANNELS } from 'clautunnel-shared';\nimport { subscribeWithTimeout } from './utils.js';\n\nexport interface RealtimeClientOptions {\n supabase: SupabaseClient;\n sessionId: string;\n}\n\nexport class RealtimeClient extends EventEmitter {\n private supabase: SupabaseClient;\n private sessionId: string;\n private outputChannel: RealtimeChannel | null = null;\n private inputChannel: RealtimeChannel | null = null;\n private presenceChannel: RealtimeChannel | null = null;\n private seq: number = 0;\n private realtimeEnabled: boolean = false;\n\n constructor(options: RealtimeClientOptions) {\n super();\n this.supabase = options.supabase;\n this.sessionId = options.sessionId;\n }\n\n async connect(): Promise<void> {\n // Subscribe to output channel (CLI broadcasts to mobile)\n const outputChannelName = REALTIME_CHANNELS.sessionOutput(this.sessionId);\n this.outputChannel = this.supabase.channel(outputChannelName);\n\n // Subscribe to input channel (mobile sends to CLI)\n const inputChannelName = REALTIME_CHANNELS.sessionInput(this.sessionId);\n this.inputChannel = this.supabase.channel(inputChannelName);\n\n this.inputChannel.on('broadcast', { event: 'input' }, (payload) => {\n this.emit('input', payload.payload as RealtimeMessage);\n });\n\n const results = await Promise.all([\n subscribeWithTimeout(this.outputChannel, 'output'),\n subscribeWithTimeout(this.inputChannel, 'input'),\n ]);\n\n // Only enable realtime if both channels subscribed successfully\n this.realtimeEnabled = results.every((success) => success);\n\n // Set up presence channel to track CLI online status\n if (this.realtimeEnabled) {\n const presenceChannelName = REALTIME_CHANNELS.sessionPresence(this.sessionId);\n this.presenceChannel = this.supabase.channel(presenceChannelName);\n\n // Subscribe and track presence - re-track on every SUBSCRIBED (handles reconnection)\n this.presenceChannel.subscribe(async (status, err) => {\n if (status === 'SUBSCRIBED' && this.presenceChannel) {\n try {\n const payload: PresencePayload = {\n type: 'cli',\n online_at: new Date().toISOString(),\n };\n await this.presenceChannel.track(payload);\n } catch (trackError) {\n // Presence tracking is non-critical - log and continue\n console.warn('[WARN] Failed to track presence:', trackError);\n }\n } else if (status === 'CHANNEL_ERROR') {\n // Presence is non-critical - log and continue\n console.warn('[WARN] Presence channel error:', err?.message || 'Unknown error');\n }\n });\n }\n\n this.emit('connected');\n }\n\n async disconnect(): Promise<void> {\n // Untrack presence before disconnecting\n if (this.presenceChannel) {\n await this.presenceChannel.untrack();\n await this.supabase.removeChannel(this.presenceChannel);\n this.presenceChannel = null;\n }\n\n if (this.outputChannel) {\n await this.supabase.removeChannel(this.outputChannel);\n this.outputChannel = null;\n }\n\n if (this.inputChannel) {\n await this.supabase.removeChannel(this.inputChannel);\n this.inputChannel = null;\n }\n\n this.emit('disconnected');\n }\n\n async broadcast(content: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n const message: RealtimeMessage = {\n type: 'output',\n content,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n // Persist message to database for history\n try {\n const { error } = await this.supabase.from('messages').insert({\n session_id: this.sessionId,\n type: message.type,\n content: message.content,\n seq: message.seq,\n });\n if (error) {\n console.warn('[WARN] Failed to persist message:', error.message);\n }\n } catch (error) {\n // Log but don't fail - message persistence is secondary to realtime\n console.warn('[WARN] Failed to persist message:', error);\n }\n\n // Skip realtime broadcasting if not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n try {\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n } catch (error) {\n throw error;\n }\n\n this.emit('broadcast', message);\n }\n\n async broadcastMode(mode: PermissionMode): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'mode',\n permissionMode: mode,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastCommands(commands: SlashCommand[]): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'commands',\n commands,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastModel(model: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'model',\n model,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastModels(models: ModelInfo[]): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'models',\n availableModels: models,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastSystem(content: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n const message: RealtimeMessage = {\n type: 'system',\n content,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n // Persist message to database for history\n try {\n const { error } = await this.supabase.from('messages').insert({\n session_id: this.sessionId,\n type: message.type,\n content: message.content,\n seq: message.seq,\n });\n if (error) {\n console.warn('[WARN] Failed to persist system message:', error.message);\n }\n } catch (error) {\n console.warn('[WARN] Failed to persist system message:', error);\n }\n\n // Skip realtime broadcasting if not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n try {\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n } catch (error) {\n throw error;\n }\n\n this.emit('broadcast', message);\n }\n\n async broadcastInteractiveResponse(data: InteractiveCommandData): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'interactive-response',\n interactiveData: data,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastInteractiveConfirm(\n command: InteractiveCommandType,\n result: InteractiveResult\n ): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'interactive-confirm',\n interactiveCommand: command,\n interactiveResult: result,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastResumeHistory(historySessionId: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'resume-history',\n historySessionId,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastUserQuestion(questionData: UserQuestionData): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'user-question',\n userQuestion: questionData,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastPermissionRequest(requestData: PermissionRequestData): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'permission-request',\n permissionRequest: requestData,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastToolUse(toolUseData: ToolUseData): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n const message: RealtimeMessage = {\n type: 'tool-use',\n toolUseData,\n content: JSON.stringify(toolUseData),\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n // Persist to database for history\n try {\n const { error } = await this.supabase.from('messages').insert({\n session_id: this.sessionId,\n type: message.type,\n content: message.content,\n seq: message.seq,\n });\n if (error) {\n console.warn('[WARN] Failed to persist tool-use message:', error.message);\n }\n } catch (error) {\n console.warn('[WARN] Failed to persist tool-use message:', error);\n }\n\n // Skip realtime broadcasting if not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n try {\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n } catch (error) {\n throw error;\n }\n\n this.emit('broadcast', message);\n }\n\n async broadcastComplete(): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'complete',\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastSessionTitle(title: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'session-title',\n sessionTitle: title,\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastQueued(): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'request-queued',\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n async broadcastError(errorMessage: string, errorCode?: string): Promise<void> {\n if (!this.outputChannel) {\n throw new Error('Not connected');\n }\n\n // Skip broadcasting if realtime is not enabled\n if (!this.realtimeEnabled) {\n return;\n }\n\n const message: RealtimeMessage = {\n type: 'error',\n content: errorMessage,\n errorCode: errorCode || 'unknown',\n timestamp: Date.now(),\n seq: ++this.seq,\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'output',\n payload: message,\n });\n\n this.emit('broadcast', message);\n }\n\n getSeq(): number {\n return this.seq;\n }\n\n isConnected(): boolean {\n return this.outputChannel !== null && this.inputChannel !== null;\n }\n\n isRealtimeEnabled(): boolean {\n return this.realtimeEnabled;\n }\n}\n","import type { RealtimeChannel } from '@supabase/supabase-js';\n\nconst DEFAULT_TIMEOUT = 10000;\n\nexport function subscribeWithTimeout(\n channel: RealtimeChannel,\n channelName: string,\n timeout: number = DEFAULT_TIMEOUT\n): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n let lastStatus = 'unknown';\n\n const timer = setTimeout(() => {\n console.warn(\n `[WARN] Realtime subscription timeout for ${channelName} (last status: ${lastStatus}).`\n );\n resolve(false);\n }, timeout);\n\n channel.subscribe((status, err) => {\n lastStatus = status;\n\n if (status === 'SUBSCRIBED') {\n clearTimeout(timer);\n resolve(true);\n } else if (\n status === 'CHANNEL_ERROR' ||\n status === 'CLOSED' ||\n status === 'TIMED_OUT'\n ) {\n clearTimeout(timer);\n console.warn(\n `[WARN] Channel ${channelName} ${status.toLowerCase()}.`\n );\n if (err) {\n console.warn(`[WARN] Error details: ${err.message || err}`);\n }\n resolve(false);\n }\n });\n });\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type { Session, SessionStatus } from 'clautunnel-shared';\n\nexport interface SessionManagerOptions {\n supabase: SupabaseClient;\n}\n\nexport class SessionManager {\n private supabase: SupabaseClient;\n\n constructor(options: SessionManagerOptions) {\n this.supabase = options.supabase;\n }\n\n async createSession(\n machineId: string,\n workingDirectory?: string\n ): Promise<Session> {\n const { data, error } = await this.supabase\n .from('sessions')\n .insert({\n machine_id: machineId,\n status: 'active' as SessionStatus,\n working_directory: workingDirectory,\n started_at: new Date().toISOString(),\n })\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to create session: ${error.message}`);\n }\n\n return data as Session;\n }\n\n async endSession(sessionId: string): Promise<void> {\n const { error } = await this.supabase\n .from('sessions')\n .update({\n status: 'ended' as SessionStatus,\n ended_at: new Date().toISOString(),\n })\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to end session: ${error.message}`);\n }\n }\n\n async getSession(sessionId: string): Promise<Session | null> {\n const { data, error } = await this.supabase\n .from('sessions')\n .select()\n .eq('id', sessionId)\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n // Not found\n return null;\n }\n throw new Error(`Failed to get session: ${error.message}`);\n }\n\n return data as Session;\n }\n\n async updateSessionStatus(\n sessionId: string,\n status: SessionStatus\n ): Promise<void> {\n const updates: Partial<Session> = { status };\n\n if (status === 'ended') {\n updates.ended_at = new Date().toISOString();\n }\n\n const { error } = await this.supabase\n .from('sessions')\n .update(updates)\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to update session status: ${error.message}`);\n }\n }\n\n async updateSessionModel(\n sessionId: string,\n model: string\n ): Promise<void> {\n const { error } = await this.supabase\n .from('sessions')\n .update({ model })\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to update session model: ${error.message}`);\n }\n }\n\n async updateSdkSessionId(\n sessionId: string,\n sdkSessionId: string\n ): Promise<void> {\n const { error } = await this.supabase\n .from('sessions')\n .update({ sdk_session_id: sdkSessionId })\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to update SDK session ID: ${error.message}`);\n }\n }\n\n async updateSessionTitle(\n sessionId: string,\n title: string\n ): Promise<void> {\n const { error } = await this.supabase\n .from('sessions')\n .update({ title })\n .eq('id', sessionId);\n\n if (error) {\n throw new Error(`Failed to update session title: ${error.message}`);\n }\n }\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type { Machine, MachineStatus } from 'clautunnel-shared';\nimport * as os from 'os';\n\nexport interface MachineManagerOptions {\n supabase: SupabaseClient;\n}\n\nexport class MachineManager {\n private supabase: SupabaseClient;\n\n constructor(options: MachineManagerOptions) {\n this.supabase = options.supabase;\n }\n\n async registerMachine(\n userId: string,\n name?: string,\n machineId?: string\n ): Promise<Machine> {\n const hostname = os.hostname();\n const machineName = name || hostname;\n\n // If machineId provided, try to update existing machine\n if (machineId) {\n const existing = await this.getMachine(machineId);\n if (existing) {\n await this.updateMachineStatus(machineId, 'online');\n return existing;\n }\n }\n\n // Check if machine with same user_id and hostname already exists\n const { data: existingByHostname } = await this.supabase\n .from('machines')\n .select()\n .eq('user_id', userId)\n .eq('hostname', hostname)\n .single();\n\n if (existingByHostname) {\n // Update existing machine and return it\n await this.updateMachineStatus(existingByHostname.id, 'online');\n return existingByHostname as Machine;\n }\n\n // Create new machine\n const { data, error } = await this.supabase\n .from('machines')\n .insert({\n user_id: userId,\n name: machineName,\n hostname,\n status: 'online' as MachineStatus,\n last_seen_at: new Date().toISOString(),\n })\n .select()\n .single();\n\n if (error) {\n throw new Error(`Failed to register machine: ${error.message}`);\n }\n\n return data as Machine;\n }\n\n async getMachine(machineId: string): Promise<Machine | null> {\n const { data, error } = await this.supabase\n .from('machines')\n .select()\n .eq('id', machineId)\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n // Not found\n return null;\n }\n throw new Error(`Failed to get machine: ${error.message}`);\n }\n\n return data as Machine;\n }\n\n async updateMachineStatus(\n machineId: string,\n status: MachineStatus\n ): Promise<void> {\n const { error } = await this.supabase\n .from('machines')\n .update({\n status,\n last_seen_at: new Date().toISOString(),\n })\n .eq('id', machineId);\n\n if (error) {\n throw new Error(`Failed to update machine status: ${error.message}`);\n }\n }\n\n async heartbeat(machineId: string): Promise<void> {\n const { error } = await this.supabase\n .from('machines')\n .update({\n last_seen_at: new Date().toISOString(),\n })\n .eq('id', machineId);\n\n if (error) {\n throw new Error(`Failed to update heartbeat: ${error.message}`);\n }\n }\n\n async listMachines(userId: string): Promise<Machine[]> {\n const { data, error } = await this.supabase\n .from('machines')\n .select()\n .eq('user_id', userId)\n .order('last_seen_at', { ascending: false });\n\n if (error) {\n throw new Error(`Failed to list machines: ${error.message}`);\n }\n\n return data as Machine[];\n }\n}\n","import { EventEmitter } from 'events';\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport { SdkSession } from './sdk-session.js';\nimport { SessionManager } from './session.js';\nimport { MachineManager } from './machine.js';\nimport { ConfigManager } from './config-manager.js';\nimport { RealtimeClient } from '../realtime/client.js';\nimport type { Session, Machine, RealtimeMessage, ImageAttachment, PermissionMode, UserQuestionData, PermissionRequestData, ToolUseData } from 'clautunnel-shared';\n\nexport interface DaemonOptions {\n supabase: SupabaseClient;\n userId: string;\n machineId?: string;\n machineName?: string;\n cwd: string;\n hybrid?: boolean;\n}\n\nexport class Daemon extends EventEmitter {\n private options: DaemonOptions;\n private sdkSession: SdkSession;\n private sessionManager: SessionManager;\n private machineManager: MachineManager;\n private configManager: ConfigManager;\n private realtimeClient: RealtimeClient | null = null;\n private machine: Machine | null = null;\n private session: Session | null = null;\n private running: boolean = false;\n private commandsBroadcast: boolean = false;\n private sdkCommandsBroadcast: boolean = false;\n private titleSet: boolean = false;\n\n constructor(options: DaemonOptions) {\n super();\n this.options = options;\n\n this.sdkSession = new SdkSession({\n cwd: options.cwd,\n });\n\n this.sessionManager = new SessionManager({\n supabase: options.supabase,\n });\n\n this.machineManager = new MachineManager({\n supabase: options.supabase,\n });\n\n this.configManager = new ConfigManager({\n cwd: options.cwd,\n });\n\n // Initialize thinking mode from settings\n const thinkingEnabled = this.configManager.getThinkingMode();\n if (thinkingEnabled) {\n this.sdkSession.setThinkingMode(true);\n }\n }\n\n async start(): Promise<void> {\n if (this.running) {\n throw new Error('Daemon is already running');\n }\n\n // Register machine\n this.machine = await this.machineManager.registerMachine(\n this.options.userId,\n this.options.machineName,\n this.options.machineId\n );\n\n // Create session\n this.session = await this.sessionManager.createSession(\n this.machine.id,\n this.options.cwd\n );\n\n // Initialize realtime client\n this.realtimeClient = new RealtimeClient({\n supabase: this.options.supabase,\n sessionId: this.session.id,\n });\n\n // Wire up SDK session output to broadcast\n this.sdkSession.on('output', async (data: string) => {\n // Hybrid mode: output to local stdout\n if (this.options.hybrid !== false) {\n process.stdout.write(data);\n }\n\n // Emit for external listeners (e.g., start command logging)\n this.emit('mobile-output', data);\n\n // Broadcast to mobile\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcast(data);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n this.sdkSession.on('error', (error: Error) => {\n this.emit('error', error);\n });\n\n // Broadcast commands when they're updated from init message (includes plugins/skills)\n this.sdkSession.on('commands-updated', async () => {\n await this.broadcastCommands();\n });\n\n // Save SDK session ID to Supabase for resume functionality\n this.sdkSession.on('session-started', async (sdkSessionId: string) => {\n if (!this.session) return;\n try {\n await this.sessionManager.updateSdkSessionId(this.session.id, sdkSessionId);\n } catch {\n // Silently handle - non-critical for basic functionality\n }\n });\n\n this.sdkSession.on('complete', async () => {\n // Session query completed, ready for next input\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n> ');\n }\n\n // Broadcast completion to mobile so it knows Claude is done\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastComplete();\n } catch {\n // Silently handle broadcast errors\n }\n }\n\n // Broadcast real SDK commands (including custom skills) after first query completion\n // This updates the fallback commands with the full list from the SDK\n if (!this.sdkCommandsBroadcast && this.realtimeClient) {\n this.sdkCommandsBroadcast = true;\n await this.broadcastCommands();\n }\n });\n\n // Wire up permission mode changes to broadcast\n this.sdkSession.on('permission-mode', async (mode: PermissionMode) => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastMode(mode);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up user questions to broadcast to mobile\n this.sdkSession.on('user-question', async (questionData: UserQuestionData) => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastUserQuestion(questionData);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up request queuing to broadcast to mobile\n this.sdkSession.on('request-queued', async () => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastQueued();\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up permission requests to broadcast to mobile\n this.sdkSession.on('permission-request', async (requestData: PermissionRequestData) => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastPermissionRequest(requestData);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up tool use data to broadcast to mobile (for code diffs)\n this.sdkSession.on('tool-use', async (toolUseData: ToolUseData) => {\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastToolUse(toolUseData);\n } catch (err) {\n console.warn('[Daemon] Failed to broadcast tool-use:', err);\n }\n }\n });\n\n // Wire up model changes to broadcast and persist\n this.sdkSession.on('model', async (model: string) => {\n // Persist model to database for this session\n if (this.session) {\n try {\n await this.sessionManager.updateSessionModel(this.session.id, model);\n } catch {\n // Silently handle persistence errors\n }\n }\n\n // Broadcast to mobile\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastModel(model);\n } catch {\n // Silently handle broadcast errors\n }\n }\n });\n\n // Wire up input from mobile\n this.realtimeClient.on('input', async (message: RealtimeMessage) => {\n // Broadcast commands on first message from mobile if not already done\n if (!this.commandsBroadcast) {\n this.commandsBroadcast = true;\n await this.broadcastCommands();\n }\n\n // Handle mode change requests\n if (message.type === 'mode-change' && message.permissionMode) {\n this.sdkSession.setPermissionMode(message.permissionMode);\n // Broadcast the new mode back to confirm\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastMode(message.permissionMode);\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle commands request\n if (message.type === 'commands-request') {\n await this.broadcastCommands();\n return;\n }\n\n // Handle model change requests\n if (message.type === 'model-change' && message.model) {\n const previousModel = this.sdkSession.getModel();\n await this.sdkSession.setModel(message.model);\n\n // Output confirmation message if model actually changed\n if (previousModel !== message.model) {\n const modelNames: Record<string, string> = {\n 'default': 'Opus 4.6',\n 'sonnet': 'Sonnet 4.5',\n 'opus': 'Opus 4.6',\n 'haiku': 'Haiku 3.5',\n };\n const displayName = modelNames[message.model] || message.model;\n const confirmationMsg = `[Model switched to ${displayName}]`;\n\n // Output to local terminal\n if (this.options.hybrid !== false) {\n process.stdout.write(`\\n${confirmationMsg}\\n`);\n }\n\n // Broadcast to mobile as system message (appears as separate bubble)\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastSystem(confirmationMsg);\n } catch {\n // Silently handle broadcast errors\n }\n }\n } else {\n // Model didn't change — still broadcast current model so mobile clears loading state\n try {\n await this.realtimeClient?.broadcastModel(this.sdkSession.getModel());\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle models request - send both available models and current model\n if (message.type === 'models-request') {\n await this.broadcastModels();\n // Also broadcast the current model so UI shows the correct selection\n try {\n await this.realtimeClient?.broadcastModel(this.sdkSession.getModel());\n } catch {\n // Silently handle broadcast errors\n }\n return;\n }\n\n // Handle status request - re-broadcast any pending question or permission\n if (message.type === 'status-request') {\n if (this.realtimeClient) {\n try {\n const pendingQuestion = this.sdkSession.getPendingQuestionData();\n if (pendingQuestion) {\n await this.realtimeClient.broadcastUserQuestion(pendingQuestion);\n }\n const pendingPermission = this.sdkSession.getPendingPermissionData();\n if (pendingPermission) {\n await this.realtimeClient.broadcastPermissionRequest(pendingPermission);\n }\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle mobile disconnect notification\n if (message.type === 'mobile-disconnect') {\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[ClauTunnel] Mobile client disconnected.\\n');\n }\n this.emit('mobile-disconnected');\n return;\n }\n\n // Handle interactive command request\n if (message.type === 'interactive-request' && message.interactiveCommand) {\n const data = this.configManager.getInteractiveData(message.interactiveCommand);\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastInteractiveResponse(data);\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle interactive apply\n if (message.type === 'interactive-apply' && message.interactivePayload) {\n const result = this.configManager.applyChange(message.interactivePayload);\n\n // If thinking mode was changed, also update the running SDK session\n if (\n message.interactivePayload.command === 'config' &&\n message.interactivePayload.key === 'alwaysThinkingEnabled'\n ) {\n const enabled = Boolean(message.interactivePayload.value);\n await this.sdkSession.setThinkingMode(enabled);\n }\n\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastInteractiveConfirm(\n message.interactivePayload.command,\n result\n );\n // Also broadcast a system message for confirmation\n const statusText = result.success\n ? `✓ ${result.message}`\n : `✗ ${result.message}`;\n await this.realtimeClient.broadcastSystem(statusText);\n } catch {\n // Silently handle broadcast errors\n }\n }\n return;\n }\n\n // Handle cancel request from mobile - stop Claude mid-processing\n if (message.type === 'cancel-request') {\n this.sdkSession.cancel();\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[Cancelled]\\n> ');\n }\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastSystem('[Cancelled]');\n await this.realtimeClient.broadcastComplete();\n } catch (error) {\n console.warn('[Daemon] Failed to broadcast cancel:', error);\n }\n }\n return;\n }\n\n // Handle clear request from mobile (doesn't appear in chat)\n if (message.type === 'clear-request') {\n this.sdkSession.clearHistory();\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[Conversation cleared]\\n> ');\n }\n return;\n }\n\n // Handle user answer (response to AskUserQuestion)\n // Use provideAnswer() to stream into the existing query instead of\n // sendPrompt() which would be rejected since isProcessing is true\n if (message.type === 'user-answer' && message.userAnswer) {\n const answerText = Object.values(message.userAnswer.answers).join('\\n');\n this.emit('mobile-input', `(answer) ${answerText}`);\n await this.sdkSession.provideAnswer(answerText, message.userAnswer.answers);\n return;\n }\n\n // Handle permission response from mobile\n if (message.type === 'permission-response' && message.permissionResponse) {\n this.sdkSession.handlePermissionResponse(message.permissionResponse);\n return;\n }\n\n // Handle resume request from mobile (doesn't appear in chat)\n if (message.type === 'resume-request' && message.resumeSessionId) {\n const targetSdkSessionId = message.resumeSessionId;\n this.sdkSession.resumeSession(targetSdkSessionId);\n\n const confirmationMsg = `[Resuming session: ${targetSdkSessionId.slice(0, 8)}...]`;\n if (this.options.hybrid !== false) {\n process.stdout.write(`\\n${confirmationMsg}\\n`);\n }\n\n if (this.realtimeClient) {\n try {\n // Find the Supabase session with this SDK session ID to load its messages\n const { data: sessionData } = await this.options.supabase\n .from('sessions')\n .select('id')\n .eq('sdk_session_id', targetSdkSessionId)\n .single();\n\n if (sessionData) {\n // Tell mobile to load messages from this session\n await this.realtimeClient.broadcastResumeHistory(sessionData.id);\n }\n\n await this.realtimeClient.broadcastSystem(confirmationMsg);\n } catch {\n // Silently handle broadcast errors\n }\n }\n\n // Send a prompt to trigger the resumed session\n await this.sdkSession.sendPrompt('Continue from where we left off.');\n return;\n }\n\n // Remove trailing newline/carriage return for SDK\n const prompt = message.content?.replace(/[\\r\\n]+$/, '') || '';\n const attachments = message.attachments;\n\n // Send if there's text or attachments\n if (prompt.trim() || (attachments && attachments.length > 0)) {\n const trimmedPrompt = prompt.trim();\n\n // Emit mobile input event for logging\n this.emit('mobile-input', trimmedPrompt, attachments);\n\n // Handle /clear typed in chat (legacy support)\n if (trimmedPrompt === '/clear') {\n this.sdkSession.clearHistory();\n if (this.realtimeClient) {\n try {\n await this.realtimeClient.broadcastSystem('Conversation cleared');\n } catch {\n // Silently handle broadcast errors\n }\n }\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[Conversation cleared]\\n> ');\n }\n return;\n }\n\n // Auto-set session title from the first user message\n if (!this.titleSet && this.session) {\n this.titleSet = true;\n const title = trimmedPrompt.length > 50\n ? trimmedPrompt.slice(0, 50) + '...'\n : trimmedPrompt;\n this.sessionManager.updateSessionTitle(this.session.id, title).catch(() => {\n // Non-critical - silently handle\n });\n if (this.realtimeClient) {\n this.realtimeClient.broadcastSessionTitle(title).catch(() => {\n // Non-critical - silently handle\n });\n }\n }\n\n await this.sdkSession.sendPrompt(prompt, attachments);\n }\n });\n\n // Connect to realtime\n await this.realtimeClient.connect();\n\n // Broadcast initial permission mode\n try {\n await this.realtimeClient.broadcastMode(this.sdkSession.getPermissionMode());\n } catch {\n // Silently handle broadcast errors\n }\n\n // Broadcast available commands immediately\n await this.broadcastCommands();\n\n // Broadcast available models immediately\n await this.broadcastModels();\n\n // Broadcast current model\n try {\n await this.realtimeClient.broadcastModel(this.sdkSession.getModel());\n } catch {\n // Silently handle broadcast errors\n }\n\n this.running = true;\n this.emit('started', {\n machine: this.machine,\n session: this.session,\n mobileSyncEnabled: this.realtimeClient?.isRealtimeEnabled() ?? false,\n });\n\n // Show initial prompt\n if (this.options.hybrid !== false) {\n process.stdout.write('\\n[ClauTunnel] Ready for input.\\n> ');\n }\n }\n\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n this.running = false;\n\n // Cancel any ongoing SDK operation\n this.sdkSession.cancel();\n\n // End session\n if (this.session) {\n await this.sessionManager.endSession(this.session.id);\n }\n\n // Note: We don't set machine status to 'offline' here because other\n // sessions may still be running on the same machine. The machine\n // status is set to 'online' when any session starts.\n\n // Disconnect realtime\n if (this.realtimeClient) {\n await this.realtimeClient.disconnect();\n }\n\n this.emit('stopped');\n }\n\n async sendPrompt(prompt: string, attachments?: ImageAttachment[]): Promise<void> {\n await this.sdkSession.sendPrompt(prompt, attachments);\n }\n\n isRunning(): boolean {\n return this.running;\n }\n\n getSession(): Session | null {\n return this.session;\n }\n\n getMachine(): Machine | null {\n return this.machine;\n }\n\n private async broadcastCommands(): Promise<void> {\n if (!this.realtimeClient) {\n return;\n }\n\n try {\n const commands = await this.sdkSession.getSupportedCommands();\n await this.realtimeClient.broadcastCommands(commands);\n } catch {\n // Silently handle broadcast errors\n }\n }\n\n private async broadcastModels(): Promise<void> {\n if (!this.realtimeClient) {\n return;\n }\n\n try {\n const models = await this.sdkSession.getSupportedModels();\n await this.realtimeClient.broadcastModels(models);\n } catch {\n // Silently handle broadcast errors\n }\n }\n}\n","import { EventEmitter } from 'events';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { unstable_v2_createSession, unstable_v2_resumeSession } from '@anthropic-ai/claude-agent-sdk';\nimport type { SDKSession as V2Session, SDKSessionOptions, SDKMessage, SlashCommand as SDKSlashCommand, CanUseTool, PermissionResult, PermissionUpdate as SDKPermissionUpdate, SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';\nimport type { ImageAttachment, ModelInfo, PermissionMode, SlashCommand, UserQuestionData, UserQuestion, PermissionRequestData, PermissionResponseData, PermissionUpdate, ToolUseData } from 'clautunnel-shared';\nimport { v4 as uuidv4 } from 'uuid';\n\n/** Maximum characters to capture from tool use content */\nconst MAX_TOOL_CONTENT = 10000;\n\n/** Commands unsupported in remote/mobile context */\nconst UNSUPPORTED_COMMANDS = new Set([\n 'keybindings-help', 'help', 'context', 'cost', 'release-notes',\n 'vim', 'mcp', 'agents', 'hooks', 'status',\n]);\n\nexport interface SdkSessionOptions {\n cwd: string;\n allowedTools?: string[];\n permissionMode?: PermissionMode;\n model?: string;\n}\n\ninterface ConversationMessage {\n role: 'user' | 'assistant';\n content: string;\n}\n\n// Pending permission request with resolver\ninterface PendingPermissionRequest {\n resolve: (result: PermissionResult) => void;\n reject: (error: Error) => void;\n signal: AbortSignal;\n}\n\nexport class SdkSession extends EventEmitter {\n private options: SdkSessionOptions;\n private sessionId: string | null = null;\n private isProcessing: boolean = false;\n private currentPermissionMode: PermissionMode;\n private v2Session: V2Session | null = null;\n private streamLoopRunning: boolean = false;\n private cachedCommands: SlashCommand[] | null = null;\n private cachedModels: ModelInfo[] | null = null;\n private currentModel: string = 'opus';\n private conversationHistory: ConversationMessage[] = [];\n private pendingContextTransfer: boolean = false;\n private thinkingEnabled: boolean = false;\n private pendingPermissionRequests: Map<string, PendingPermissionRequest> = new Map();\n // Pending AskUserQuestion answer resolver - resolved by provideAnswer()\n private pendingAnswerResolve: ((answers: Record<string, string>) => void) | null = null;\n // Track pending question/permission data for re-broadcast on status-request\n private pendingQuestionData: UserQuestionData | null = null;\n private pendingPermissionData: PermissionRequestData | null = null;\n // Track current assistant response text for conversation history\n private currentAssistantResponse: string = '';\n // Queued prompt to send after current processing completes (last-one-wins)\n private pendingPrompt: { prompt: string; attachments?: ImageAttachment[] } | null = null;\n\n constructor(options: SdkSessionOptions) {\n super();\n this.options = options;\n this.currentPermissionMode = options.permissionMode || 'default';\n this.currentModel = options.model || 'opus';\n }\n\n /**\n * Handle permission response from mobile\n */\n handlePermissionResponse(response: PermissionResponseData): void {\n const pending = this.pendingPermissionRequests.get(response.requestId);\n if (!pending) {\n console.warn(`[WARN] No pending permission request found for ID: ${response.requestId}`);\n return;\n }\n\n this.pendingPermissionRequests.delete(response.requestId);\n this.pendingPermissionData = null;\n\n if (response.behavior === 'allow') {\n const result: PermissionResult = {\n behavior: 'allow',\n updatedInput: response.updatedInput,\n updatedPermissions: response.updatedPermissions as SDKPermissionUpdate[] | undefined,\n };\n pending.resolve(result);\n } else {\n const result: PermissionResult = {\n behavior: 'deny',\n message: response.message || 'Permission denied by user',\n };\n pending.resolve(result);\n }\n }\n\n /**\n * Create canUseTool callback for SDK\n *\n * AskUserQuestion goes through this path: the subprocess sends a\n * control_request with subtype \"can_use_tool\" and blocks until a\n * control_response is returned. For AskUserQuestion we emit a\n * user-question event, wait for provideAnswer() to resolve the pending\n * promise, and return {behavior:'allow', updatedInput:{questions, answers}}\n * so the subprocess can produce the tool_result and continue.\n */\n private createCanUseTool(): CanUseTool {\n return async (\n toolName: string,\n input: Record<string, unknown>,\n options: {\n signal: AbortSignal;\n suggestions?: SDKPermissionUpdate[];\n blockedPath?: string;\n decisionReason?: string;\n toolUseID: string;\n agentID?: string;\n }\n ): Promise<PermissionResult> => {\n\n // --- AskUserQuestion: route through user-question event -----------\n if (toolName === 'AskUserQuestion') {\n const questionInput = input as {\n questions?: Array<{\n question: string;\n header: string;\n options: Array<{ label: string; description: string }>;\n multiSelect?: boolean;\n }>;\n };\n\n if (questionInput.questions && Array.isArray(questionInput.questions)) {\n const questions: UserQuestion[] = questionInput.questions.map(q => ({\n question: q.question,\n header: q.header,\n options: (q.options || []).map(o => ({\n label: o.label,\n description: o.description,\n })),\n multiSelect: q.multiSelect,\n }));\n\n const questionData: UserQuestionData = {\n toolUseId: options.toolUseID,\n questions,\n };\n\n // Store and broadcast to mobile\n this.pendingQuestionData = questionData;\n this.emit('user-question', questionData);\n\n // Wait for provideAnswer() to supply the answers\n const answers = await new Promise<Record<string, string>>(\n (resolve, reject) => {\n this.pendingAnswerResolve = resolve;\n\n // Clean up if the request is aborted (e.g. session cancelled)\n options.signal.addEventListener('abort', () => {\n this.pendingAnswerResolve = null;\n this.pendingQuestionData = null;\n reject(new Error('Question aborted'));\n });\n }\n );\n\n this.pendingAnswerResolve = null;\n this.pendingQuestionData = null;\n\n // Return updatedInput so the subprocess can build the tool_result\n return {\n behavior: 'allow' as const,\n updatedInput: {\n questions: questionInput.questions,\n answers,\n },\n };\n }\n }\n\n // --- Regular permission request: broadcast to mobile and wait -----\n const requestId = uuidv4();\n\n // Convert SDK permission updates to our type\n const suggestions = options.suggestions?.map((s): PermissionUpdate => {\n // Handle different permission update types\n if (s.type === 'addRules' || s.type === 'replaceRules' || s.type === 'removeRules') {\n return {\n type: s.type,\n rules: s.rules,\n behavior: s.behavior,\n destination: s.destination,\n };\n } else if (s.type === 'setMode') {\n return {\n type: 'setMode',\n mode: s.mode as PermissionMode,\n destination: s.destination,\n };\n } else if (s.type === 'addDirectories' || s.type === 'removeDirectories') {\n return {\n type: s.type,\n directories: s.directories,\n destination: s.destination,\n };\n }\n // Fallback - should never reach here\n return s as PermissionUpdate;\n });\n\n const requestData: PermissionRequestData = {\n requestId,\n toolName,\n toolInput: input,\n toolUseId: options.toolUseID,\n suggestions,\n blockedPath: options.blockedPath,\n decisionReason: options.decisionReason,\n agentId: options.agentID,\n };\n\n // Store and emit event for daemon to broadcast to mobile\n this.pendingPermissionData = requestData;\n this.emit('permission-request', requestData);\n\n // Create promise that will be resolved when mobile responds\n return new Promise<PermissionResult>((resolve, reject) => {\n this.pendingPermissionRequests.set(requestId, {\n resolve,\n reject,\n signal: options.signal,\n });\n\n // Handle abort\n options.signal.addEventListener('abort', () => {\n this.pendingPermissionRequests.delete(requestId);\n this.pendingPermissionData = null;\n reject(new Error('Permission request aborted'));\n });\n });\n };\n }\n\n setPermissionMode(mode: PermissionMode): void {\n this.currentPermissionMode = mode;\n this.emit('permission-mode', mode);\n }\n\n getPermissionMode(): PermissionMode {\n return this.currentPermissionMode;\n }\n\n async setThinkingMode(enabled: boolean): Promise<void> {\n this.thinkingEnabled = enabled;\n this.emit('thinking-mode', enabled);\n }\n\n getThinkingMode(): boolean {\n return this.thinkingEnabled;\n }\n\n /**\n * Build V2 session options from current state\n */\n private buildSessionOptions(): SDKSessionOptions {\n const opts: SDKSessionOptions = {\n // SDK accepts shorthand model names: 'opus' | 'sonnet' | 'haiku'\n // Full model IDs (e.g. 'claude-opus-4-6') are also valid but shorthand is preferred\n model: this.currentModel,\n allowedTools: this.options.allowedTools || ['Read', 'Edit', 'Write', 'Bash', 'Glob', 'Grep'],\n canUseTool: this.createCanUseTool(),\n permissionMode: this.currentPermissionMode,\n };\n return opts;\n }\n\n /**\n * Ensure a V2 session exists, creating one if needed\n */\n private ensureSession(): V2Session {\n if (!this.v2Session) {\n const opts = this.buildSessionOptions();\n\n if (this.sessionId) {\n // Resume existing session\n this.v2Session = unstable_v2_resumeSession(this.sessionId, opts);\n } else {\n // Create new session\n this.v2Session = unstable_v2_createSession(opts);\n }\n\n // Start the background message processing loop\n this.startStreamLoop();\n }\n return this.v2Session;\n }\n\n /**\n * Background loop that processes messages from the V2 session stream.\n * Runs continuously for the lifetime of the session.\n */\n private async startStreamLoop(): Promise<void> {\n if (this.streamLoopRunning || !this.v2Session) return;\n this.streamLoopRunning = true;\n\n try {\n // The V2 stream() returns after each 'result' message.\n // For multi-turn sessions, we need to call stream() again after each result.\n while (this.v2Session && !this.v2Session['closed']) {\n for await (const message of this.v2Session.stream()) {\n this.processMessage(message);\n }\n }\n } catch (error) {\n if ((error as Error).name !== 'AbortError') {\n this.emit('error', error);\n }\n } finally {\n this.streamLoopRunning = false;\n // If the stream loop exits without a 'result' message (e.g. unexpected\n // disconnect or error), ensure isProcessing is reset so subsequent\n // requests are not permanently blocked.\n if (this.isProcessing) {\n this.isProcessing = false;\n this.pendingPrompt = null;\n this.emit('complete');\n }\n }\n }\n\n /**\n * Process a single SDK message from the stream\n */\n private processMessage(message: SDKMessage): void {\n // Handle different message types\n if (message.type === 'system' && 'subtype' in message && message.subtype === 'init') {\n // Capture session ID for resuming\n this.sessionId = message.session_id;\n this.emit('session-started', this.sessionId);\n\n // Emit permission mode if present\n if ('permissionMode' in message) {\n this.emit('permission-mode', message.permissionMode);\n }\n\n // Capture slash commands from init message (includes plugins/skills)\n if ('slash_commands' in message && Array.isArray(message.slash_commands)) {\n this.cachedCommands = message.slash_commands.map((cmd: unknown) => {\n if (typeof cmd === 'string') {\n return { name: cmd, description: '', argumentHint: '' };\n } else if (typeof cmd === 'object' && cmd !== null) {\n const cmdObj = cmd as SDKSlashCommand;\n return {\n name: cmdObj.name || '',\n description: cmdObj.description || '',\n argumentHint: cmdObj.argumentHint || '',\n };\n }\n return { name: String(cmd), description: '', argumentHint: '' };\n });\n this.emit('commands-updated', this.cachedCommands);\n }\n } else if (message.type === 'assistant') {\n // Assistant text output and tool use\n if (message.message?.content) {\n for (const block of message.message.content) {\n if ('type' in block && block.type === 'text' && 'text' in block) {\n this.emit('output', block.text);\n this.currentAssistantResponse += block.text;\n } else if ('type' in block && block.type === 'tool_use' && 'name' in block) {\n // AskUserQuestion tool_use blocks are handled via the canUseTool\n // callback (which emits 'user-question' and waits for the answer).\n const toolName = (block as any).name as string;\n if (toolName !== 'AskUserQuestion') {\n const input = (block as any).input || {};\n let toolUseData: ToolUseData;\n\n if (toolName === 'Edit' && input.file_path && input.old_string !== undefined) {\n toolUseData = {\n action: 'Edit',\n filePath: input.file_path,\n oldString: String(input.old_string).slice(0, MAX_TOOL_CONTENT),\n newString: String(input.new_string || '').slice(0, MAX_TOOL_CONTENT),\n };\n } else if (toolName === 'Write' && input.file_path) {\n toolUseData = {\n action: 'Write',\n filePath: input.file_path,\n content: String(input.content || '').slice(0, MAX_TOOL_CONTENT),\n };\n } else {\n toolUseData = {\n action: toolName,\n toolName,\n input,\n };\n }\n\n this.emit('tool-use', toolUseData);\n }\n }\n }\n }\n } else if (message.type === 'result') {\n // Emit result text if no assistant output was captured (e.g. slash commands like /context)\n if (!this.currentAssistantResponse.trim() && 'result' in message && message.result) {\n const resultText = String(message.result);\n this.emit('output', resultText);\n this.currentAssistantResponse = resultText;\n }\n // Final result - track assistant response in history\n if (this.currentAssistantResponse.trim()) {\n this.conversationHistory.push({ role: 'assistant', content: this.currentAssistantResponse.trim() });\n }\n\n this.currentAssistantResponse = '';\n this.isProcessing = false;\n\n // Auto-send queued message if one is pending\n const queued = this.pendingPrompt;\n if (queued) {\n this.pendingPrompt = null;\n // Don't emit 'complete' — mobile isTyping stays true seamlessly\n this.sendPrompt(queued.prompt, queued.attachments);\n } else {\n this.emit('complete');\n }\n } else if (message.type === 'tool_progress') {\n // Tool progress (tool being used)\n if ('tool_name' in message) {\n this.emit('output', `\\n[Using tool: ${message.tool_name}]\\n`);\n }\n } else if (message.type === 'tool_use_summary') {\n // Tool use summary\n if ('tool_name' in message) {\n this.emit('output', `[Tool ${message.tool_name} completed]\\n`);\n }\n }\n }\n\n async sendPrompt(prompt: string, attachments?: ImageAttachment[]): Promise<void> {\n if (this.isProcessing) {\n // Queue the message instead of rejecting — last one wins\n this.pendingPrompt = { prompt, attachments };\n this.emit('request-queued');\n return;\n }\n\n this.isProcessing = true;\n this.currentAssistantResponse = '';\n\n // Track user message in conversation history\n if (prompt.trim()) {\n this.conversationHistory.push({ role: 'user', content: prompt });\n }\n\n try {\n // Build the prompt text, including context if transferring to new session\n let finalPrompt = prompt;\n if (this.pendingContextTransfer && this.conversationHistory.length > 1) {\n // Build context from previous conversation (excluding current message)\n const previousHistory = this.conversationHistory.slice(0, -1);\n const contextLines = previousHistory.map(msg =>\n `${msg.role === 'user' ? 'User' : 'Assistant'}: ${msg.content}`\n );\n const contextPrefix = `[Previous conversation context - you switched to a new model]\\n${contextLines.join('\\n')}\\n\\n[Continue with new message]\\n`;\n finalPrompt = contextPrefix + prompt;\n this.pendingContextTransfer = false;\n }\n\n // Ensure we have a V2 session\n const session = this.ensureSession();\n\n // Build message content\n const contentBlocks: Array<{ type: string; text?: string; source?: { type: string; media_type: string; data: string } }> = [];\n\n // Add images if present\n if (attachments && attachments.length > 0) {\n for (const attachment of attachments) {\n contentBlocks.push({\n type: 'image',\n source: {\n type: 'base64',\n media_type: attachment.mediaType,\n data: attachment.data,\n },\n });\n }\n }\n\n // Add text\n if (finalPrompt.trim()) {\n contentBlocks.push({\n type: 'text',\n text: finalPrompt,\n });\n }\n\n // Build and send the user message via V2 session.send()\n const userMessage: SDKUserMessage = {\n type: 'user' as const,\n message: {\n role: 'user' as const,\n content: contentBlocks.length > 0 ? contentBlocks : [{ type: 'text' as const, text: finalPrompt }],\n },\n parent_tool_use_id: null,\n session_id: this.sessionId || '',\n };\n\n await session.send(userMessage);\n } catch (error) {\n if ((error as Error).name === 'AbortError') {\n this.emit('output', '\\n[Cancelled]\\n');\n } else {\n this.emit('error', error);\n this.emit('output', `\\n[Error: ${(error as Error).message}]\\n`);\n }\n this.isProcessing = false;\n }\n }\n\n /**\n * Provide an answer to a pending AskUserQuestion.\n *\n * AskUserQuestion flows through the canUseTool callback which blocks\n * waiting for a Promise to resolve. This method resolves that Promise\n * with the user's answers, which causes canUseTool to return\n * {behavior:'allow', updatedInput:{questions, answers}} → the SDK\n * sends the control_response back to the subprocess → it unblocks and\n * builds the tool_result for the Claude API.\n */\n async provideAnswer(answerText: string, answers?: Record<string, string>): Promise<void> {\n // Track in conversation history\n if (answerText.trim()) {\n this.conversationHistory.push({ role: 'user', content: answerText });\n }\n\n if (this.pendingAnswerResolve) {\n // Resolve the pending canUseTool callback with the answers\n const resolvedAnswers = answers || { result: answerText };\n this.pendingAnswerResolve(resolvedAnswers);\n this.pendingAnswerResolve = null;\n return;\n }\n\n // No pending question - fall back to sendPrompt\n await this.sendPrompt(answerText);\n }\n\n cancel(): void {\n this.pendingAnswerResolve = null;\n this.pendingQuestionData = null;\n this.pendingPermissionData = null;\n this.pendingPermissionRequests.clear();\n if (this.v2Session) {\n this.v2Session.close();\n this.v2Session = null;\n this.streamLoopRunning = false;\n }\n this.isProcessing = false;\n this.pendingPrompt = null;\n }\n\n getSessionId(): string | null {\n return this.sessionId;\n }\n\n /**\n * Resume a different session by setting its ID.\n * The next sendPrompt call will use this session ID.\n */\n resumeSession(sessionId: string): void {\n // Close existing session if any\n if (this.v2Session) {\n this.v2Session.close();\n this.v2Session = null;\n this.streamLoopRunning = false;\n }\n this.sessionId = sessionId;\n this.isProcessing = false;\n this.pendingPrompt = null;\n this.conversationHistory = []; // Clear local history since we're resuming a different session\n this.emit('session-resumed', sessionId);\n }\n\n isActive(): boolean {\n return this.isProcessing;\n }\n\n getPendingQuestionData(): UserQuestionData | null {\n return this.pendingQuestionData;\n }\n\n getPendingPermissionData(): PermissionRequestData | null {\n return this.pendingPermissionData;\n }\n\n async setModel(model: string): Promise<void> {\n if (model === this.currentModel) return;\n\n this.currentModel = model;\n\n // Close existing session - a new one will be created with the new model on next sendPrompt()\n if (this.v2Session) {\n this.v2Session.close();\n this.v2Session = null;\n this.streamLoopRunning = false;\n this.sessionId = null;\n this.isProcessing = false;\n this.pendingPrompt = null;\n this.pendingContextTransfer = true;\n } else if (this.sessionId) {\n this.sessionId = null;\n this.pendingContextTransfer = true;\n }\n\n this.emit('model', model);\n }\n\n getModel(): string {\n return this.currentModel;\n }\n\n getConversationHistory(): ConversationMessage[] {\n return [...this.conversationHistory];\n }\n\n clearHistory(): void {\n this.conversationHistory = [];\n // Close existing session and force a fresh one on next prompt\n if (this.v2Session) {\n this.v2Session.close();\n this.v2Session = null;\n this.streamLoopRunning = false;\n }\n this.sessionId = null;\n this.isProcessing = false;\n this.pendingPrompt = null;\n }\n\n async getSupportedModels(): Promise<ModelInfo[]> {\n // Fallback models matching SDK response format\n const coreModels: ModelInfo[] = [\n { value: 'opus', displayName: 'Opus 4.6', description: 'Opus 4.6 · Most capable for complex work' },\n { value: 'haiku', displayName: 'Haiku 4.5', description: 'Haiku 4.5 · Fastest for quick answers' },\n { value: 'sonnet', displayName: 'Sonnet 4.5', description: 'Sonnet 4.5 · Best for everyday tasks' },\n ];\n\n // Return cached SDK models if available\n if (this.cachedModels) {\n return this.cachedModels;\n }\n\n return coreModels;\n }\n\n /**\n * Scan file system for custom commands/skills\n * Commands are in ~/.claude/commands/ and .claude/commands/\n * Subdirectories create namespaced commands (e.g., gsd/add-phase.md -> gsd:add-phase)\n */\n private scanCustomCommands(): SlashCommand[] {\n const commands: SlashCommand[] = [];\n const homeDir = os.homedir();\n\n // Directories to scan\n const dirs = [\n path.join(homeDir, '.claude', 'commands'), // Personal commands\n path.join(this.options.cwd, '.claude', 'commands'), // Project commands\n ];\n\n for (const dir of dirs) {\n if (!fs.existsSync(dir)) continue;\n\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n // Namespaced commands (e.g., gsd/)\n const namespace = entry.name;\n const subDir = path.join(dir, namespace);\n const subEntries = fs.readdirSync(subDir);\n\n for (const file of subEntries) {\n if (file.endsWith('.md')) {\n const name = `${namespace}:${file.replace('.md', '')}`;\n const description = this.extractDescription(path.join(subDir, file));\n commands.push({ name, description, argumentHint: '' });\n }\n }\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n // Top-level commands\n const name = entry.name.replace('.md', '');\n const description = this.extractDescription(path.join(dir, entry.name));\n commands.push({ name, description, argumentHint: '' });\n }\n }\n } catch {\n // Ignore errors scanning directories\n }\n }\n\n return commands;\n }\n\n /**\n * Extract description from markdown file (first line or frontmatter)\n */\n private extractDescription(filePath: string): string {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n // Check for frontmatter description\n if (lines[0] === '---') {\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (!line) continue;\n if (line === '---') break;\n if (line.startsWith('description:')) {\n return line.replace('description:', '').trim().replace(/^[\"']|[\"']$/g, '');\n }\n }\n }\n\n // Use first heading or first line as description\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith('# ')) {\n return trimmed.replace('# ', '');\n }\n if (trimmed && !trimmed.startsWith('---')) {\n return trimmed.slice(0, 100);\n }\n }\n } catch {\n // Ignore errors\n }\n return '';\n }\n\n async getSupportedCommands(): Promise<SlashCommand[]> {\n // Fallback commands - known Claude Code built-in commands\n const fallbackCommands: SlashCommand[] = [\n // Session management\n { name: 'help', description: 'Show all commands and custom slash commands', argumentHint: '' },\n { name: 'clear', description: 'Clear the conversation history', argumentHint: '' },\n { name: 'compact', description: 'Compress conversation by summarizing older messages', argumentHint: '' },\n { name: 'resume', description: 'Resume a previous conversation', argumentHint: '<session-id>' },\n { name: 'rewind', description: 'Go back to a previous message in the session', argumentHint: '' },\n { name: 'context', description: 'Check context and excluded skills', argumentHint: '' },\n // Configuration\n { name: 'config', description: 'Configure Claude Code settings interactively', argumentHint: '' },\n { name: 'permissions', description: 'View or update tool permissions', argumentHint: '' },\n { name: 'allowed-tools', description: 'Configure tool permissions interactively', argumentHint: '' },\n { name: 'model', description: 'Change the AI model', argumentHint: '' },\n { name: 'vim', description: 'Enable vim-style editing mode', argumentHint: '' },\n // Integrations\n { name: 'hooks', description: 'Configure hooks', argumentHint: '' },\n { name: 'mcp', description: 'Manage MCP servers', argumentHint: '' },\n { name: 'agents', description: 'Manage subagents (create, edit, list)', argumentHint: '' },\n { name: 'terminal-setup', description: 'Install terminal shortcuts for iTerm2/VS Code', argumentHint: '' },\n { name: 'install-github-app', description: 'Set up GitHub Actions integration', argumentHint: '' },\n { name: 'ide', description: 'Open in IDE or configure IDE integration', argumentHint: '' },\n // Project\n { name: 'init', description: 'Initialize Claude Code and generate CLAUDE.md', argumentHint: '' },\n { name: 'memory', description: 'Edit CLAUDE.md memory file', argumentHint: '' },\n { name: 'add-dir', description: 'Add a directory to the context', argumentHint: '<path>' },\n // Git & Code Review\n { name: 'commit', description: 'Commit changes to git with a generated message', argumentHint: '' },\n { name: 'review', description: 'Review code changes', argumentHint: '' },\n { name: 'review-pr', description: 'Review a GitHub pull request', argumentHint: '<pr-url>' },\n { name: 'pr-comments', description: 'Get comments from a GitHub pull request', argumentHint: '' },\n { name: 'release-notes', description: 'Generate release notes', argumentHint: '' },\n { name: 'security-review', description: 'Perform a security review', argumentHint: '' },\n // Account & System\n { name: 'login', description: 'Log in to your Anthropic account', argumentHint: '' },\n { name: 'logout', description: 'Log out of your Anthropic account', argumentHint: '' },\n { name: 'doctor', description: 'Check Claude Code health and configuration', argumentHint: '' },\n { name: 'bug', description: 'Report a bug to Anthropic', argumentHint: '' },\n { name: 'cost', description: 'Show token usage and cost', argumentHint: '' },\n { name: 'status', description: 'Show current session status', argumentHint: '' },\n ];\n\n // Get custom commands from file system (includes gsd:* etc.)\n const customCommands = this.scanCustomCommands();\n\n // Start with all commands\n let allCommands: SlashCommand[] = [...customCommands];\n\n // Add cached commands from init message\n if (this.cachedCommands && this.cachedCommands.length > 0) {\n const existingNames = new Set(allCommands.map(c => c.name));\n const newCached = this.cachedCommands.filter(c => !existingNames.has(c.name));\n allCommands = [...allCommands, ...newCached];\n }\n\n // Add fallback commands\n const existingNames = new Set(allCommands.map(c => c.name));\n const uniqueFallbacks = fallbackCommands.filter(c => !existingNames.has(c.name));\n allCommands = [...allCommands, ...uniqueFallbacks];\n\n allCommands = allCommands.filter(c => !UNSUPPORTED_COMMANDS.has(c.name));\n\n return allCommands;\n }\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport type {\n InteractiveCommandType,\n InteractiveCommandData,\n InteractiveApplyPayload,\n InteractiveResult,\n InteractiveOption,\n} from 'clautunnel-shared';\n\ninterface ClaudeSettings {\n preferences?: {\n verboseMode?: boolean;\n theme?: string;\n autoCompact?: boolean;\n };\n permissions?: {\n mode?: string;\n allowedTools?: string[];\n allow?: string[];\n };\n vim?: boolean;\n alwaysThinkingEnabled?: boolean;\n}\n\nexport interface ConfigManagerOptions {\n cwd?: string;\n homeDir?: string;\n}\n\nexport class ConfigManager {\n private claudeDir: string;\n private cwd: string;\n\n constructor(options: ConfigManagerOptions = {}) {\n const home = options.homeDir || homedir();\n this.claudeDir = join(home, '.claude');\n this.cwd = options.cwd || process.cwd();\n }\n\n private getGlobalSettingsPath(): string {\n return join(this.claudeDir, 'settings.json');\n }\n\n private getLocalSettingsPath(): string {\n return join(this.claudeDir, 'settings.local.json');\n }\n\n private getProjectSettingsPath(): string {\n return join(this.cwd, '.claude', 'settings.json');\n }\n\n private readSettingsFile(path: string): ClaudeSettings | null {\n try {\n if (existsSync(path)) {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content);\n }\n } catch {\n // Silently ignore read errors\n }\n return null;\n }\n\n private writeSettingsFile(path: string, settings: ClaudeSettings): boolean {\n try {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(path, JSON.stringify(settings, null, 2));\n return true;\n } catch {\n return false;\n }\n }\n\n private getMergedSettings(): ClaudeSettings {\n const global = this.readSettingsFile(this.getGlobalSettingsPath()) || {};\n const local = this.readSettingsFile(this.getLocalSettingsPath()) || {};\n const project = this.readSettingsFile(this.getProjectSettingsPath()) || {};\n\n // Merge settings with project > local > global precedence\n return {\n ...global,\n ...local,\n ...project,\n preferences: {\n ...global.preferences,\n ...local.preferences,\n ...project.preferences,\n },\n permissions: {\n ...global.permissions,\n ...local.permissions,\n ...project.permissions,\n },\n };\n }\n\n /**\n * Get the current thinking mode setting from merged settings\n */\n getThinkingMode(): boolean {\n const settings = this.getMergedSettings();\n return settings.alwaysThinkingEnabled ?? false;\n }\n\n getInteractiveData(command: InteractiveCommandType): InteractiveCommandData {\n const settings = this.getMergedSettings();\n\n switch (command) {\n case 'config':\n return this.getConfigData(settings);\n case 'permissions':\n return this.getPermissionsData(settings);\n case 'vim':\n return this.getVimData(settings);\n case 'allowed-tools':\n return this.getAllowedToolsData(settings);\n default:\n return {\n command,\n uiType: 'select',\n title: `${command} Settings`,\n description: 'This command is not yet supported in mobile.',\n options: [],\n };\n }\n }\n\n private getConfigData(settings: ClaudeSettings): InteractiveCommandData {\n const options: InteractiveOption[] = [\n {\n id: 'alwaysThinkingEnabled',\n label: 'Thinking Mode',\n description: 'Enable extended thinking for complex tasks',\n value: settings.alwaysThinkingEnabled || false,\n selected: settings.alwaysThinkingEnabled || false,\n },\n {\n id: 'autoCompact',\n label: 'Auto-Compact',\n description: 'Automatically compact conversation when context is full',\n value: settings.preferences?.autoCompact ?? true,\n selected: settings.preferences?.autoCompact ?? true,\n },\n ];\n\n return {\n command: 'config',\n uiType: 'nested',\n title: 'Configuration',\n description: 'Claude Code preferences and settings',\n options,\n };\n }\n\n private getPermissionsData(settings: ClaudeSettings): InteractiveCommandData {\n const currentMode = settings.permissions?.mode || 'default';\n const options: InteractiveOption[] = [\n {\n id: 'default',\n label: 'Default',\n description: 'Ask before making changes to files',\n value: 'default',\n selected: currentMode === 'default',\n },\n {\n id: 'acceptEdits',\n label: 'Auto-approve Edits',\n description: 'Automatically approve file edits',\n value: 'acceptEdits',\n selected: currentMode === 'acceptEdits',\n },\n {\n id: 'plan',\n label: 'Plan Mode',\n description: 'Only plan changes without executing',\n value: 'plan',\n selected: currentMode === 'plan',\n },\n {\n id: 'bypassPermissions',\n label: 'Yolo Mode',\n description: 'Bypass all permission prompts',\n value: 'bypassPermissions',\n selected: currentMode === 'bypassPermissions',\n },\n ];\n\n return {\n command: 'permissions',\n uiType: 'select',\n title: 'Permission Mode',\n description: 'Select how Claude handles file edits',\n options,\n currentValue: currentMode,\n };\n }\n\n private getVimData(settings: ClaudeSettings): InteractiveCommandData {\n const enabled = settings.vim ?? false;\n\n return {\n command: 'vim',\n uiType: 'toggle',\n title: 'Vim Mode',\n description: 'Enable vim keybindings in the editor',\n options: [\n {\n id: 'vim-enabled',\n label: 'Vim Mode',\n description: enabled ? 'Currently enabled' : 'Currently disabled',\n value: enabled,\n selected: enabled,\n },\n ],\n currentValue: enabled,\n };\n }\n\n private getAllowedToolsData(settings: ClaudeSettings): InteractiveCommandData {\n const allowedTools = settings.permissions?.allowedTools || [];\n const allTools = [\n { id: 'Bash', label: 'Bash', description: 'Execute shell commands' },\n { id: 'Read', label: 'Read', description: 'Read file contents' },\n { id: 'Write', label: 'Write', description: 'Write to files' },\n { id: 'Edit', label: 'Edit', description: 'Edit file contents' },\n { id: 'Glob', label: 'Glob', description: 'Search for files' },\n { id: 'Grep', label: 'Grep', description: 'Search file contents' },\n { id: 'WebFetch', label: 'WebFetch', description: 'Fetch web content' },\n { id: 'WebSearch', label: 'WebSearch', description: 'Search the web' },\n ];\n\n const options: InteractiveOption[] = allTools.map((tool) => ({\n ...tool,\n value: tool.id,\n selected: allowedTools.includes(tool.id),\n }));\n\n return {\n command: 'allowed-tools',\n uiType: 'multi-select',\n title: 'Allowed Tools',\n description: 'Select which tools Claude can use',\n options,\n currentValue: allowedTools,\n };\n }\n\n applyChange(payload: InteractiveApplyPayload): InteractiveResult {\n const globalPath = this.getGlobalSettingsPath();\n const settings = this.readSettingsFile(globalPath) || {};\n\n try {\n switch (payload.command) {\n case 'config':\n return this.applyConfigChange(settings, globalPath, payload);\n case 'permissions':\n return this.applyPermissionsChange(settings, globalPath, payload);\n case 'vim':\n return this.applyVimChange(settings, globalPath, payload);\n case 'allowed-tools':\n return this.applyAllowedToolsChange(settings, globalPath, payload);\n default:\n return {\n success: false,\n message: `Unknown command: ${payload.command}`,\n };\n }\n } catch (error) {\n return {\n success: false,\n message: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n\n private applyConfigChange(\n settings: ClaudeSettings,\n path: string,\n payload: InteractiveApplyPayload\n ): InteractiveResult {\n if (!settings.preferences) {\n settings.preferences = {};\n }\n\n switch (payload.key) {\n case 'theme':\n settings.preferences.theme = payload.value as string;\n break;\n case 'alwaysThinkingEnabled':\n // alwaysThinkingEnabled is at root level, not in preferences\n settings.alwaysThinkingEnabled = payload.value as boolean;\n break;\n case 'autoCompact':\n settings.preferences.autoCompact = payload.value as boolean;\n break;\n case 'verbose':\n settings.preferences.verboseMode = payload.value as boolean;\n break;\n default:\n return { success: false, message: `Unknown config key: ${payload.key}` };\n }\n\n if (this.writeSettingsFile(path, settings)) {\n return { success: true, message: `Config ${payload.key} updated` };\n }\n return { success: false, message: 'Failed to write settings file' };\n }\n\n private applyPermissionsChange(\n settings: ClaudeSettings,\n path: string,\n payload: InteractiveApplyPayload\n ): InteractiveResult {\n if (!settings.permissions) {\n settings.permissions = {};\n }\n\n settings.permissions.mode = payload.value as string;\n\n if (this.writeSettingsFile(path, settings)) {\n return { success: true, message: `Permission mode set to ${payload.value}` };\n }\n return { success: false, message: 'Failed to write settings file' };\n }\n\n private applyVimChange(\n settings: ClaudeSettings,\n path: string,\n payload: InteractiveApplyPayload\n ): InteractiveResult {\n if (payload.action === 'toggle') {\n settings.vim = !settings.vim;\n } else {\n settings.vim = payload.value as boolean;\n }\n\n if (this.writeSettingsFile(path, settings)) {\n return { success: true, message: `Vim mode ${settings.vim ? 'enabled' : 'disabled'}` };\n }\n return { success: false, message: 'Failed to write settings file' };\n }\n\n private applyAllowedToolsChange(\n settings: ClaudeSettings,\n path: string,\n payload: InteractiveApplyPayload\n ): InteractiveResult {\n if (!settings.permissions) {\n settings.permissions = {};\n }\n if (!settings.permissions.allowedTools) {\n settings.permissions.allowedTools = [];\n }\n\n const toolId = payload.value as string;\n\n switch (payload.action) {\n case 'add':\n if (!settings.permissions.allowedTools.includes(toolId)) {\n settings.permissions.allowedTools.push(toolId);\n }\n break;\n case 'remove':\n settings.permissions.allowedTools = settings.permissions.allowedTools.filter(\n (t) => t !== toolId\n );\n break;\n case 'set':\n settings.permissions.allowedTools = payload.value as string[];\n break;\n case 'toggle':\n if (settings.permissions.allowedTools.includes(toolId)) {\n settings.permissions.allowedTools = settings.permissions.allowedTools.filter(\n (t) => t !== toolId\n );\n } else {\n settings.permissions.allowedTools.push(toolId);\n }\n break;\n }\n\n if (this.writeSettingsFile(path, settings)) {\n return { success: true, message: 'Allowed tools updated' };\n }\n return { success: false, message: 'Failed to write settings file' };\n }\n}\n","import { Command } from 'commander';\nimport WebSocket from 'ws';\nimport { Daemon } from '../daemon/daemon.js';\nimport { MachineManager } from '../daemon/machine.js';\nimport { MachineRealtimeClient } from '../realtime/machine-client.js';\nimport { Config, ConfigurationError } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { Spinner } from '../utils/spinner.js';\nimport { createSupabaseClient, restoreSession } from '../utils/supabase.js';\nimport {\n promptYesNo,\n enableSleepPrevention,\n startCaffeinate,\n cleanup as cleanupSleep,\n isMacOS,\n checkFullDiskAccess,\n getFullDiskAccessStatus,\n getTerminalAppName,\n openFullDiskAccessSettings,\n type SleepPreventionState,\n type FullDiskAccessStatus,\n} from '../utils/sleep-prevention.js';\nimport { MobileServerManager } from '../mobile/mobile-server.js';\nimport type { MachineCommand } from 'clautunnel-shared';\n\n// Polyfill WebSocket for Node.js (Supabase Realtime needs this)\nif (typeof globalThis.WebSocket === 'undefined') {\n // @ts-expect-error WebSocket polyfill for Node.js\n globalThis.WebSocket = WebSocket;\n}\n\nexport interface StartOptions {\n name?: string;\n preventSleep?: boolean;\n mobile?: boolean;\n}\n\nexport function createStartCommand(): Command {\n const command = new Command('start');\n\n command\n .description('Start ClauTunnel and listen for session requests from mobile app')\n .option('-n, --name <name>', 'Machine name')\n .option('--prevent-sleep', 'Auto-enable sleep prevention (skip prompt)')\n .option('--no-mobile', 'Skip mobile server startup')\n .action(async (options: StartOptions) => {\n const config = new Config();\n const logger = new Logger();\n const spinner = new Spinner('Starting ClauTunnel...');\n\n const daemons: Map<string, Daemon> = new Map(); // sessionId -> Daemon\n let machineClient: MachineRealtimeClient | null = null;\n\n try {\n config.requireConfiguration();\n\n spinner.start();\n\n const supabase = createSupabaseClient(\n config.getSupabaseUrl(),\n config.getSupabaseAnonKey(),\n { realtime: true }\n );\n\n // Restore session from stored tokens\n spinner.update('Authenticating...');\n\n const session = await restoreSession(supabase, config);\n if (!session) {\n spinner.fail('Not authenticated');\n logger.error(\n 'Run \"clautunnel login\" or \"clautunnel signup\" first.'\n );\n process.exit(1);\n }\n\n const { user } = session;\n spinner.update(`Authenticated as ${user.email}...`);\n\n // Check Full Disk Access (macOS only)\n let fdaStatus: FullDiskAccessStatus | null = null;\n\n if (isMacOS()) {\n spinner.stop();\n\n const terminalApp = getTerminalAppName();\n let fdaEnabled = checkFullDiskAccess();\n fdaStatus = getFullDiskAccessStatus(fdaEnabled, terminalApp);\n\n if (fdaStatus.enabled) {\n logger.info(`✓ Full Disk Access: ${fdaStatus.label}`);\n } else {\n logger.warn(`⚠ Full Disk Access: ${fdaStatus.label}`);\n logger.warn('');\n for (const line of fdaStatus.warning!.split('\\n')) {\n logger.warn(` ${line}`);\n }\n logger.warn('');\n\n const openSettings = await promptYesNo(\n 'Open Full Disk Access settings? [Y/n]: '\n );\n\n if (openSettings) {\n openFullDiskAccessSettings();\n logger.info('');\n await promptYesNo(\n 'Press Enter after enabling Full Disk Access (or Enter to skip): '\n );\n\n // Recheck FDA status\n fdaEnabled = checkFullDiskAccess();\n fdaStatus = getFullDiskAccessStatus(fdaEnabled, terminalApp);\n\n if (fdaStatus.enabled) {\n logger.info('✓ Full Disk Access: Enabled');\n } else {\n logger.warn('Full Disk Access still not enabled. Continuing without it.');\n }\n }\n\n logger.info('');\n }\n\n spinner.start();\n }\n\n // Handle sleep prevention (macOS only)\n const sleepState: SleepPreventionState = {\n caffeinateProcess: null,\n pmsetEnabled: false,\n };\n\n if (isMacOS()) {\n spinner.stop();\n\n // Auto-enable if --prevent-sleep flag is used, otherwise ask\n const enableSleep =\n options.preventSleep ||\n (await promptYesNo(\n 'Prevent sleep when lid is closed? (keeps clautunnel running) [y/N]: '\n ));\n\n if (enableSleep) {\n logger.info('');\n logger.info('Enabling sleep prevention...');\n if (!options.preventSleep) {\n logger.info('This requires sudo password (auto-restored on exit)');\n logger.info('');\n }\n\n sleepState.pmsetEnabled = enableSleepPrevention();\n if (sleepState.pmsetEnabled) {\n logger.info('✓ Lid-closed mode enabled');\n } else {\n logger.warn('Failed to enable lid-closed mode. Using basic mode.');\n }\n\n // Start caffeinate to prevent idle sleep\n sleepState.caffeinateProcess = startCaffeinate();\n\n sleepState.caffeinateProcess.on('error', () => {\n logger.warn('Failed to start caffeinate');\n });\n\n logger.info('');\n }\n\n spinner.start();\n }\n\n // Mobile server\n let mobileServer: MobileServerManager | null = null;\n\n if (options.mobile !== false) {\n const mobileProjectPath = config.getMobileProjectPath();\n mobileServer = new MobileServerManager({\n mobileProjectPath,\n supabaseUrl: config.getSupabaseUrl(),\n supabaseAnonKey: config.getSupabaseAnonKey(),\n onProgress: (msg) => spinner.update(msg),\n });\n\n const result = await mobileServer.start();\n spinner.stop();\n\n if (result.started) {\n logger.info('');\n logger.info(` Tunnel: ${result.tunnelUrl}`);\n logger.info('');\n } else {\n logger.error(`Mobile server failed: ${result.error}`);\n process.exit(1);\n }\n\n spinner.start();\n }\n\n // Cleanup helper\n const cleanup = async () => {\n if (mobileServer) {\n try {\n await mobileServer.stop();\n } catch {\n // Best-effort cleanup\n }\n }\n if (sleepState.pmsetEnabled) {\n console.log('Restoring sleep settings...');\n }\n cleanupSleep(sleepState);\n };\n\n // Handle process signals\n let isShuttingDown = false;\n\n const gracefulShutdown = async (signal: string) => {\n if (isShuttingDown) {\n console.log('\\nForce exiting...');\n process.exit(1);\n }\n isShuttingDown = true;\n console.log(`\\n[${signal}] Shutting down gracefully...`);\n try {\n for (const [sessionId, d] of daemons) {\n try {\n await d.stop();\n } catch {\n // Continue stopping other daemons\n }\n daemons.delete(sessionId);\n }\n if (machineClient) {\n await machineClient.disconnect();\n machineClient = null;\n }\n console.log('[Cleanup] All sessions ended in database');\n await cleanup();\n } catch (error) {\n console.error('[Cleanup] Error during shutdown:', error);\n }\n process.exit(0);\n };\n\n process.on('SIGINT', () => {\n gracefulShutdown('SIGINT').catch(console.error);\n });\n\n process.on('SIGTERM', () => {\n gracefulShutdown('SIGTERM').catch(console.error);\n });\n\n spinner.update('Registering machine...');\n\n // Register machine\n const machineManager = new MachineManager({ supabase });\n const machine = await machineManager.registerMachine(\n user.id,\n options.name,\n config.getMachineId()\n );\n\n // Save machine ID for future use\n config.setMachineId(machine.id);\n\n spinner.update('Connecting to realtime...');\n\n // Create machine-level realtime client\n machineClient = new MachineRealtimeClient({\n supabase,\n machineId: machine.id,\n });\n\n const connected = await machineClient.connect();\n\n spinner.stop();\n\n if (!connected) {\n logger.error('Failed to connect to Supabase Realtime.');\n logger.error('');\n logger.error('This may be a temporary issue. Try the following:');\n logger.error(' 1. Open a new terminal and run \"clautunnel start\" again');\n logger.error(' 2. Check your network connection');\n logger.error(' 3. Try \"clautunnel login\" to refresh your session');\n process.exit(1);\n }\n\n logger.info('');\n logger.info('✓ ClauTunnel is ready!');\n logger.info(` Machine: ${machine.name}`);\n if (fdaStatus) {\n if (fdaStatus.enabled) {\n logger.info(` Full Disk Access: ${fdaStatus.label}`);\n } else {\n logger.warn(` Full Disk Access: ${fdaStatus.label}`);\n }\n }\n if (sleepState.caffeinateProcess) {\n logger.info(\n ` Sleep prevention: ${sleepState.pmsetEnabled ? 'Lid-closed mode' : 'Basic mode'}`\n );\n }\n if (mobileServer) {\n logger.info(' Mobile server: Running');\n }\n logger.info('');\n logger.info('Open the mobile app to start a session.');\n logger.info('Press Ctrl+C to stop.');\n logger.info('');\n\n // Handle incoming commands from mobile\n machineClient.on('command', async (cmd: MachineCommand) => {\n if (cmd.type === 'start-session') {\n logger.info('Starting session (requested from mobile)...');\n\n try {\n const newDaemon = new Daemon({\n supabase,\n userId: user.id,\n machineId: machine.id,\n machineName: options.name,\n cwd: process.cwd(),\n hybrid: false,\n });\n\n newDaemon.on('started', async ({ session }) => {\n daemons.set(session.id, newDaemon);\n\n logger.info(` Session: ${session.id.slice(0, 8)}...`);\n logger.info(' Mobile sync: Enabled');\n logger.info(` Active sessions: ${daemons.size}`);\n logger.info('');\n\n await machineClient?.broadcastSessionStarted(\n session.id,\n process.cwd()\n );\n });\n\n newDaemon.on('error', (error: Error) => {\n logger.error(`Session error: ${error.message}`);\n });\n\n newDaemon.on('mobile-input', (prompt: string, attachments?: unknown[]) => {\n const hasImages = attachments && attachments.length > 0;\n const imageInfo = hasImages ? ` [+${attachments.length} image${attachments.length > 1 ? 's' : ''}]` : '';\n logger.info(`[Mobile] ${prompt}${imageInfo}`);\n });\n\n newDaemon.on('mobile-output', (data: string) => {\n const trimmed = data.trim();\n if (trimmed) {\n logger.info(`[Claude] ${trimmed}`);\n }\n });\n\n newDaemon.on('mobile-disconnected', async () => {\n logger.info('Mobile disconnected. Ending session...');\n try {\n await newDaemon.stop();\n } catch {\n // Silently handle stop errors - stopped handler handles the rest\n }\n });\n\n newDaemon.on('stopped', async () => {\n const sessionId = newDaemon.getSession()?.id;\n if (sessionId) {\n daemons.delete(sessionId);\n await machineClient?.broadcastSessionEnded(sessionId);\n }\n\n logger.info('Session ended.');\n logger.info(` Active sessions: ${daemons.size}`);\n logger.info('');\n if (daemons.size === 0) {\n logger.info('Waiting for next session request...');\n logger.info('');\n }\n });\n\n await newDaemon.start();\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n logger.error(`Failed to start session: ${errorMessage}`);\n await machineClient?.broadcastError(errorMessage);\n }\n }\n\n if (cmd.type === 'stop-session' && cmd.sessionId) {\n const targetDaemon = daemons.get(cmd.sessionId);\n if (targetDaemon) {\n logger.info(`Stopping session ${cmd.sessionId.slice(0, 8)}... (requested from mobile)`);\n try {\n await targetDaemon.stop();\n } catch {\n // Silently handle stop errors\n }\n }\n }\n });\n } catch (error) {\n if (error instanceof ConfigurationError) {\n spinner.stop();\n logger.error(error.message);\n process.exit(1);\n }\n spinner.fail('Failed to start');\n logger.error(\n `${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { EventEmitter } from 'events';\nimport type { SupabaseClient, RealtimeChannel } from '@supabase/supabase-js';\nimport type { MachineCommand, PresencePayload } from 'clautunnel-shared';\nimport { REALTIME_CHANNELS } from 'clautunnel-shared';\nimport { subscribeWithTimeout } from './utils.js';\n\nexport interface MachineRealtimeClientOptions {\n supabase: SupabaseClient;\n machineId: string;\n}\n\nexport class MachineRealtimeClient extends EventEmitter {\n private supabase: SupabaseClient;\n private machineId: string;\n private inputChannel: RealtimeChannel | null = null;\n private outputChannel: RealtimeChannel | null = null;\n private presenceChannel: RealtimeChannel | null = null;\n\n constructor(options: MachineRealtimeClientOptions) {\n super();\n this.supabase = options.supabase;\n this.machineId = options.machineId;\n }\n\n async connect(): Promise<boolean> {\n // Subscribe to input channel (receives commands from mobile)\n const inputChannelName = REALTIME_CHANNELS.machineInput(this.machineId);\n this.inputChannel = this.supabase.channel(inputChannelName);\n\n this.inputChannel.on('broadcast', { event: 'machine-command' }, (payload) => {\n this.emit('command', payload.payload as MachineCommand);\n });\n\n // Subscribe to output channel (sends responses to mobile)\n const outputChannelName = REALTIME_CHANNELS.machineOutput(this.machineId);\n this.outputChannel = this.supabase.channel(outputChannelName);\n\n const results = await Promise.all([\n subscribeWithTimeout(this.inputChannel, 'machine-input'),\n subscribeWithTimeout(this.outputChannel, 'machine-output'),\n ]);\n\n const connected = results.every((success) => success);\n\n // Set up presence channel to track listener online status\n if (connected) {\n const presenceChannelName = REALTIME_CHANNELS.machinePresence(this.machineId);\n this.presenceChannel = this.supabase.channel(presenceChannelName);\n\n this.presenceChannel.subscribe(async (status) => {\n if (status === 'SUBSCRIBED' && this.presenceChannel) {\n try {\n const payload: PresencePayload = {\n type: 'cli',\n online_at: new Date().toISOString(),\n };\n await this.presenceChannel.track(payload);\n } catch (trackError) {\n console.warn('[WARN] Failed to track machine presence:', trackError);\n }\n }\n });\n }\n\n return connected;\n }\n\n async broadcastSessionStarted(sessionId: string, workingDirectory: string): Promise<void> {\n if (!this.outputChannel) return;\n\n const command: MachineCommand = {\n type: 'session-started',\n sessionId,\n workingDirectory,\n timestamp: Date.now(),\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'machine-command',\n payload: command,\n });\n }\n\n async broadcastSessionEnded(sessionId: string): Promise<void> {\n if (!this.outputChannel) return;\n\n const command: MachineCommand = {\n type: 'session-ended',\n sessionId,\n timestamp: Date.now(),\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'machine-command',\n payload: command,\n });\n }\n\n async broadcastError(error: string): Promise<void> {\n if (!this.outputChannel) return;\n\n const command: MachineCommand = {\n type: 'start-session-error',\n error,\n timestamp: Date.now(),\n };\n\n await this.outputChannel.send({\n type: 'broadcast',\n event: 'machine-command',\n payload: command,\n });\n }\n\n async disconnect(): Promise<void> {\n if (this.presenceChannel) {\n await this.presenceChannel.untrack();\n await this.supabase.removeChannel(this.presenceChannel);\n this.presenceChannel = null;\n }\n\n if (this.inputChannel) {\n await this.supabase.removeChannel(this.inputChannel);\n this.inputChannel = null;\n }\n\n if (this.outputChannel) {\n await this.supabase.removeChannel(this.outputChannel);\n this.outputChannel = null;\n }\n\n this.emit('disconnected');\n }\n}\n","export class Spinner {\n private frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n private currentFrame = 0;\n private interval: NodeJS.Timeout | null = null;\n private message: string;\n private stream: NodeJS.WriteStream;\n\n constructor(message: string, stream: NodeJS.WriteStream = process.stdout) {\n this.message = message;\n this.stream = stream;\n }\n\n start(): void {\n if (this.interval) {\n return;\n }\n\n // Hide cursor\n this.stream.write('\\x1B[?25l');\n\n this.interval = setInterval(() => {\n const frame = this.frames[this.currentFrame];\n this.stream.write(`\\r${frame} ${this.message}`);\n this.currentFrame = (this.currentFrame + 1) % this.frames.length;\n }, 80);\n }\n\n update(message: string): void {\n this.message = message;\n }\n\n stop(): void {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n\n // Clear the line and show cursor\n this.stream.write('\\r\\x1B[K');\n this.stream.write('\\x1B[?25h');\n }\n\n succeed(message: string): void {\n this.stop();\n this.stream.write(`\\r✓ ${message}\\n`);\n }\n\n fail(message: string): void {\n this.stop();\n this.stream.write(`\\r✗ ${message}\\n`);\n }\n}\n","import { createClient, type SupabaseClient } from '@supabase/supabase-js';\n\nexport interface CreateSupabaseClientOptions {\n realtime?: boolean;\n}\n\nexport function createSupabaseClient(\n url: string,\n anonKey: string,\n options?: CreateSupabaseClientOptions\n): SupabaseClient {\n const clientOptions = options?.realtime\n ? {\n realtime: {\n params: { eventsPerSecond: 10 },\n timeout: 30000,\n },\n }\n : undefined;\n\n return createClient(url, anonKey, clientOptions);\n}\n\nexport interface SessionTokenStore {\n getSessionTokens(): { accessToken: string; refreshToken: string } | null;\n clearSessionTokens(): void;\n}\n\nexport async function restoreSession(\n supabase: SupabaseClient,\n config: SessionTokenStore\n): Promise<{ user: any } | null> {\n const sessionTokens = config.getSessionTokens();\n if (!sessionTokens) {\n return null;\n }\n\n const { error: sessionError } = await supabase.auth.setSession({\n access_token: sessionTokens.accessToken,\n refresh_token: sessionTokens.refreshToken,\n });\n\n if (sessionError) {\n config.clearSessionTokens();\n return null;\n }\n\n const {\n data: { user },\n error: authError,\n } = await supabase.auth.getUser();\n\n if (authError || !user) {\n return null;\n }\n\n return { user };\n}\n","import { spawn, execSync, type ChildProcess } from 'child_process';\nimport * as readline from 'readline';\nimport { readdirSync } from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nexport interface SleepPreventionState {\n caffeinateProcess: ChildProcess | null;\n pmsetEnabled: boolean;\n}\n\nexport async function promptYesNo(question: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');\n });\n });\n}\n\nexport function enableSleepPrevention(): boolean {\n try {\n execSync('sudo pmset -a disablesleep 1', { stdio: 'inherit' });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function disableSleepPrevention(): void {\n try {\n execSync('sudo pmset -a disablesleep 0', { stdio: 'inherit' });\n } catch {\n // Ignore errors on cleanup\n }\n}\n\nexport function startCaffeinate(): ChildProcess {\n const process = spawn('caffeinate', ['-i', '-s'], {\n stdio: 'ignore',\n detached: false,\n });\n\n return process;\n}\n\nexport function stopCaffeinate(process: ChildProcess | null): void {\n if (process) {\n process.kill();\n }\n}\n\nexport function cleanup(state: SleepPreventionState): void {\n stopCaffeinate(state.caffeinateProcess);\n if (state.pmsetEnabled) {\n disableSleepPrevention();\n }\n}\n\nexport function isMacOS(): boolean {\n return process.platform === 'darwin';\n}\n\nexport interface FullDiskAccessStatus {\n enabled: boolean;\n label: string;\n warning?: string;\n}\n\n/**\n * Checks if Full Disk Access is granted on macOS by attempting to read\n * a TCC-protected directory. Returns true on non-macOS platforms.\n */\nexport function checkFullDiskAccess(): boolean {\n if (!isMacOS()) return true;\n\n try {\n const safariDir = path.join(os.homedir(), 'Library', 'Safari');\n readdirSync(safariDir);\n return true;\n } catch {\n return false;\n }\n}\n\nconst TERM_PROGRAM_MAP: Record<string, string> = {\n vscode: 'Visual Studio Code',\n Apple_Terminal: 'Terminal',\n 'iTerm.app': 'iTerm2',\n WarpTerminal: 'Warp',\n Hyper: 'Hyper',\n};\n\n/**\n * Detects the terminal application name from the TERM_PROGRAM environment variable.\n */\nexport function getTerminalAppName(): string {\n const termProgram = process.env.TERM_PROGRAM;\n if (termProgram && TERM_PROGRAM_MAP[termProgram]) {\n return TERM_PROGRAM_MAP[termProgram];\n }\n return 'your terminal app';\n}\n\n/**\n * Opens macOS System Settings to the Full Disk Access pane.\n * Returns true on success, false on failure or non-macOS platforms.\n */\nexport function openFullDiskAccessSettings(): boolean {\n if (!isMacOS()) return false;\n\n try {\n execSync(\n 'open \"x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles\"'\n );\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Returns a structured status object with label and optional warning message\n * describing the Full Disk Access state and its implications for remote usage.\n */\nexport function getFullDiskAccessStatus(enabled: boolean, terminalApp?: string): FullDiskAccessStatus {\n if (enabled) {\n return {\n enabled: true,\n label: 'Enabled',\n };\n }\n\n const appName = terminalApp || 'your terminal app';\n\n return {\n enabled: false,\n label: 'Not enabled',\n warning: [\n 'Without Full Disk Access, macOS may show permission dialogs',\n 'when Claude tries to access certain files or directories.',\n 'These dialogs are only visible on this machine\\'s screen —',\n 'you won\\'t be able to see or approve them from the mobile app,',\n 'which will cause Claude\\'s operations to silently hang.',\n '',\n 'To enable:',\n ` 1. Open System Settings → Privacy & Security → Full Disk Access`,\n ` 2. Toggle ON \"${appName}\" in the list`,\n ' 3. Restart your terminal and run \"clautunnel start\" again',\n ].join('\\n'),\n };\n}\n","import { spawn, execSync, type ChildProcess } from 'child_process';\nimport {\n existsSync,\n mkdirSync,\n writeFileSync,\n createWriteStream,\n type WriteStream,\n} from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { get } from 'http';\nimport qrcode from 'qrcode-terminal';\n\nconst REPO_URL = 'https://github.com/TongilKim/ClauTunnel.git';\nconst DEFAULT_MOBILE_DIR = join(homedir(), '.clautunnel', 'mobile');\n\nexport interface MobileServerOptions {\n mobileProjectPath?: string;\n supabaseUrl: string;\n supabaseAnonKey: string;\n expoPort?: number;\n logDir?: string;\n onProgress?: (message: string) => void;\n}\n\nexport interface MobileServerResult {\n started: boolean;\n tunnelUrl?: string;\n error?: string;\n}\n\ninterface PrerequisiteResult {\n ready: boolean;\n issues: string[];\n needsInstall: boolean;\n}\n\nexport class MobileServerManager {\n private options: MobileServerOptions;\n private mobileProjectPath: string;\n private logDir: string;\n private expoPort: number;\n private ngrokProcess: ChildProcess | null = null;\n private expoProcess: ChildProcess | null = null;\n private ngrokLogStream: WriteStream | null = null;\n private expoLogStream: WriteStream | null = null;\n private tunnelUrl: string | null = null;\n private onProgress: (message: string) => void;\n private hasCustomPath: boolean;\n\n constructor(options: MobileServerOptions) {\n this.options = options;\n this.hasCustomPath = options.mobileProjectPath !== undefined;\n this.mobileProjectPath = options.mobileProjectPath ?? DEFAULT_MOBILE_DIR;\n this.expoPort = options.expoPort ?? 8081;\n this.logDir = options.logDir ?? join(homedir(), '.clautunnel', 'logs');\n this.onProgress = options.onProgress ?? (() => {});\n }\n\n getMobileProjectPath(): string {\n return this.mobileProjectPath;\n }\n\n checkPrerequisites(): PrerequisiteResult {\n const issues: string[] = [];\n let needsInstall = false;\n\n // Path check is skipped here — ensureMobileProject handles it\n\n // Check ngrok\n try {\n execSync('which ngrok', { stdio: 'pipe' });\n } catch {\n issues.push(\n 'ngrok is not installed.\\n' +\n ' Install: brew install ngrok\\n' +\n ' Sign up: https://ngrok.com\\n' +\n ' Auth: ngrok config add-authtoken <your-token>'\n );\n }\n\n // Check node_modules\n const nodeModulesPath = join(this.mobileProjectPath, 'node_modules');\n if (!existsSync(nodeModulesPath)) {\n needsInstall = true;\n }\n\n return { ready: issues.length === 0, issues, needsInstall };\n }\n\n ensureMobileProject(): { ready: boolean; cloned: boolean; error?: string } {\n // Check if apps/mobile subdir exists (handles both custom path and cloned repo)\n const packageJson = join(this.mobileProjectPath, 'package.json');\n if (existsSync(packageJson)) {\n return { ready: true, cloned: false };\n }\n\n // If custom path was provided and doesn't exist, don't auto-clone\n if (this.hasCustomPath) {\n return {\n ready: false,\n cloned: false,\n error: `Mobile project path not found: ${this.mobileProjectPath}`,\n };\n }\n\n // Auto-clone to default location\n try {\n // Check git is installed\n execSync('which git', { stdio: 'pipe' });\n } catch {\n return {\n ready: false,\n cloned: false,\n error: 'git is required to download the mobile app.\\n' +\n ' Install: https://git-scm.com/downloads\\n' +\n ' macOS: xcode-select --install',\n };\n }\n\n try {\n // Clone only the apps/mobile directory using sparse checkout\n const clautunnelDir = join(homedir(), '.clautunnel');\n if (!existsSync(clautunnelDir)) {\n mkdirSync(clautunnelDir, { recursive: true });\n }\n\n // Clone with depth 1 and sparse checkout for apps/mobile only\n const repoDir = join(clautunnelDir, 'repo');\n if (existsSync(repoDir)) {\n // Pull latest\n execSync('git pull --ff-only', {\n cwd: repoDir,\n stdio: 'pipe',\n timeout: 60000,\n });\n } else {\n execSync(\n `git clone --depth 1 --filter=blob:none --sparse \"${REPO_URL}\" repo`,\n {\n cwd: clautunnelDir,\n stdio: 'pipe',\n timeout: 60000,\n }\n );\n execSync('git sparse-checkout set apps/mobile packages/shared', {\n cwd: repoDir,\n stdio: 'pipe',\n timeout: 30000,\n });\n }\n\n // Point mobileProjectPath to the cloned apps/mobile\n this.mobileProjectPath = join(repoDir, 'apps', 'mobile');\n\n if (!existsSync(join(this.mobileProjectPath, 'package.json'))) {\n return { ready: false, cloned: false, error: 'Clone succeeded but apps/mobile not found' };\n }\n\n return { ready: true, cloned: true };\n } catch (error) {\n return {\n ready: false,\n cloned: false,\n error: `Failed to clone mobile project: ${error instanceof Error ? error.message : 'Unknown error'}`,\n };\n }\n }\n\n ensureEnvFile(): void {\n const envPath = join(this.mobileProjectPath, '.env');\n const envContent = [\n `EXPO_PUBLIC_SUPABASE_URL=${this.options.supabaseUrl}`,\n `EXPO_PUBLIC_SUPABASE_ANON_KEY=${this.options.supabaseAnonKey}`,\n '',\n ].join('\\n');\n writeFileSync(envPath, envContent);\n }\n\n installDependencies(): boolean {\n const nodeModulesPath = join(this.mobileProjectPath, 'node_modules');\n const repoRoot = join(this.mobileProjectPath, '..', '..');\n const sharedDistPath = join(repoRoot, 'packages', 'shared', 'dist', 'index.js');\n\n if (existsSync(nodeModulesPath) && existsSync(sharedDistPath)) return true;\n\n // Run pnpm install from repo root so workspace links resolve correctly\n try {\n execSync('pnpm install', {\n cwd: repoRoot,\n stdio: 'pipe',\n timeout: 120000, // 2 minute timeout\n });\n\n // Build shared package so dist/index.js exists for Metro\n const sharedDir = join(repoRoot, 'packages', 'shared');\n if (existsSync(join(sharedDir, 'tsconfig.json'))) {\n execSync('pnpm build', {\n cwd: sharedDir,\n stdio: 'pipe',\n timeout: 30000,\n });\n }\n\n return true;\n } catch {\n return false;\n }\n }\n\n async startNgrok(): Promise<string | null> {\n this.ensureLogDir();\n\n this.ngrokLogStream = createWriteStream(join(this.logDir, 'ngrok.log'));\n\n this.ngrokProcess = spawn('ngrok', ['http', String(this.expoPort)], {\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: false,\n });\n\n // Redirect output to log file\n this.ngrokProcess.stdout?.pipe(this.ngrokLogStream);\n this.ngrokProcess.stderr?.pipe(this.ngrokLogStream);\n\n this.ngrokProcess.on('error', () => {\n // Silently handle spawn errors\n });\n\n // Poll for tunnel URL\n for (let i = 0; i < 10; i++) {\n await this.sleep(1000);\n const url = await this.getNgrokTunnelUrl();\n if (url) {\n this.tunnelUrl = url;\n return url;\n }\n }\n\n // Failed to get tunnel URL\n this.killProcess(this.ngrokProcess);\n this.ngrokProcess = null;\n return null;\n }\n\n async startExpo(tunnelUrl: string): Promise<boolean> {\n this.ensureLogDir();\n\n this.expoLogStream = createWriteStream(join(this.logDir, 'expo.log'));\n\n this.expoProcess = spawn('npx', ['expo', 'start', '--port', String(this.expoPort)], {\n cwd: this.mobileProjectPath,\n env: {\n ...process.env,\n EXPO_PACKAGER_PROXY_URL: tunnelUrl,\n },\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: false,\n });\n\n this.expoProcess.on('error', () => {\n // Silently handle spawn errors\n });\n\n // Wait for Expo to be ready, print QR code if available\n return new Promise<boolean>((resolve) => {\n let ready = false;\n let resolved = false;\n let qrActive = false;\n\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n this.expoProcess?.stdout?.pipe(this.expoLogStream!);\n this.expoProcess?.stderr?.pipe(this.expoLogStream!);\n resolve(false);\n }\n }, 60000); // 60 second timeout\n\n this.expoProcess?.stdout?.on('data', (data: Buffer) => {\n const text = data.toString();\n const lines = text.split('\\n');\n\n for (const line of lines) {\n if (ready) {\n this.expoLogStream?.write(line + '\\n');\n continue;\n }\n\n // Print QR code lines to terminal\n if (this.isQrCodeLine(line)) {\n qrActive = true;\n process.stdout.write(line + '\\n');\n } else if (qrActive && !this.isExpoReadyLine(line) && line.trim()) {\n // Lines between QR code blocks (spacing, URL info)\n process.stdout.write(line + '\\n');\n } else if (this.isExpoReadyLine(line)) {\n // Expo is ready — this is our success signal\n process.stdout.write(line + '\\n');\n ready = true;\n\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n // Redirect remaining output to log\n this.expoProcess?.stdout?.pipe(this.expoLogStream!);\n this.expoProcess?.stderr?.pipe(this.expoLogStream!);\n resolve(true);\n }\n } else {\n // Pre-ready output goes to log\n this.expoLogStream?.write(line + '\\n');\n }\n }\n });\n\n this.expoProcess?.stderr?.pipe(this.expoLogStream!);\n\n this.expoProcess?.on('exit', () => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve(false);\n }\n });\n });\n }\n\n async start(): Promise<MobileServerResult> {\n // Step 1: Ensure mobile project exists (auto-clone if needed)\n this.onProgress('Checking mobile project...');\n const projectResult = this.ensureMobileProject();\n if (!projectResult.ready) {\n return { started: false, error: projectResult.error };\n }\n if (projectResult.cloned) {\n this.onProgress('Mobile project cloned to ~/.clautunnel/repo/apps/mobile');\n }\n\n // Step 2: Check prerequisites (ngrok, etc.)\n this.onProgress('Checking prerequisites...');\n const prereqs = this.checkPrerequisites();\n if (!prereqs.ready) {\n return { started: false, error: prereqs.issues.join('; ') };\n }\n\n // Step 3: Install dependencies if needed\n if (prereqs.needsInstall) {\n this.onProgress('Installing dependencies (this may take a minute)...');\n const installed = this.installDependencies();\n if (!installed) {\n return { started: false, error: 'Failed to install mobile dependencies' };\n }\n }\n\n // Step 4: Sync .env file\n this.onProgress('Syncing credentials...');\n this.ensureEnvFile();\n\n // Step 5: Start ngrok tunnel\n this.onProgress('Starting ngrok tunnel...');\n const tunnelUrl = await this.startNgrok();\n if (!tunnelUrl) {\n return { started: false, error: 'Failed to start ngrok tunnel' };\n }\n\n // Step 6: Start Expo server\n this.onProgress('Starting Expo server...');\n const expoStarted = await this.startExpo(tunnelUrl);\n if (!expoStarted) {\n // Expo failed, kill ngrok too\n await this.stop();\n return { started: false, error: 'Failed to start Expo server' };\n }\n\n // Step 7: Show QR code for Expo Go\n // Convert https://xxx.ngrok-free.app → exp://xxx.ngrok-free.app:443\n const host = tunnelUrl.replace(/^https?:\\/\\//, '');\n const expoUrl = `exp://${host}:443`;\n console.log('');\n console.log(' Scan with Expo Go:');\n qrcode.generate(expoUrl, { small: true }, (code: string) => {\n // Indent each line for alignment\n for (const line of code.split('\\n')) {\n console.log(` ${line}`);\n }\n });\n console.log(` ${expoUrl}`);\n console.log('');\n\n return { started: true, tunnelUrl };\n }\n\n async stop(): Promise<void> {\n if (this.expoProcess) {\n this.killProcess(this.expoProcess);\n this.expoProcess = null;\n }\n\n if (this.ngrokProcess) {\n this.killProcess(this.ngrokProcess);\n this.ngrokProcess = null;\n }\n\n if (this.expoLogStream) {\n this.expoLogStream.end();\n this.expoLogStream = null;\n }\n\n if (this.ngrokLogStream) {\n this.ngrokLogStream.end();\n this.ngrokLogStream = null;\n }\n\n this.tunnelUrl = null;\n }\n\n getTunnelUrl(): string | null {\n return this.tunnelUrl;\n }\n\n private isQrCodeLine(line: string): boolean {\n return line.includes('\\u2588') || line.includes('\\u2584') || line.includes('\\u2580');\n }\n\n private isExpoReadyLine(line: string): boolean {\n return line.includes('Metro waiting on') || line.includes('Logs for your project');\n }\n\n private getNgrokTunnelUrl(): Promise<string | null> {\n return new Promise((resolve) => {\n const req = get('http://localhost:4040/api/tunnels', (res) => {\n let data = '';\n res.on('data', (chunk) => (data += chunk));\n res.on('end', () => {\n try {\n const tunnels = JSON.parse(data).tunnels;\n const httpsTunnel = tunnels?.find(\n (t: { proto: string }) => t.proto === 'https'\n );\n resolve(httpsTunnel?.public_url ?? null);\n } catch {\n resolve(null);\n }\n });\n });\n\n req.on('error', () => resolve(null));\n req.setTimeout(2000, () => {\n req.destroy();\n resolve(null);\n });\n });\n }\n\n private killProcess(proc: ChildProcess): void {\n try {\n proc.kill('SIGTERM');\n // Give it 3 seconds before SIGKILL\n setTimeout(() => {\n try {\n proc.kill('SIGKILL');\n } catch {\n // Already dead\n }\n }, 3000);\n } catch {\n // Process already exited\n }\n }\n\n private ensureLogDir(): void {\n if (!existsSync(this.logDir)) {\n mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { Logger } from '../utils/logger.js';\n\nconst PID_FILE = path.join(os.homedir(), '.clautunnel', 'daemon.pid');\n\nexport function createStopCommand(): Command {\n const command = new Command('stop');\n\n command.description('Stop the running daemon').action(async () => {\n const logger = new Logger();\n\n try {\n if (!fs.existsSync(PID_FILE)) {\n logger.info('No daemon is running');\n return;\n }\n\n const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim(), 10);\n\n if (isNaN(pid)) {\n logger.error('Invalid PID file');\n fs.unlinkSync(PID_FILE);\n return;\n }\n\n try {\n // Check if process exists\n process.kill(pid, 0);\n\n // Send SIGTERM\n process.kill(pid, 'SIGTERM');\n logger.info(`Sent stop signal to daemon (PID: ${pid})`);\n\n // Wait for process to exit\n let attempts = 0;\n while (attempts < 10) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n try {\n process.kill(pid, 0);\n attempts++;\n } catch {\n // Process has exited\n break;\n }\n }\n\n if (attempts >= 10) {\n logger.warn('Daemon did not stop gracefully, sending SIGKILL');\n process.kill(pid, 'SIGKILL');\n }\n\n logger.info('Daemon stopped');\n } catch (err: any) {\n if (err.code === 'ESRCH') {\n logger.info('Daemon process not found (already stopped)');\n } else {\n throw err;\n }\n }\n\n // Clean up PID file\n if (fs.existsSync(PID_FILE)) {\n fs.unlinkSync(PID_FILE);\n }\n } catch (error) {\n logger.error(\n `Failed to stop daemon: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { MachineManager } from '../daemon/machine.js';\nimport { createSupabaseClient, restoreSession } from '../utils/supabase.js';\n\nexport function createStatusCommand(): Command {\n const command = new Command('status');\n\n command\n .description('Show connection status')\n .action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n const supabase = createSupabaseClient(\n config.getSupabaseUrl(),\n config.getSupabaseAnonKey()\n );\n\n // Restore session from stored tokens\n const session = await restoreSession(supabase, config);\n if (!session) {\n logger.info('Status: Not authenticated');\n logger.info('Run \"clautunnel login\" to authenticate');\n return;\n }\n\n const { user } = session;\n\n logger.info(`User: ${user.email}`);\n\n const machineId = config.getMachineId();\n if (!machineId) {\n logger.info('Machine: Not registered');\n logger.info('Run \"clautunnel start\" to register this machine');\n return;\n }\n\n const machineManager = new MachineManager({ supabase });\n const machine = await machineManager.getMachine(machineId);\n\n if (!machine) {\n logger.info(`Machine ID: ${machineId} (not found)`);\n return;\n }\n\n logger.info(`Machine: ${machine.name} (${machine.id})`);\n logger.info(`Status: ${machine.status}`);\n logger.info(`Last seen: ${machine.last_seen_at}`);\n } catch (error) {\n logger.error(\n `Failed to get status: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config, ConfigurationError } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { prompt, promptHidden } from '../utils/prompt.js';\nimport { createSupabaseClient } from '../utils/supabase.js';\n\nexport function createLoginCommand(): Command {\n const command = new Command('login');\n\n command.description('Authenticate with ClauTunnel').action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n config.requireConfiguration();\n\n const supabase = createSupabaseClient(\n config.getSupabaseUrl(),\n config.getSupabaseAnonKey()\n );\n\n const email = await prompt('Email: ');\n const password = await promptHidden('Password: ');\n\n if (!email || !password) {\n logger.error('Email and password are required');\n process.exit(1);\n }\n\n const { data, error } = await supabase.auth.signInWithPassword({\n email,\n password,\n });\n\n if (error) {\n logger.error(`Login failed: ${error.message}`);\n process.exit(1);\n }\n\n if (data.user) {\n logger.info(`Logged in as ${data.user.email}`);\n\n // Store session tokens securely\n if (data.session) {\n config.setSession({\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n });\n logger.info('Session saved');\n }\n\n logger.info('');\n logger.info('Next steps:');\n logger.info(' 1. Run \"clautunnel start\" to begin a session');\n logger.info(' 2. Set up the mobile app:');\n logger.info(' https://github.com/TongilKim/ClauTunnel#mobile-app-setup');\n }\n } catch (error) {\n if (error instanceof ConfigurationError) {\n logger.error(error.message);\n process.exit(1);\n }\n logger.error(\n `Login failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import * as readline from 'readline';\n\nexport function prompt(question: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n}\n\nexport function promptHidden(question: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n process.stdout.write(question);\n\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n }\n\n let password = '';\n\n const onData = (char: Buffer) => {\n const c = char.toString();\n\n if (c === '\\n' || c === '\\r') {\n process.stdin.removeListener('data', onData);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(false);\n }\n process.stdout.write('\\n');\n rl.close();\n resolve(password);\n } else if (c === '\\u0003') {\n // Ctrl+C\n process.exit(0);\n } else if (c === '\\u007F' || c === '\\b') {\n // Backspace\n if (password.length > 0) {\n password = password.slice(0, -1);\n }\n } else {\n password += c;\n }\n };\n\n process.stdin.on('data', onData);\n process.stdin.resume();\n });\n}\n","import { Command } from 'commander';\nimport { Config } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\n\nexport function createLogoutCommand(): Command {\n const command = new Command('logout');\n\n command.description('Log out of ClauTunnel').action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n const session = config.getSessionTokens();\n if (!session) {\n logger.info('Not currently logged in.');\n return;\n }\n\n config.clearSessionTokens();\n logger.info('Logged out successfully.');\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config, ConfigurationError } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { prompt, promptHidden } from '../utils/prompt.js';\nimport { createSupabaseClient } from '../utils/supabase.js';\n\nexport function createSignupCommand(): Command {\n const command = new Command('signup');\n\n command.description('Create a new ClauTunnel account').action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n config.requireConfiguration();\n\n const supabase = createSupabaseClient(\n config.getSupabaseUrl(),\n config.getSupabaseAnonKey()\n );\n\n logger.info('Create a new ClauTunnel account');\n logger.info('');\n\n const email = await prompt('Email: ');\n if (!email) {\n logger.error('Email is required');\n process.exit(1);\n }\n\n const password = await promptHidden('Password: ');\n if (!password) {\n logger.error('Password is required');\n process.exit(1);\n }\n\n if (password.length < 6) {\n logger.error('Password must be at least 6 characters');\n process.exit(1);\n }\n\n const confirmPassword = await promptHidden('Confirm Password: ');\n if (password !== confirmPassword) {\n logger.error('Passwords do not match');\n process.exit(1);\n }\n\n const { data, error } = await supabase.auth.signUp({\n email,\n password,\n });\n\n if (error) {\n logger.error(`Signup failed: ${error.message}`);\n process.exit(1);\n }\n\n if (data.user) {\n logger.info('');\n logger.info(`Account created for ${data.user.email}`);\n\n if (data.session) {\n config.setSession({\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n });\n logger.info('Logged in automatically');\n }\n\n logger.info('');\n logger.info('Next steps:');\n logger.info(' 1. Run \"clautunnel start\" to begin a session');\n logger.info(' 2. Set up the mobile app:');\n logger.info(' https://github.com/TongilKim/ClauTunnel#mobile-app-setup');\n }\n } catch (error) {\n if (error instanceof ConfigurationError) {\n logger.error(error.message);\n process.exit(1);\n }\n logger.error(\n `Signup failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { prompt } from '../utils/prompt.js';\n\nexport function createSetupCommand(): Command {\n const command = new Command('setup');\n\n command\n .description('Configure ClauTunnel with Supabase credentials')\n .action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n logger.info('ClauTunnel Setup');\n logger.info('================');\n logger.info('');\n\n // Step 1: Project ID\n logger.info('[Step 1/2] Supabase Project ID');\n logger.info('');\n logger.info(' 1. Go to your Supabase project dashboard');\n logger.info(' 2. Settings > General > Copy \"Project ID\"');\n logger.info('');\n\n const projectId = await prompt('Project ID: ');\n if (!projectId) {\n logger.error('Supabase Project ID is required');\n process.exit(1);\n }\n\n // Check if user accidentally pasted a full URL\n if (projectId.includes('supabase.co') || projectId.startsWith('http')) {\n logger.error('');\n logger.error('Please enter only the Project ID, not the full URL.');\n logger.error('');\n logger.error('Example: abcdefghijklmnop');\n logger.error('NOT: https://abcdefghijklmnop.supabase.co');\n process.exit(1);\n }\n\n // Validate Project ID format (alphanumeric, no spaces/special chars)\n if (!/^[a-zA-Z0-9-]+$/.test(projectId)) {\n logger.error('');\n logger.error('Invalid Project ID format.');\n logger.error('The Project ID should only contain letters, numbers, and hyphens.');\n logger.error('');\n logger.error('You can find it at: Settings > General > Project ID');\n process.exit(1);\n }\n\n const url = `https://${projectId}.supabase.co`;\n logger.info('✓ Project ID saved');\n logger.info('');\n\n // Step 2: Anon Key\n logger.info('[Step 2/2] Supabase Anon Key');\n logger.info('');\n logger.info(' 1. Go to your Supabase project dashboard');\n logger.info(' 2. Settings > API Keys > Legacy anon Tab > Copy anon key');\n logger.info('');\n\n const anonKey = await prompt('Anon Key: ');\n if (!anonKey) {\n logger.error('Supabase Anon Key is required');\n process.exit(1);\n }\n\n config.setSupabaseCredentials({ url, anonKey });\n\n logger.info('');\n logger.info('✓ Configuration saved successfully!');\n logger.info('');\n logger.info('Next steps:');\n logger.info(' - New user? Run \"clautunnel signup\" to create an account');\n logger.info(' - Have account? Run \"clautunnel login\" to authenticate');\n } catch (error) {\n logger.error(\n `Setup failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n","import { Command } from 'commander';\nimport { Config, ConfigurationError } from '../utils/config.js';\nimport { Logger } from '../utils/logger.js';\nimport { existsSync, writeFileSync } from 'fs';\nimport { join, resolve } from 'path';\n\nexport function createMobileSetupCommand(): Command {\n const command = new Command('mobile-setup');\n\n command\n .description('Generate mobile app .env file from CLI credentials')\n .action(async () => {\n const config = new Config();\n const logger = new Logger();\n\n try {\n config.requireConfiguration();\n\n const supabaseUrl = config.getSupabaseUrl();\n const supabaseAnonKey = config.getSupabaseAnonKey();\n\n // Look for apps/mobile directory relative to cwd\n const mobileDir = resolve(process.cwd(), 'apps', 'mobile');\n if (!existsSync(mobileDir)) {\n logger.error('Could not find apps/mobile directory.');\n logger.error('');\n logger.error('Make sure you run this command from the ClauTunnel project root:');\n logger.error(' cd clautunnel');\n logger.error(' clautunnel mobile-setup');\n process.exit(1);\n }\n\n const envPath = join(mobileDir, '.env');\n\n // Warn if .env already exists\n if (existsSync(envPath)) {\n logger.warn('apps/mobile/.env already exists and will be overwritten.');\n }\n\n const envContent = [\n `EXPO_PUBLIC_SUPABASE_URL=${supabaseUrl}`,\n `EXPO_PUBLIC_SUPABASE_ANON_KEY=${supabaseAnonKey}`,\n '',\n ].join('\\n');\n\n writeFileSync(envPath, envContent);\n\n // Save mobile project path to config for clautunnel start\n config.setMobileProjectPath(mobileDir);\n\n logger.info('');\n logger.info('Mobile app configured successfully!');\n logger.info(` Project: ${mobileDir}`);\n logger.info(` .env: ${envPath}`);\n logger.info('');\n logger.info('The mobile server will start automatically with \"clautunnel start\".');\n logger.info('Use \"clautunnel start --no-mobile\" to skip mobile server.');\n } catch (error) {\n if (error instanceof ConfigurationError) {\n logger.error(error.message);\n process.exit(1);\n }\n logger.error(\n `Mobile setup failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n process.exit(1);\n }\n });\n\n return command;\n}\n"],"mappings":"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","names":["resolve","dirname","readFileSync","path","resolve","hostname","EventEmitter","EventEmitter","os","resolve","prompt","existingNames","existsSync","readFileSync","writeFileSync","mkdirSync","join","homedir","path","EventEmitter","prompt","Command","import_clautunnel_shared","EventEmitter","EventEmitter","config","readdirSync","path","os","resolve","process","spawn","execSync","existsSync","mkdirSync","writeFileSync","join","homedir","packageJson","resolve","config","cleanup","session","prompt","Command","fs","path","os","Command","resolve","Command","Command","config","Command","readline","resolve","Command","config","Command","Command","config","Command","Command","config","Command","Command","config","Command","existsSync","writeFileSync","join","Command","config","dirname","resolve","readFileSync","Command"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tongil_kim/clautunnel",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "type": "module",
5
5
  "description": "Remote monitoring and control for Claude Code CLI",
6
6
  "author": "TongilKim",