Add cliproxy.backend config field to choose between CLIProxyAPI (original)
and CLIProxyAPIPlus backends. Includes CLI --backend flag, Dashboard toggle,
and provider validation to block Kiro/ghcp on original backend.
The previous test relied on client socket receiving close event from
server-side destroy, which is timing-dependent and flaky in CI.
New approach:
- Verify stop() behavior directly via getPort() returning null
- Test what we control (server state) not what we observe (client state)
- Remove timing-dependent assertions
- Faster and more reliable (83ms vs 1000ms+ timeout)
- Fix connection tracking test: wait for 'close' event instead of only
checking socket.destroyed (more reliable in CI environments)
- Increase timeout from 500ms to 1000ms for CI latency
- Add proper socket cleanup after test
- Merge dev changes: add projectId parameter to registerAccount()
- Add express-rate-limit to restore endpoint (5 req/min)
- Add JSDoc documentation to RestoreMutex class
- Extract magic numbers to named constants in BackupsSection
- Add unit tests for persist-routes.ts (23 tests)
- Add unit tests for BackupsSection component (28 tests)
Addresses PR #339 code review feedback.
- Fix timeout test to use HTTPS server (tunnel uses https.request)
- Fix timeout event handling - call reject directly instead of relying on destroy error event
- Fix misleading comment in remote-token-uploader (Authorization header, not X-Management-Key)
- Remove unused imports in test files
Built [OnSteroids](https://onsteroids.ai)
Co-Authored-By: OnSteroids <built@onsteroids.ai>
* feat(cliproxy): add HTTPS tunnel for remote proxy mode
Claude Code doesn't support HTTPS in ANTHROPIC_BASE_URL directly (undici
limitation). This adds an HTTP→HTTPS tunnel proxy for remote CLIProxyAPI
connections.
Changes:
- Add HttpsTunnelProxy: local HTTP server tunneling to remote HTTPS
- Add CodexReasoningProxy HTTPS support and path prefix stripping
- Remote mode now uses root paths (/v1/messages) not provider-prefixed
- Add remote token uploader for syncing OAuth tokens to remote server
- Auto-upload tokens after OAuth auth when remote mode is enabled
Flow for remote HTTPS:
Claude CLI → CodexReasoningProxy → HttpsTunnel → Remote HTTPS
Built with [OnSteroids](https://onsteroids.ai)
Co-Authored-By: OnSteroids <built@onsteroids.ai>
* fix: address PR review issues for HTTPS tunnel proxy
- Add connection tracking with activeConnections Set for proper cleanup
- Add port validation after start() to reject port 0
- Add Authorization header fallback injection in buildForwardHeaders()
- Handle client disconnect (premature close) and request errors
- Improve error handling in uploadTokenToRemoteAsync (log instead of silent catch)
- Add comprehensive tests for HttpsTunnelProxy (97% coverage)
- Add integration tests for remote-token-uploader
- Add stripPathPrefix unit tests for remote mode
Built with [OnSteroids](https://onsteroids.ai)
Co-Authored-By: OnSteroids <built@onsteroids.ai>
* fix: bump Node.js engine requirement to >=18.0.0
FormData and Blob APIs used in remote-token-uploader require Node.js 18+.
Addresses coderabbit review comment about Node.js engine compatibility.
Built [OnSteroids](https://onsteroids.ai)
Co-Authored-By: OnSteroids <built@onsteroids.ai>
* fix: address remaining PR suggestions
- Add verbose parameter to registerAccountFromToken for proper propagation
- Improve stripPathPrefix with path normalization (double slashes, leading slash)
- Add edge case tests for path normalization
Built [OnSteroids](https://onsteroids.ai)
Co-Authored-By: OnSteroids <built@onsteroids.ai>
* fix: add timeout to flaky npm CLI tests
Tests 'handles empty arguments gracefully' and 'handles very long argument'
were missing timeout option in execSync, causing occasional timeouts when
bun test's 5000ms limit was reached before CLI completed.
Built [OnSteroids](https://onsteroids.ai)
Co-Authored-By: OnSteroids <built@onsteroids.ai>
* fix: address new PR review feedback
- Add path segment boundary check to prevent partial matches (/codex vs /codextra)
- Add hostname validation in HttpsTunnelProxy constructor
- Add race condition protection with 'starting' flag in start()
- Sanitize error messages (detailed only in verbose mode)
- Update comments for clarity (regex behavior)
- Add comprehensive tests for all edge cases
Built [OnSteroids](https://onsteroids.ai)
Co-Authored-By: OnSteroids <built@onsteroids.ai>
---------
Co-authored-by: OnSteroids <built@onsteroids.ai>
Add backup management functionality to the persist command:
- List available backups with timestamps and dates
- Restore from most recent or specific backup
- Improved error handling for corrupted settings.json
- Updated CLAUDE.md to document the persist command and the exception to the non-invasive constraint
- test budget bounds and constants
- test off/auto/level values handling
- test budget-type and level-type models
- test edge cases and unknown models
Refs #307
- Fix path traversal in trace() via safe dir validation
- Add RFC 7230 hop-by-hop header filtering
- Fix isRecord() to exclude arrays
- Add req.destroy() on oversized body rejection
- Add missing ANTHROPIC_BASE_URL warning for Codex
- Use cwd() fallback when HOME undefined
- Add 4 edge case unit tests
Kiro/GHCP OAuth tokens have empty email field, causing all accounts to
use accountId='default' and overwrite each other. This fix:
- Add PROVIDERS_WITHOUT_EMAIL constant for kiro/ghcp identification
- Require nickname for kiro/ghcp during registration (CLI + web UI)
- Use nickname as accountId instead of email for these providers
- Enforce nickname uniqueness to prevent collisions
- Update discoverExistingAccounts() to generate unique IDs (kiro-1, etc.)
Closes#258, #267
- Test kiro/ghcp provider type mapping
- Test email extraction from filename fallback
- Test multiple accounts per provider
- Test edge cases (invalid JSON, missing type, unknown provider)
- Export validatePort() from config-generator with full edge case handling
- Add YAML port validation in proxy-config-resolver before use
- Add final port validation in cliproxy-executor after config merge
- Add default port parameter and validation to proxy-detector
- Add 38 new tests covering all port validation edge cases
Fixes undefined port bug when upgrading from 7.11.1 to 7.12.0
* fix(cliproxy): pass variant port to executor for isolation
Variants configured with dedicated ports (8318-8417) were not using
their assigned port. The executor always defaulted to 8317.
Changes:
- Add port field to ProfileDetectionResult interface
- Pass variant.port from profile-detector to ccs.ts
- Forward port to execClaudeWithCLIProxy options
- Update executor priority: CLI flags > variant port > config.yaml > default
Closes#228
* fix(cliproxy): propagate port in unified config and UI preset handlers
Edge case fixes identified in codebase review:
- Unified config variant detection: add settingsPath and port fields
- Provider editor: use variant port in handleApplyPreset/handleCustomPresetApply
- preset-utils: add optional port parameter to applyDefaultPreset()
* chore(release): 7.11.1-dev.1 [skip ci]
* fix(cliproxy): use correct default port (8317) for remote HTTP connections
Root cause: Inconsistent default port logic across code paths.
- Test Connection used 8317 (correct)
- Actual API calls used 80 (wrong)
Changes:
- Add centralized getRemoteDefaultPort() helper in config-generator.ts
- Fix proxy-target-resolver.ts to use shared helper
- Fix rewriteLocalhostUrls() and getRemoteEnvVars() in config-generator.ts
- Update remote-proxy-client.ts to use shared helper (DRY)
Fixes all 3 reported issues:
1. Port empty → now correctly uses :8317 instead of :80
2. BASEURL construction → now includes correct port
3. CLIProxy Plus auth → now fetches from remote on correct port
* chore(release): 7.11.1-dev.2 [skip ci]
* feat(delegation): add Claude Code CLI flag passthrough
Add explicit passthrough support for key Claude Code CLI flags:
- --max-turns: Limit agentic turns (prevents infinite loops)
- --fallback-model: Auto-fallback when model overloaded
- --agents: Dynamic subagent JSON injection
- --betas: Enable experimental features
Maintain extraArgs catch-all for future Claude Code flags.
Update help command with new "Delegation Flags" section.
Closes#89
* test(delegation): add comprehensive CLI flag passthrough tests
Add 45 test cases covering all edge cases for CLI flag passthrough:
- DelegationHandler: timeout/max-turns/fallback-model/agents/betas validation
- HeadlessExecutor: duplicate flag filtering, undefined vs truthy checks
* chore(release): 7.11.1-dev.3 [skip ci]
* fix(ui): enable cancel button during OAuth authentication
Resolves#234 - Cancel button was disabled during authentication flow,
preventing users from canceling the OAuth process.
Changes:
- Add auth-session-manager.ts for tracking active OAuth sessions
- Add POST /cliproxy/auth/:provider/cancel endpoint to abort sessions
- Kill spawned CLIProxy auth process when cancel is triggered
- Enable Cancel button in AddAccountDialog during authentication
- Add cancel support to QuickSetupWizard auth step
- Update useCancelAuth hook to call backend cancel endpoint
* chore(release): 7.11.1-dev.4 [skip ci]
* fix(prompt): add stdin.pause() to prevent process hang after password input
Fixes#236. The password() method called resume() on stdin but never
paused it in cleanup, keeping the event loop alive indefinitely.
* chore(release): 7.11.1-dev.5 [skip ci]
* feat(cliproxy): add --allow-self-signed flag for HTTPS connections (#227)
Previously, allowSelfSigned was hardcoded to true for all HTTPS protocol
connections, forcing use of the native https module which has issues with
Cloudflare-proxied connections causing timeouts.
This change:
- Adds --allow-self-signed CLI flag (default: false)
- Adds CCS_ALLOW_SELF_SIGNED environment variable
- Uses standard fetch API by default for HTTPS (works with valid certs)
- Only uses native https module when --allow-self-signed is specified
Usage:
- For production HTTPS proxies with valid certs: no flag needed
- For dev proxies with self-signed certs: use --allow-self-signed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* chore(release): 7.11.1-dev.6 [skip ci]
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Shun Kakinoki <39187513+shunkakinoki@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Update tests to use renamed function after refactoring getConfigPath
to getCliproxyConfigPath in cliproxy/config-generator.ts
Files updated:
- tests/unit/cliproxy/config-generator-port.test.js
- tests/unit/cliproxy/config-generator.test.js
Add comprehensive test suite mapping to PR #184 test plan:
- Create multiple variants with unique ports (8318-8417)
- Verify port persistence in config and separate config-{port}.yaml
- Run multiple variants concurrently with isolated sessions
- Verify list shows port column for each variant
- Remove variant cleans config, session, and port-specific files
25 new tests covering edge cases:
- Port exhaustion (100 variant max)
- Port reuse after deletion
- Legacy variants without port field
- Stale session cleanup for dead PIDs
- Default port special handling (sessions.json)
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
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.
- 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)
- dev versions (X.Y.Z-dev.N) now treated as newer than base release (X.Y.Z)
- reflects convention that dev work is AFTER the release, not before
- update GH Actions message to use 'ccs update --dev' instead of npm install
- update tests to match new semantic
- Add DNS_FAILED and NETWORK_UNREACHABLE error codes
- Map "fetch failed" errors to NETWORK_UNREACHABLE for better UX
- Extract nested error cause for more accurate error detection
- Improve error messages with actionable hints
Fixes#142
CLIProxyAPI doesn't expose a /health endpoint, causing 404 errors
when testing remote proxy connections. Changed to use /v1/models
which is always available and returns 200 when operational.
Fixes#142
Fixes tag-agnostic cache issue causing 'ccs update --dev' to require
force. Implements tag-specific caching (dev_version vs latest_version)
to correctly detect updates across channels. Disables duplicate bot
comments on dev releases in .releaserc.cjs.
Dashboard Stop/Update buttons failed with contradictory errors:
- Stop: "No active CLIProxy session found"
- Update: "CLIProxy was already running"
Root cause: service-manager spawned proxy but never called registerSession(),
so stopProxy() couldn't find the lock file.
Changes:
- service-manager.ts: Add registerSession() after spawn
- session-tracker.ts: Make stopProxy() async with port-based fallback
- routes.ts: Update proxy-stop endpoint to async
- cliproxy-command.ts: Update handleStop() to await async stopProxy()
- port-utils.ts: Fix double-escaped regex for Windows port detection
- session-tracker.test.js: Update tests for async stopProxy()
Add comprehensive unit tests for CLIProxy proxy lifecycle:
- Status command logic: session lock exists/not, uptime formatting
- Stop command logic: stale lock cleanup, active proxy stop
- Command routing: stop/status subcommands, unknown handling
Tests cover the CLI handlers for the new proxy persistence feature.
Add unit tests for the new session tracker functions:
- stopProxy: error handling, stale lock cleanup, success structure
- getProxyStatus: not running, full status, dead proxy cleanup, session count
- Removed MAX_THINKING_TOKENS (8191) limit for Claude models via agy.
- Updated default agy haiku model to gemini-3-flash-preview.
- Updated unit tests to match new model expectations.
Add session tracking with reference counting for CLIProxy instances.
Multiple CCS sessions now safely share a single proxy on port 8317.
When any session exits, proxy only terminates if it was the last session.
Changes:
- Add session-tracker.ts: lock file based reference counting
- Modify cliproxy-executor.ts: reuse existing proxy, conditional cleanup
- Add 21 unit tests for session tracker functionality
Fixes#118
Relaxed isUnifiedConfig() type guard to accept version >= 1 and partial
configs. Added mergeWithDefaults() to preserve user data while filling
missing sections. Fixes profile "not found" after terminal restart.
Closes#82
- Remove deprecated flag from Claude Opus 4.5 Thinking and Sonnet 4.5 Thinking
- Reorder models with thinking models at top (Opus → Sonnet Thinking → Sonnet → Gemini)
- Change default model to gemini-claude-opus-4-5-thinking
- Update tests to reflect new ordering and non-deprecated status
Deprecated 2 Claude thinking models:
- gemini-claude-opus-4-5-thinking
- gemini-claude-sonnet-4-5-thinking
These models have compatibility issues with Antigravity.
A new deprecation system was added with badges and warnings in the UI.
- Add `ccs cliproxy create/list/remove` commands for variant management
- Interactive wizard with provider/model selection from catalog
- Settings file auto-generated with all 6 ANTHROPIC_* env fields
- Fix `ccs api create` to include all 4 model fields (was missing 3)
- Fix `--config` flag to save to correct variant settings file
- Remove paid tier badge from AGY models (all free via Antigravity)
- Add settings file format example to README for CLIProxy variants
- Add 22 unit tests for cliproxy command validation and config handling