- remove removeHookConfig() call from uninstallWebSearchHook()
- add removeMigrationMarker() cleanup
- update postuninstall.js to only clean CCS files
- global ~/.claude/settings.json is never touched
* feat(ci): add AI code review workflow with Claude via CLIProxyAPI
- Self-hosted runner calls CLIProxyAPI at localhost:8317
- Triggers on PR open/update and /review comment
- Uses gemini-claude-opus-4-5-thinking for deep reviews
- Posts summary + inline comments via gh CLI
- Handles self-PR fallback to COMMENT mode
* chore(release): 7.15.0-dev.1 [skip ci]
* refactor(ci): use GitHub App for reviewer identity + new review format
- Posts as ccs-agy-reviewer[bot] via GitHub App token
- New review format: structured markdown with verdict, summary, issues table
- Single PR comment instead of inline comments
- Concise, focused on PR changes only
* chore(release): 7.15.0-dev.2 [skip ci]
* refactor(ci): switch to Claude Code CLI for reviews
- Use claude -p instead of custom TypeScript script
- Auto-install if not present on runner
- CLIProxyAPI via env vars (ANTHROPIC_BASE_URL, ANTHROPIC_MODEL)
- Allowed tools: Read, Glob, Grep
- Max 3 turns for file exploration
* chore(release): 7.15.0-dev.3 [skip ci]
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Add dev:symlink and dev:unlink scripts to enable seamless testing of
development changes using the global 'ccs' command without needing to
pack/install globally each time.
- scripts/dev-symlink.sh: New script that safely creates symlinks from
global ccs to dev dist/ccs.js with backup/restore functionality
- package.json: Added dev:symlink and dev:unlink npm scripts
- CONTRIBUTING.md: Updated development setup documentation with
symlink workflow option
This improves developer experience by allowing immediate testing of
changes with 'ccs <command>' instead of './dist/ccs.js <command>'.
- 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
- dev-release.sh: save release notes to .dev-release-info.json
- send-discord-release.cjs: read from generated file for dev releases
- add .dev-release-info.json to .gitignore
Replaces semantic-release for dev branch with custom script that:
- Bases dev versions on current stable (e.g., 6.7.1-dev.N)
- Increments only the dev number, not the base version
- Keeps GitHub releases, issue tagging, Discord notifications
Bun's `add -g` with file: protocol appends instead of replacing existing
entries, causing duplicate key warnings on repeated installs. Fix by
removing the package before re-adding.
- Add split-view provider editor with model mapping UI and JSON editor
- Implement persistent custom presets (save/load per provider)
- Add provider logos with white backgrounds for light/dark theme
- Integrate CLIProxyAPI control panel embed via iframe
- Add service manager for CLIProxyAPI lifecycle control
- Support variant logo display using parent provider
- Add categorized model selector with search and groups
- Disable subject-case rule in commitlint to allow capital letters in commit subjects
- Add clean-dist.js script to preserve UI bundle during TypeScript builds
- Update package.json prebuild script to use new clean-dist.js
- Settings editor with API key masking and conflict detection
- Health dashboard with status cards and one-click fixes
- Home dashboard with stats and quick actions
- Shared data viewer for commands/skills/agents
- Build scripts for UI + server bundle
- Bundle size verification (<500KB gzipped)
- Pre-release checklist script
- Styled cliproxy help output with UI primitives and added status hint
- Added cliproxy --help reference to main help command
- Updated bash, zsh, fish, and PowerShell completions with:
- Missing commands (api, cliproxy)
- CLIProxy OAuth profiles (gemini, codex, agy, qwen)
- Provider flags and update command flags
- Update base-kimi.settings.json with model fields
- Update install.sh KIMI_MODEL variable
- Update postinstall.js template and migration to add model fields
- Migration now adds model fields instead of removing them (v5.5.0)
When upgrading from older CCS versions, ~/.ccs/shared/* directories may
exist as broken symlinks (dangling symlinks pointing to deleted targets).
Problem:
- fs.existsSync() returns false for broken symlinks
- fs.mkdirSync() fails with ENOENT because path exists as broken symlink
Solution:
- Added removeIfBrokenSymlink() helper that detects and removes dangling
symlinks using lstatSync (doesn't follow symlinks) + statSync (follows)
- Applied to shared directory and all subdirectories before mkdir
Fixes npm install error: ENOENT: no such file or directory, mkdir
Update CI/CD configuration, documentation, and scripts to use dev as the
primary integration branch instead of beta. Changes include GitHub Actions
workflow triggers, semantic-release configuration, and all relevant
documentation and helper scripts.
Issue #37: When running `ccs` (default profile), users were unknowingly
using GLM API instead of their Claude subscription because:
1. config.json had `default: '~/.claude/settings.json'` entry
2. ProfileDetector treated this as settings-based profile
3. CCS passed `--settings ~/.claude/settings.json` flag to Claude
4. Any stale ANTHROPIC_* env vars in that file got applied
Fix (3-pronged approach):
- Remove `default` entry from new config.json template
- Add migration to remove existing `default: ~/.claude/settings.json`
- Add ProfileDetector safety net: if default points to ~/.claude/settings.json,
treat as pass-through to Claude's native auth (no --settings flag)
Now `ccs` (no profile) correctly uses Claude's native OAuth authentication
without loading potentially polluted env vars from previous sessions.
Closes#37
- Simplify test files by removing custom TestRunner class
- Use standard Node.js assert module across all unit tests
- Update CLAUDE.md with streamlined development instructions
- Update tests/README.md with current testing approach
- Reduce boilerplate in delegation and GLMT test suites (652 lines removed)
- Remove lib/ccs and lib/ccs.ps1 version updates (now bootstraps)
- Update comments explaining v4.5.0+ architecture
- Use ASCII markers [OK]/[X]/[!] instead of emojis
- Update next steps to reflect new file list
Problem: Test suite was directly modifying user's personal ~/.ccs/
directory, causing configuration interference during development.
Solution:
- Add test-environment.js fixture with CCS_HOME env var support
- Update postinstall.js to respect CCS_HOME for test isolation
- Update config-manager.ts with getCcsHome() helper
- Update postinstall.test.js and cli.test.js to use isolated env
- Remove auto-install of .claude/ symlinks from postinstall
(users can run "ccs sync" to opt-in)
Benefits:
- Tests run in temp directories, no user config affected
- Users control when .claude/ items are installed via "ccs sync"
- All 39 tests passing with proper isolation
Phase 05: Migrate test imports from bin/ to dist/
- Update 19 test files to import from dist/ instead of bin/
- Update CLI path in cli.test.js and special-commands.test.js
- Update cross-platform.test.js to check dist/ directory
Phase 06: Cleanup & validation
- Remove bin/ directory (32 JS files)
- Fix ClaudeSymlinkManager import in doctor.ts
- Update postinstall.js to use dist/ modules
- Regenerate package-lock.json (now points to dist/ccs.js)
All 39 tests passing. TypeScript migration complete.
* feat(shared): add plugin support to shared directories
Add Claude Code plugins to the .ccs/shared/ symlink architecture,
enabling plugin sharing across all CCS profiles (GLM, GLMT, Kimi, etc).
Changes:
- SharedManager: Add 'plugins' to sharedDirs array
- Help text: Update all three implementations (Node.js, bash, PowerShell)
- Postinstall: Create ~/.ccs/shared/plugins/ directory on install
Architecture:
~/.claude/plugins/ <- ~/.ccs/shared/plugins/ <- instance/plugins/
This follows the existing pattern for commands/skills/agents and
maintains cross-platform compatibility with Windows fallback support.
* chore: bump version to 4.3.6
* docs: update CHANGELOG for v4.3.6
* feat(completion): improve fish shell completion with category prefixes
- Remove problematic inline set_color commands that prevented descriptions from displaying
- Add [cmd], [model], and [account] prefixes to visually group completions
- Update file header to document categorization features
This brings fish completion quality closer to zsh by making categories
clear and ensuring descriptions actually display to users.
Fixes issue where fish completions showed no descriptions.
* chore: bump version to 4.3.1
Add comprehensive update functionality with intelligent notification system.
Supports manual update checking, automatic notifications every 24h, and works
across npm and direct installations with proper error handling.
Closes#12
* feat: add -sc short flag for --shell-completion
Add -sc as a short flag alias for --shell-completion,
matching the pattern of -h for --help and -v for --version.
Changes:
- bin/ccs.js: Add -sc support in help text and flag detection
- lib/ccs: Add -sc support in help text and flag detection
- lib/ccs.ps1: Add -sc support in help text and flag detection
* chore: bump version to 4.1.4
* chore: bump version to 4.1.5
* feat: emphasize concurrent account usage in auth help text
Update all auth-related help messages to emphasize the ability
to run multiple Claude accounts concurrently.
Changes:
- bin/ccs.js: "Run multiple Claude accounts concurrently"
- bin/auth/auth-commands.js: "CCS Concurrent Account Management"
- lib/ccs: Updated both main help and auth_help function
- lib/ccs.ps1: Updated both main help and Show-AuthHelp function
* feat: implement ccs update command across all platforms
Add cross-platform ccs update command to sync delegation commands
and skills from ~/.ccs/.claude/ to ~/.claude/. Replaces vague
"CCS items" wording with specific "delegation commands and skills".
Changes:
- bin/ccs.js: Add update command handler and update help text
- bin/utils/claude-symlink-manager.js: Update user-facing messages
- lib/ccs: Implement update_run() function with symlink logic
- lib/ccs.ps1: Implement Update-Run function with Junction/SymbolicLink support
Features:
- Automatically backs up existing files before symlinking
- Skips items that are already correctly symlinked
- Reports installed vs up-to-date counts
- Handles Windows permissions gracefully (suggests Admin/Developer Mode)
Cross-platform parity: bash, PowerShell, and Node.js now all support ccs update
* refactor: rename ccs update to ccs sync for clarity
Rename the update command to sync across all platforms to avoid
confusion with updating the CCS tool itself. The sync command
clearly communicates syncing delegation features from the CCS
package to ~/.claude/.
Changes:
- bin/ccs.js: Rename handleUpdateCommand → handleSyncCommand
- bin/utils/claude-symlink-manager.js: Rename update() → sync()
- lib/ccs: Rename update_run() → sync_run()
- lib/ccs.ps1: Rename Update-Run → Sync-Run
- All: Update help text "update" → "sync"
- All: Update messages "Updating" → "Syncing"
Command usage: ccs sync or ccs --sync
* fix: update GitHub documentation links to stable permalink
Update broken #usage anchor links to stable /blob/main/README.md
permalink format. This matches the format already used in PowerShell
version and ensures links always work.
Changes:
- bin/ccs.js: Update link from #usage to /blob/main/README.md
- lib/ccs: Update link from #usage to /blob/main/README.md
- Now consistent with lib/ccs.ps1 which already used this format
Old: https://github.com/kaitranntt/ccs#usage
New: https://github.com/kaitranntt/ccs/blob/main/README.md
* feat: add sync command and -sc flag to shell completions
Update all shell completion scripts to include the newly added
sync command and -sc short flag for --shell-completion.
Changes across all completion scripts (bash, zsh, fish, PowerShell):
- Add 'sync' command to completion suggestions
- Add '-sc' as short flag for '--shell-completion'
- Update fish to handle both -sc and --shell-completion for subflags
- Update PowerShell to recognize -sc for shell completion flags
- Add sync command description: "Sync delegation commands and skills"
This ensures tab completion discovers the sync command and users
can use both -sc and --shell-completion interchangeably.
* fix: standardize help text across all implementations
Fix inconsistencies in help text that appeared after merge from main.
Ensures all three implementations (bash, PowerShell, Node.js) display
identical help messages.
Changes:
- lib/ccs: Update "Delegation (Token Optimization)" → "Delegation (inside Claude Code CLI)"
- lib/ccs: Remove redundant /ccs:create line, simplify description
- lib/ccs.ps1: Add missing Delegation section
- All: Now use consistent messaging about delegation features
This ensures users see the same information regardless of which
platform they're using (Linux/macOS bash, Windows PowerShell, or npm).
* fix: update description text to emphasize concurrent sessions
Update outdated description in lib/ccs and lib/ccs.ps1 to match
the improved wording already in bin/ccs.js. The new description
better emphasizes running concurrent Claude CLI sessions.
Changes:
- lib/ccs: Update description to emphasize "Run different Claude CLI sessions concurrently"
- lib/ccs.ps1: Update description to match bash and Node.js versions
- Remove "(work, personal, team)" examples to keep description cleaner
- Emphasize "Run different Claude CLI sessions concurrently" over vague "Concurrent sessions"
Old: "Switch between multiple Claude accounts (work, personal, team) and
alternative models (GLM, Kimi) instantly. Concurrent sessions with
auto-recovery. Zero downtime."
New: "Switch between multiple Claude accounts and alternative models
(GLM, Kimi) instantly. Run different Claude CLI sessions concurrently
with auto-recovery. Zero downtime."
All three implementations now show identical, clearer description text.
* feat(cli): enhance version display formatting and delegation status
---------
* fix(shell-completion): resolve ENOTDIR error when parent path is a file
Fixes issue where `--shell-completion` fails with ENOTDIR error when
a file exists where a directory should be created (e.g., ~/.zsh exists
as a file instead of a directory).
Changes:
- Added ensureDirectory() helper that safely creates directories
- Validates parent paths are directories, not files
- Provides clear error message when file conflicts occur
- Applied to all shell installers (bash, zsh, fish, powershell)
- Maintains idempotent behavior (safe to call multiple times)
Before: mkdir with recursive:true fails silently with ENOTDIR
After: Clear error message guides user to resolve file conflict
* chore: bump version to 4.1.4
* feat(completion): improve UI/UX with descriptions and grouping
Improves shell completion UI/UX across all shells (bash, zsh, fish,
PowerShell) with better organization and clearer descriptions.
Changes:
- Zsh: Added descriptions for all profiles and grouped by category
- Commands: "auth", "doctor" with descriptions
- Model profiles: glm, glmt, kimi, etc. with descriptions
- Account profiles: Dynamic with "Account-based profile" label
- Used _alternative for visual grouping
- Fish: Added explicit completions with descriptions for known profiles
- Replaced generic profile listing with specific entries
- Each profile now shows clear description (e.g., "GLM-4.6 (cost-optimized)")
- Bash: Added --shell-completion flag and subflags completion
- PowerShell: Added --shell-completion flag and subflags completion
- All shells: Added completion for --shell-completion subflags
Before (zsh):
ccs
auth -- Manage multiple Claude accounts
doctor -- Run health check and diagnostics
default glm glmt kimi max
After (zsh):
commands
auth -- Manage multiple Claude accounts
doctor -- Run health check and diagnostics
model profiles
default -- Default Claude Sonnet 4.5
glm -- GLM-4.6 (cost-optimized)
glmt -- GLM-4.6 with thinking mode
kimi -- Kimi for Coding (long-context)
max -- Claude Opus (maximum capability)
account profiles
work -- Account-based profile
personal -- Account-based profile
Consistent, organized, and informative completion across all shells.
* fix(completion): handle custom profiles and fix zsh syntax errors
Fixes two issues:
1. Zsh syntax errors with _describe -t flag in _alternative
2. Adds general handling for custom settings profiles (e.g., m2)
Changes:
- Zsh: Fixed _alternative syntax (removed -t tag from _describe calls)
- Error was: "_describe:21: bad option: -M"
- Cause: Tag is auto-derived in _alternative, don't specify with -t
- Fish: Added __fish_ccs_get_custom_settings_profiles function
- Dynamically loads non-hardcoded profiles from config.json
- Shows "Settings-based profile" description for custom profiles
- Removed 'max' from hardcoded known profiles
- 'max' is user's account-based profile, not a default setting
Now supports any custom settings profile (e.g., m2.settings.json for
Minimax M2) without hardcoding. Custom profiles show with generic
"Settings-based profile" description.
Installation properly overwrites:
- fs.copyFileSync overwrites completion files by default
- RC files only modified if marker not already present
* fix(zsh): simplify completion to avoid _alternative syntax issues
Replaced _alternative with multiple _describe calls to fix persistent
zsh completion errors.
The _alternative approach was causing:
- '_describe:21: bad option: -M'
- '(eval):1: bad substitution'
- Unwanted variable expansion in completion menu
New approach uses sequential _describe calls which zsh handles correctly.
Simpler, more reliable, and still shows grouped completion with
descriptions.
Before: _alternative with complex nested _describe calls (broken)
After: Three simple _describe calls (works correctly)
* feat(zsh): add colors and improved formatting to completion
Enhances zsh completion UI/UX with colors and better spacing:
Colors:
- Blue: commands (auth, doctor)
- Green: model profiles (default, glm, glmt, kimi, custom)
- Yellow: account profiles
- Gray: descriptions
Formatting:
- Wider separator ( -- ) for better readability
- Group headers in bold cyan
- Menu selection enabled for navigation
- list-rows-first for better column layout
Before:
auth -- Manage multiple Claude accounts
default -- Default Claude Sonnet 4.5
doctor -- Run health check and diagnostics
glm -- GLM-4.6 (cost-optimized)
After:
commands (cyan header)
auth -- Manage multiple Claude accounts (blue)
doctor -- Run health check and diagnostics (blue)
model profiles (cyan header)
default -- Default Claude Sonnet 4.5 (green)
glm -- GLM-4.6 (cost-optimized) (green)
glmt -- GLM-4.6 with thinking mode (green)
kimi -- Kimi for Coding (long-context) (green)
account profiles (cyan header)
max -- Account-based profile (yellow)
Table-like appearance with colors matching --help output style.
* feat(fish): add colors to completion descriptions
Adds color-coded descriptions to Fish completion matching zsh style:
Colors:
- Blue: commands (auth, doctor)
- Green: model profiles (default, glm, glmt, kimi, custom)
- Yellow: account profiles
Fish has excellent native color support via set_color, making this
straightforward to implement.
Before:
auth Manage multiple Claude accounts
default Default Claude Sonnet 4.5
glm GLM-4.6 (cost-optimized)
max Account profile
After:
auth Manage multiple Claude accounts (blue)
default Default Claude Sonnet 4.5 (green)
glm GLM-4.6 (cost-optimized) (green)
max Account profile (yellow)
Consistent color scheme across zsh and fish shells.
* fix(zsh): correct color application for commands vs descriptions
Fixed color codes being applied backwards - commands were gray while
descriptions were colorful.
Issue:
- Used '1;34' format which zsh misinterpreted
- Commands appeared gray (unreadable)
- Descriptions appeared in color
Fix:
- Simplified color codes from '1;34' to '34' (just the color, no style prefix)
- Pattern now: =(#b)(command)(-- description)=34=90
- First group (command): color 34 (blue/green/yellow)
- Second group (description): color 90 (gray)
Before:
auth -- Manage multiple Claude accounts (gray) (blue)
After:
auth -- Manage multiple Claude accounts (blue) (gray)
Commands now properly colored, descriptions muted.
* feat(zsh): improve section header visibility with separators
Makes section headers more distinct and recognizable as dividers:
Before:
commands
auth -- ...
After:
── commands ──
auth -- ...
Changes:
- Added blank line before headers ($'\n')
- Bold yellow with decorative separators (── text ──)
- Clearly distinguishes section headers from actual commands
Now it's obvious that 'commands', 'model profiles', and 'account
profiles' are just section labels, not completable items.
* fix(zsh): use full ANSI color codes to fix reversed colors
The issue was using shorthand color codes (34, 90) instead of full
ANSI format (0;34, 2;37). Zsh was misinterpreting the shorthand,
causing colors to be applied to wrong groups.
Fixed:
- Commands: 0;34 (normal blue) - was appearing gray
- Model profiles: 0;32 (normal green) - was appearing gray
- Account profiles: 0;33 (normal yellow) - was appearing gray
- Descriptions: 2;37 (dim white) - was appearing colorful
Color codes must be escaped as 0\;34 in zsh strings.
Before fix:
auth (gray) -- description (blue)
After fix:
auth (blue) -- description (dim gray)
* fix(zsh): swap color order for completion groups
Zsh may apply colors in reverse order to capture groups on some systems.
Swapped color order: group 2 first, then group 1.
Pattern: (command)(separator + description)
Was: =blue=dim_white (applied as: blue to cmd, dim to desc)
Now: =dim_white=blue (applied as: dim to desc, blue to cmd)
Testing if this resolves the reversed color issue.
* fix(zsh): add empty leading color to fix reversed coloring
ROOT CAUSE: Zsh list-colors apply first color to WHOLE match, then
override with subsequent colors for each group. Without an empty
leading color, the whole match color leaks to groups without overrides.
Pattern behavior:
=(#b)(cmd)(desc)=BLUE=DIM
→ Whole: BLUE, Group1: DIM (override), Group2: BLUE (no override)
→ Result: cmd=dim, desc=BLUE (REVERSED!)
=(#b)(cmd)(desc)==BLUE=DIM
→ Whole: none, Group1: BLUE, Group2: DIM
→ Result: cmd=BLUE, desc=dim (CORRECT!)
The '==' at start means 'no whole-match color', preventing color bleed.
Now commands will be colorful (blue/green/yellow) and descriptions dim.
* refactor(help): remove specific account examples and generalize description
Removed deterministic account examples (work, personal, team) to make
the help text more generic and less prescriptive.
Changes:
- Removed 'ccs work' and 'ccs personal' example lines
- Removed 'Multi-account workflow' examples section
- Updated description from 'multiple Claude accounts (work, personal, team)'
to 'multiple Claude accounts and alternative models'
- Changed to 'Run different Claude CLI sessions concurrently'
- Applied consistently across Node.js (bin/ccs.js), bash (lib/ccs),
and PowerShell (lib/ccs.ps1)
This makes the help text more flexible and doesn't imply specific
use cases or account naming conventions.
* refactor(help): clarify delegation section and remove non-existent command
Updated delegation section in help text across all implementations:
Changes:
- Renamed section from 'Delegation (Token Optimization)' to
'Delegation (inside Claude Code CLI)' to clarify context
- Removed non-existent '/ccs:create m2' command
- Simplified description to focus on cost savings
- Updated command descriptions:
- '/ccs:glm' now 'for simple tasks' (clearer use case)
- '/ccs:kimi' unchanged (already clear)
- Added delegation section to PowerShell help (was missing)
- Consistent messaging across Node.js, bash, and PowerShell
The new section makes it immediately clear that delegation commands
are used within Claude Code CLI sessions, not as standalone commands.
---------
- Remove 5 deprecated model fields from Kimi settings causing auth failures
- Update config/base-kimi.settings.json template with clean configuration
- Add automatic migration in scripts/postinstall.js to remove deprecated fields
- Preserve user API keys and custom settings during migration
- Update CHANGELOG.md with v4.1.1 and v4.1.2 entries
- Bump version to 4.1.2 across all files and installers
Fixes authentication issues with Moonshot AI (Kimi) API due to deprecated
model parameters that are now rejected by the service.
Fixes issue where npm install -g or ccs update would fail to copy
.claude/ directory to ~/.ccs/.claude/, causing symlink installation
errors. ClaudeDirInstaller now ensures source exists before
ClaudeSymlinkManager attempts linking.
- update require path from '../bin/shared-manager' to '../bin/management/shared-manager'
- fixes symlink creation failure in postinstall
- bump version to 3.4.4
- Add GLMT proxy server for GLM model routing
- Add GLMT transformer for output format conversion
- Update CLI with new proxy and transformer commands
- Add comprehensive test suite for new functionality
- Update documentation and architecture guides
- Bump version and update changelog