diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2642f2a2..06da872f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,7 @@ on: push: branches: - main - - beta + - dev workflow_dispatch: jobs: diff --git a/.releaserc.json b/.releaserc.json index 29c4836c..8bde2f39 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -1,7 +1,7 @@ { "branches": [ "main", - { "name": "beta", "prerelease": true } + { "name": "dev", "prerelease": true } ], "plugins": [ "@semantic-release/commit-analyzer", diff --git a/CHANGELOG.md b/CHANGELOG.md index d3a3701d..2f925bfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [5.4.1-dev.1](https://github.com/kaitranntt/ccs/compare/v5.4.0...v5.4.1-dev.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) + # [5.4.0](https://github.com/kaitranntt/ccs/compare/v5.3.0...v5.4.0) (2025-12-02) diff --git a/CLAUDE.md b/CLAUDE.md index 3935f770..6063af47 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -159,22 +159,22 @@ git commit -m "WIP" ### Branch Hierarchy ``` -main (production) ← beta (integration) ← feat/* | fix/* | docs/* - ↑ ↑ - │ └── All development merges here FIRST +main (production) ← dev (integration) ← feat/* | fix/* | docs/* + ↑ ↑ + │ └── All development merges here FIRST │ - └── Only receives: (1) Tested code from beta, (2) Hotfixes + └── Only receives: (1) Tested code from dev, (2) Hotfixes ``` ### Branch Types | Branch | Purpose | Merges From | Releases To | |--------|---------|-------------|-------------| -| `main` | Production-ready | `beta`, `hotfix/*` | npm `@latest` | -| `beta` | Integration/staging | `feat/*`, `fix/*`, `docs/*` | npm `@beta` | -| `feat/*` | New features | - | → `beta` | -| `fix/*` | Bug fixes | - | → `beta` | -| `docs/*` | Documentation | - | → `beta` | +| `main` | Production-ready | `dev`, `hotfix/*` | npm `@latest` | +| `dev` | Integration/staging | `feat/*`, `fix/*`, `docs/*` | npm `@dev` | +| `feat/*` | New features | - | → `dev` | +| `fix/*` | Bug fixes | - | → `dev` | +| `docs/*` | Documentation | - | → `dev` | | `hotfix/*` | Critical production fixes | - | → `main` directly | ### Branch Naming Convention @@ -189,34 +189,34 @@ docs/update-installation-guide hotfix/critical-auth-bug ``` -### Standard Development Workflow (Features/Fixes → Beta → Main) +### Standard Development Workflow (Features/Fixes → Dev → Main) ```bash -# 1. ALWAYS start from beta (integration branch) -git checkout beta -git pull origin beta +# 1. ALWAYS start from dev (integration branch) +git checkout dev +git pull origin dev -# 2. Create feature branch FROM BETA +# 2. Create feature branch FROM DEV git checkout -b feat/my-feature # 3. Make changes with conventional commits git commit -m "feat(scope): add new feature" git commit -m "test(scope): add unit tests" -# 4. Push and create PR to BETA (not main!) +# 4. Push and create PR to DEV (not main!) git push -u origin feat/my-feature -gh pr create --base beta --title "feat(scope): add new feature" -# → Merge triggers npm @beta release for testing +gh pr create --base dev --title "feat(scope): add new feature" +# → Merge triggers npm @dev release for testing -# 5. After testing in beta, promote to main (MUST use feat: or fix: prefix!) -git checkout beta -gh pr create --base main --title "feat(release): promote beta to main" +# 5. After testing in dev, promote to main (MUST use feat: or fix: prefix!) +git checkout dev +gh pr create --base main --title "feat(release): promote dev to main" # → Merge triggers npm @latest release # WARNING: Using "chore:" will NOT trigger a release! # 6. Clean up -git checkout beta -git pull origin beta +git checkout dev +git pull origin dev git branch -d feat/my-feature ``` @@ -233,39 +233,39 @@ git checkout -b hotfix/critical-bug # 3. Fix and commit git commit -m "fix: critical authentication bypass" -# 4. PR directly to main (skip beta) +# 4. PR directly to main (skip dev) gh pr create --base main --title "fix: critical authentication bypass" # → Merge triggers immediate npm @latest release -# 5. Sync hotfix back to beta -git checkout beta -git pull origin beta +# 5. Sync hotfix back to dev +git checkout dev +git pull origin dev git merge main -git push origin beta +git push origin dev # 6. Clean up git branch -d hotfix/critical-bug ``` -### Keeping Beta in Sync with Main +### Keeping Dev in Sync with Main ```bash -# After any main release, sync to beta -git checkout beta -git pull origin beta +# After any main release, sync to dev +git checkout dev +git pull origin dev git merge main -git push origin beta +git push origin dev ``` ### Rules -1. **NEVER commit directly to `main` or `beta`** - always use PRs -2. **ALWAYS create feature branches from `beta`** (not main) +1. **NEVER commit directly to `main` or `dev`** - always use PRs +2. **ALWAYS create feature branches from `dev`** (not main) 3. **Only `hotfix/*` branches go directly to `main`** -4. **`beta` must always be up-to-date with `main`** +4. **`dev` must always be up-to-date with `main`** 5. **Delete feature branches after merge** -6. **Test in `@beta` before promoting to `@latest`** -7. **beta→main PRs MUST use `feat:` or `fix:` prefix** - `chore:` won't trigger npm release +6. **Test in `@dev` before promoting to `@latest`** +7. **dev→main PRs MUST use `feat:` or `fix:` prefix** - `chore:` won't trigger npm release ## Automated Releases (DO NOT MANUALLY TAG) @@ -275,7 +275,7 @@ git push origin beta | Branch | npm Tag | When | |--------|---------|------| | `main` | `@latest` | Merge PR to main | -| `beta` | `@beta` | Push to beta branch | +| `dev` | `@dev` | Push to dev branch | ### What CI Does Automatically 1. Analyzes commits since last release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 88905c92..fe0a7c50 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -99,22 +99,22 @@ Test on all platforms before submitting PR: #### Branch Hierarchy ``` -main (production) ← beta (integration) ← feat/* | fix/* | docs/* - ↑ ↑ - │ └── All contributions merge here FIRST +main (production) ← dev (integration) ← feat/* | fix/* | docs/* + ↑ ↑ + │ └── All contributions merge here FIRST │ - └── Only: tested beta code OR hotfix/* + └── Only: tested dev code OR hotfix/* ``` #### Branch Types | Branch | Purpose | PRs Target | Releases To | |--------|---------|------------|-------------| -| `main` | Production | From `beta` only | npm `@latest` | -| `beta` | Integration/testing | From `feat/*`, `fix/*` | npm `@beta` | -| `feat/*` | New features | → `beta` | - | -| `fix/*` | Bug fixes | → `beta` | - | -| `docs/*` | Documentation | → `beta` | - | +| `main` | Production | From `dev` only | npm `@latest` | +| `dev` | Integration/testing | From `feat/*`, `fix/*` | npm `@dev` | +| `feat/*` | New features | → `dev` | - | +| `fix/*` | Bug fixes | → `dev` | - | +| `docs/*` | Documentation | → `dev` | - | | `hotfix/*` | Critical fixes | → `main` directly | npm `@latest` | #### Branch Naming Convention @@ -139,11 +139,11 @@ cd ccs # 2. Add upstream remote git remote add upstream https://github.com/kaitranntt/ccs.git -# 3. ALWAYS start from latest BETA (not main!) -git checkout beta -git pull upstream beta +# 3. ALWAYS start from latest DEV (not main!) +git checkout dev +git pull upstream dev -# 4. Create feature branch FROM BETA +# 4. Create feature branch FROM DEV git checkout -b feat/my-feature # for features git checkout -b fix/bug-name # for bug fixes git checkout -b docs/update-readme # for documentation @@ -154,16 +154,16 @@ git commit -m "feat(scope): add new feature" # 6. Push to your fork git push -u origin feat/my-feature -# 7. Create PR targeting BETA (not main!) -gh pr create --base beta --title "feat(scope): add new feature" -# → After merge, your changes release to npm @beta for testing +# 7. Create PR targeting DEV (not main!) +gh pr create --base dev --title "feat(scope): add new feature" +# → After merge, your changes release to npm @dev for testing -# 8. Maintainers will promote tested beta to main +# 8. Maintainers will promote tested dev to main # → This triggers npm @latest release # 9. After PR merged, clean up -git checkout beta -git pull upstream beta +git checkout dev +git pull upstream dev git branch -d feat/my-feature ``` @@ -181,18 +181,18 @@ git checkout -b hotfix/critical-bug # 3. Fix and commit git commit -m "fix: critical security vulnerability" -# 4. PR directly to main (skip beta) +# 4. PR directly to main (skip dev) gh pr create --base main --title "fix: critical security vulnerability" -# 5. After merge, sync to beta +# 5. After merge, sync to dev # (Maintainers will handle this) ``` #### Rules -- **NEVER** commit directly to `main` or `beta` -- **ALWAYS** create branches from `beta` (not main) -- **ALWAYS** target PRs to `beta` (not main) +- **NEVER** commit directly to `main` or `dev` +- **ALWAYS** create branches from `dev` (not main) +- **ALWAYS** target PRs to `dev` (not main) - **ONLY** `hotfix/*` branches target `main` directly - **DELETE** branches after merge @@ -200,15 +200,15 @@ gh pr create --base main --title "fix: critical security vulnerability" #### Before Submitting -1. Ensure branch is from `beta` (not main) +1. Ensure branch is from `dev` (not main) 2. Ensure branch follows naming: `feat/*`, `fix/*`, `docs/*` 3. Run `bun run validate` - must pass -4. Rebase on latest beta: `git rebase beta` +4. Rebase on latest dev: `git rebase dev` 5. Test on all platforms if possible #### Pull Request Requirements -- **Target `beta` branch** (not main!) - unless hotfix +- **Target `dev` branch** (not main!) - unless hotfix - Clear description of changes - Testing instructions if applicable - Link to relevant issues @@ -401,7 +401,7 @@ Be respectful, constructive, and focused on the project's philosophy of simplici ### How Releases Work 1. **Write conventional commits** during development -2. **Merge PR to `main`** (or push to `beta`) +2. **Merge PR to `main`** (or push to `dev`) 3. **CI automatically:** - Analyzes commits since last release - Determines version bump from commit types @@ -415,7 +415,7 @@ Be respectful, constructive, and focused on the project's philosophy of simplici | Branch | npm Tag | Use Case | |--------|---------|----------| | `main` | `@latest` | Stable production releases | -| `beta` | `@beta` | Pre-release testing | +| `dev` | `@dev` | Pre-release testing | ### Workflow @@ -426,11 +426,11 @@ git commit -m "feat: add new feature" gh pr create --base main # → Merge PR → CI auto-releases to npm @latest -# Beta release -git checkout beta +# Dev release +git checkout dev git merge feat/experimental -git push origin beta -# → CI auto-releases to npm @beta +git push origin dev +# → CI auto-releases to npm @dev ``` **NEVER DO:** diff --git a/VERSION b/VERSION index 8a30e8f9..ef39ed80 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.4.0 +5.4.1-dev.1 diff --git a/docs/version-management.md b/docs/version-management.md index 90cd0788..45cd8ef2 100644 --- a/docs/version-management.md +++ b/docs/version-management.md @@ -9,14 +9,14 @@ CCS uses **semantic-release** for fully automated versioning and releases. Versi | Branch | npm Tag | Example | Description | |--------|---------|---------|-------------| | `main` | `@latest` | `5.1.0` | Stable production releases | -| `beta` | `@beta` | `5.1.0-beta.1` | Pre-release testing | +| `dev` | `@dev` | `5.1.0-dev.1` | Pre-release testing | ## How Releases Work ### Automatic Release (Default) 1. **Write conventional commits** during development -2. **Merge PR to `main`** (or push to `beta`) +2. **Merge PR to `main`** (or push to `dev`) 3. **CI automatically**: - Analyzes commits to determine version bump - Updates `CHANGELOG.md` @@ -70,15 +70,15 @@ gh pr create --base main # 3. Merge PR → CI auto-releases to npm @latest ``` -### Beta Release +### Dev Release ```bash -# 1. Switch to beta branch -git checkout beta +# 1. Switch to dev branch +git checkout dev git merge feat/experimental -# 2. Push → CI auto-releases to npm @beta -git push origin beta +# 2. Push → CI auto-releases to npm @dev +git push origin dev ``` ### Installing Different Channels @@ -87,11 +87,11 @@ git push origin beta # Stable (default) npm install -g @kaitranntt/ccs -# Beta -npm install -g @kaitranntt/ccs@beta +# Dev +npm install -g @kaitranntt/ccs@dev # Specific version -npm install -g @kaitranntt/ccs@5.1.0-beta.1 +npm install -g @kaitranntt/ccs@5.1.0-dev.1 ``` ## Version Files @@ -163,10 +163,10 @@ git commit --amend Check if commits include releasable types (`feat:`, `fix:`, `perf:`). Documentation-only commits (`docs:`) don't trigger releases. -### Beta out of sync with main +### Dev out of sync with main ```bash -git checkout beta +git checkout dev git rebase main -git push --force-with-lease origin beta +git push --force-with-lease origin dev ``` diff --git a/installers/install.ps1 b/installers/install.ps1 index 9db970c2..a24b7d9e 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.0" +$CcsVersion = "5.4.1-dev.1" # Try to read VERSION file for git installations if ($ScriptDir) { diff --git a/installers/install.sh b/installers/install.sh index 4e389816..5de1b2b8 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.0" +CCS_VERSION="5.4.1-dev.1" # Try to read VERSION file for git installations if [[ -f "$SCRIPT_DIR/VERSION" ]]; then diff --git a/package.json b/package.json index 0eaf83cd..584e8de2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kaitranntt/ccs", - "version": "5.4.0", + "version": "5.4.1-dev.1", "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6", "keywords": [ "cli", diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh index 2648450b..cf1df612 100755 --- a/scripts/bump-version.sh +++ b/scripts/bump-version.sh @@ -4,7 +4,7 @@ # # Releases are now automated via semantic-release: # - Merge to main → stable release (npm @latest) -# - Merge to beta → beta release (npm @beta) +# - Merge to dev → dev release (npm @dev) # # Version is determined automatically from conventional commits: # - feat: commit → MINOR bump (5.0.2 → 5.1.0) @@ -23,7 +23,7 @@ echo "=============================================================" echo "[!] DEPRECATED: This script is for emergency use only." echo "" echo " Releases are now automated via semantic-release." -echo " Simply merge to 'main' or 'beta' branch." +echo " Simply merge to 'main' or 'dev' branch." echo "" echo " Version is determined from conventional commits:" echo " feat: commit -> MINOR (5.0.2 -> 5.1.0)" diff --git a/src/cliproxy/auth-handler.ts b/src/cliproxy/auth-handler.ts index eb027268..4a192c33 100644 --- a/src/cliproxy/auth-handler.ts +++ b/src/cliproxy/auth-handler.ts @@ -94,8 +94,10 @@ function isHeadlessEnvironment(): boolean { return true; } - // Non-interactive (piped stdin) - if (!process.stdin.isTTY) { + // Non-interactive (piped stdin) - skip on Windows + // Windows npm wrappers don't set isTTY correctly (returns undefined, not true) + // Windows desktop environments always have browser capability + if (process.platform !== 'win32' && !process.stdin.isTTY) { return true; } diff --git a/src/commands/help-command.ts b/src/commands/help-command.ts index edac032a..8c065226 100644 --- a/src/commands/help-command.ts +++ b/src/commands/help-command.ts @@ -1,7 +1,11 @@ +import * as fs from 'fs'; +import * as path from 'path'; import { initUI, box, color, dim, sectionHeader, subheader } from '../utils/ui'; -// Version is read from VERSION file during build -const VERSION = '5.3.0'; +// Get version from package.json (same as version-command.ts) +const VERSION = JSON.parse( + fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf8') +).version; /** * Print a major section with ═══ borders (only for 3 main sections) diff --git a/src/management/doctor.ts b/src/management/doctor.ts index ae9a98d4..51e9f5c8 100644 --- a/src/management/doctor.ts +++ b/src/management/doctor.ts @@ -6,7 +6,8 @@ import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; import { spawn } from 'child_process'; -import { detectClaudeCli } from '../utils/claude-detector'; +import { getClaudeCliInfo } from '../utils/claude-detector'; +import { escapeShellArg } from '../utils/shell-executor'; import { initUI, header, box, table, color, ok, fail, warn, info } from '../utils/ui'; import packageJson from '../../package.json'; import { @@ -180,9 +181,9 @@ class Doctor { private async checkClaudeCli(): Promise { const spinner = ora('Checking Claude CLI').start(); - const claudeCli = detectClaudeCli(); + const cliInfo = getClaudeCliInfo(); - if (!claudeCli) { + if (!cliInfo) { spinner.fail(); console.log(` ${fail('Claude CLI'.padEnd(22))} Not found in PATH`); this.results.addCheck( @@ -195,13 +196,23 @@ class Doctor { return; } + const { path: claudeCli, needsShell } = cliInfo; + // Try to execute claude --version try { const result = await new Promise((resolve, reject) => { - const child = spawn(claudeCli, ['--version'], { - stdio: 'pipe', - timeout: 5000, - }); + // When shell is needed (Windows .cmd/.bat files), concatenate into string + // to avoid DEP0190 warning about passing args with shell: true + const child = needsShell + ? spawn([claudeCli, '--version'].map(escapeShellArg).join(' '), { + stdio: 'pipe', + timeout: 5000, + shell: true, + }) + : spawn(claudeCli, ['--version'], { + stdio: 'pipe', + timeout: 5000, + }); let output = ''; child.stdout?.on('data', (data: Buffer) => (output += data));