import * as fs from 'fs'; import * as path from 'path'; import { initUI, box, color, dim, sectionHeader, subheader } from '../utils/ui'; import { isUnifiedMode } from '../config/unified-config-loader'; import { getCcsDir, getCcsDirSource } from '../utils/config-manager'; import { CLIPROXY_DEFAULT_PORT } from '../cliproxy/config/port-manager'; // Get version from package.json (same as version-command.ts) const VERSION = JSON.parse( fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf8') ).version; /** * Print a major section with ═══ borders (only for 3 main sections) * Format: * ═══ TITLE ═══ * Subtitle line 1 * Subtitle line 2 * * command Description */ function printMajorSection(title: string, subtitles: string[], items: [string, string][]): void { // Section header with ═══ borders console.log(sectionHeader(title)); // Subtitles on separate lines (dim) for (const subtitle of subtitles) { console.log(` ${dim(subtitle)}`); } // Empty line before items console.log(''); // Calculate max command length for alignment const maxCmdLen = Math.max(...items.map(([cmd]) => cmd.length)); for (const [cmd, desc] of items) { const paddedCmd = cmd.padEnd(maxCmdLen + 2); console.log(` ${color(paddedCmd, 'command')} ${desc}`); } // Extra spacing after section console.log(''); } /** * Print a sub-section with colored title * Format: * Title (context): * command Description */ function printSubSection(title: string, items: [string, string][]): void { // Sub-section header (colored, no borders) console.log(subheader(`${title}:`)); // Calculate max command length for alignment const maxCmdLen = Math.max(...items.map(([cmd]) => cmd.length)); for (const [cmd, desc] of items) { const paddedCmd = cmd.padEnd(maxCmdLen + 2); console.log(` ${color(paddedCmd, 'command')} ${desc}`); } // Spacing after section console.log(''); } /** * Print a config/paths section * Format: * Title: * Label: path */ function printConfigSection(title: string, items: [string, string][]): void { console.log(subheader(`${title}:`)); // Calculate max label length for alignment const maxLabelLen = Math.max(...items.map(([label]) => label.length)); for (const [label, path] of items) { const paddedLabel = label.padEnd(maxLabelLen); console.log(` ${paddedLabel} ${color(path, 'path')}`); } console.log(''); } /** * Display comprehensive help information for CCS (Claude Code Switch) */ export async function handleHelpCommand(): Promise { // Initialize UI (if not already) await initUI(); // Hero box with ASCII art logo and config hint // Each letter: C=╔═╗/║ /╚═╝, C=╔═╗/║ /╚═╝, S=╔═╗/╚═╗/╚═╝ const logo = ` ╔═╗ ╔═╗ ╔═╗ ║ ║ ╚═╗ v${VERSION} ╚═╝ ╚═╝ ╚═╝ Claude Code Profile & Model Switcher Run ${color('ccs config', 'command')} for web dashboard`.trim(); console.log( box(logo, { padding: 1, borderStyle: 'round', titleAlignment: 'center', }) ); console.log(''); // Resolve display path for dynamic sections const [dirSource] = getCcsDirSource(); const dirDisplay = dirSource === 'default' ? '~/.ccs' : getCcsDir(); // Usage section console.log(subheader('Usage:')); console.log(` ${color('ccs', 'command')} [profile] [claude-args...]`); console.log(` ${color('ccs', 'command')} [flags]`); console.log(''); // ═══════════════════════════════════════════════════════════════════════════ // MAJOR SECTION 1: API Key Profiles // ═══════════════════════════════════════════════════════════════════════════ printMajorSection( 'API Key Profiles', [`Configure in ${dirDisplay}/*.settings.json`], [ ['ccs', 'Use default Claude account'], ['ccs glm', 'GLM 5 (API key required)'], ['ccs glmt', 'GLM with thinking mode'], ['ccs km', 'Kimi for Coding (API key)'], ['ccs ollama', 'Local Ollama (http://localhost:11434)'], ['ccs ollama-cloud', 'Ollama Cloud (API key required)'], ['', ''], // Spacer ['ccs api create', 'Create custom API profile'], ['ccs api remove', 'Remove an API profile'], ['ccs api list', 'List all API profiles'], ] ); // ═══════════════════════════════════════════════════════════════════════════ // MAJOR SECTION 2: Account Management // ═══════════════════════════════════════════════════════════════════════════ printMajorSection( 'Account Management', ['Run multiple Claude accounts concurrently'], [ ['ccs auth --help', 'Show account management commands'], ['ccs auth create ', 'Create new account profile'], ['ccs auth list', 'List all account profiles'], ['ccs auth default ', 'Set default profile'], ['ccs auth reset-default', 'Restore original CCS default'], ] ); // ═══════════════════════════════════════════════════════════════════════════ // MAJOR SECTION 3: CLI Proxy (OAuth Providers) // ═══════════════════════════════════════════════════════════════════════════ printMajorSection( 'CLI Proxy Plus (OAuth Providers)', [ 'Zero-config OAuth authentication via CLIProxy Plus', 'First run: Browser opens for authentication, then model selection', 'Settings: ~/.ccs/{provider}.settings.json (created after auth)', ], [ ['ccs gemini', 'Google Gemini (gemini-2.5-pro or 3-pro)'], ['ccs codex', 'OpenAI Codex (supports -medium/-high/-xhigh model suffixes)'], ['ccs agy', 'Antigravity (Claude/Gemini models)'], ['ccs qwen', 'Qwen Code (qwen3-coder)'], ['ccs kimi', 'Kimi (Moonshot AI K2/K2.5 models)'], ['ccs kiro', 'Kiro (AWS CodeWhisperer Claude models)'], ['ccs ghcp', 'GitHub Copilot (OAuth via CLIProxy Plus)'], ['', ''], // Spacer ['ccs --auth', 'Authenticate only'], ['ccs --auth --add', 'Add another account'], [ 'ccs --paste-callback', 'Show auth URL and prompt for callback paste (cross-browser)', ], ['ccs --accounts', 'List all accounts'], ['ccs --use ', 'Switch to account'], ['ccs --config', 'Change model (agy, gemini)'], [ 'ccs --thinking ', 'Set thinking budget (low/medium/high/xhigh/auto/off or number)', ], ['ccs codex --effort ', 'Set codex reasoning effort (medium/high/xhigh)'], ['ccs --1m', 'Enable 1M token context window'], ['ccs --no-1m', 'Disable 1M context (use 200K default)'], ['ccs --logout', 'Clear authentication'], ['ccs --headless', 'Headless auth (for SSH)'], ['ccs --port-forward', 'Force port-forwarding mode (skip prompt)'], ['ccs kiro --auth --kiro-auth-method aws', 'Kiro via AWS Builder ID (device code)'], ['ccs kiro --auth --kiro-auth-method aws-authcode', 'Kiro via AWS auth code flow'], ['ccs kiro --auth --kiro-auth-method google', 'Kiro via Google OAuth'], ['ccs kiro --auth --kiro-auth-method github', 'Kiro via GitHub OAuth (Dashboard flow)'], ['ccs kiro --import', 'Import token from Kiro IDE'], ['ccs kiro --incognito', 'Use incognito browser (default: normal)'], ['ccs codex "explain code"', 'Use with prompt'], ] ); // ═══════════════════════════════════════════════════════════════════════════ // MAJOR SECTION 4: GitHub Copilot Integration (copilot-api) // ═══════════════════════════════════════════════════════════════════════════ printMajorSection( 'GitHub Copilot Integration (copilot-api)', [ 'Use your GitHub Copilot subscription with Claude Code via copilot-api', 'Requires: npm install -g copilot-api', 'Note: For OAuth-based access, use ccs ghcp instead', ], [ ['ccs copilot', 'Use Copilot via copilot-api daemon'], ['ccs copilot auth', 'Authenticate with GitHub'], ['ccs copilot status', 'Show integration status'], ['ccs copilot models', 'List available models'], ['ccs copilot usage', 'Show Copilot quota usage'], ['ccs copilot start', 'Start copilot-api daemon'], ['ccs copilot stop', 'Stop copilot-api daemon'], ['ccs copilot enable', 'Enable integration'], ['ccs copilot disable', 'Disable integration'], ] ); // ═══════════════════════════════════════════════════════════════════════════ // MAJOR SECTION 5: Cursor IDE Integration // ═══════════════════════════════════════════════════════════════════════════ printMajorSection( 'Cursor IDE Integration', [ 'Use Cursor IDE with Claude Code via cursor proxy daemon', 'Auto-detects token from Cursor installation', ], [ ['ccs cursor ', 'Use Cursor IDE integration'], ['ccs cursor auth', 'Import Cursor token'], ['ccs cursor auth --manual --token --machine-id ', 'Manual token import'], ['ccs cursor status', 'Show connection status'], ['ccs cursor models', 'List available models'], ['ccs cursor start', 'Start proxy daemon'], ['ccs cursor stop', 'Stop proxy daemon'], ['ccs cursor enable', 'Enable cursor integration'], ['ccs cursor disable', 'Disable cursor integration'], ] ); // ═══════════════════════════════════════════════════════════════════════════ // SUB-SECTIONS (simpler styling) // ═══════════════════════════════════════════════════════════════════════════ // Delegation printSubSection('Delegation (inside Claude Code CLI)', [ ['/ccs "task"', 'Delegate task (auto-selects profile)'], ['/ccs --glm "task"', 'Force GLM-5 for simple tasks'], ['/ccs --kimi "task"', 'Force Kimi OAuth for long context'], ['/ccs --km "task"', 'Force Kimi API key for long context'], ['/ccs:continue "follow-up"', 'Continue last delegation session'], ]); // Delegation CLI Flags (Claude Code passthrough) printSubSection('Delegation Flags (Claude Code passthrough)', [ ['--max-turns ', 'Limit agentic turns (prevents loops)'], ['--fallback-model ', 'Auto-fallback on overload (sonnet)'], ['--agents ', 'Inject dynamic subagents'], ['--betas ', 'Enable experimental features'], ['--allowedTools ', 'Restrict available tools'], ['--disallowedTools ', 'Block specific tools'], ]); // Diagnostics printSubSection('Diagnostics', [ ['ccs setup', 'First-time setup wizard'], ['ccs doctor', 'Run health check and diagnostics'], ['ccs cleanup', 'Remove old CLIProxy logs'], ['ccs config', 'Open web configuration dashboard'], ['ccs config auth setup', 'Configure dashboard login'], ['ccs config auth show', 'Show dashboard auth status'], ['ccs config image-analysis', 'Show image analysis settings'], ['ccs config image-analysis --enable', 'Enable image analysis'], ['ccs config thinking', 'Show thinking/reasoning settings'], ['ccs config thinking --mode auto', 'Set thinking mode'], ['ccs config thinking --clear-provider-override codex', 'Clear provider overrides'], ['ccs config --port 3000', 'Use specific port'], ['ccs persist ', 'Write profile env to ~/.claude/settings.json'], ['ccs persist --list-backups', 'List available settings.json backups'], ['ccs persist --restore', 'Restore settings.json from latest backup'], ['ccs sync', 'Sync delegation commands and skills'], ['ccs update', 'Update CCS to latest version'], ['ccs update --force', 'Force reinstall current version'], ['ccs update --beta', 'Install from dev channel (unstable)'], ]); // Environment export printSubSection('Environment Export', [ ['ccs env ', 'Export env vars for third-party tools'], ['ccs env --format openai', 'OpenAI-compatible vars (OpenCode/Cursor)'], ['ccs env --format anthropic', 'Anthropic vars (default)'], ['ccs env --format raw', 'All effective env vars'], ['ccs env --shell fish', 'Fish shell syntax'], ]); // Flags printSubSection('Flags', [ ['--config-dir ', 'Use custom CCS config directory'], ['--target ', 'Target CLI: claude (default), droid'], ['-h, --help', 'Show this help message'], ['-v, --version', 'Show version and installation info'], ['-sc, --shell-completion', 'Install shell auto-completion'], ]); // Aliases printSubSection('Aliases', [ ['ccsd [args]', 'Shorthand for: ccs --target droid'], ]); // Multi-target examples printSubSection('Multi-Target', [ ['ccs glm --target droid', 'Run GLM profile on Droid CLI'], ['ccsd glm', 'Same as above (alias)'], ['ccs glm', 'Run GLM profile on Claude Code (default)'], ]); // Configuration printConfigSection('Configuration', [ ['Config File:', isUnifiedMode() ? `${dirDisplay}/config.yaml` : `${dirDisplay}/config.json`], ['Profiles:', `${dirDisplay}/profiles.json`], ['Instances:', `${dirDisplay}/instances/`], ['Settings:', `${dirDisplay}/*.settings.json`], ]); // CLI Proxy management printSubSection('CLI Proxy Plus Management', [ ['ccs cliproxy', 'Show CLIProxy Plus status and version'], ['ccs cliproxy --help', 'Full CLIProxy Plus management help'], ['ccs cliproxy doctor', 'Quota diagnostics (Antigravity)'], ['ccs cliproxy --install ', 'Install specific version (e.g., 6.6.6)'], ['ccs cliproxy --latest', 'Update to latest version'], ['', ''], // Spacer ['ccs cliproxy pause

', 'Pause account from rotation'], ['ccs cliproxy resume

', 'Resume paused account'], ['ccs cliproxy status [provider]', 'Show quota/tier/pause status'], ]); // CLI Proxy configuration flags (new) printSubSection('CLI Proxy Configuration', [ ['--proxy-host ', 'Remote proxy hostname/IP'], ['--proxy-port ', `Proxy port (default: ${CLIPROXY_DEFAULT_PORT})`], ['--proxy-protocol ', 'Protocol: http or https (default: http)'], ['--proxy-auth-token ', 'Auth token for remote proxy'], ['--proxy-timeout ', 'Connection timeout in ms (default: 2000)'], ['--local-proxy', 'Force local mode, ignore remote config'], ['--remote-only', 'Fail if remote unreachable (no fallback)'], ['--allow-self-signed', 'Allow self-signed certs (for dev proxies)'], ]); // W3: Thinking Budget explanation printSubSection('Extended Thinking / Reasoning', [ ['--thinking off', 'Disable extended thinking'], ['--thinking auto', 'Let model decide dynamically'], ['--thinking low', '1K tokens - Quick responses'], ['--thinking medium', '8K tokens - Standard analysis'], ['--thinking high', '24K tokens - Deep reasoning'], ['--thinking xhigh', '32K tokens - Maximum depth'], ['--thinking ', 'Custom token budget (512-100000)'], ['', ''], ['--effort ', 'Codex alias for reasoning effort (medium/high/xhigh)'], ['--effort xhigh', 'Pin Codex effort to xhigh for this run'], ['', ''], ['Note:', 'Extended thinking allocates compute for step-by-step reasoning'], ['', 'before responding.'], ['', 'Providers: agy/gemini use --thinking, codex uses --effort (or --thinking alias).'], ['', 'Codex model suffixes also pin effort: -medium / -high / -xhigh.'], ]); // Extended Context (1M) printSubSection('Extended Context (--1m)', [ ['--1m', 'Enable 1M token context window'], ['--no-1m', 'Disable 1M context (use 200K default)'], ['', ''], ['Auto behavior:', 'Gemini models: auto-enabled by default'], ['', 'Claude models: opt-in with --1m flag'], ['', ''], ['Note:', 'Extended context enables 1M token window via [1m] suffix.'], ['', 'Premium pricing: 2x input for >200K tokens.'], ]); // Image Analysis printSubSection('Image Analysis (CLIProxy vision)', [ ['ccs config image-analysis', 'Show current settings'], ['ccs config image-analysis --enable', 'Enable for CLIProxy providers'], ['ccs config image-analysis --disable', 'Disable (use native Read)'], ['ccs config image-analysis --timeout 120', 'Set analysis timeout'], ['ccs config image-analysis --set-model

', 'Set provider model'], ['', ''], ['Note:', 'When enabled, images/PDFs are analyzed via vision models'], ['', 'instead of passing raw data to Claude. Works with CLIProxy'], ['', 'providers (agy, gemini, codex, kiro, ghcp).'], ]); // CCS Environment Variables printSubSection('Environment Variables', [ ['CCS_DIR', 'Override CCS config directory (default: ~/.ccs)'], ['CCS_HOME', 'Override home directory (legacy, appends .ccs)'], ['CCS_DEBUG', 'Enable debug logging'], ['CCS_THINKING', 'Override thinking level (flag > env > config)'], ]); // CLI Proxy env vars printSubSection('CLI Proxy Environment Variables', [ ['CCS_PROXY_HOST', 'Remote proxy hostname'], ['CCS_PROXY_PORT', 'Proxy port'], ['CCS_PROXY_PROTOCOL', 'Protocol (http/https)'], ['CCS_PROXY_AUTH_TOKEN', 'Auth token'], ['CCS_PROXY_TIMEOUT', 'Connection timeout in ms'], ['CCS_PROXY_FALLBACK_ENABLED', 'Enable local fallback (1/0)'], ['CCS_ALLOW_SELF_SIGNED', 'Allow self-signed certs (1/0)'], ]); // CLI Proxy paths console.log(subheader('CLI Proxy:')); console.log(` Binary: ${color(`${dirDisplay}/cliproxy/bin/cli-proxy-api-plus`, 'path')}`); console.log(` Config: ${color(`${dirDisplay}/cliproxy/config.yaml`, 'path')}`); console.log(` Auth: ${color(`${dirDisplay}/cliproxy/auth/`, 'path')}`); console.log(` ${dim(`Port: ${CLIPROXY_DEFAULT_PORT} (default)`)}`); console.log(''); // Shared Data console.log(subheader('Shared Data:')); console.log(` Commands: ${color(`${dirDisplay}/shared/commands/`, 'path')}`); console.log(` Skills: ${color(`${dirDisplay}/shared/skills/`, 'path')}`); console.log(` Agents: ${color(`${dirDisplay}/shared/agents/`, 'path')}`); console.log(` ${dim('Note: Symlinked across all profiles')}`); console.log(''); // Examples (aligned with consistent spacing) console.log(subheader('Examples:')); console.log(` $ ${color('ccs', 'command')} ${dim('# Use default account')}`); console.log( ` $ ${color('ccs gemini', 'command')} ${dim('# OAuth (browser opens first time)')}` ); console.log(` $ ${color('ccs glm "implement API"', 'command')} ${dim('# API key model')}`); console.log(` $ ${color('ccs config', 'command')} ${dim('# Open web dashboard')}`); console.log(''); // Update examples console.log(subheader('Update:')); console.log( ` $ ${color('ccs update', 'command')} ${dim('# Update to latest stable')}` ); console.log( ` $ ${color('ccs update --force', 'command')} ${dim('# Force reinstall current')}` ); console.log(` $ ${color('ccs update --beta', 'command')} ${dim('# Install dev channel')}`); console.log(''); // Docs link console.log(` ${dim('Docs: https://github.com/kaitranntt/ccs')}`); console.log(''); // Uninstall console.log(subheader('Uninstall:')); console.log(` ${color('npm uninstall -g @kaitranntt/ccs', 'command')}`); console.log(''); // License console.log(dim('License: MIT')); console.log(''); process.exit(0); }