- require model when changing single-variant provider to avoid mixed config
- rewrite provider-specific core env when provider changes while preserving custom fields
- preserve custom composite settings path and return persisted composite PUT state
- P1: Remove premature variant deletion in --force mode
Fix destructive overwrite path - old variant preserved if user
cancels auth or creation fails (createVariant handles overwrite)
- P2: Validate all composite tier providers at runtime
Backend gating now checks all providers in composite, not just
default tier. Prevents kiro/ghcp on non-default tiers bypassing
Plus backend requirement.
- P2: Preserve tier thinking when default tier is off
Early return skipped tier processing when default thinking was
"off". Now uses flag-based approach - only main model skipped,
tier loop continues with per-tier thinking config.
- Route all `ccs cursor *` to handleCursorCommand (no profile-switching)
- Add --ccs-daemon marker to spawned process for stable PID validation
- Use random port in lifecycle integration test to prevent CI conflicts
- Remove unnecessary .toFixed(1) on integer tokenAge
- Validate PID belongs to cursor daemon via /proc before signaling
- Tighten detectProvider regex to avoid over-matching o-prefixed models
- Add integration test for daemon start→health→stop lifecycle
- Add void cast on discarded handleHelp() return value
- Update model catalog date comment
- Export detectProvider and formatModelName from barrel index
- Export CURSOR_SUBCOMMANDS from cursor-command.ts, import in ccs.ts
- Use getCcsDir() in tests instead of manual path construction
- Add handleCursorCommand routing test for unknown subcommand
MEDIUM fixes:
- Kill orphaned process when health check times out after 30s
- Prevents zombie processes from consuming resources
LOW fixes:
- Return exit code 1 for unknown cursor subcommands (was 0)
- Simplify exit handler dead code branch (else if code !== null → else)
- Add handleEdit() interactive wizard for modifying existing variants
- Add updateCompositeVariant() to variant-service for partial tier updates
- Route 'edit' subcommand in cliproxy index
- Update help text with edit command documentation
- Export updateCompositeVariant from services index
- Add --composite flag to 'ccs cliproxy variant create'
- Implement selectTierConfig() interactive prompt per tier
- Add default tier selection after all tiers configured
- Display composite label in auth list and variant remove
- Show per-tier details in remove confirmation
- Update help text with --composite usage
Refs #506
- Wire cursor command into main router (ccs.ts) following copilot pattern
- Centralize default port (4242) and model (gpt-4.1) as constants
- Remove duplicate types already in cursor-protobuf-schema from dev
- Handle daemon exit code 0 before health check succeeds
- Export PID helpers and model utils for testability
- Add unit tests for cursor-daemon (PID file ops, isDaemonRunning)
- Add unit tests for cursor-models (detectProvider, formatModelName, defaults)
- 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
* fix(version): show active config path instead of deprecated config.json
The version command was using deprecated getConfigPath() which always
returned config.json path. Now uses getActiveConfigPath() which shows
config.yaml in unified mode or config.json in legacy mode.
* chore(release): 7.37.1-dev.1 [skip ci]
* fix(ui): use native dynamic import to fix Node 24 ESM/CJS interop
TypeScript compiles import() to require() when targeting CommonJS,
which breaks ESM packages like ora on Node 24. Use new Function()
to create native dynamic import at runtime, bypassing TS transform.
Closes#472
* chore(release): 7.37.1-dev.2 [skip ci]
* fix(env): strip ANTHROPIC_* from account/default profiles
Account and default profiles inherit process.env which may contain
stale ANTHROPIC_BASE_URL from prior CLIProxy sessions. This causes
ConnectionRefused errors when Claude tries to hit an unavailable proxy.
Settings-based profiles already handle this by explicitly injecting
their own ANTHROPIC_* values. This fix applies the same protection
to account/default profiles by stripping ANTHROPIC_* before spawn.
Closes#474
* test(env): add unit tests for stripAnthropicEnv
Address code review feedback from PR #475. Tests cover:
- Removing all ANTHROPIC_* keys
- Preserving non-ANTHROPIC keys
- Empty object handling
- Undefined value preservation
- Case sensitivity (only uppercase ANTHROPIC_)
- All ANTHROPIC_ prefixed variants stripped
* chore(release): 7.37.1-dev.3 [skip ci]
* feat(cliproxy): add extended context support for 1M token window
Add --1m and --no-1m flags to enable/disable 1M token context window.
Uses Claude Code's [1m] suffix mechanism.
Behavior:
- Gemini models: auto-enabled by default
- Claude models: opt-in with --1m flag
- New extendedContext field in model catalog
Also adds Claude Opus 4.6 to model catalog with extended context support.
Closes#103
* feat(ui): add extended context toggle in dashboard model config
- Add ExtendedContextToggle component for 1M token context window
- Add Claude Opus 4.6 (claude-opus-4-6-20260203) to model catalogs
- Mark Gemini and Claude models with extendedContext: true
- Toggle only appears when selected model supports extended context
- Auto-enabled info for native Gemini, opt-in info for Claude
Part of extended context feature implementation for issue #103.
* fix: address code review findings and CI failure
- Fix CI error: add missing 'provider' prop to ModelConfigSection
- Fix case sensitivity in applyExtendedContextSuffix
- Fix whitespace handling in stripModelSuffixes
- Handle --1m=value and --no-1m=value CLI patterns
- Add warning when --1m used on unsupported model
- Sync agy catalog: add extendedContext to gemini-3-pro-preview
- Extract isNativeGeminiModel to shared utility (DRY)
- Add 21 unit tests for extended-context-config
* fix(catalog): rename claude-opus-4-6-20260203 to claude-opus-4-6
* fix(ui): wire extended context toggle through component tree
- Add extendedContextEnabled and toggleExtendedContext to useProviderEditor hook
- Store setting as CCS_EXTENDED_CONTEXT env var in provider settings
- Pass props through provider-editor → model-config-tab → model-config-section
- Update UseProviderEditorReturn type with new properties
* fix(ui): apply [1m] suffix directly to model strings in settings
- Toggle now applies/strips [1m] suffix to all ANTHROPIC_*MODEL env vars
- Extended context detected by checking if any model has [1m] suffix
- Remove legacy CCS_EXTENDED_CONTEXT flag approach
- Add suffix utilities: applyExtendedContextSuffix, stripExtendedContextSuffix
- Raw Configuration now shows actual model values with [1m] suffix
* fix(qwen): update model catalog with correct context windows and tier mappings
- Update context window specs from official Alibaba docs:
- Qwen3 Coder Plus: 1M context (was 32K)
- Qwen3 Max: 256K context (flagship)
- Qwen3 Coder Flash: fast code generation
- Fix preset mappings for Claude tier equivalence:
- Opus → qwen3-max (flagship 256K)
- Sonnet → qwen3-coder-plus (balanced 1M)
- Haiku → qwen3-coder-flash (fast)
- Update provider descriptions to reflect 256K-1M context range
- Add all 7 Qwen models from CLIProxyAPI: qwen3-coder-plus, qwen3-max,
qwen3-max-preview, qwen3-235b, qwen3-vl-plus, qwen3-coder-flash, qwen3-32b
Closes#478
* fix(ui): only apply [1m] suffix to ANTHROPIC_MODEL, fix toggle refresh
- Only ANTHROPIC_MODEL gets [1m] suffix, not tier mappings
- Strip [1m] when looking up model in catalog to prevent toggle disappearing
- Fix odd page refresh when toggling extended context
* chore(release): 7.37.1-dev.4 [skip ci]
* fix(ui): remove duplicate import in use-provider-editor
* chore: address PR review feedback - sync comment and unused import
* chore(release): 7.37.1-dev.5 [skip ci]
* feat(cliproxy): add Opus 4.6 to Antigravity model catalog (#482)
* feat(cliproxy): add Opus 4.6 to Antigravity model catalog
- Add gemini-claude-opus-4-6-thinking as new default agy model
- Update preset mappings to route opus tier to Opus 4.6
- Bump CLIProxy fallback versions to v6.8.2
- Keep Opus 4.5 as previous flagship option
* fix(cliproxy): include oauth-model-alias in config generation
Root cause: CLIProxy config.yaml was missing Opus 4.6 alias because:
1. CLIProxyPlus startup migration is disabled (intentional)
2. CCS config generator never wrote oauth-model-alias section
3. Existing users with outdated aliases got 502 on Opus 4.6
Fix:
- Add DEFAULT_ANTIGRAVITY_ALIASES to config generator
- Generate oauth-model-alias section in config.yaml template
- Preserve claude-api-key and custom aliases during regeneration
- Bump config version to v6 to trigger auto-regeneration
- Update model catalog tests for new model count
* fix(cliproxy): preserve YAML indentation in extractYamlSection
- Replace .trim() with regex to strip only leading/trailing newlines,
preserving 2-space indent on claude-api-key children
- Skip standalone comments at col 0 in section boundary detection
- Update stale test description (4 → 5 models)
* chore(release): 7.37.1-dev.6 [skip ci]
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- Add promptOAuthModeChoice() for headless OAuth mode selection
- Add --port-forward flag to force port-forwarding mode
- Add conflict detection for --paste-callback + --port-forward
- Handle edge cases: Ctrl+C, invalid input, non-TTY stdin
- Update help docs with new flag
Closes#461
On Windows, bun's global binary symlink may not update properly when
reinstalling the same package. Pre-remove the existing installation
to ensure a clean update, mirroring the dev-install.sh behavior.
Closes#435
Address review feedback:
- Add line-buffering to handle chunk splitting edge case
- Add 14 unit tests for stderr filter logic
- Test chunk boundary handling, mixed output, edge cases
Handles case where "npm warn cleanup" could be split across chunks.