# CLAUDE.md AI-facing guidance for Claude Code when working with this repository. ## Core Function CLI wrapper for instant switching between multiple Claude accounts and alternative models (GLM, GLMT, Kimi). See README.md for user documentation. ## Design Principles (ENFORCE STRICTLY) - **YAGNI**: No features "just in case" - **KISS**: Simple bash/PowerShell/Node.js only - **DRY**: One source of truth (config.json) - **CLI-First**: All features must have CLI interface ## Quality Gates (MANDATORY) Quality gates MUST pass before committing. Run from project root. ### Main Project (src/) ```bash # Full validation (REQUIRED before commit/PR) bun run validate # typecheck + lint:fix + format:check + test:all # Individual commands bun run typecheck # tsc --noEmit bun run lint:fix # eslint src/ --fix bun run format:check # prettier --check src/ bun run test:all # bun test # Fix issues bun run lint:fix # Auto-fix lint issues bun run format # Auto-fix formatting (prettier --write) ``` **ESLint rules (eslint.config.mjs) - ALL errors:** | Rule | Level | Notes | |------|-------|-------| | `@typescript-eslint/no-unused-vars` | error | Ignore `_` prefix | | `@typescript-eslint/no-explicit-any` | error | Use proper types or `unknown` | | `@typescript-eslint/no-non-null-assertion` | error | No `!` assertions | | `prefer-const`, `no-var`, `eqeqeq` | error | Code quality | **TypeScript (tsconfig.json) - strict mode:** | Option | Value | Notes | |--------|-------|-------| | `strict` | true | All strict flags enabled | | `noUnusedLocals` | true | No unused variables | | `noUnusedParameters` | true | No unused params | | `noImplicitReturns` | true | All paths must return | | `noFallthroughCasesInSwitch` | true | Explicit case handling | ### UI Project (ui/) ```bash cd ui # Full validation (REQUIRED before commit/PR) bun run validate # typecheck + lint:fix + format:check (no tests) # Individual commands bun run typecheck # tsc -b --noEmit bun run lint:fix # eslint . --fix bun run format:check # prettier --check src/ # Fix issues bun run lint:fix # Auto-fix lint issues bun run format # Auto-fix formatting ``` **ESLint rules (ui/eslint.config.js) - ALL errors:** | Rule | Level | Notes | |------|-------|-------| | `@typescript-eslint/no-unused-vars` | error | Ignore `_` prefix | | `@typescript-eslint/no-explicit-any` | error | Use proper types or `unknown` | | `@typescript-eslint/no-non-null-assertion` | error | No `!` assertions | | `prefer-const`, `no-var`, `eqeqeq` | error | Code quality | | `react-hooks/*` | recommended | Hooks rules from plugin | | `react-refresh/*` | vite | Fast refresh compatibility | **TypeScript (ui/tsconfig.app.json) - strict mode:** | Option | Value | Notes | |--------|-------|-------| | `strict` | true | All strict flags enabled | | `noUnusedLocals` | true | No unused variables | | `noUnusedParameters` | true | No unused params | | `noFallthroughCasesInSwitch` | true | Explicit case handling | | `erasableSyntaxOnly` | true | No runtime type constructs | | `noUncheckedSideEffectImports` | true | Validate side-effect imports | ### Automatic Enforcement - `prepublishOnly` / `prepack` runs `build:all` + `validate` + `sync-version.js` - CI/CD runs `bun run validate` on every PR - husky pre-commit hooks enforce conventional commits ### File Structure ``` src/ → TypeScript source (main project) dist/ → Compiled JavaScript (npm package) lib/ → Native shell scripts (bash, PowerShell) ui/src/ → React components, hooks, pages ui/src/components/ui/ → shadcn/ui components dist/ui/ → Built UI bundle (served by Express) ``` ### Development Server ```bash bun run dev # Build + start config server (http://localhost:3000) ``` **IMPORTANT:** Use `bun run dev` at CCS root for always up-to-date code. Do NOT use `ccs config` during development as it uses the globally installed version. ## Critical Constraints (NEVER VIOLATE) 1. **NO EMOJIS** - ASCII only: [OK], [!], [X], [i] 2. **TTY-aware colors** - Respect NO_COLOR env var 3. **Non-invasive** - NEVER modify `~/.claude/settings.json` 4. **Cross-platform parity** - bash/PowerShell/Node.js must behave identically 5. **CLI documentation** - ALL changes MUST update `--help` in src/ccs.ts, lib/ccs, lib/ccs.ps1 6. **Idempotent** - All install operations safe to run multiple times ## Key Technical Details ### Profile Mechanisms (Priority Order) 1. **CLIProxy hardcoded**: gemini, codex, agy → OAuth-based, zero config 2. **CLIProxy variants**: `config.cliproxy` section → user-defined providers 3. **Settings-based**: `config.profiles` section → GLM, GLMT, Kimi 4. **Account-based**: `profiles.json` → isolated instances via `CLAUDE_CONFIG_DIR` ### Settings Format (CRITICAL) All env values MUST be strings (not booleans/objects) to prevent PowerShell crashes. ```json { "env": { "ANTHROPIC_BASE_URL": "https://api.example.com/anthropic", "ANTHROPIC_AUTH_TOKEN": "your-api-key", "ANTHROPIC_MODEL": "model-name" } } ``` ### Shared Data Architecture Symlinked from `~/.ccs/shared/`: commands/, skills/, agents/ Profile-specific: settings.json, sessions/, todolists/, logs/ Windows fallback: Copies if symlinks unavailable ## Code Standards (REQUIRED) ### Architecture - `lib/ccs`, `lib/ccs.ps1` - Bootstrap scripts (delegate to Node.js via npx) - `src/*.ts` → `dist/*.js` - Main implementation (TypeScript) ### Bash (lib/*.sh) - bash 3.2+, `set -euo pipefail`, quote all vars `"$VAR"`, `[[ ]]` tests - NO external dependencies ### PowerShell (lib/*.ps1) - PowerShell 5.1+, `$ErrorActionPreference = "Stop"` - Native JSON only, no external dependencies ### TypeScript (src/*.ts) - Node.js 14+, Bun 1.0+, TypeScript 5.3, strict mode - `child_process.spawn`, handle SIGINT/SIGTERM - Run `bun run validate` before committing ### Terminal Output (ENFORCE) - ASCII only: [OK], [!], [X], [i] (NO emojis) - TTY detect before colors, respect NO_COLOR - Box borders for errors: ╔═╗║╚╝ ## Conventional Commits (MANDATORY) **ALL commits MUST follow conventional commit format. Non-compliant commits are rejected by husky.** ### Commit Format ``` (): [optional body] [optional footer] ``` ### Commit Types (determines version bump) | Type | Version Bump | Use For | |------|--------------|---------| | `feat:` | MINOR | New features | | `fix:` | PATCH | Bug fixes | | `perf:` | PATCH | Performance improvements | | `feat!:` | MAJOR | Breaking changes | | `docs:` | None | Documentation only | | `style:` | None | Formatting, no code change | | `refactor:` | None | Code restructure | | `test:` | None | Adding tests | | `chore:` | None | Maintenance | | `ci:` | None | CI/CD changes | | `build:` | None | Build system | ### Examples ```bash # Good - will be accepted git commit -m "feat(cliproxy): add OAuth token refresh" git commit -m "fix(doctor): handle missing config gracefully" git commit -m "feat!: remove deprecated GLMT proxy" # BREAKING CHANGE # Bad - will be REJECTED git commit -m "added new feature" git commit -m "Fixed bug" git commit -m "WIP" ``` ## Branching Strategy (FOLLOW STRICTLY) ### Branch Hierarchy ``` main (production) ← dev (integration) ← feat/* | fix/* | docs/* ↑ ↑ │ └── All development merges here FIRST │ └── Only receives: (1) Tested code from dev, (2) Hotfixes ``` ### Branch Types | Branch | Purpose | Merges From | Releases To | |--------|---------|-------------|-------------| | `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 ``` / # Examples: feat/oauth-token-refresh fix/doctor-missing-config docs/update-installation-guide hotfix/critical-auth-bug ``` ### Standard Development Workflow (Features/Fixes → Dev → Main) ```bash # 1. ALWAYS start from dev (integration branch) git checkout dev git pull origin dev # 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 DEV (not main!) git push -u origin feat/my-feature gh pr create --base dev --title "feat(scope): add new feature" # → Merge triggers npm @dev release for testing # 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 dev git pull origin dev git branch -d feat/my-feature ``` ### Hotfix Workflow (Critical Production Fixes Only) ```bash # 1. Start from main (production) git checkout main git pull origin main # 2. Create hotfix branch git checkout -b hotfix/critical-bug # 3. Fix and commit git commit -m "fix: critical authentication bypass" # 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 dev git checkout dev git pull origin dev git merge main git push origin dev # 6. Clean up git branch -d hotfix/critical-bug ``` ### Keeping Dev in Sync with Main ```bash # After any main release, sync to dev git checkout dev git pull origin dev git merge main git push origin dev ``` ### Rules 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. **`dev` must always be up-to-date with `main`** 5. **Delete feature branches after merge** 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) **Releases are FULLY AUTOMATED via semantic-release. NEVER manually bump versions or create tags.** ### Release Channels | Branch | npm Tag | When | |--------|---------|------| | `main` | `@latest` | Merge PR to main | | `dev` | `@dev` | Push to dev branch | ### What CI Does Automatically 1. Analyzes commits since last release 2. Determines version bump from commit types 3. Updates `CHANGELOG.md`, `VERSION`, `package.json`, installers 4. Creates git tag 5. Publishes to npm 6. Creates GitHub release **NEVER DO:** - `./scripts/bump-version.sh` (deprecated, emergency only) - `git tag vX.Y.Z` (tags are auto-created) - Manual `npm publish` (CI handles it) - Commit directly to `main` ## Development Workflows ### Testing (REQUIRED before PR) ```bash bun run test # All tests bun run test:npm # npm package tests bun run test:native # Native install tests bun run test:unit # Unit tests ``` ### Local Development ```bash ./scripts/dev-install.sh # Build, pack, install globally rm -rf ~/.ccs # Clean environment ``` ## Development Tasks (FOLLOW STRICTLY) ### New Feature Checklist 1. Verify YAGNI/KISS/DRY alignment - reject if doesn't align 2. Implement in TypeScript (`src/*.ts`) 3. **REQUIRED**: Update `--help` in src/ccs.ts, lib/ccs, lib/ccs.ps1 4. Add unit tests (`tests/unit/**/*.test.js`) 5. Run `bun run validate` 6. Update README.md if user-facing 7. **Commit with**: `git commit -m "feat(scope): description"` ### Bug Fix Checklist 1. Add regression test first 2. Fix in TypeScript (or native scripts if bootstrap-related) 3. Run `bun run validate` 4. **Commit with**: `git commit -m "fix(scope): description"` ## Pre-PR Checklist (MANDATORY) **Quality Gates:** - [ ] `bun run validate` passes (main: typecheck + lint:fix + format:check + tests) - [ ] `cd ui && bun run validate` passes (ui: typecheck + lint:fix + format:check) **Code Quality:** - [ ] All commits follow conventional format (`feat:`, `fix:`, etc.) - [ ] `--help` updated and consistent across src/ccs.ts, lib/ccs, lib/ccs.ps1 - [ ] ASCII only (NO emojis), NO_COLOR respected - [ ] Idempotent install, concurrent sessions work, instance isolation maintained - [ ] **DO NOT** manually bump version or create tags ## Error Handling Principles - Validate early, fail fast with clear messages - Show available options on mistakes - Never leave broken state