diff --git a/README.md b/README.md index b3125fb0..b4861825 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,15 @@ ccs cliproxy doctor # Check quota status for all agy accounts **Auto-Failover**: When an Antigravity account runs out of quota, CCS automatically switches to another account with remaining capacity. Shared GCP project accounts are excluded (pooled quota). +### CLIProxy Lifecycle + +```bash +ccs cliproxy start # Start CLIProxy background service +ccs cliproxy status # Check running status +ccs cliproxy restart # Restart CLIProxy service +ccs cliproxy stop # Stop running CLIProxy service +``` +
## Configuration diff --git a/package.json b/package.json index 4a73a123..74a1dbaa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "7.43.0-dev.15", + "version": "7.43.0-dev.17", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli", diff --git a/src/cliproxy/services/proxy-lifecycle-service.ts b/src/cliproxy/services/proxy-lifecycle-service.ts index 4c140262..2d1388f2 100644 --- a/src/cliproxy/services/proxy-lifecycle-service.ts +++ b/src/cliproxy/services/proxy-lifecycle-service.ts @@ -62,6 +62,16 @@ export async function startProxy( return ensureCliproxyService(port, verbose); } +/** + * Start CLIProxy service (or reuse existing running instance) + */ +export async function startProxy( + port: number = CLIPROXY_DEFAULT_PORT, + verbose: boolean = false +): Promise { + return ensureCliproxyService(port, verbose); +} + /** * Check if proxy is currently running */ diff --git a/src/commands/cliproxy/proxy-lifecycle-subcommand.ts b/src/commands/cliproxy/proxy-lifecycle-subcommand.ts index 1dad5b5a..f9b52cad 100644 --- a/src/commands/cliproxy/proxy-lifecycle-subcommand.ts +++ b/src/commands/cliproxy/proxy-lifecycle-subcommand.ts @@ -76,6 +76,57 @@ export async function handleRestart(verbose = false): Promise { console.log(''); } +export async function handleStart(verbose = false): Promise { + await initUI(); + console.log(header('Start CLIProxy')); + console.log(''); + + const result = await startProxy(CLIPROXY_DEFAULT_PORT, verbose); + if (result.started) { + if (result.alreadyRunning) { + console.log(info(`CLIProxy already running on port ${result.port}`)); + if (result.configRegenerated) { + console.log(warn('Config updated - restart CLIProxy to apply changes')); + } + } else { + console.log(ok(`CLIProxy started on port ${result.port}`)); + } + console.log(dim('To stop: ccs cliproxy stop')); + } else { + console.log(warn(result.error || 'Failed to start CLIProxy')); + } + console.log(''); +} + +export async function handleRestart(verbose = false): Promise { + await initUI(); + console.log(header('Restart CLIProxy')); + console.log(''); + + const stopResult = await stopProxy(); + if (stopResult.stopped) { + console.log(ok(`CLIProxy stopped (PID ${stopResult.pid})`)); + } else if (stopResult.error === 'No active CLIProxy session found') { + console.log(info('No active CLIProxy session found, starting a new instance')); + } else { + console.log(warn(stopResult.error || 'Failed to stop existing CLIProxy')); + console.log(info('Attempting to start a fresh instance...')); + } + + const startResult = await startProxy(CLIPROXY_DEFAULT_PORT, verbose); + if (startResult.started) { + if (startResult.alreadyRunning) { + console.log(info(`CLIProxy already running on port ${startResult.port}`)); + } else { + console.log(ok(`CLIProxy started on port ${startResult.port}`)); + } + } else { + console.log(warn(startResult.error || 'Failed to restart CLIProxy')); + } + + console.log(''); +} + export async function handleProxyStatus(): Promise { await initUI(); console.log(header('CLIProxy Status'));