codesail 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/index.ts","../src/commands/login.ts","../src/core/crypto/backup.ts","../src/commands/daemon.ts","../src/commands/sessions.ts","../src/commands/send.ts","../src/commands/approve.ts","../src/commands/backup.ts","../src/commands/config.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { loginCommand, showPairingQR } from './commands/login.js';\nimport { daemonStartCommand, daemonStopCommand, daemonStatusCommand } from './commands/daemon.js';\nimport { sessionsCommand } from './commands/sessions.js';\nimport { sendCommand } from './commands/send.js';\nimport { approveCommand } from './commands/approve.js';\nimport { denyCommand } from './commands/deny.js';\nimport { backupShowCommand, backupRestoreCommand } from './commands/backup.js';\nimport { configSetCommand, configGetCommand, configListCommand } from './commands/config.js';\n\nconst program = new Command();\n\nprogram\n .name('codesail')\n .description('CLI for CodeSail — control Claude Code sessions from your terminal')\n .version('0.1.0');\n\n// ── Login ──\nprogram\n .command('login')\n .description('Create new account or show QR for mobile pairing')\n .option('-s, --server <url>', 'Server URL')\n .action(loginCommand);\n\n// ── Auth ──\nconst auth = program\n .command('auth')\n .description('Authentication commands');\n\nauth\n .command('login')\n .description('Display QR code for mobile app to scan & pair')\n .option('-s, --server <url>', 'Server URL')\n .action(async (opts) => {\n await showPairingQR(opts.server);\n });\n\n// ── Daemon ──\nconst daemon = program\n .command('daemon')\n .description('Background daemon management');\n\ndaemon\n .command('start')\n .description('Start the background daemon')\n .action(daemonStartCommand);\n\ndaemon\n .command('stop')\n .description('Stop the background daemon')\n .action(daemonStopCommand);\n\ndaemon\n .command('status')\n .description('Show daemon status')\n .action(daemonStatusCommand);\n\n// ── Sessions ──\nprogram\n .command('sessions')\n .description('List active sessions')\n .action(sessionsCommand);\n\n// ── Send ──\nprogram\n .command('send <session> <message>')\n .description('Send a message to a session')\n .action(sendCommand);\n\n// ── Approve ──\nprogram\n .command('approve <session>')\n .description('Approve pending permission request')\n .option('-d, --decision <decision>', 'Decision type (approved, approved_for_session)', 'approved')\n .action(approveCommand);\n\n// ── Deny ──\nprogram\n .command('deny <session>')\n .description('Deny pending permission request')\n .action(denyCommand);\n\n// ── Backup ──\nconst backup = program\n .command('backup')\n .description('Backup key management');\n\nbackup\n .command('show')\n .description('Display your backup key')\n .action(backupShowCommand);\n\nbackup\n .command('restore')\n .description('Restore account from backup key')\n .option('-s, --server <url>', 'Server URL')\n .action(backupRestoreCommand);\n\n// ── Config ──\nconst config = program\n .command('config')\n .description('Configuration management');\n\nconfig\n .command('set <key> <value>')\n .description('Set a config value')\n .action(configSetCommand);\n\nconfig\n .command('get <key>')\n .description('Get a config value')\n .action(configGetCommand);\n\nconfig\n .command('list')\n .description('List all config values')\n .action(configListCommand);\n\nprogram.parse();\n","import nacl from 'tweetnacl';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport qrcode from 'qrcode-terminal';\nimport { encodeBase64 } from '../core/crypto/nacl.js';\nimport { base64urlEncode, generateBoxKeyPair } from '../core/crypto/nacl.js';\nimport { boxOpen } from '../core/crypto/nacl.js';\nimport { authenticate, createAuthRequest } from '../core/api.js';\nimport { saveCredentials, loadCredentials } from '../storage/credentials.js';\nimport { DEFAULT_SERVER_URL, QR_PREFIX } from '../core/config.js';\nimport { base32Encode, formatBase32 } from '../core/crypto/backup.js';\n\nexport async function loginCommand(opts: { server?: string }) {\n const serverURL = opts.server ?? DEFAULT_SERVER_URL;\n\n // Check for existing credentials\n const existing = await loadCredentials();\n if (existing) {\n console.log(chalk.yellow('Already logged in. Showing QR for mobile pairing...'));\n await showPairingQR(serverURL);\n return;\n }\n\n console.log(chalk.bold('Creating new CodeSail account...\\n'));\n\n // 1. Generate master secret\n const masterSecret = nacl.randomBytes(32);\n\n // 2. Authenticate with server\n const spinner = ora('Authenticating with server...').start();\n let token: string;\n try {\n token = await authenticate(masterSecret, serverURL);\n spinner.succeed('Authenticated successfully');\n } catch (err) {\n spinner.fail('Authentication failed');\n console.error(chalk.red((err as Error).message));\n process.exit(1);\n }\n\n // 3. Save credentials\n await saveCredentials({\n token,\n masterSecret: encodeBase64(masterSecret),\n serverURL,\n });\n console.log(chalk.green('Credentials saved to ~/.codesail/credentials.json'));\n\n // 4. Show backup key\n const backupKey = formatBase32(base32Encode(masterSecret));\n console.log('\\n' + chalk.bold('Backup Key (save this somewhere safe!):'));\n console.log(chalk.cyan(backupKey));\n console.log(chalk.dim('You can restore your account on any device with this key.\\n'));\n\n // 5. Show QR for mobile pairing\n await showPairingQR(serverURL);\n}\n\nexport async function showPairingQR(serverURL?: string) {\n const resolvedURL = serverURL ?? DEFAULT_SERVER_URL;\n\n // Generate ephemeral box keypair for pairing\n const ephemeral = generateBoxKeyPair();\n const publicKeyBase64 = encodeBase64(ephemeral.publicKey);\n const publicKeyBase64url = base64urlEncode(ephemeral.publicKey);\n\n // Create auth request on server\n const spinner = ora('Creating pairing request...').start();\n try {\n await createAuthRequest(publicKeyBase64, true, resolvedURL);\n spinner.succeed('Pairing request created');\n } catch (err) {\n spinner.fail('Failed to create pairing request');\n console.error(chalk.red((err as Error).message));\n return;\n }\n\n // Display QR code\n const qrContent = QR_PREFIX + publicKeyBase64url;\n console.log('\\n' + chalk.bold('Scan this QR code with the CodeSail iOS app:'));\n qrcode.generate(qrContent, { small: true });\n\n // Poll for response\n console.log(chalk.dim('\\nWaiting for mobile app to scan and approve...'));\n const pollSpinner = ora('Polling...').start();\n\n for (let i = 0; i < 120; i++) { // 2 minutes max\n await sleep(1000);\n try {\n const result = await createAuthRequest(publicKeyBase64, true, resolvedURL);\n\n if (result.response) {\n pollSpinner.succeed('Mobile app approved the pairing!');\n\n // Decrypt the response\n const responseData = Buffer.from(result.response, 'base64');\n const decrypted = boxOpen(new Uint8Array(responseData), ephemeral.secretKey);\n\n if (decrypted[0] === 0x00 && decrypted.length === 33) {\n // V2 response: version byte + content public key\n console.log(chalk.green('V2 pairing complete — content public key received'));\n } else if (decrypted.length === 32) {\n // V1 response: master secret\n console.log(chalk.green('V1 pairing complete — master secret received'));\n // Re-authenticate with the received master secret\n const token = await authenticate(decrypted, resolvedURL);\n await saveCredentials({\n token,\n masterSecret: encodeBase64(decrypted),\n serverURL: resolvedURL,\n });\n console.log(chalk.green('Credentials updated'));\n }\n return;\n }\n\n if (result.status === 'not_found') {\n pollSpinner.text = 'Request expired, creating new one...';\n await createAuthRequest(publicKeyBase64, true, resolvedURL);\n }\n } catch {\n // Retry on error\n }\n }\n\n pollSpinner.fail('Pairing timed out. Run `codesail auth login` to try again.');\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","const BASE32_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';\n\n/** OCR correction map: commonly confused characters */\nconst OCR_CORRECTIONS: Record<string, string> = {\n '0': 'O',\n '1': 'I',\n '8': 'B',\n 'l': 'I',\n 'o': 'O',\n};\n\n/** Encode bytes to Base32 (RFC 4648) */\nexport function base32Encode(data: Uint8Array): string {\n let bits = 0;\n let value = 0;\n let result = '';\n\n for (const byte of data) {\n value = (value << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n bits -= 5;\n result += BASE32_ALPHABET[(value >>> bits) & 0x1f];\n }\n }\n\n if (bits > 0) {\n result += BASE32_ALPHABET[(value << (5 - bits)) & 0x1f];\n }\n\n // Pad to multiple of 8\n while (result.length % 8 !== 0) {\n result += '=';\n }\n\n return result;\n}\n\n/** Decode Base32 (RFC 4648) with OCR correction */\nexport function base32Decode(input: string): Uint8Array {\n // Strip whitespace and dashes, apply OCR corrections\n const cleaned = input\n .replace(/[\\s-]/g, '')\n .replace(/=+$/, '')\n .split('')\n .map(c => OCR_CORRECTIONS[c] ?? c.toUpperCase())\n .join('');\n\n const bytes: number[] = [];\n let bits = 0;\n let value = 0;\n\n for (const char of cleaned) {\n const idx = BASE32_ALPHABET.indexOf(char);\n if (idx === -1) throw new Error(`Invalid Base32 character: ${char}`);\n value = (value << 5) | idx;\n bits += 5;\n if (bits >= 8) {\n bits -= 8;\n bytes.push((value >>> bits) & 0xff);\n }\n }\n\n return new Uint8Array(bytes);\n}\n\n/** Format Base32 string into groups of 4 for readability */\nexport function formatBase32(encoded: string): string {\n const clean = encoded.replace(/=+$/, '');\n return clean.match(/.{1,4}/g)?.join('-') ?? clean;\n}\n","import { fork } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join, resolve } from 'node:path';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { readDaemonState, isDaemonRunning } from '../daemon/state.js';\nimport { loadCredentials } from '../storage/credentials.js';\n\n/** Resolve daemon entry point relative to this file's location in dist/ */\nfunction findDaemonEntry(): string {\n const thisFile = fileURLToPath(import.meta.url);\n const distDir = dirname(thisFile);\n // Walk up from chunk files to find dist root, then into daemon/\n // After tsup build: dist/index.js, dist/chunk-*.js, dist/daemon/index.js\n // import.meta.url could be dist/index.js or dist/chunk-*.js\n const candidate = join(distDir, 'daemon', 'index.js');\n // If we're already in dist/, this works. If in a chunk subdir somehow, go up.\n return candidate;\n}\n\nexport async function daemonStartCommand() {\n // Check for credentials\n const creds = await loadCredentials();\n if (!creds) {\n console.error(chalk.red('Not logged in. Run `codesail login` first.'));\n process.exit(1);\n }\n\n // Check if already running\n if (await isDaemonRunning()) {\n const state = await readDaemonState();\n console.log(chalk.yellow(`Daemon already running (PID: ${state?.pid}, port: ${state?.httpPort})`));\n return;\n }\n\n const spinner = ora('Starting daemon...').start();\n\n // Fork the daemon process\n const daemonEntry = findDaemonEntry();\n\n const child = fork(daemonEntry, [], {\n detached: true,\n stdio: 'ignore',\n });\n\n child.unref();\n\n // Wait a bit for the daemon to start and write its state file\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n const state = await readDaemonState();\n if (state) {\n spinner.succeed(`Daemon started (PID: ${state.pid}, port: ${state.httpPort})`);\n } else {\n spinner.fail('Daemon may have failed to start. Check logs.');\n }\n}\n\nexport async function daemonStopCommand() {\n const state = await readDaemonState();\n if (!state) {\n console.log(chalk.yellow('Daemon is not running.'));\n return;\n }\n\n const spinner = ora('Stopping daemon...').start();\n try {\n process.kill(state.pid, 'SIGTERM');\n // Wait for clean shutdown\n await new Promise(resolve => setTimeout(resolve, 1000));\n spinner.succeed(`Daemon stopped (was PID: ${state.pid})`);\n } catch {\n spinner.warn('Daemon process not found — cleaning up state file.');\n const { removeDaemonState } = await import('../daemon/state.js');\n await removeDaemonState();\n }\n}\n\nexport async function daemonStatusCommand() {\n const running = await isDaemonRunning();\n const state = await readDaemonState();\n\n if (running && state) {\n console.log(chalk.green('Daemon is running'));\n console.log(` PID: ${state.pid}`);\n console.log(` Port: ${state.httpPort}`);\n console.log(` URL: http://127.0.0.1:${state.httpPort}`);\n } else {\n console.log(chalk.yellow('Daemon is not running'));\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { decodeBase64 } from '../core/crypto/nacl.js';\nimport { resolveSessionEncryption, decryptValue } from '../core/crypto/encryption.js';\nimport { fetchSessions } from '../core/api.js';\nimport { loadCredentials } from '../storage/credentials.js';\nimport { readDaemonState, isDaemonRunning } from '../daemon/state.js';\nimport { DEFAULT_SERVER_URL } from '../core/config.js';\nimport type { SessionMetadata, RawSession } from '../types/session.js';\nimport type { AgentState } from '../types/update.js';\n\nexport async function sessionsCommand() {\n // Try daemon first\n if (await isDaemonRunning()) {\n const state = await readDaemonState();\n if (state) {\n try {\n const resp = await fetch(`http://127.0.0.1:${state.httpPort}/sessions`);\n const data = await resp.json() as { sessions: Array<Record<string, unknown>> };\n displayDaemonSessions(data.sessions);\n return;\n } catch {\n // Fall through to direct API\n }\n }\n }\n\n // Direct API approach\n const creds = await loadCredentials();\n if (!creds) {\n console.error(chalk.red('Not logged in. Run `codesail login` first.'));\n process.exit(1);\n }\n\n const spinner = ora('Fetching sessions...').start();\n try {\n const masterSecret = decodeBase64(creds.masterSecret);\n const serverURL = creds.serverURL ?? DEFAULT_SERVER_URL;\n const rawSessions = await fetchSessions(creds.token, serverURL);\n spinner.succeed(`Found ${rawSessions.length} sessions`);\n displaySessions(rawSessions, masterSecret);\n } catch (err) {\n spinner.fail('Failed to fetch sessions');\n console.error(chalk.red((err as Error).message));\n process.exit(1);\n }\n}\n\nfunction displaySessions(rawSessions: RawSession[], masterSecret: Uint8Array) {\n if (rawSessions.length === 0) {\n console.log(chalk.dim('No sessions found.'));\n return;\n }\n\n console.log('');\n for (const raw of rawSessions) {\n const encryption = resolveSessionEncryption(raw.dataEncryptionKey, masterSecret);\n\n let metadata: SessionMetadata | null = null;\n let agentState: AgentState | null = null;\n try {\n const metaData = decodeBase64(raw.metadata);\n metadata = decryptValue(encryption, metaData) as SessionMetadata;\n } catch { /* ignore */ }\n\n if (raw.agentState) {\n try {\n const stateData = decodeBase64(raw.agentState);\n agentState = decryptValue(encryption, stateData) as AgentState;\n } catch { /* ignore */ }\n }\n\n const name = metadata?.name ?? metadata?.path?.split('/').pop() ?? raw.id.slice(0, 8);\n const path = metadata?.path ?? '';\n const host = metadata?.host ?? '';\n const hasPending = agentState?.requests && Object.keys(agentState.requests).length > 0;\n const lifecycle = metadata?.lifecycleState;\n const updatedAt = new Date(raw.updatedAt).toLocaleString();\n\n // Status indicator\n let status = chalk.dim('idle');\n if (hasPending) {\n const tools = Object.values(agentState!.requests!).map(r => r.tool);\n status = chalk.yellow(`⚠ permission: ${tools[0]}`);\n } else if (lifecycle === 'archived') {\n status = chalk.dim('archived');\n }\n\n console.log(chalk.bold(name) + chalk.dim(` [${raw.id.slice(0, 8)}]`));\n console.log(` ${chalk.dim('Path:')} ${path}`);\n if (host) console.log(` ${chalk.dim('Host:')} ${host}`);\n console.log(` ${chalk.dim('Status:')} ${status}`);\n console.log(` ${chalk.dim('Updated:')} ${updatedAt}`);\n if (metadata?.summary?.text) {\n console.log(` ${chalk.dim('Summary:')} ${metadata.summary.text.slice(0, 100)}`);\n }\n console.log('');\n }\n}\n\nfunction displayDaemonSessions(sessions: Array<Record<string, unknown>>) {\n if (sessions.length === 0) {\n console.log(chalk.dim('No sessions found.'));\n return;\n }\n\n console.log('');\n for (const s of sessions) {\n const name = (s.name as string) || (s.id as string).slice(0, 8);\n const path = (s.path as string) || '';\n const host = (s.host as string) || '';\n const hasPending = s.hasPendingPermission === true;\n const updatedAt = new Date(s.updatedAt as number).toLocaleString();\n const lifecycle = s.lifecycleState as string | undefined;\n\n let status = chalk.dim('idle');\n if (hasPending) {\n const reqs = s.pendingRequests as Record<string, { tool: string }>;\n const tools = Object.values(reqs).map(r => r.tool);\n status = chalk.yellow(`⚠ permission: ${tools[0]}`);\n } else if (lifecycle === 'archived') {\n status = chalk.dim('archived');\n } else {\n const activity = s.activity as { isActive?: boolean; isThinking?: boolean } | null;\n if (activity?.isThinking) status = chalk.blue('thinking...');\n else if (activity?.isActive) status = chalk.green('active');\n }\n\n console.log(chalk.bold(name) + chalk.dim(` [${(s.id as string).slice(0, 8)}]`));\n console.log(` ${chalk.dim('Path:')} ${path}`);\n if (host) console.log(` ${chalk.dim('Host:')} ${host}`);\n console.log(` ${chalk.dim('Status:')} ${status}`);\n console.log(` ${chalk.dim('Updated:')} ${updatedAt}`);\n if (s.summary) {\n console.log(` ${chalk.dim('Summary:')} ${(s.summary as string).slice(0, 100)}`);\n }\n console.log('');\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { decodeBase64 } from '../core/crypto/nacl.js';\nimport { resolveSessionEncryption, encryptToBase64 } from '../core/crypto/encryption.js';\nimport { fetchSessions } from '../core/api.js';\nimport { createSocketClient } from '../core/socket.js';\nimport { loadCredentials } from '../storage/credentials.js';\nimport { readDaemonState, isDaemonRunning } from '../daemon/state.js';\nimport { DEFAULT_SERVER_URL } from '../core/config.js';\n\nexport async function sendCommand(sessionQuery: string, message: string) {\n // Try daemon first\n if (await isDaemonRunning()) {\n const state = await readDaemonState();\n if (state) {\n try {\n const sessionId = await resolveSessionId(sessionQuery, state.httpPort);\n const resp = await fetch(`http://127.0.0.1:${state.httpPort}/send-message`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ sessionId, text: message }),\n });\n const data = await resp.json() as { success: boolean; error?: string };\n if (data.success) {\n console.log(chalk.green('Message sent.'));\n } else {\n console.error(chalk.red(`Failed: ${data.error}`));\n }\n return;\n } catch {\n // Fall through\n }\n }\n }\n\n // Direct approach (connect socket, send, disconnect)\n const creds = await loadCredentials();\n if (!creds) {\n console.error(chalk.red('Not logged in. Run `codesail login` first.'));\n process.exit(1);\n }\n\n const spinner = ora('Sending message...').start();\n const masterSecret = decodeBase64(creds.masterSecret);\n const serverURL = creds.serverURL ?? DEFAULT_SERVER_URL;\n\n // Find session\n const rawSessions = await fetchSessions(creds.token, serverURL);\n const session = rawSessions.find(s =>\n s.id === sessionQuery || s.id.startsWith(sessionQuery)\n );\n\n if (!session) {\n spinner.fail(`Session not found: ${sessionQuery}`);\n process.exit(1);\n }\n\n const encryption = resolveSessionEncryption(session.dataEncryptionKey, masterSecret);\n\n const content = {\n role: 'user',\n content: { type: 'text', text: message },\n meta: { sentFrom: 'cli' },\n };\n\n const encrypted = encryptToBase64(encryption, content);\n\n // Connect socket and send\n const socket = createSocketClient(serverURL, creds.token);\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n socket.disconnect();\n reject(new Error('Connection timeout'));\n }, 10000);\n\n socket.onConnect(() => {\n clearTimeout(timeout);\n socket.sendMessage(session.id, encrypted);\n // Give the message a moment to be sent\n setTimeout(() => {\n socket.disconnect();\n resolve();\n }, 500);\n });\n\n socket.connect();\n });\n\n spinner.succeed('Message sent.');\n}\n\nasync function resolveSessionId(query: string, daemonPort: number): Promise<string> {\n const resp = await fetch(`http://127.0.0.1:${daemonPort}/sessions`);\n const data = await resp.json() as { sessions: Array<{ id: string; name: string; path: string }> };\n\n // Try exact ID match\n const exact = data.sessions.find(s => s.id === query);\n if (exact) return exact.id;\n\n // Try prefix match\n const prefix = data.sessions.find(s => s.id.startsWith(query));\n if (prefix) return prefix.id;\n\n // Try name match (case-insensitive)\n const name = data.sessions.find(s =>\n s.name.toLowerCase().includes(query.toLowerCase()) ||\n s.path.toLowerCase().includes(query.toLowerCase())\n );\n if (name) return name.id;\n\n throw new Error(`Session not found: ${query}`);\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { decodeBase64 } from '../core/crypto/nacl.js';\nimport { resolveSessionEncryption, encryptToBase64 } from '../core/crypto/encryption.js';\nimport { fetchSessions } from '../core/api.js';\nimport { createSocketClient } from '../core/socket.js';\nimport { loadCredentials } from '../storage/credentials.js';\nimport { readDaemonState, isDaemonRunning } from '../daemon/state.js';\nimport { DEFAULT_SERVER_URL } from '../core/config.js';\nimport type { AgentState } from '../types/update.js';\n\nexport async function approveCommand(sessionQuery: string, opts: { decision?: string }) {\n const decision = opts.decision ?? 'approved';\n await handlePermission(sessionQuery, true, decision);\n}\n\nexport async function denyCommand(sessionQuery: string) {\n await handlePermission(sessionQuery, false, 'denied');\n}\n\nasync function handlePermission(sessionQuery: string, approved: boolean, decision: string) {\n const action = approved ? 'Approving' : 'Denying';\n const pastAction = approved ? 'approved' : 'denied';\n\n // Try daemon first\n if (await isDaemonRunning()) {\n const state = await readDaemonState();\n if (state) {\n try {\n const { sessionId, requestId } = await findPendingVia(sessionQuery, state.httpPort);\n const endpoint = approved ? 'approve-permission' : 'deny-permission';\n const body: Record<string, unknown> = { sessionId, requestId };\n if (approved) body.decision = decision;\n\n const resp = await fetch(`http://127.0.0.1:${state.httpPort}/${endpoint}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n const data = await resp.json() as { success: boolean; error?: string };\n if (data.success) {\n console.log(chalk.green(`Permission ${pastAction}.`));\n } else {\n console.error(chalk.red(`Failed: ${data.error}`));\n }\n return;\n } catch (err) {\n console.error(chalk.dim(`Daemon error: ${(err as Error).message}, falling back to direct API`));\n }\n }\n }\n\n // Direct approach\n const creds = await loadCredentials();\n if (!creds) {\n console.error(chalk.red('Not logged in. Run `codesail login` first.'));\n process.exit(1);\n }\n\n const spinner = ora(`${action} permission...`).start();\n const masterSecret = decodeBase64(creds.masterSecret);\n const serverURL = creds.serverURL ?? DEFAULT_SERVER_URL;\n\n const rawSessions = await fetchSessions(creds.token, serverURL);\n const session = rawSessions.find(s =>\n s.id === sessionQuery || s.id.startsWith(sessionQuery)\n );\n\n if (!session) {\n spinner.fail(`Session not found: ${sessionQuery}`);\n process.exit(1);\n }\n\n const encryption = resolveSessionEncryption(session.dataEncryptionKey, masterSecret);\n\n // Decrypt agent state to find pending request\n let agentState: AgentState | null = null;\n if (session.agentState) {\n try {\n const stateData = decodeBase64(session.agentState);\n const { decryptValue } = await import('../core/crypto/encryption.js');\n agentState = decryptValue(encryption, stateData) as AgentState;\n } catch { /* ignore */ }\n }\n\n if (!agentState?.requests || Object.keys(agentState.requests).length === 0) {\n spinner.fail('No pending permission requests for this session.');\n process.exit(1);\n }\n\n const [requestId, request] = Object.entries(agentState.requests)[0];\n spinner.text = `${action} \"${request.tool}\" request...`;\n\n const params = {\n id: requestId,\n approved,\n decision,\n };\n\n const encrypted = encryptToBase64(encryption, params);\n\n // Connect socket and send RPC\n const socket = createSocketClient(serverURL, creds.token);\n\n const result = await new Promise<Record<string, unknown>>((resolve, reject) => {\n const timeout = setTimeout(() => {\n socket.disconnect();\n reject(new Error('Connection timeout'));\n }, 15000);\n\n socket.onConnect(async () => {\n clearTimeout(timeout);\n try {\n const res = await socket.rpcCall(`${session.id}:permission`, encrypted);\n socket.disconnect();\n resolve(res);\n } catch (err) {\n socket.disconnect();\n reject(err);\n }\n });\n\n socket.connect();\n });\n\n spinner.succeed(`Permission ${pastAction} for \"${request.tool}\".`);\n}\n\nasync function findPendingVia(\n sessionQuery: string,\n daemonPort: number,\n): Promise<{ sessionId: string; requestId: string }> {\n const resp = await fetch(`http://127.0.0.1:${daemonPort}/sessions`);\n const data = await resp.json() as {\n sessions: Array<{\n id: string;\n name: string;\n path: string;\n hasPendingPermission: boolean;\n pendingRequests: Record<string, { tool: string }>;\n }>;\n };\n\n const session = data.sessions.find(s =>\n s.id === sessionQuery ||\n s.id.startsWith(sessionQuery) ||\n s.name.toLowerCase().includes(sessionQuery.toLowerCase()) ||\n s.path.toLowerCase().includes(sessionQuery.toLowerCase())\n );\n\n if (!session) throw new Error(`Session not found: ${sessionQuery}`);\n if (!session.hasPendingPermission) throw new Error('No pending permission requests');\n\n const requestId = Object.keys(session.pendingRequests)[0];\n return { sessionId: session.id, requestId };\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { createInterface } from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { encodeBase64, decodeBase64 } from '../core/crypto/nacl.js';\nimport { base32Encode, base32Decode, formatBase32 } from '../core/crypto/backup.js';\nimport { authenticate } from '../core/api.js';\nimport { loadCredentials, saveCredentials } from '../storage/credentials.js';\nimport { DEFAULT_SERVER_URL } from '../core/config.js';\n\nexport async function backupShowCommand() {\n const creds = await loadCredentials();\n if (!creds) {\n console.error(chalk.red('Not logged in. Run `codesail login` first.'));\n process.exit(1);\n }\n\n const masterSecret = decodeBase64(creds.masterSecret);\n const encoded = formatBase32(base32Encode(masterSecret));\n\n console.log(chalk.bold('\\nBackup Key:'));\n console.log(chalk.cyan(encoded));\n console.log(chalk.dim('\\nStore this key safely. It can restore your account on any device.'));\n}\n\nexport async function backupRestoreCommand(opts: { server?: string }) {\n const serverURL = opts.server ?? DEFAULT_SERVER_URL;\n\n const rl = createInterface({ input: stdin, output: stdout });\n const input = await rl.question(chalk.bold('Enter your backup key: '));\n rl.close();\n\n if (!input.trim()) {\n console.error(chalk.red('No key entered.'));\n process.exit(1);\n }\n\n const spinner = ora('Decoding backup key...').start();\n let masterSecret: Uint8Array;\n try {\n masterSecret = base32Decode(input.trim());\n if (masterSecret.length !== 32) {\n throw new Error(`Expected 32 bytes, got ${masterSecret.length}`);\n }\n spinner.succeed('Backup key decoded');\n } catch (err) {\n spinner.fail('Invalid backup key');\n console.error(chalk.red((err as Error).message));\n process.exit(1);\n }\n\n // Authenticate with the restored secret\n spinner.start('Authenticating...');\n try {\n const token = await authenticate(masterSecret, serverURL);\n await saveCredentials({\n token,\n masterSecret: encodeBase64(masterSecret),\n serverURL,\n });\n spinner.succeed('Account restored successfully');\n console.log(chalk.green('Credentials saved to ~/.codesail/credentials.json'));\n } catch (err) {\n spinner.fail('Authentication failed');\n console.error(chalk.red((err as Error).message));\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { loadConfig, setConfigValue } from '../storage/config.js';\n\nexport async function configSetCommand(key: string, value: string) {\n await setConfigValue(key, value);\n console.log(chalk.green(`Set ${key} = ${value}`));\n}\n\nexport async function configGetCommand(key: string) {\n const config = await loadConfig();\n const value = config[key];\n if (value === undefined) {\n console.log(chalk.dim(`${key} is not set`));\n } else {\n console.log(`${key} = ${value}`);\n }\n}\n\nexport async function configListCommand() {\n const config = await loadConfig();\n const entries = Object.entries(config);\n if (entries.length === 0) {\n console.log(chalk.dim('No config values set.'));\n return;\n }\n for (const [key, value] of entries) {\n console.log(`${key} = ${value}`);\n }\n}\n"],"mappings":"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","names":["resolve","chalk","ora","chalk","state","ora","resolve","chalk","ora","chalk","ora","chalk","ora","chalk","ora","resolve","chalk","ora","requestId","chalk","ora","decryptValue","resolve","chalk","ora","chalk","ora","chalk","chalk","config"]}
@@ -0,0 +1,14 @@
1
+ import {
2
+ isDaemonRunning,
3
+ readDaemonState,
4
+ removeDaemonState,
5
+ writeDaemonState
6
+ } from "./chunk-4OXDCPSF.js";
7
+ import "./chunk-HG54UP2Y.js";
8
+ export {
9
+ isDaemonRunning,
10
+ readDaemonState,
11
+ removeDaemonState,
12
+ writeDaemonState
13
+ };
14
+ //# sourceMappingURL=state-J732R3HC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "codesail",
3
+ "version": "0.1.0",
4
+ "description": "CLI for CodeSail — control Claude Code sessions from your terminal",
5
+ "type": "module",
6
+ "bin": {
7
+ "codesail": "./bin/codesail.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "scripts": {
11
+ "build": "tsup",
12
+ "dev": "tsx src/index.ts",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "dependencies": {
16
+ "chalk": "^5.3.0",
17
+ "commander": "^12.1.0",
18
+ "fastify": "^5.2.1",
19
+ "ora": "^8.1.1",
20
+ "qrcode-terminal": "^0.12.0",
21
+ "socket.io-client": "^4.8.1",
22
+ "tweetnacl": "^1.0.3",
23
+ "tweetnacl-util": "^0.15.1"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^22.10.0",
27
+ "@types/qrcode-terminal": "^0.12.2",
28
+ "tsup": "^8.3.5",
29
+ "tsx": "^4.19.2",
30
+ "typescript": "^5.7.2"
31
+ },
32
+ "engines": {
33
+ "node": ">=20.0.0"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "bin"
38
+ ],
39
+ "license": "MIT"
40
+ }