diff --git a/CHANGELOG.md b/CHANGELOG.md index d17d69e0..6e6a30df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,33 @@ -## [5.4.1-dev.1](https://github.com/kaitranntt/ccs/compare/v5.4.0...v5.4.1-dev.1) (2025-12-04) +## [5.4.3-dev.1](https://github.com/kaitranntt/ccs/compare/v5.4.3...v5.4.3-dev.1) (2025-12-04) ### Bug Fixes -* **cliproxy:** resolve windows auth browser not opening ([af4d6cf](https://github.com/kaitranntt/ccs/commit/af4d6cff89395a74e2eaf56551d3f56b95e0a6ce)), closes [#42](https://github.com/kaitranntt/ccs/issues/42) -* **doctor:** resolve windows claude cli detection failure ([cfe9ba0](https://github.com/kaitranntt/ccs/commit/cfe9ba05a4351302fbb330ca00b6025cb65a8f20)), closes [#41](https://github.com/kaitranntt/ccs/issues/41) * **tests:** migrate test suite from mocha to bun test runner ([bd46c8d](https://github.com/kaitranntt/ccs/commit/bd46c8de1237e3a76c774b00a1c9e026f4c0cd4b)) -## [5.4.1-dev.1](https://github.com/kaitranntt/ccs/compare/v5.4.0...v5.4.1-dev.1) (2025-12-03) +## [5.4.3](https://github.com/kaitranntt/ccs/compare/v5.4.2...v5.4.3) (2025-12-03) + + +### Bug Fixes + +* **postinstall:** handle broken symlinks during npm install ([81add5a](https://github.com/kaitranntt/ccs/commit/81add5a05eeb8297ceef840071f11b6a194df707)) + +## [5.4.2](https://github.com/kaitranntt/ccs/compare/v5.4.1...v5.4.2) (2025-12-03) + + +### Bug Fixes + +* **merge:** resolve conflicts between dev and main ([8347ea6](https://github.com/kaitranntt/ccs/commit/8347ea64c6b919a79f5ab63c398b6c36f012ca2d)) +* **sync:** implement copy fallback for windows when symlinks unavailable ([6b3f93a](https://github.com/kaitranntt/ccs/commit/6b3f93a80a0232e8c964d73e51aa0afb0768b00f)), closes [#45](https://github.com/kaitranntt/ccs/issues/45) + +## [5.4.1](https://github.com/kaitranntt/ccs/compare/v5.4.0...v5.4.1) (2025-12-03) ### Bug Fixes * **cliproxy:** resolve windows auth browser not opening ([af4d6cf](https://github.com/kaitranntt/ccs/commit/af4d6cff89395a74e2eaf56551d3f56b95e0a6ce)), closes [#42](https://github.com/kaitranntt/ccs/issues/42) * **doctor:** resolve windows claude cli detection failure ([cfe9ba0](https://github.com/kaitranntt/ccs/commit/cfe9ba05a4351302fbb330ca00b6025cb65a8f20)), closes [#41](https://github.com/kaitranntt/ccs/issues/41) +* **sync:** implement copy fallback for windows when symlinks unavailable ([6b3f93a](https://github.com/kaitranntt/ccs/commit/6b3f93a80a0232e8c964d73e51aa0afb0768b00f)), closes [#45](https://github.com/kaitranntt/ccs/issues/45) # [5.4.0](https://github.com/kaitranntt/ccs/compare/v5.3.0...v5.4.0) (2025-12-02) @@ -29,45 +43,6 @@ * **prompt:** improve password input handling with raw mode and buffer support ([bc56d2e](https://github.com/kaitranntt/ccs/commit/bc56d2e135532b2ae443144dd42217b26bcba951)) -### Features - -* **cliproxy:** add qwen code oauth provider support ([#31](https://github.com/kaitranntt/ccs/issues/31)) ([a3f1e52](https://github.com/kaitranntt/ccs/commit/a3f1e52ac68600ba0806d67aacceb6477ffa3543)), closes [#29](https://github.com/kaitranntt/ccs/issues/29) -* **cliproxy:** auto-update cliproxyapi to latest release on startup ([8873ccd](https://github.com/kaitranntt/ccs/commit/8873ccd981679e8acff8965accdc22215c6e4aa2)) -* **profile:** add profile command with configuration display ([53d7a15](https://github.com/kaitranntt/ccs/commit/53d7a15c047e760723e051dc0f7be3c0dd42d087)) -* **shell-completion:** add --force flag and fix zsh profile coloring ([7faed1d](https://github.com/kaitranntt/ccs/commit/7faed1d84ba29ba02bf687bae5b3458617512e67)) -* **ui:** add central ui abstraction layer for cli styling ([6e49e0e](https://github.com/kaitranntt/ccs/commit/6e49e0e7e157abd4a38c98553dbe3c16473b57d9)) -* **ui:** enhance auth commands with new ui layer ([6f42a65](https://github.com/kaitranntt/ccs/commit/6f42a6527b1bf02cbf29ec23525c9f27af6f0c98)) -* **ui:** enhance delegation with listr2 task lists and styled output ([716193a](https://github.com/kaitranntt/ccs/commit/716193a682a1504767c7f32409a0de51278242eb)) -* **ui:** enhance doctor and error manager with new ui layer ([57016f3](https://github.com/kaitranntt/ccs/commit/57016f3f765f207915161514e1827b18c0b03d5c)) -* **ui:** enhance help and profile commands with new ui layer ([f3ed359](https://github.com/kaitranntt/ccs/commit/f3ed359050ce66d96c0109cf60c242bfd092114d)) -* **ui:** enhance section headers with gradient and rename profile to api ([073a5e1](https://github.com/kaitranntt/ccs/commit/073a5e15ee8f895d7485864526d8946b774bb728)) - -# [5.4.0-beta.3](https://github.com/kaitranntt/ccs/compare/v5.4.0-beta.2...v5.4.0-beta.3) (2025-12-02) - - -### Bug Fixes - -* **cliproxy:** convert windows backslashes to forward slashes in config.yaml auth-dir ([a6663cb](https://github.com/kaitranntt/ccs/commit/a6663cbd0471d1a08e8bbcdea897760b434ae937)), closes [#36](https://github.com/kaitranntt/ccs/issues/36) - -# [5.4.0-beta.2](https://github.com/kaitranntt/ccs/compare/v5.4.0-beta.1...v5.4.0-beta.2) (2025-12-02) - - -### Bug Fixes - -* **auth:** prevent default profile from using stale glm env vars ([13d13da](https://github.com/kaitranntt/ccs/commit/13d13dab516332bc17345dc77afd44ae48bdd2aa)), closes [#37](https://github.com/kaitranntt/ccs/issues/37) - -# [5.4.0-beta.1](https://github.com/kaitranntt/ccs/compare/v5.3.0...v5.4.0-beta.1) (2025-12-02) - - -### Bug Fixes - -* **cliproxy:** improve qwen oauth error handling ([7e0b0fe](https://github.com/kaitranntt/ccs/commit/7e0b0feca8ce2ed5d505c5bf6c84e54c6df8839e)), closes [#29](https://github.com/kaitranntt/ccs/issues/29) -* **cliproxy:** use double-dash flags for cliproxyapi auth ([#24](https://github.com/kaitranntt/ccs/issues/24)) ([4c81f28](https://github.com/kaitranntt/ccs/commit/4c81f28f0b67ef92cf74d0f5c13a5943ff0a7f00)) -* **deps:** add chalk, boxen, gradient-string, listr2 as dependencies ([a214749](https://github.com/kaitranntt/ccs/commit/a214749725cfe05612e2c84cefa2ab3f619c6a2e)) -* **glmt:** handle 401 errors and headers-already-sent exception ([#30](https://github.com/kaitranntt/ccs/issues/30)) ([c953382](https://github.com/kaitranntt/ccs/commit/c95338232a37981b95b785b47185ce18d6d94b7a)), closes [#26](https://github.com/kaitranntt/ccs/issues/26) -* **prompt:** improve password input handling with raw mode and buffer support ([bc56d2e](https://github.com/kaitranntt/ccs/commit/bc56d2e135532b2ae443144dd42217b26bcba951)) - - ### Features * **cliproxy:** add qwen code oauth provider support ([#31](https://github.com/kaitranntt/ccs/issues/31)) ([a3f1e52](https://github.com/kaitranntt/ccs/commit/a3f1e52ac68600ba0806d67aacceb6477ffa3543)), closes [#29](https://github.com/kaitranntt/ccs/issues/29) @@ -88,26 +63,6 @@ * **profile,shell-completion,prompt:** add profile commands and improve input handling ([#34](https://github.com/kaitranntt/ccs/issues/34)) ([7ec8cc8](https://github.com/kaitranntt/ccs/commit/7ec8cc83690a595bba9bb5f62fb3b9fa6b6a2f8f)), closes [#24](https://github.com/kaitranntt/ccs/issues/24) [#30](https://github.com/kaitranntt/ccs/issues/30) [#26](https://github.com/kaitranntt/ccs/issues/26) [#31](https://github.com/kaitranntt/ccs/issues/31) [#29](https://github.com/kaitranntt/ccs/issues/29) [#29](https://github.com/kaitranntt/ccs/issues/29) -# [5.3.0-beta.4](https://github.com/kaitranntt/ccs/compare/v5.3.0-beta.3...v5.3.0-beta.4) (2025-12-01) - - -### Bug Fixes - -* **cliproxy:** improve qwen oauth error handling ([#33](https://github.com/kaitranntt/ccs/issues/33)) ([1c3374f](https://github.com/kaitranntt/ccs/commit/1c3374f6a7e4440e299d49b58808c6454b4547c2)), closes [#29](https://github.com/kaitranntt/ccs/issues/29) - -# [5.3.0-beta.3](https://github.com/kaitranntt/ccs/compare/v5.3.0-beta.2...v5.3.0-beta.3) (2025-12-01) - - -### Bug Fixes - -* **prompt:** improve password input handling with raw mode and buffer support ([bc56d2e](https://github.com/kaitranntt/ccs/commit/bc56d2e135532b2ae443144dd42217b26bcba951)) - - -### Features - -* **profile:** add profile command with configuration display ([53d7a15](https://github.com/kaitranntt/ccs/commit/53d7a15c047e760723e051dc0f7be3c0dd42d087)) -* **shell-completion:** add --force flag and fix zsh profile coloring ([7faed1d](https://github.com/kaitranntt/ccs/commit/7faed1d84ba29ba02bf687bae5b3458617512e67)) - ## [5.2.1](https://github.com/kaitranntt/ccs/compare/v5.2.0...v5.2.1) (2025-12-01) @@ -115,27 +70,6 @@ * **cliproxy:** improve qwen oauth error handling ([#33](https://github.com/kaitranntt/ccs/issues/33)) ([1c3374f](https://github.com/kaitranntt/ccs/commit/1c3374f6a7e4440e299d49b58808c6454b4547c2)), closes [#29](https://github.com/kaitranntt/ccs/issues/29) -# [5.3.0-beta.2](https://github.com/kaitranntt/ccs/compare/v5.3.0-beta.1...v5.3.0-beta.2) (2025-12-01) - - -### Bug Fixes - -* **cliproxy:** improve qwen oauth error handling ([7e0b0fe](https://github.com/kaitranntt/ccs/commit/7e0b0feca8ce2ed5d505c5bf6c84e54c6df8839e)), closes [#29](https://github.com/kaitranntt/ccs/issues/29) - -# [5.3.0-beta.1](https://github.com/kaitranntt/ccs/compare/v5.2.0...v5.3.0-beta.1) (2025-12-01) - - -### Bug Fixes - -* **cliproxy:** use double-dash flags for cliproxyapi auth ([#24](https://github.com/kaitranntt/ccs/issues/24)) ([4c81f28](https://github.com/kaitranntt/ccs/commit/4c81f28f0b67ef92cf74d0f5c13a5943ff0a7f00)) -* **glmt:** handle 401 errors and headers-already-sent exception ([#30](https://github.com/kaitranntt/ccs/issues/30)) ([c953382](https://github.com/kaitranntt/ccs/commit/c95338232a37981b95b785b47185ce18d6d94b7a)), closes [#26](https://github.com/kaitranntt/ccs/issues/26) - - -### Features - -* **cliproxy:** add qwen code oauth provider support ([#31](https://github.com/kaitranntt/ccs/issues/31)) ([a3f1e52](https://github.com/kaitranntt/ccs/commit/a3f1e52ac68600ba0806d67aacceb6477ffa3543)), closes [#29](https://github.com/kaitranntt/ccs/issues/29) -* **cliproxy:** auto-update cliproxyapi to latest release on startup ([8873ccd](https://github.com/kaitranntt/ccs/commit/8873ccd981679e8acff8965accdc22215c6e4aa2)) - # [5.2.0](https://github.com/kaitranntt/ccs/compare/v5.1.1...v5.2.0) (2025-12-01) @@ -150,13 +84,6 @@ * **cliproxy:** use double-dash flags for cliproxyapi auth ([9489884](https://github.com/kaitranntt/ccs/commit/94898848ea4533dcfc142e1b6c9bf939ba655537)) -## [5.1.1-beta.1](https://github.com/kaitranntt/ccs/compare/v5.1.0...v5.1.1-beta.1) (2025-12-01) - - -### Bug Fixes - -* **cliproxy:** use double-dash flags for cliproxyapi auth ([#24](https://github.com/kaitranntt/ccs/issues/24)) ([4c81f28](https://github.com/kaitranntt/ccs/commit/4c81f28f0b67ef92cf74d0f5c13a5943ff0a7f00)) - # [5.1.0](https://github.com/kaitranntt/ccs/compare/v5.0.2...v5.1.0) (2025-12-01) @@ -281,552 +208,3 @@ Format: [Keep a Changelog](https://keepachangelog.com/) - **Quality Gates**: All Phase 01 ESLint strictness rules maintained - **Type Safety**: Comprehensive TypeScript coverage with zero `any` types - **Interface Consistency**: All commands follow standardized `CommandHandler` interface - -## [4.4.0] - 2025-11-23 - -### Changed -- **BREAKING**: settings.json now shared across profiles via symlinks - - Each profile previously had isolated settings.json - - Now all profiles share ~/.claude/settings.json - - Migration automatic on install (uses ~/.claude/settings.json) - - Backups created: `/settings.json.pre-shared-migration` - - Rollback: restore backup manually if needed - -### Added -- Doctor validates settings.json symlink integrity -- Sync repairs broken settings.json symlinks -- Migration from isolated to shared settings (automatic) - -### Fixed -- Consistent shared data architecture across all .claude/ items - -## [4.3.10] - 2025-11-23 - -### Fixed -- **Update Cache Issue**: Fixed `ccs update` serving cached package versions instead of fresh downloads -- Package manager cache is now automatically cleared before updating -- Update now ensures users always receive the latest version from registry - -### Technical Details -- **Node.js (bin/ccs.js)**: Added cache clearing for npm, yarn, pnpm before update - - npm: `npm cache clean --force` - - yarn: `yarn cache clean` - - pnpm: `pnpm store prune` - - bun: No explicit cache clearing needed -- **Bash (lib/ccs)**: Added `npm cache clean --force` before npm update -- **PowerShell (lib/ccs.ps1)**: Added `npm cache clean --force` before npm update -- **Non-blocking**: Update continues even if cache clearing fails (with warning) -- **Manual fallback commands**: Updated to include cache clearing step - -### Impact -- Users no longer need to manually run `npm cache clean --force` before `ccs update` -- Resolves issue where update reported success but installed cached/outdated version -- Ensures fresh package downloads from npm registry on every update - -## [4.3.8] - 2025-11-23 - -### Fixed -- **ora v9 Compatibility**: Fixed "ora is not a function" errors in `ccs doctor` and installer utilities -- Properly handle ora v9+ ES module format when using CommonJS `require()` -- All spinner-based operations now work correctly with ora v9.0.0 - -### Technical Details -- ora v9+ is an ES module, requiring `.default` property access in CommonJS -- Updated import: `const oraModule = require('ora'); ora = oraModule.default || oraModule` -- Fallback spinner implementation ensures graceful degradation when ora is unavailable -- Affects: `bin/management/doctor.js`, `bin/utils/claude-dir-installer.js`, `bin/utils/claude-symlink-manager.js` -- Impact: `ccs doctor` command and postinstall scripts now work correctly with latest ora version - -## [4.3.7] - 2025-11-23 - -### Fixed -- **Postinstall Script**: Fixed missing `~/.ccs/.claude/` directory during `npm install` -- Made `ora` dependency optional in `ClaudeDirInstaller` and `ClaudeSymlinkManager` -- Postinstall script now gracefully handles missing `ora` module during installation -- Ensures `.claude/` directory and symlinks are properly created even when `ora` is unavailable - -### Technical Details -- Root cause: `ora` module not available during `npm install` postinstall execution -- Solution: Optional require with fallback to `console.log` when `ora` is unavailable -- Affects: `bin/utils/claude-dir-installer.js`, `bin/utils/claude-symlink-manager.js` -- Impact: All npm installations now properly create `~/.ccs/.claude/` and CCS symlinks - -## [4.3.6] - 2025-11-23 - -### Added -- **Plugin Support**: Claude Code plugins now shared across all CCS profiles via `~/.ccs/shared/plugins/` -- Symlink architecture: `~/.claude/plugins/` ← `~/.ccs/shared/plugins/` ← `instance/plugins/` -- Install plugins once, use across GLM, GLMT, Kimi, and all Claude accounts -- Cross-platform support with Windows fallback (copy mode) - -## [4.3.5] - 2025-11-22 - -### Changed -- **Deprecated Agent Cleanup**: Removed deprecated `ccs-delegator.md` agent file from installations -- Enhanced installation process to automatically clean up obsolete files -- Improved `ccs sync` command with migration logic for deprecated components - -### Removed -- **ccs-delegator.md**: Agent file deprecated in favor of `ccs-delegation` skill (v4.3.2) -- Clean up of package copy in `~/.ccs/.claude/agents/ccs-delegator.md` -- Clean up of user symlink in `~/.claude/agents/ccs-delegator.md` - -### Added -- Automatic migration marker system for tracking cleanup completion -- Intelligent backup system for user-modified deprecated files -- Version-aware migration logic following existing patterns - -### Migration -- **Automatic**: Users upgrading from v4.3.2 or earlier will have deprecated files cleaned up automatically -- **Manual**: Run `ccs sync` to trigger cleanup manually -- **Backups**: User-modified files are backed up with timestamp before removal -- **Idempotent**: Cleanup is safe to run multiple times - -### Technical Details -- Integrated into `npm postinstall` script for automatic cleanup on package updates -- Added to `ccs sync` command for manual cleanup operations -- Uses migration markers in `~/.ccs/.migrations/v435-delegator-cleanup` -- Follows existing SharedManager migration patterns for consistency - -## [4.3.4] - 2025-11-22 - -### Fixed -- **CCS Update Command**: Enhanced `ccs update` to support multiple package managers -- Added automatic detection for npm, yarn, pnpm, and bun package managers -- Update commands now use the appropriate package manager automatically -- Improved installation method detection for more reliable updates - -## [4.3.3] - 2025-11-21 - -### ⚠️ BREAKING CHANGES - -- **CCS Delegation Commands Consolidated**: Replaced 4 hardcoded commands with 2 intelligent commands - - Old: `/ccs:glm`, `/ccs:kimi`, `/ccs:glm:continue`, `/ccs:kimi:continue` - - New: `/ccs` (auto-selects profile), `/ccs:continue` (auto-detects profile) - - Override with flags: `/ccs --glm "task"`, `/ccs --kimi "task"` - -### Changed -- Updated `--help` text across Node.js, Bash, and PowerShell implementations -- Updated delegation examples in README.md and workflow documentation -- Fixed CCS Doctor health checks to validate new command files -- Updated user configuration templates with new command syntax - -### Added -- Intelligent profile selection based on task analysis (reasoning, long-context, cost-optimized) -- Support for custom profiles without creating new commands -- Enhanced session management with automatic profile detection - -### Migration -| Old Command | New Command | -|-------------|-------------| -| `/ccs:glm "task"` | `/ccs "task"` (or `/ccs --glm "task"`) | -| `/ccs:kimi "task"` | `/ccs "task"` (or `/ccs --kimi "task"`) | -| `/ccs:glm:continue` | `/ccs:continue` | -| `/ccs:kimi:continue` | `/ccs:continue` | - ---- - -## [4.1.5] - 2025-11-17 - -### Added -- **Sync command** (`ccs sync`) for updating delegation commands and skills -- **Short flag** `-sc` for `--shell-completion` command -- **Enhanced version display** with delegation status information - -### Changed -- **Auth help text** now emphasizes concurrent account usage across all platforms -- **Help text standardization** ensures consistent messaging across bash, PowerShell, and Node.js -- **Description text** emphasizes running different Claude CLI sessions concurrently -- **GitHub documentation links** updated to stable permalinks -- **Shell completions** updated to include sync command and -sc flag - -### Fixed -- **Inconsistent help text** across different platform implementations -- **Outdated description** text to emphasize concurrent sessions over specific examples - ---- - -## [4.1.4] - 2025-11-17 - -### Fixed -- **Shell completion ENOTDIR errors** when parent path conflicts with existing files -- **Zsh completion syntax errors** with _alternative and _describe functions -- **Reversed color application** in zsh completion (commands vs descriptions) - -### Added -- **Enhanced shell completion UI/UX** with descriptions and grouping -- **Color-coded completions** for zsh and fish shells -- **Custom settings profile support** in shell completions -- **Improved completion formatting** with section headers and separators - -### Changed -- **Generalized help text** removed specific account examples for broader applicability -- **Delegation help section** clarified context and removed non-existent commands -- **Shell completion organization** grouped by categories (commands, model profiles, account profiles) - ---- - -## [4.1.3] - 2025-11-17 - -### Fixed -- **Doctor command delegation check false positive** - - Fixed `ccs doctor` incorrectly checking for delegation commands in `~/.ccs/shared/commands/ccs/` instead of `~/.ccs/.claude/commands/ccs/` - - Removed check for non-existent `create.md` file - - Now correctly detects installed delegation commands (glm.md, kimi.md) after npm install - - Users will no longer see "[!] Delegation commands not found" warning when delegation is properly installed - ---- - -## [4.1.2] - 2025-11-16 - -### Fixed -- **Kimi API 401 errors** caused by deprecated model fields - - Removed `ANTHROPIC_MODEL`, `ANTHROPIC_SMALL_FAST_MODEL`, `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL` from Kimi settings - - Kimi API update now rejects requests with these fields (previously optional, now break authentication) - - Automatic migration removes deprecated fields from existing `~/.ccs/kimi.settings.json` - - Preserves user API keys and custom settings during migration - - Updated `config/base-kimi.settings.json` template - - Users experiencing 401 errors will be automatically fixed on next install/update - -### Changed -- Kimi settings now minimal: only `ANTHROPIC_BASE_URL` and `ANTHROPIC_AUTH_TOKEN` required - ---- - -## [4.1.1] - 2025-11-16 - -### Fixed -- **npm install fails to copy .claude/ directory** to `~/.ccs/.claude/` - - Error: "[!] CCS .claude/ directory not found, skipping symlink installation" - - Created `bin/utils/claude-dir-installer.js` utility to copy `.claude/` from package - - Updated `scripts/postinstall.js` to copy `.claude/` before creating symlinks - - Updated `ccs update` command to re-install `.claude/` directory - - Supports Node.js 14+ with fallback for versions < 16.7.0 - -### Added -- `ClaudeDirInstaller` utility class for managing `.claude/` directory installation - ---- - -## [4.1.0] - 2025-11-16 - -### Added -- **Selective .claude/ directory symlinking** for shared resources across profiles -- `claude-symlink-manager.js` utility for managing symlinks with Windows fallback -- Enhanced `ccs doctor` command to verify .claude/ directory health -- Postinstall script for automatic .claude/ directory setup -- **Stream-JSON output** for real-time delegation visibility (`--output-format stream-json --verbose`) -- **Real-time tool tracking** with verbose context (shows file paths, commands, patterns) -- **Smart slash command detection** (preserves /cook, /plan, /commit in delegated prompts) -- **Signal handling** (Ctrl+C/Esc kills delegated child processes, prevents orphans) -- **Comprehensive tool support** (13 Claude Code tools: Bash, Read, Write, Edit, Glob, Grep, NotebookEdit, NotebookRead, SlashCommand, Task, TodoWrite, WebFetch, WebSearch) -- **Active task display** for TodoWrite (shows current task instead of count) -- Documentation: Stream-JSON workflow diagrams - -### Changed -- Installers now create selective symlinks (commands/, skills/, agents/) instead of full directory copies -- Windows support: Falls back to directory copying when symlinks unavailable -- Profile-specific files (settings.json, sessions/, todolists/, logs/) remain isolated -- Improved README with symlink architecture documentation -- **BREAKING**: Delegation now uses stream-json instead of single JSON blob -- **Time-based limits** replace turn-based limits (10min default timeout vs 20 max-turns) -- **Graceful termination** with SIGTERM → SIGKILL fallback (2s grace period) -- Removed `--max-turns` flag (deprecated, use timeout instead) -- Simplified slash command docs (removed over-prescriptive instructions) -- Internal tools (TodoWrite, Skill) now show meaningful progress - -### Fixed -- Duplicate .claude/ resources across multiple profiles -- Installer logic now handles symlink creation during setup -- Orphaned `claude -p` processes after parent termination -- Slash commands broken by IMPORTANT safety prefix -- Slash commands detected as file paths (/home vs /cook) -- Stream-json requires `--verbose` flag with `-p` -- Tool output spam (filtered internal tools, show active tasks) - -### Removed -- IMPORTANT safety prefix (broke slash command positioning) -- Outdated test files (json-output.test.js, max-turns.test.js) -- TTY detection (now shows progress unless CCS_QUIET=1) - ---- - -## [3.5.0] - 2025-11-15 - -### Added -- Shell auto-completion (bash, zsh, PowerShell, Fish) -- `--shell-completion` command (auto-installs for detected shell with proper comment markers, cross-platform) -- Error codes (E101-E901) with documentation at docs/errors/ -- Fuzzy matching "Did you mean?" suggestions (Levenshtein distance) -- Progress indicators (doctor command: [n/9] counter, GLMT proxy startup spinner) -- Interactive confirmation prompts for destructive operations -- `--yes/-y` flag for automation (skips confirmations) -- `--json` flag for auth commands (list, show) -- Impact display (session count, paths) before profile deletion -- Comprehensive test suite (15 tests, 100% pass rate) - -### Changed -- Error boxes: Unicode (╔═╗) → ASCII (===) for cross-platform compatibility -- JSON output uses CCS version (3.5.0) instead of separate schema version -- Help text includes EXAMPLES section across all platforms -- Test suite properly counts test cases (not assertions) - -### Fixed -- Standalone installer dependency handling (now downloads error-codes, progress-indicator, prompt files) -- `--yes` flag bug (returned false instead of true, preventing auto-confirmation) -- Help text consistency between Node.js and bash versions (added Uninstall section to bash) -- Test pass rate calculation (now excludes skipped tests from denominator) -- Help section comparison (locale-specific sort order) - ---- - -## [3.4.6] - 2025-11-12 - -### Added -- GLMT ReasoningEnforcer: Prompt injection + API params hybrid (4 effort levels, always enabled) - -### Changed -- Added GLMT production warnings (NOT PRODUCTION READY) -- Streamlined CLAUDE.md (-337 lines) -- Simplified GLMT controls: 4 mechanisms → 3 automatic -- Locale + reasoning enforcement now always enabled - -### Removed -- GLMT Budget Calculator mechanism (consolidated into automatic controls) -- Deprecated GLMT environment variables (`CCS_GLMT_FORCE_ENGLISH`, `CCS_GLMT_THINKING_BUDGET`, `CCS_GLMT_STREAMING`) -- Outdated test scenarios for removed environment variables - ---- - -## [3.4.5] - 2025-11-11 - -### Fixed -- Thinking block signature timing race (blocks appeared blank in Claude CLI UI) -- Content verification guard in `_createSignatureDeltaEvent()` returns null if empty - -### Changed -- Consolidated debug flags: `CCS_DEBUG_LOG`, `CCS_GLMT_DEBUG` → `CCS_DEBUG` only - -### Added -- 6 regression tests for thinking signature race (`test-thinking-signature-race.js`) - ---- - -## [3.4.4] - 2025-11-11 - -### Fixed -- Postinstall symlink creation (fixed require path to shared-manager.js) - ---- - -## [3.4.3] - 2025-11-11 - -### Added -- Keyword thinking control: `think` < `think hard` < `think harder` < `ultrathink` -- Streaming auto-fallback on error - -### Changed -- YAGNI/KISS: Removed budget-calculator.js, task-classifier.js (-272 LOC) -- `CCS_DEBUG_LOG` → `CCS_DEBUG` (backward compatible) - -### Removed -- `CCS_GLMT_THINKING_BUDGET`, `CCS_GLMT_STREAMING`, `CCS_GLMT_FORCE_ENGLISH` env vars - -### Fixed -- GLMT proxy path (glmt/glmt-proxy.js) -- `ultrathink` effort: `high` → `max` - ---- - -## [3.4.2] - 2025-11-11 - -### Changed -- Version bump for npm CI workaround - ---- - -## [3.4.1] - 2025-11-11 - -### Added -- GLMT loop prevention (locale enforcer, budget calculator, task classifier, loop detector) -- Env vars: `CCS_GLMT_FORCE_ENGLISH`, `CCS_GLMT_THINKING_BUDGET` -- 110 GLMT tests (all passing) - -### Changed -- Directory structure: bin/{glmt,auth,management,utils}, tests/{unit,integration} -- Token savings: 50-80% for execution tasks - -### Fixed -- Thinking parameter processing from Claude CLI -- GLMT tool support (MCP tools, function calling) -- Unbounded planning loops (20+ min → <2 min) -- Chinese output issues - ---- - -## [3.4.0] - 2025-11-11 - -### Added -- GLMT streaming (5-20x faster TTFB: <500ms vs 2-10s) -- SSEParser, DeltaAccumulator classes -- Security limits (1MB SSE, 10MB content, 100 blocks) - ---- - -## [3.3.0] - 2025-11-11 - -### Added -- Debug mode: `CCS_DEBUG_LOG=1` -- Verbose flag: `ccs glmt --verbose` -- GLMT config defaults - ---- - -## [3.2.0] - 2025-11-10 - -### Changed -- **BREAKING**: Symlink-based shared data (was copy-based) -- ~/.ccs/shared/ → ~/.claude/ symlinks -- 60% faster installs - ---- - -## [3.1.1] - 2025-11-10 - -### Fixed -- Migration now runs during install (not on first `ccs` execution) - ---- - -## [3.1.0] - 2025-11-10 - -### Added -- Shared data architecture (commands/skills/agents shared across profiles) - ---- - -## [3.0.2] - 2025-11-10 - -### Fixed -- Profile creation no longer auto-sets as default -- Help text simplified (40% shorter) - ---- - -## [3.0.1] - 2025-11-10 - -### Added -- Auto-recovery system for missing/corrupted configs -- `ccs doctor` health check command -- ErrorManager class - ---- - -## [3.0.0] - 2025-11-09 - -### Added -- **Multi-account switching**: Run multiple Claude accounts concurrently -- Auth commands: create, list, show, remove, default -- Profile isolation (sessions, todos, logs per profile) - -### BREAKING -- Removed v2.x vault encryption -- Login-per-profile model - ---- - -## [2.5.1] - 2025-11-07 -### Added -- Kimi `ANTHROPIC_SMALL_FAST_MODEL` support - -## [2.5.0] - 2025-11-07 -### Added -- Kimi integration - -## [2.4.9] - 2025-11-05 -### Fixed -- Node.js DEP0190 warning - -## [2.4.8] - 2025-11-05 -### Fixed -- Deprecation warning (platform-specific shell) - -## [2.4.7] - 2025-11-05 -### Fixed -- Windows spawn EINVAL error - -## [2.4.6] - 2025-11-05 -### Fixed -- Color detection, TTY handling - -## [2.4.5] - 2025-11-05 -### Added -- Performance benchmarks (npm vs shell) - -## [2.4.3] - 2025-11-04 -### Fixed -- **CRITICAL**: DEP0190 command injection vulnerability - -## [2.4.2] - 2025-11-04 -### Changed -- Version bump for republish - -## [2.4.1] - 2025-11-04 -### Fixed -- **CRITICAL**: Windows PATH detection -- PowerShell terminal termination - -## [2.4.0] - 2025-11-04 -### Added -- npm package support -### BREAKING -- Executables moved to lib/ - -## [2.3.1] - 2025-11-04 -### Fixed -- PowerShell syntax errors - -## [2.3.0] - 2025-11-04 -### Added -- Custom Claude CLI path: `CCS_CLAUDE_PATH` - -## [2.2.3] - 2025-11-03 -### Added -- `ccs --uninstall` command - -## [2.2.2] - 2025-11-03 -### Fixed -- `ccs --install` via symlinks - -## [2.2.1] - 2025-11-03 -### Changed -- Hardcoded versions (no VERSION file) - -## [2.2.0] - 2025-11-03 -### Added -- Auto PATH configuration -- Terminal colors (NO_COLOR support) -### Changed -- Unified install: ~/.local/bin (Unix) -### Fixed -- **CRITICAL**: Shell injection vulnerability - -## [2.1.0] - 2025-11-02 -### Changed -- Windows uses --settings flag (27% code reduction) - -## [2.0.0] - 2025-11-02 -### BREAKING -- Removed `ccs son` profile -### Added -- Config templates, installers/ folder -### Fixed -- **CRITICAL**: PowerShell env var crash - -## [1.1.0] - 2025-11-01 -### Added -- Git worktrees support - -## [1.0.0] - 2025-10-31 -### Added -- Initial release diff --git a/VERSION b/VERSION index ef39ed80..a6e6cd04 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.4.1-dev.1 +5.4.3-dev.1 diff --git a/installers/install.ps1 b/installers/install.ps1 index a24b7d9e..a16c3881 100644 --- a/installers/install.ps1 +++ b/installers/install.ps1 @@ -83,7 +83,7 @@ $InstallMethod = if ($ScriptDir -and ((Test-Path "$ScriptDir\lib\ccs.ps1") -or ( # IMPORTANT: Update this version when releasing new versions! # This hardcoded version is used for standalone installations (irm | iex) # For git installations, VERSION file is read if available -$CcsVersion = "5.4.1-dev.1" +$CcsVersion = "5.4.3" # Try to read VERSION file for git installations if ($ScriptDir) { diff --git a/installers/install.sh b/installers/install.sh index 5de1b2b8..aef2873f 100755 --- a/installers/install.sh +++ b/installers/install.sh @@ -84,7 +84,7 @@ fi # IMPORTANT: Update this version when releasing new versions! # This hardcoded version is used for standalone installations (curl | bash) # For git installations, VERSION file is read if available -CCS_VERSION="5.4.1-dev.1" +CCS_VERSION="5.4.3" # Try to read VERSION file for git installations if [[ -f "$SCRIPT_DIR/VERSION" ]]; then diff --git a/package.json b/package.json index fb9abdbe..02176604 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "5.4.1-dev.1", + "version": "5.4.3-dev.1", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli", diff --git a/scripts/postinstall.js b/scripts/postinstall.js index c761c920..4db3256b 100755 --- a/scripts/postinstall.js +++ b/scripts/postinstall.js @@ -24,6 +24,35 @@ function getCcsHome() { return process.env.CCS_HOME || os.homedir(); } +/** + * Check if path is a broken symlink and remove it if so + * Fixes: ENOENT error when mkdir tries to create over a dangling symlink + * @param {string} targetPath - Path to check + * @returns {boolean} true if broken symlink was removed + */ +function removeIfBrokenSymlink(targetPath) { + try { + // lstatSync doesn't follow symlinks - it checks the link itself + const stats = fs.lstatSync(targetPath); + if (stats.isSymbolicLink()) { + // Check if symlink target exists + try { + fs.statSync(targetPath); // This follows symlinks + return false; // Symlink is valid + } catch { + // Target doesn't exist - broken symlink + fs.unlinkSync(targetPath); + console.log(`[!] Removed broken symlink: ${targetPath}`); + return true; + } + } + return false; + } catch { + // Path doesn't exist at all + return false; + } +} + /** * Validate created configuration files * @returns {object} { success: boolean, errors: string[], warnings: string[] } @@ -85,6 +114,8 @@ function createConfigFiles() { // Create ~/.ccs/shared/ directory structure (Phase 1) const sharedDir = path.join(ccsDir, 'shared'); + // Handle broken symlinks (common when upgrading from older versions) + removeIfBrokenSymlink(sharedDir); if (!fs.existsSync(sharedDir)) { fs.mkdirSync(sharedDir, { recursive: true, mode: 0o755 }); console.log('[OK] Created directory: ~/.ccs/shared/'); @@ -94,6 +125,8 @@ function createConfigFiles() { const sharedSubdirs = ['commands', 'skills', 'agents', 'plugins']; for (const subdir of sharedSubdirs) { const subdirPath = path.join(sharedDir, subdir); + // Handle broken symlinks before creating directory + removeIfBrokenSymlink(subdirPath); if (!fs.existsSync(subdirPath)) { fs.mkdirSync(subdirPath, { recursive: true, mode: 0o755 }); console.log(`[OK] Created directory: ~/.ccs/shared/${subdir}/`); diff --git a/src/utils/claude-symlink-manager.ts b/src/utils/claude-symlink-manager.ts index 4011d007..29c98260 100644 --- a/src/utils/claude-symlink-manager.ts +++ b/src/utils/claude-symlink-manager.ts @@ -164,12 +164,9 @@ export class ClaudeSymlinkManager { if (!silent) console.log(`[OK] Symlinked ${item.target}`); return true; } catch (err) { - // Windows fallback: stub for now, full implementation in v4.2 + // Windows fallback: copy instead of symlink when symlinks unavailable if (process.platform === 'win32') { - if (!silent) { - console.log(`[!] Symlink failed for ${item.target} (Windows fallback deferred to v4.2)`); - console.log(`[i] Enable Developer Mode or wait for next update`); - } + return this.copyFallback(sourcePath, targetPath, item, silent); } else { const error = err as Error; if (!silent) console.log(`[!] Failed to symlink ${item.target}: ${error.message}`); @@ -178,6 +175,61 @@ export class ClaudeSymlinkManager { } } + /** + * Windows fallback: copy files/directories when symlinks unavailable + * Note: Changes won't auto-sync; user must run 'ccs sync' after updates + */ + private copyFallback( + sourcePath: string, + targetPath: string, + item: CcsItem, + silent = false + ): boolean { + try { + if (item.type === 'directory') { + // Copy directory recursively + this.copyDirRecursive(sourcePath, targetPath); + } else { + // Copy single file + fs.copyFileSync(sourcePath, targetPath); + } + if (!silent) { + console.log(`[OK] Copied ${item.target} (symlink unavailable)`); + console.log(`[i] Run 'ccs sync' after CCS updates to refresh`); + } + return true; + } catch (copyErr) { + const error = copyErr as Error; + if (!silent) { + console.log(`[!] Failed to copy ${item.target}: ${error.message}`); + console.log(`[i] Enable Developer Mode for symlinks, or check permissions`); + } + return false; + } + } + + /** + * Recursively copy directory (for Windows fallback) + */ + private copyDirRecursive(src: string, dest: string): void { + if (!fs.existsSync(dest)) { + fs.mkdirSync(dest, { recursive: true }); + } + + const entries = fs.readdirSync(src, { withFileTypes: true }); + + for (const entry of entries) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + + if (entry.isDirectory()) { + this.copyDirRecursive(srcPath, destPath); + } else { + fs.copyFileSync(srcPath, destPath); + } + } + } + /** * Check if target is already the correct symlink pointing to source */ @@ -224,8 +276,8 @@ export class ClaudeSymlinkManager { } /** - * Uninstall CCS items from ~/.claude/ (remove symlinks only) - * Safe: only removes items that are CCS symlinks + * Uninstall CCS items from ~/.claude/ (remove symlinks or copied files) + * Safe: only removes items that are CCS symlinks or valid copies */ uninstall(): void { let removed = 0; @@ -234,10 +286,20 @@ export class ClaudeSymlinkManager { const targetPath = path.join(this.userClaudeDir, item.target); const sourcePath = path.join(this.ccsClaudeDir, item.source); - // Only remove if it's our symlink - if (fs.existsSync(targetPath) && this.isOurSymlink(targetPath, sourcePath)) { + // Check if it's our symlink or a valid copy (Windows fallback) + const isSymlink = this.isOurSymlink(targetPath, sourcePath); + const isCopy = + process.platform === 'win32' && this.isCopiedItem(targetPath, sourcePath, item.type); + + if (fs.existsSync(targetPath) && (isSymlink || isCopy)) { try { - fs.unlinkSync(targetPath); + if (item.type === 'directory' && !isSymlink) { + // Remove copied directory recursively + fs.rmSync(targetPath, { recursive: true, force: true }); + } else { + // Remove symlink or file + fs.unlinkSync(targetPath); + } console.log(`[OK] Removed ${item.target}`); removed++; } catch (err) { @@ -286,14 +348,47 @@ export class ClaudeSymlinkManager { issues.push(`Not installed: ${item.target} (run 'ccs sync' to install)`); healthy = false; } else if (!this.isOurSymlink(targetPath, sourcePath)) { - issues.push(`Not a CCS symlink: ${item.target} (run 'ccs sync' to fix)`); - healthy = false; + // On Windows, copied files are valid (symlink fallback) + if (process.platform === 'win32' && this.isCopiedItem(targetPath, sourcePath, item.type)) { + // Copied file is valid on Windows, but note it's not a symlink + issues.push(`${item.target} is a copy (not symlink) - run 'ccs sync' after updates`); + // Still healthy, just a warning + } else { + issues.push(`Not a CCS symlink: ${item.target} (run 'ccs sync' to fix)`); + healthy = false; + } } } return { healthy, issues }; } + /** + * Check if target is a valid copy of source (Windows fallback check) + */ + private isCopiedItem( + targetPath: string, + sourcePath: string, + type: 'file' | 'directory' + ): boolean { + try { + const targetStats = fs.statSync(targetPath); + const sourceStats = fs.statSync(sourcePath); + + if (type === 'directory') { + // For directories, just check both exist and are directories + return targetStats.isDirectory() && sourceStats.isDirectory(); + } else { + // For files, compare size as basic validation + return ( + targetStats.isFile() && sourceStats.isFile() && targetStats.size === sourceStats.size + ); + } + } catch { + return false; + } + } + /** * Sync delegation commands and skills to ~/.claude/ (used by 'ccs sync' command) * Same as install() but with explicit sync message