- Fix bitwise shift overflow in generateChecksum: use Math.trunc
division for >>40/>>32 which wrap modulo 32 in JS
- Add FIXED64/FIXED32 bounds checks in protobuf decoder to prevent
out-of-bounds slice on truncated buffers
- Consolidate COMPRESS_FLAG to single definition in schema (DRY):
executor now imports from schema, added GZIP_ALT/GZIP_BOTH values
- Fix token split edge case: use indexOf+slice instead of split('::')[1]
to handle tokens containing multiple :: delimiters
- Fix AbortSignal listener leak: store handler ref, use once:true,
remove listener on request end/error
CRITICAL FIX:
- CursorCredentials interface now matches types.ts (machineId, ghostMode as top-level)
- Fixes runtime error when cursor-auth saves credentials and cursor-executor reads them
HIGH:
- Replace 18+ non-null assertions with guard clauses across executor and decoder
- Prefix unused params in translator (_model, _stream, _credentials)
- HTTP/2 client closes on connection error to prevent leak
- AbortSignal listener leak documented with TODO (inline arrow prevents cleanup)
MEDIUM:
- Export concatArrays from encoder, remove duplicate from protobuf.ts
- Varint decoder now enforces 5-byte max to prevent overflow
- Buffer slice bounds check prevents out-of-range read
- Empty messages array validation with explicit error
- Buffered streaming limitation documented with TODO comment
All edge cases from code review now addressed.
- Split protobuf into 3 files: schema, encoder, decoder for <200 LOC constraint
- Implement ConnectRPC wire format encoding (varint, fields, messages, frames)
- Implement protobuf decoder with gzip decompression support
- Port Cursor executor with HTTP/2 support and checksum generation (Jyh cipher)
- Add OpenAI to Cursor message translator (system→user, tool results handling)
- Transform protobuf responses to both SSE and JSON formats
- Use Node.js built-in crypto/zlib (no uuid dependency)
- All files TypeScript strict mode compliant
* fix(hooks): isolate image type check before error-prone processing
Restructure processHook() into two phases so non-image Read calls
never see hook error messages. Phase 1 defensively checks tool name
and file extension, exiting 0 silently on any failure. Phase 2 only
runs for confirmed image/PDF files where errors are relevant.
Closes#511
* fix(hooks): sync image analyzer hook file on every profile launch
Add installImageAnalyzerHook() call to cliproxy executor, matching
the existing installWebSearchHook() pattern. This ensures the .cjs
file in ~/.ccs/hooks/ gets refreshed from the npm package on every
launch, so users receive hook updates after npm update.
* fix(cliproxy): migrate deprecated gemini-claude-* model names to upstream claude-* names
CLIProxyAPI registry no longer recognizes the gemini-claude-* prefix convention.
Model names in catalog, base config, and user settings are migrated to upstream
claude-* names. Auto-migration in env-builder rewrites existing user settings on
load and persists the change.
Closes#513
* fix: address code review feedback — sync UI layer and add migration tests
- Sync UI isNativeGeminiModel() with backend (remove gemini-claude- exclusion)
- Update UI model catalog agy entries from gemini-claude-* to claude-*
- Update CI/CD workflow and code-reviewer default model names
- Add unit tests for migrateDeprecatedModelNames() logic
- Extract shared _resolveCcsDir() to prevent getCcsDir/getCcsDirSource divergence
- Replace all hardcoded ~/.ccs/ and ~/.claude/ in recovery-manager.ts with
dynamic paths from instance properties (ccsDir, claudeDir, sharedDir, etc.)
- Add cloud sync detection for CCS_HOME env var (parity with CCS_DIR/--config-dir)
- Cache getSessionSecretPath() in local var in auth-middleware.ts
- Cache getCacheDir() in local var in disk-cache.ts ensureCacheDir()
- Replace hardcoded ~/.ccs in error messages: ccs.ts (lines 83, 151)
and delegation-handler.ts (line 333) now use getCcsDir()
- Cache repeated getter calls in local vars for readability:
openrouter-catalog.ts getCachedModels/setCachedModels,
aggregator.ts getInstancePaths
- Add path.resolve() for CCS_HOME env var consistency with CCS_DIR
- Convert 4 module-level constants to lazy-evaluated functions to avoid
import-time caching: openrouter-catalog, aggregator, disk-cache, auth-middleware
- Fix symlink-checks.ts to use ccsDir parameter instead of homedir/.ccs,
remove unused homedir parameter from checkSettingsSymlinks()
- Replace TOCTOU existsSync+statSync with single statSync in try/catch
for --config-dir validation in ccs.ts
- Switch detectCloudSyncPath from substring to path-segment-boundary matching
to prevent false positives (e.g., megauser != MEGA, Dropbox-api != Dropbox)
- Add test for false-positive protection
- Return {} instead of null for valid-but-empty settings profiles
- Consolidate VALID_SHELLS and validShellInputs into VALID_SHELL_INPUTS
- Fix docs test count 33 → 34
- Add profile name completions to fish env subcommand
- Add iflow, kiro, ghcp, claude to zsh proxy_profiles and PS1 cliproxyProfiles
- Distinguish non-API profile type error from "profile not found"
Allow users to relocate the entire ~/.ccs/ directory via CCS_DIR env var
or --config-dir CLI flag. Precedence: --config-dir > CCS_DIR > CCS_HOME > default.
Includes cloud sync path detection warning and doctor diagnostics.
Closes#507
- Add iflow, kiro, ghcp, claude to bash completion env block
- Add --shell flag validation matching --format pattern
- Add backtick injection test case
- P1: Fix bash completion $cliproxy_profiles scoping — inline profiles
in env block since variable is only defined at COMP_CWORD=1 scope
- P2: Detect account-based profiles and show specific error message
instead of generic "not found"
- P2: Show `ccs migrate` hint when unified mode is disabled and settings
profile resolution fails
- P2: transformToOpenAI omits empty entries at transform time instead of
relying on output filter (removes fragile coupling)
- P3: Add zsh and auto to --shell completions across all 4 shells; map
--shell zsh to bash in command handler since syntax is identical
- P3: Auto-detect PowerShell from SHELL containing pwsh on non-Windows
- Tests: 33 pass (+1 pwsh detection test, updated transform assertions)
- Fix P0: fish single-quote escaping uses '\'' (end-quote, literal, reopen)
instead of \' which fish doesn't support inside single-quoted strings
- Fix P0: profile arg parsing now skips flag values via findProfile() so
`ccs env --format openai gemini` correctly resolves to 'gemini'
- Add OPENAI_MODEL mapping from ANTHROPIC_MODEL in transformToOpenAI
- Add stderr warning when invalid env var keys are silently dropped
- Update --shell help text to mention zsh compatibility
- Add findProfile tests (6) and OPENAI_MODEL omission test
- Add settings profiles to zsh env completion (was proxy-only)
- Document intentional ANTHROPIC_MODEL omission in transformToOpenAI
- Use getCcsDir() in error hint instead of hardcoded ~/.ccs/
- Export parseFlag and add 5 unit tests for flag parsing
- Add fish and PowerShell single-quote escaping tests
- Validate env var keys match ^[A-Za-z_][A-Za-z0-9_]*$ before output
to prevent injection via crafted config files
- Add env command to all 4 shell completion scripts (bash, zsh, fish,
PowerShell) with sub-completions for --format and --shell flags
Switch formatExportLine from double quotes to single quotes to prevent
shell metacharacter expansion ($(), backticks, etc.) when output is
consumed via eval. Also fix parseFlag to handle values containing =,
remove unused test imports, and add empty-output guard after format
transformation.
New `ccs env <profile>` command exports shell-evaluable environment
variables for OpenCode, Cursor, Continue, and other third-party tools.
Supports --format (openai|anthropic|raw) and --shell (auto|bash|fish|
powershell) flags. Auto-detects shell from $SHELL env var.
Closes#503
- Add 7 test cases covering SIGTERM/SIGKILL escalation, timer cleanup,
default and custom grace periods, and already-exited process edge case
- Add timer.unref() to prevent keeping event loop alive during shutdown
- Add comment explaining 10s grace period in headless-executor timeout
- Move killWithEscalation to src/utils/process-utils.ts (DRY)
- Fix handleCancel to use exitCode === null and killWithEscalation
- Fix import ordering in both oauth-process.ts and headless-executor.ts
- Replace `!proc.killed` with `proc.exitCode === null` in headless-executor
- Extract `killWithEscalation` helper for SIGTERM→SIGKILL escalation
- Fixes pre-existing dead code where SIGKILL was never sent
- Escalate SIGTERM to SIGKILL after 3s if Go binary is stuck in blocking HTTP call
- Extend timeout to 300s for device code flows matching CLIProxy binary polling window
- Apply SIGKILL escalation to both SIGINT cleanup and timeout handlers
Closes#314
Replace permissive JSON Schema Draft-07 whitelist with strict
Gemini-compatible field set (22 fields). The "examples" field
in Claude Code tool schemas caused 400 errors from Gemini API.
Also strips other unsupported fields: $ref, $defs, oneOf, allOf,
additionalProperties, const, if/then/else, etc.
Safe change — sanitizer only runs for CLIProxy profiles (Gemini,
Codex, Antigravity), never for direct Anthropic API requests.
Closes#155
Consolidate 5 duplicate boolean tracking variables into a lifecycle
object with an update() method, reducing event detection from 4
locations to centralized calls. Add pause/drain/resume backpressure
to the passthrough path to prevent unbounded memory buffering with
slow clients.