@delt/claude-alarm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/constants.ts","../src/shared/logger.ts","../src/hub/session-manager.ts","../src/hub/notifier.ts","../src/hub/server.ts","../src/cli.ts","../src/shared/config.ts"],"sourcesContent":["import path from 'node:path';\nimport os from 'node:os';\n\nexport const DEFAULT_HUB_HOST = '127.0.0.1';\nexport const DEFAULT_HUB_PORT = 7890;\n\nexport const CONFIG_DIR = path.join(os.homedir(), '.claude-alarm');\nexport const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');\nexport const PID_FILE = path.join(CONFIG_DIR, 'hub.pid');\nexport const LOG_FILE = path.join(CONFIG_DIR, 'hub.log');\n\nexport const WS_PATH_CHANNEL = '/ws/channel';\nexport const WS_PATH_DASHBOARD = '/ws/dashboard';\n\nexport const CHANNEL_SERVER_NAME = 'claude-alarm';\nexport const CHANNEL_SERVER_VERSION = '0.1.0';\n","/**\n * Logger that writes to stderr only.\n * CRITICAL: In MCP channel servers, stdout is used for the stdio protocol.\n * Any console.log() would corrupt the protocol. Always use this logger.\n */\nexport const logger = {\n info(msg: string, ...args: unknown[]) {\n console.error(`[claude-alarm] ${msg}`, ...args);\n },\n warn(msg: string, ...args: unknown[]) {\n console.error(`[claude-alarm WARN] ${msg}`, ...args);\n },\n error(msg: string, ...args: unknown[]) {\n console.error(`[claude-alarm ERROR] ${msg}`, ...args);\n },\n debug(msg: string, ...args: unknown[]) {\n if (process.env.CLAUDE_ALARM_DEBUG) {\n console.error(`[claude-alarm DEBUG] ${msg}`, ...args);\n }\n },\n};\n","import type { SessionInfo, SessionStatus } from '../shared/types.js';\n\nexport class SessionManager {\n private sessions = new Map<string, SessionInfo>();\n\n register(session: SessionInfo): void {\n this.sessions.set(session.id, { ...session });\n }\n\n unregister(sessionId: string): SessionInfo | undefined {\n const session = this.sessions.get(sessionId);\n this.sessions.delete(sessionId);\n return session;\n }\n\n updateStatus(sessionId: string, status: SessionStatus): SessionInfo | undefined {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.status = status;\n session.lastActivity = Date.now();\n }\n return session;\n }\n\n updateActivity(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.lastActivity = Date.now();\n }\n }\n\n get(sessionId: string): SessionInfo | undefined {\n return this.sessions.get(sessionId);\n }\n\n getAll(): SessionInfo[] {\n return Array.from(this.sessions.values());\n }\n\n count(): number {\n return this.sessions.size;\n }\n}\n","import notifier from 'node-notifier';\nimport { execFile } from 'node:child_process';\nimport { logger } from '../shared/logger.js';\nimport type { NotifyLevel, WebhookConfig } from '../shared/types.js';\n\nexport class Notifier {\n private webhooks: WebhookConfig[] = [];\n private desktopEnabled = true;\n private notificationSettingsOpened = false;\n private dashboardUrl?: string;\n\n configure(options: { desktop?: boolean; webhooks?: WebhookConfig[]; dashboardUrl?: string }): void {\n if (options.dashboardUrl) this.dashboardUrl = options.dashboardUrl;\n if (options.desktop !== undefined) this.desktopEnabled = options.desktop;\n if (options.webhooks) this.webhooks = options.webhooks;\n }\n\n async notify(title: string, message: string, level: NotifyLevel = 'info'): Promise<void> {\n const promises: Promise<void>[] = [];\n\n if (this.desktopEnabled) {\n promises.push(this.sendDesktop(title, message, level));\n }\n\n for (const webhook of this.webhooks) {\n promises.push(this.sendWebhook(webhook, title, message, level));\n }\n\n await Promise.allSettled(promises);\n }\n\n private async sendDesktop(title: string, message: string, _level: NotifyLevel): Promise<void> {\n if (process.platform === 'win32') {\n // Check if notifications are enabled by running snoretoast directly\n const enabled = await this.checkWindowsNotifications();\n if (!enabled) {\n this.openNotificationSettings();\n return;\n }\n }\n\n return new Promise((resolve) => {\n const notification = (notifier as any).notify(\n {\n title: `Claude Alarm: ${title}`,\n message,\n sound: true,\n wait: true,\n },\n (err: Error | null) => {\n if (err) {\n logger.warn(`Desktop notification failed: ${err.message}`);\n }\n resolve();\n },\n );\n\n if (this.dashboardUrl && notification) {\n const url = this.dashboardUrl;\n notification.on('click', () => {\n execFile('powershell', ['-Command', `Start-Process \"${url}\"`]);\n });\n }\n });\n }\n\n private checkWindowsNotifications(): Promise<boolean> {\n return new Promise((resolve) => {\n execFile(\n 'powershell',\n ['-Command', '(Get-ItemProperty -Path \"HKCU:\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\PushNotifications\" -Name ToastEnabled -ErrorAction SilentlyContinue).ToastEnabled'],\n (err, stdout) => {\n if (err) { resolve(true); return; } // assume enabled on error\n const value = stdout.trim();\n resolve(value !== '0');\n },\n );\n });\n }\n\n private openNotificationSettings(): void {\n if (this.notificationSettingsOpened) return;\n this.notificationSettingsOpened = true;\n\n logger.warn('Windows notifications are disabled. Opening notification settings...');\n logger.warn('Please enable notifications for this app, then try again.');\n\n if (process.platform === 'win32') {\n execFile('powershell', ['-Command', 'Start-Process ms-settings:notifications']);\n }\n\n // Allow re-opening after 5 minutes\n setTimeout(() => { this.notificationSettingsOpened = false; }, 5 * 60 * 1000);\n }\n\n private async sendWebhook(\n webhook: WebhookConfig,\n title: string,\n message: string,\n level: NotifyLevel,\n ): Promise<void> {\n try {\n const response = await fetch(webhook.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...webhook.headers,\n },\n body: JSON.stringify({\n title,\n message,\n level,\n timestamp: Date.now(),\n source: 'claude-alarm',\n }),\n });\n\n if (!response.ok) {\n logger.warn(`Webhook ${webhook.url} returned ${response.status}`);\n }\n } catch (err) {\n logger.warn(`Webhook ${webhook.url} failed: ${(err as Error).message}`);\n }\n }\n}\n","import http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { logger } from '../shared/logger.js';\nimport {\n DEFAULT_HUB_HOST,\n DEFAULT_HUB_PORT,\n WS_PATH_CHANNEL,\n WS_PATH_DASHBOARD,\n} from '../shared/constants.js';\nimport { SessionManager } from './session-manager.js';\nimport { Notifier } from './notifier.js';\nimport type { ChannelMessage, AppConfig } from '../shared/types.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport class HubServer {\n private httpServer: http.Server;\n private wssChannel: WebSocketServer;\n private wssDashboard: WebSocketServer;\n private sessions = new SessionManager();\n private notifier = new Notifier();\n private startTime = Date.now();\n\n // Map sessionId -> channel WebSocket\n private channelSockets = new Map<string, WebSocket>();\n // All connected dashboard WebSockets\n private dashboardSockets = new Set<WebSocket>();\n\n private host: string;\n private port: number;\n private token?: string;\n\n constructor(config?: Partial<AppConfig>) {\n this.host = config?.hub?.host ?? DEFAULT_HUB_HOST;\n this.port = config?.hub?.port ?? DEFAULT_HUB_PORT;\n this.token = config?.hub?.token;\n\n if (config?.notifications) {\n this.notifier.configure({\n desktop: config.notifications.desktop,\n });\n }\n if (config?.webhooks) {\n this.notifier.configure({ webhooks: config.webhooks });\n }\n this.notifier.configure({ dashboardUrl: `http://${this.host}:${this.port}` });\n\n // HTTP Server\n this.httpServer = http.createServer((req, res) => this.handleHttp(req, res));\n\n // WebSocket for channel servers\n this.wssChannel = new WebSocketServer({ noServer: true });\n this.wssChannel.on('connection', (ws) => this.handleChannelConnection(ws));\n\n // WebSocket for dashboard\n this.wssDashboard = new WebSocketServer({ noServer: true });\n this.wssDashboard.on('connection', (ws) => this.handleDashboardConnection(ws));\n\n // Route WebSocket upgrade requests\n this.httpServer.on('upgrade', (req, socket, head) => {\n const url = new URL(req.url!, `http://${req.headers.host}`);\n const pathname = url.pathname;\n\n // Token auth for WebSocket connections (skip for local requests)\n if (this.token && !this.isLocalRequest(req)) {\n const wsToken = url.searchParams.get('token');\n if (wsToken !== this.token) {\n socket.destroy();\n return;\n }\n }\n\n if (pathname === WS_PATH_CHANNEL) {\n this.wssChannel.handleUpgrade(req, socket, head, (ws) => {\n this.wssChannel.emit('connection', ws, req);\n });\n } else if (pathname === WS_PATH_DASHBOARD) {\n this.wssDashboard.handleUpgrade(req, socket, head, (ws) => {\n this.wssDashboard.emit('connection', ws, req);\n });\n } else {\n socket.destroy();\n }\n });\n }\n\n async start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.httpServer.on('error', reject);\n this.httpServer.listen(this.port, this.host, () => {\n logger.info(`Hub server listening on http://${this.host}:${this.port}`);\n resolve();\n });\n });\n }\n\n stop(): Promise<void> {\n return new Promise((resolve) => {\n // Close all WebSocket connections\n for (const ws of this.channelSockets.values()) ws.close();\n for (const ws of this.dashboardSockets) ws.close();\n\n this.wssChannel.close();\n this.wssDashboard.close();\n this.httpServer.close(() => {\n logger.info('Hub server stopped');\n resolve();\n });\n });\n }\n\n // --- HTTP Handler ---\n\n private handleHttp(req: http.IncomingMessage, res: http.ServerResponse): void {\n const url = new URL(req.url!, `http://${req.headers.host}`);\n\n // CORS headers - restrict to same origin\n const origin = req.headers.origin;\n if (origin && (origin.includes('127.0.0.1') || origin.includes('localhost'))) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n }\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Token auth for API endpoints (skip dashboard HTML serving)\n if (url.pathname !== '/' && this.token) {\n if (!this.isLocalRequest(req)) {\n const authHeader = req.headers['authorization'];\n const bearerToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;\n if (bearerToken !== this.token) {\n this.jsonResponse(res, 401, { error: 'Unauthorized' });\n return;\n }\n }\n }\n\n // Route\n if (url.pathname === '/' && req.method === 'GET') {\n this.serveDashboard(res);\n } else if (url.pathname === '/api/sessions' && req.method === 'GET') {\n this.jsonResponse(res, 200, { sessions: this.sessions.getAll() });\n } else if (url.pathname === '/api/status' && req.method === 'GET') {\n this.jsonResponse(res, 200, {\n running: true,\n pid: process.pid,\n port: this.port,\n sessions: this.sessions.count(),\n uptime: Date.now() - this.startTime,\n });\n } else if (url.pathname === '/api/send' && req.method === 'POST') {\n this.handleApiSend(req, res);\n } else if (url.pathname === '/api/notify' && req.method === 'POST') {\n this.handleApiNotify(req, res);\n } else {\n this.jsonResponse(res, 404, { error: 'Not found' });\n }\n }\n\n private serveDashboard(res: http.ServerResponse): void {\n // Look for dashboard HTML relative to this file (dist) or source\n const candidates = [\n path.join(__dirname, '..', 'dashboard', 'index.html'), // from dist/hub/\n path.join(__dirname, '..', '..', 'src', 'dashboard', 'index.html'), // from dist/hub/ -> src/\n path.join(process.cwd(), 'dist', 'dashboard', 'index.html'), // from cwd\n path.join(process.cwd(), 'src', 'dashboard', 'index.html'), // from cwd/src\n ];\n logger.debug(`Dashboard candidates: ${JSON.stringify(candidates)}`);\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n const html = fs.readFileSync(candidate, 'utf-8');\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(html);\n return;\n }\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end('<html><body><h1>claude-alarm</h1><p>Dashboard HTML not found. Reinstall the package.</p></body></html>');\n }\n\n private async handleApiSend(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {\n const body = await this.readBody(req);\n if (!body) { this.jsonResponse(res, 400, { error: 'Invalid JSON' }); return; }\n\n const { sessionId, content } = body as { sessionId?: string; content?: string };\n if (!sessionId || !content) {\n this.jsonResponse(res, 400, { error: 'sessionId and content are required' });\n return;\n }\n\n const ws = this.channelSockets.get(sessionId);\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n this.jsonResponse(res, 404, { error: 'Session not connected' });\n return;\n }\n\n const msg: ChannelMessage = { type: 'message_to_session', sessionId, content };\n ws.send(JSON.stringify(msg));\n this.jsonResponse(res, 200, { ok: true });\n }\n\n private async handleApiNotify(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {\n const body = await this.readBody(req);\n if (!body) { this.jsonResponse(res, 400, { error: 'Invalid JSON' }); return; }\n\n const { title, message, level } = body as { title?: string; message?: string; level?: string };\n if (!title || !message) {\n this.jsonResponse(res, 400, { error: 'title and message are required' });\n return;\n }\n\n await this.notifier.notify(title, message, (level as any) ?? 'info');\n this.jsonResponse(res, 200, { ok: true });\n }\n\n // --- Channel WebSocket ---\n\n private handleChannelConnection(ws: WebSocket): void {\n logger.info('Channel server connected');\n\n ws.on('message', (data) => {\n try {\n const msg = JSON.parse(data.toString()) as ChannelMessage;\n this.handleChannelMessage(ws, msg);\n } catch {\n logger.warn('Invalid message from channel');\n }\n });\n\n ws.on('close', () => {\n // Find and remove the session for this socket\n for (const [sessionId, sock] of this.channelSockets) {\n if (sock === ws) {\n const session = this.sessions.unregister(sessionId);\n this.channelSockets.delete(sessionId);\n logger.info(`Channel disconnected: ${sessionId}`);\n this.broadcastToDashboards({\n type: 'session_disconnected',\n sessionId,\n });\n break;\n }\n }\n });\n }\n\n private handleChannelMessage(ws: WebSocket, msg: ChannelMessage): void {\n switch (msg.type) {\n case 'register': {\n const session = msg.session;\n this.sessions.register(session);\n this.channelSockets.set(session.id, ws);\n logger.info(`Session registered: ${session.id} (${session.name})`);\n this.broadcastToDashboards({ type: 'session_connected', session });\n break;\n }\n\n case 'status': {\n const updated = this.sessions.updateStatus(msg.sessionId, msg.status);\n if (updated) {\n this.broadcastToDashboards({ type: 'session_updated', session: updated });\n }\n break;\n }\n\n case 'notify': {\n this.sessions.updateActivity(msg.sessionId);\n this.notifier.notify(msg.title, msg.message, msg.level ?? 'info');\n this.broadcastToDashboards({\n type: 'notification',\n sessionId: msg.sessionId,\n title: msg.title,\n message: msg.message,\n level: msg.level,\n timestamp: Date.now(),\n });\n break;\n }\n\n case 'reply': {\n this.sessions.updateActivity(msg.sessionId);\n this.broadcastToDashboards({\n type: 'reply_from_session',\n sessionId: msg.sessionId,\n content: msg.content,\n timestamp: Date.now(),\n });\n break;\n }\n }\n }\n\n // --- Dashboard WebSocket ---\n\n private handleDashboardConnection(ws: WebSocket): void {\n this.dashboardSockets.add(ws);\n logger.info(`Dashboard connected (total: ${this.dashboardSockets.size})`);\n\n // Send current session list\n const sessionsMsg: ChannelMessage = {\n type: 'sessions_list',\n sessions: this.sessions.getAll(),\n };\n ws.send(JSON.stringify(sessionsMsg));\n\n ws.on('message', (data) => {\n try {\n const msg = JSON.parse(data.toString()) as ChannelMessage;\n if (msg.type === 'message_to_session') {\n const channelWs = this.channelSockets.get(msg.sessionId);\n if (channelWs?.readyState === WebSocket.OPEN) {\n channelWs.send(JSON.stringify(msg));\n }\n }\n } catch {\n logger.warn('Invalid message from dashboard');\n }\n });\n\n ws.on('close', () => {\n this.dashboardSockets.delete(ws);\n logger.info(`Dashboard disconnected (total: ${this.dashboardSockets.size})`);\n });\n }\n\n // --- Helpers ---\n\n private broadcastToDashboards(msg: ChannelMessage): void {\n const payload = JSON.stringify(msg);\n for (const ws of this.dashboardSockets) {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(payload);\n }\n }\n }\n\n private jsonResponse(res: http.ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(body));\n }\n\n private isLocalRequest(req: http.IncomingMessage): boolean {\n const addr = req.socket.remoteAddress;\n return addr === '127.0.0.1' || addr === '::1' || addr === '::ffff:127.0.0.1';\n }\n\n private readBody(req: http.IncomingMessage, maxSize = 1024 * 1024): Promise<unknown | null> {\n return new Promise((resolve) => {\n let data = '';\n let size = 0;\n req.on('data', (chunk) => {\n size += chunk.length;\n if (size > maxSize) {\n req.destroy();\n resolve(null);\n return;\n }\n data += chunk;\n });\n req.on('end', () => {\n try {\n resolve(JSON.parse(data));\n } catch {\n resolve(null);\n }\n });\n });\n }\n}\n\n// Direct execution support\nif (process.argv[1] && (\n process.argv[1].endsWith('hub/server.js') ||\n process.argv[1].endsWith('hub/server.ts')\n)) {\n const hub = new HubServer();\n hub.start().catch((err) => {\n logger.error('Failed to start hub:', err);\n process.exit(1);\n });\n\n const shutdown = () => {\n hub.stop().then(() => process.exit(0));\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n","import { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport readline from 'node:readline';\nimport { fileURLToPath } from 'node:url';\nimport { loadConfig, ensureConfigDir, setupMcpConfig, getOrCreateToken } from './shared/config.js';\nimport { PID_FILE, LOG_FILE, DEFAULT_HUB_HOST, DEFAULT_HUB_PORT } from './shared/constants.js';\nimport { logger } from './shared/logger.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nfunction printUsage() {\n console.log(`\nclaude-alarm - Monitor Claude Code sessions with notifications\n\nUsage:\n claude-alarm init Setup everything and show next steps\n claude-alarm hub start [-d] Start the hub server (-d for daemon)\n claude-alarm hub stop Stop the hub daemon\n claude-alarm hub status Show hub status\n claude-alarm setup [dir] Add claude-alarm to .mcp.json\n claude-alarm test Send a test notification\n claude-alarm token Show current auth token\n claude-alarm help Show this help\n\nQuick start:\n claude-alarm init\n`);\n}\n\nasync function hubStart(daemon: boolean) {\n const config = loadConfig();\n const host = config.hub.host ?? DEFAULT_HUB_HOST;\n const port = config.hub.port ?? DEFAULT_HUB_PORT;\n\n // Check if already running\n if (fs.existsSync(PID_FILE)) {\n const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim(), 10);\n if (isProcessRunning(pid)) {\n console.log(`Hub is already running (PID: ${pid}) on http://${host}:${port}`);\n return;\n }\n // Stale PID file\n fs.unlinkSync(PID_FILE);\n }\n\n if (daemon) {\n ensureConfigDir();\n const logFd = fs.openSync(LOG_FILE, 'a');\n const hubScript = path.join(__dirname, 'hub', 'server.js');\n\n const child = spawn(process.execPath, [hubScript], {\n detached: true,\n stdio: ['ignore', logFd, logFd],\n env: { ...process.env },\n });\n\n if (child.pid) {\n fs.writeFileSync(PID_FILE, String(child.pid), 'utf-8');\n child.unref();\n console.log(`Hub started as daemon (PID: ${child.pid})`);\n console.log(`Dashboard: http://${host}:${port}`);\n console.log(`Token: ${config.hub.token}`);\n console.log(`Logs: ${LOG_FILE}`);\n } else {\n console.error('Failed to start hub daemon');\n process.exit(1);\n }\n } else {\n // Foreground mode - import and run directly\n console.log(`Starting hub on http://${host}:${port} (press Ctrl+C to stop)`);\n console.log(`Token: ${config.hub.token}`);\n const { HubServer } = await import('./hub/server.js');\n const hub = new HubServer(config);\n await hub.start();\n\n // Write PID file even in foreground\n ensureConfigDir();\n fs.writeFileSync(PID_FILE, String(process.pid), 'utf-8');\n\n const shutdown = async () => {\n console.log('\\nShutting down...');\n await hub.stop();\n if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);\n process.exit(0);\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n }\n}\n\nfunction hubStop() {\n if (!fs.existsSync(PID_FILE)) {\n console.log('Hub is not running (no PID file found)');\n return;\n }\n\n const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim(), 10);\n try {\n process.kill(pid, 'SIGTERM');\n console.log(`Hub stopped (PID: ${pid})`);\n } catch {\n console.log('Hub process not found (may have already stopped)');\n }\n fs.unlinkSync(PID_FILE);\n}\n\nasync function hubStatus() {\n const config = loadConfig();\n const host = config.hub.host ?? DEFAULT_HUB_HOST;\n const port = config.hub.port ?? DEFAULT_HUB_PORT;\n\n // Check PID file\n let pidInfo = 'not running';\n if (fs.existsSync(PID_FILE)) {\n const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim(), 10);\n if (isProcessRunning(pid)) {\n pidInfo = `running (PID: ${pid})`;\n } else {\n pidInfo = 'not running (stale PID file)';\n }\n }\n\n // Try to reach the hub HTTP API\n try {\n const res = await fetch(`http://${host}:${port}/api/status`);\n if (res.ok) {\n const data = await res.json() as any;\n console.log(`Hub: running (PID: ${data.pid})`);\n console.log(`Port: ${data.port}`);\n console.log(`Sessions: ${data.sessions}`);\n console.log(`Uptime: ${Math.round(data.uptime / 1000)}s`);\n console.log(`Dashboard: http://${host}:${port}`);\n const token = config.hub.token;\n if (token) {\n console.log(`Token: ${token.slice(0, 8)}...(masked)`);\n }\n return;\n }\n } catch {\n // Hub not reachable\n }\n\n console.log(`Hub: ${pidInfo}`);\n console.log(`Configured: http://${host}:${port}`);\n}\n\nfunction setup(targetDir?: string) {\n const mcpPath = setupMcpConfig(targetDir);\n console.log(`Added claude-alarm to ${mcpPath}`);\n console.log('\\nTo use with Claude Code:');\n console.log(' 1. Start the hub: claude-alarm hub start -d');\n console.log(' 2. Run Claude Code: claude --dangerously-load-development-channels server:claude-alarm');\n}\n\nasync function test() {\n const config = loadConfig();\n const host = config.hub.host ?? DEFAULT_HUB_HOST;\n const port = config.hub.port ?? DEFAULT_HUB_PORT;\n\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (config.hub.token) {\n headers['Authorization'] = `Bearer ${config.hub.token}`;\n }\n const res = await fetch(`http://${host}:${port}/api/notify`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n title: 'Test Notification',\n message: 'Claude Alarm is working! This is a test notification.',\n level: 'success',\n }),\n });\n\n if (res.ok) {\n console.log('Test notification sent! Check your desktop for the toast.');\n } else {\n console.error(`Hub returned ${res.status}. Is the hub running?`);\n }\n } catch {\n console.error('Could not reach hub. Start it first: claude-alarm hub start');\n }\n}\n\nfunction ask(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nasync function init() {\n const dir = process.cwd();\n const projectName = path.basename(dir);\n\n console.log(`\\nclaude-alarm init for \"${projectName}\"\\n`);\n\n const remote = await ask('Connect to a remote hub? (y/N): ');\n\n let env: Record<string, string> = {\n CLAUDE_ALARM_SESSION_NAME: projectName,\n };\n\n if (remote.toLowerCase() === 'y') {\n const host = await ask('Hub host (e.g. 192.168.1.100): ');\n const port = await ask('Hub port (default: 7890): ');\n const token = await ask('Hub token: ');\n\n if (!host) {\n console.error('Host is required.');\n process.exit(1);\n }\n env.CLAUDE_ALARM_HUB_HOST = host;\n if (port) env.CLAUDE_ALARM_HUB_PORT = port;\n if (token) env.CLAUDE_ALARM_HUB_TOKEN = token;\n }\n\n // Write .mcp.json\n const mcpPath = path.join(dir, '.mcp.json');\n let mcpConfig: Record<string, any> = {};\n if (fs.existsSync(mcpPath)) {\n try { mcpConfig = JSON.parse(fs.readFileSync(mcpPath, 'utf-8')); } catch { mcpConfig = {}; }\n }\n if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};\n mcpConfig.mcpServers['claude-alarm'] = {\n command: 'npx',\n args: ['-y', '@delt/claude-alarm'],\n env,\n };\n fs.writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2), 'utf-8');\n\n console.log(`\\nāœ“ Created ${mcpPath}`);\n\n if (remote.toLowerCase() !== 'y') {\n // Check if hub is running locally\n const config = loadConfig();\n const host = config.hub.host ?? DEFAULT_HUB_HOST;\n const port = config.hub.port ?? DEFAULT_HUB_PORT;\n let hubRunning = false;\n try {\n const res = await fetch(`http://${host}:${port}/api/status`);\n hubRunning = res.ok;\n } catch {}\n\n if (hubRunning) {\n console.log('āœ“ Hub is running');\n } else {\n console.log('āœ— Hub is not running. Start it with:');\n console.log(` claude-alarm hub start`);\n }\n console.log(` Dashboard: http://${host}:${port}`);\n }\n\n console.log(`\\nNext step:`);\n console.log(` claude --dangerously-load-development-channels server:claude-alarm\\n`);\n}\n\nfunction showToken() {\n const token = getOrCreateToken();\n console.log(`Token: ${token}`);\n}\n\nfunction isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n// --- Main CLI ---\nasync function main() {\n const args = process.argv.slice(2);\n const cmd = args[0];\n const sub = args[1];\n\n if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {\n printUsage();\n return;\n }\n\n if (cmd === 'init') {\n await init();\n return;\n }\n\n if (cmd === 'hub') {\n if (sub === 'start') {\n const daemon = args.includes('-d') || args.includes('--daemon');\n await hubStart(daemon);\n } else if (sub === 'stop') {\n hubStop();\n } else if (sub === 'status') {\n await hubStatus();\n } else {\n console.error(`Unknown hub command: ${sub}`);\n printUsage();\n process.exit(1);\n }\n return;\n }\n\n if (cmd === 'setup') {\n setup(args[1]);\n return;\n }\n\n if (cmd === 'test') {\n await test();\n return;\n }\n\n if (cmd === 'token') {\n showToken();\n return;\n }\n\n console.error(`Unknown command: ${cmd}`);\n printUsage();\n process.exit(1);\n}\n\nmain().catch((err) => {\n logger.error('CLI error:', err);\n process.exit(1);\n});\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { CONFIG_DIR, CONFIG_FILE, DEFAULT_HUB_HOST, DEFAULT_HUB_PORT } from './constants.js';\nimport type { AppConfig } from './types.js';\n\nconst DEFAULT_CONFIG: AppConfig = {\n hub: {\n host: DEFAULT_HUB_HOST,\n port: DEFAULT_HUB_PORT,\n },\n notifications: {\n desktop: true,\n sound: true,\n },\n webhooks: [],\n};\n\nexport function ensureConfigDir(): void {\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n }\n}\n\nexport function loadConfig(): AppConfig {\n ensureConfigDir();\n let config: AppConfig;\n if (!fs.existsSync(CONFIG_FILE)) {\n config = { ...DEFAULT_CONFIG, hub: { ...DEFAULT_CONFIG.hub } };\n } else {\n try {\n const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');\n const parsed = JSON.parse(raw);\n config = { ...DEFAULT_CONFIG, ...parsed, hub: { ...DEFAULT_CONFIG.hub, ...parsed.hub } };\n } catch {\n config = { ...DEFAULT_CONFIG, hub: { ...DEFAULT_CONFIG.hub } };\n }\n }\n\n // Auto-generate token if missing\n if (!config.hub.token) {\n config.hub.token = randomUUID();\n saveConfig(config);\n }\n\n return config;\n}\n\n/** Get the current token, generating one if needed */\nexport function getOrCreateToken(): string {\n const config = loadConfig();\n return config.hub.token!;\n}\n\nexport function saveConfig(config: AppConfig): void {\n ensureConfigDir();\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: 0o600 });\n}\n\n/**\n * Add claude-alarm as an MCP channel server to .mcp.json\n */\nexport function setupMcpConfig(targetDir?: string): string {\n const dir = targetDir ?? process.cwd();\n const mcpPath = path.join(dir, '.mcp.json');\n\n let mcpConfig: Record<string, any> = {};\n if (fs.existsSync(mcpPath)) {\n try {\n mcpConfig = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));\n } catch {\n mcpConfig = {};\n }\n }\n\n if (!mcpConfig.mcpServers) {\n mcpConfig.mcpServers = {};\n }\n\n mcpConfig.mcpServers['claude-alarm'] = {\n command: 'npx',\n args: ['-y', '@delt/claude-alarm'],\n env: {\n CLAUDE_ALARM_SESSION_NAME: path.basename(dir),\n },\n };\n\n fs.writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2), 'utf-8');\n return mcpPath;\n}\n"],"mappings":"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","names":["fs","path","fs","path","fileURLToPath","path","__dirname","path","fileURLToPath","fs","HubServer"]}