Call initUI() at the start of main() to ensure chalk is loaded
before any status messages. Previously, colors only worked when
an update notification was displayed because showUpdateNotification()
was the only place calling initUI().
Fixes#201
When CCS updates trigger CLIProxy config regeneration, user-added API
keys in ~/.ccs/cliproxy/config.yaml were being overwritten with only
the internal CCS key.
Changes:
- Add parseUserApiKeys() to extract user keys from existing config
- Modify regenerateConfig() to preserve user API keys alongside port
- Update generateUnifiedConfigContent() to accept userApiKeys param
- Add comprehensive test suite (14 tests) for key preservation
Fixes#200
Add three new Anthropic-compatible API providers as presets:
- Minimax: M2.1/M2.1-lightning/M2 models with 1M context
- DeepSeek: V3.2 and R1 reasoning model (128K context)
- Qwen: Alibaba Cloud qwen3-coder-plus (256K context)
Closes#123
- variant-settings.ts: Use expandPath() in deleteSettingsFile()
- profile-writer.ts: Use expandPath() in removeApiProfileUnified()
- migration-manager.ts: Remove local expandPath(), import from helpers
All path expansion now uses the central expandPath() from utils/helpers.ts
which handles ~, ~\, ${VAR}, $VAR, and %VAR% on all platforms.
- Check legacy config.json/profiles.json in isFirstTimeInstall()
- Use expandPath() for cross-platform path handling in profile-detector
- Add pre-flight API key validation for better error messages
- Enhance 401 error handling with Z.AI refresh guidance
Fixes#195
- Change default to noIncognito=true (normal browser) for reliability
- Always print OAuth URL to terminal for VS Code popup detection
- Move incognito toggle from Proxy settings to Kiro provider page
- Add --incognito flag to opt into incognito mode (was --no-incognito)
- Update help text to reflect new defaults
- Add "Kiro: Use normal browser" toggle in config dashboard (Proxy section)
- Add --no-incognito documentation to ccs --help output
- Show hint after successful Kiro auth about saving AWS credentials
Kiro OAuth always opens in incognito browser mode, which doesn't save
login credentials. Users need to re-enter email each authentication.
Changes:
- Add noIncognito option to OAuthOptions interface
- Add kiro_no_incognito config option to CLIProxyConfig
- Pass --no-incognito flag to CLIProxyAPI binary when enabled
- Support both CLI flag (--no-incognito) and config.yaml setting
Usage:
- CLI: ccs kiro --auth --no-incognito
- Config: cliproxy.kiro_no_incognito: true in config.yaml
Enables running multiple CLIProxy variants simultaneously on different
ports. Each variant now gets a unique port in the 18100-18199 range,
allowing concurrent use of providers like Gemini + Codex + custom variants.
Key changes:
- Add port field to variant config schema
- Implement automatic port allocation (18100 + variant index)
- Support variant-specific settings paths in config generator
- Display port in dashboard UI for debugging
- Show all models in variant editor dropdown
- Add comprehensive tests for port allocation edge cases
Closes related variant isolation work.
Device Code flows (Qwen, GHCP) may require interactive terminal input
before generating the device code. For example, Qwen prompts for email.
Previously, all auth processes used piped stdin which blocked user input.
Now Device Code flows use 'inherit' for stdin, allowing users to respond
to prompts directly in the terminal.
Authorization Code flows (Gemini, Codex) still use piped stdin for
programmatic project selection.
Closes#188
- Fix port default logic: HTTP→8317, HTTPS→443 (was always 8317)
- Fix enabled:false being ignored in proxy config resolution
- Update stale comments referencing HTTP:80 to HTTP:8317
- Add 9 unit tests for edge cases (enabled handling, port defaults)
When authenticating with GitHub Copilot using device code flow,
the user code was not being displayed. This fix:
- Parses device codes from CLIProxy output in oauth-process.ts
- Displays code prominently in CLI terminal with box formatting
- Broadcasts device code events via WebSocket for UI display
- Creates DeviceCodeDialog component for web UI (ccs config)
- Follows same pattern as Gemini project selection dialog
Closes#189
- setup-command.ts: Add Ctrl+C handling (UserCancelledError), port
validation (1-65535), protocol stripping from host, try-catch with
user-friendly error messages
- postinstall.js: Add ~/.ccs file check (not directory), wrap js-yaml
require in try-catch with JSON fallback, validate config.json before
migration, warn when both config files exist
- recovery-manager.ts: Verify config is loadable (not just exists),
add nested error handling for fallback write
- ccs.ts: Make first-time install hint independent of recovery status
(shows even when user manually created empty config.yaml)
All edge cases identified by code review addressed.
- Update postinstall.js to create config.yaml instead of config.json
- Update recovery-manager to create config.yaml as primary config
- Fix isFirstTimeInstall() to check for meaningful config content
(profiles, accounts, variants, oauth_accounts, remote proxy)
- Update validation to accept config.yaml OR config.json
- Preserve backward compatibility: legacy config.json is migrated
to config.yaml on first run via autoMigrate()
- Update postinstall tests to verify config.yaml creation
Fixes#142 - remote CLIProxyAPI configuration
- Add categorized error detection for socket, timeout, HTTP, and redirect errors
- Implement smarter exponential backoff (longer delays for socket errors)
- Increase max retries from 3 to 5 with dynamic timeout adjustment
- Add resource cleanup (disable connection pooling for clean process exit)
- Add user-friendly error messages for each error type
- Refactor fetchText/fetchJson with retry logic and proper error handling
- Set 120s timeout for large binary downloads, 15-30s for text/JSON
- Prevent double-resolution and race conditions in Promise handlers
Add Microsoft Azure AI Foundry as a provider preset for `ccs api create`.
Usage: `ccs api create --preset foundry`
This is a cleaner implementation than the postinstall-based approach,
leveraging the existing preset system.
Co-authored-by: MinhOmega <49482201+MinhOmega@users.noreply.github.com>
- rename base-copilot.settings.json to base-ghcp.settings.json
- add kiro and ghcp to variant adapter providers list
- update provider display names in config generator
- Change binaryName from CLIProxyAPI_ to CLIProxyAPIPlus_ prefix
- Update download URL to use CLIProxyAPIPlus repository
- Update checksums URL to use CLIProxyAPIPlus repository
- Change executable name from cli-proxy-api to cli-proxy-api-plus
- Update User-Agent header to CCS-CLIProxyPlus-Updater
- Update status messages to say "CLIProxy Plus"
Fixes HTTP 404 error when running `ccs cliproxy --latest`
- Update cliproxy-command.ts status output and install messages
- Update help-command.ts with Plus branding and new kiro/copilot providers
- Update doctor.ts header to show CLIPROXY PLUS
- Update cliproxy-check.ts binary check output
- Update proxy-status-widget.tsx label to CLIProxy Plus
- Point release URLs to CLIProxyAPIPlus repository
- Add base-kiro.settings.json with default Kiro models
- Add base-copilot.settings.json with default Copilot models
- Update config-generator for new provider sections
- Extend CLIProxyProvider type with kiro and copilot
- Add kiro (port 8329) and copilot (port 8330) to auth-types
- Implement OAuth flows in oauth-handler
- Update token-manager to include new providers
- Add new providers to CLIPROXY_PROFILES
- Update diagnostics and API routes for new providers
- Update GitHub repo URL to router-for-me/CLIProxyAPIPlus
- Handle new release naming pattern (v6.6.X-0 suffix)
- Add version comparison support for Plus releases
- Add try-catch to all route handlers in settings, variant, config routes
- Implement 5 missing endpoints in cliproxy-stats-routes:
- GET/PUT /config.yaml for YAML config management
- GET /auth-files to list auth directory files
- GET /auth-files/download for file download
- PUT /models/:provider to update model settings
- All handlers now return proper error messages on failure
- Add try-catch to cliproxy-auth-routes GET /
- Add try-catch to health-routes GET / and POST /fix/:checkId
- Add try-catch to config-routes GET /format and POST /migrate
- Improve error messages with specific context
- All handlers now return 500 with error message on failure
- Add /usage alias for /cliproxy/stats (frontend compatibility)
- Create account-routes.ts to fix /accounts/accounts double path
- Update index.ts to mount accountRoutes at /accounts
- Remove account code from profile-routes.ts
- Clean up unused imports in profile-routes.ts
getRemoteEnvVars was ignoring user settings and always loading
models from base config. Now follows same priority as local mode:
1. Custom settings path (variant configs)
2. User settings file (~/.ccs/{provider}.settings.json)
3. Base config defaults
This fixes the issue where selecting Opus 4.5 in UI resulted in
Gemini 3 preview being loaded when using remote proxy mode.
- Import loadOrCreateUnifiedConfig to access cliproxy_server settings
- Pass remote/local config to resolveProxyConfig() function
- Enables CLI to detect remote mode from user's config.yaml
- Add rewriteLocalhostUrls() to detect and rewrite localhost URLs
- Support 127.0.0.1, localhost, 0.0.0.0 patterns
- Update getEffectiveEnvVars() to accept remoteRewriteConfig param
- Auto-rewrite saved settings URLs to remote server at runtime
- Add key prop to ProfileEditor to force remount on profile change
- Reset editorHasChanges on discard confirmation
- Add text-white to destructive dialog button
- Change OpenRouter default model to claude-opus-4.5
- Add runtime API response validation in remote-auth-fetcher
- Add AbortController cleanup to prevent state updates after unmount
- Validate postMessage origin matches iframe src before sending creds
- Mask auth token display (show ***last4) for security
- Reset error/connected state on refresh
- Fix port default to use protocol-based (443 for https, 80 for http)
- Normalize path in buildProxyUrl to ensure leading slash
- Add fallback for undefined email (default to 'Unknown')
- Extract timeout constant (REMOTE_FETCH_TIMEOUT_MS)
- Remove unused RemoteAuthFilesResponse interface
- Refactor stats-fetcher.ts: 5 functions now use getProxyTarget()
- Add remote-auth-fetcher.ts: fetch auth status from remote /v0/management/auth-files
- Update cliproxy-auth-routes.ts: branch on isRemote for GET routes
- Return 501 for account management in remote mode (unsupported)