diff --git a/.ccs.example.json b/.ccs.example.json index a72ad40b..063c868c 100644 --- a/.ccs.example.json +++ b/.ccs.example.json @@ -5,3 +5,4 @@ "default": "~/.claude/settings.json" } } + diff --git a/README.md b/README.md index 6d6a24c6..daf093fb 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,23 @@ [![Bash](https://img.shields.io/badge/bash-3.2%2B-blue.svg)](https://www.gnu.org/software/bash/) [![GitHub Stars](https://img.shields.io/github/stars/kaitranntt/ccs.svg)](https://github.com/kaitranntt/ccs/stargazers) -> Ultra-simple Claude CLI profile switcher. One command instead of long paths. +> Switch between Claude Sonnet 4.5 and GLM 4.6 instantly. Use the right model for each task. -**Before**: `claude --settings ~/.claude/glm.settings.json --verbose` -**After**: `ccs glm --verbose` +**The Problem**: You have both Claude subscription and GLM Coding Plan. Two scenarios happen daily: +1. **Rate limits**: Claude hits limit mid-project, you manually edit `~/.claude/settings.json` to switch +2. **Task optimization**: Complex planning needs Claude Sonnet 4.5's intelligence, but simple coding works fine with GLM 4.6 + +Manual switching is tedious and error-prone. + +**The Solution**: +```bash +ccs sonnet # Complex refactoring? Use Claude Sonnet 4.5 +ccs glm # Simple bug fix? Use GLM 4.6 +# Hit rate limit? Switch instantly: +ccs glm # Continue working with GLM +``` + +One command. Zero downtime. No file editing. Right model, right task. ## Quick Start @@ -39,12 +52,49 @@ ccs sonnet # Use Sonnet profile ## Why CCS? -Claude CLI's `--settings` flag is powerful but verbose. CCS gives you friendly aliases. +**Built for developers with both Claude subscription and GLM Coding Plan.** -**Features**: -- Single command profile switching +### Two Real Use Cases + +#### 1. Task-Appropriate Model Selection +**Claude Sonnet 4.5** excels at: +- Complex architectural decisions +- System design and planning +- Debugging tricky issues +- Code reviews requiring deep reasoning + +**GLM 4.6** works great for: +- Simple bug fixes +- Straightforward implementations +- Routine refactoring +- Documentation writing + +**With CCS**: Switch models based on task complexity, maximize quality while managing costs. + +```bash +ccs sonnet # Planning new feature architecture +# Got the plan? Implement with GLM: +ccs glm # Write the straightforward code +``` + +#### 2. Rate Limit Management +If you have both Claude subscription and GLM Coding Plan, you know the pain: +- Claude hits rate limit mid-project +- You manually copy GLM config to `~/.claude/settings.json` +- 5 minutes later, need to switch back +- Repeat 10x per day + +**CCS solves this**: +- One command to switch: `ccs glm` or `ccs sonnet` +- Keep both configs saved as profiles +- Switch in <1 second +- No file editing, no copy-paste, no mistakes + +### Features +- Instant profile switching (Claude ↔ GLM) - Pass-through all Claude CLI args -- Zero configuration complexity +- Smart setup: detects your current provider +- Auto-creates configs during install - No proxies, no magic—just bash + jq ## Installation @@ -119,31 +169,71 @@ ccs glm ## Use Cases -### Claude Subscription + GLM Coding Plan +### Real Workflow: Task-Based Model Selection -Switch between Claude sub and GLM plan: +**Scenario**: Building a new payment integration feature +```bash +# Step 1: Architecture & Planning (needs Claude's intelligence) +ccs sonnet +/plan "Design payment integration with Stripe, handle webhooks, errors, retries" +# → Claude Sonnet 4.5 thinks deeply about edge cases, security, architecture + +# Step 2: Implementation (straightforward coding, use GLM) +ccs glm +/code "implement the payment webhook handler from the plan" +# → GLM 4.6 writes the code efficiently, saves Claude usage + +# Step 3: Code Review (needs deep analysis) +ccs sonnet +/review "check the payment handler for security issues" +# → Claude Sonnet 4.5 catches subtle vulnerabilities + +# Step 4: Bug Fixes (simple) +ccs glm +/fix "update error message formatting" +# → GLM 4.6 handles routine fixes +``` + +**Result**: Best model for each task, lower costs, better quality. + +### Real Workflow: Rate Limit Management + +```bash +# Working on complex refactoring with Claude +ccs sonnet +/plan "refactor authentication system" + +# Claude hits rate limit mid-task +# → Error: Rate limit exceeded + +# Switch to GLM instantly +ccs glm +# Continue working without interruption + +# Rate limit resets? Switch back +ccs sonnet +``` + +### Configuration Examples + +**Standard setup** (Claude sub + GLM): ```json { "profiles": { - "claude": "~/.claude/claude-sub.settings.json", "glm": "~/.claude/glm.settings.json", + "sonnet": "~/.claude/sonnet.settings.json", "default": "~/.claude/settings.json" } } ``` -```bash -ccs claude # Use Claude subscription -ccs glm # Use GLM coding plan -``` - -### Different Models - +**Advanced setup** (multiple providers): ```json { "profiles": { "sonnet": "~/.claude/sonnet.settings.json", + "glm": "~/.claude/glm.settings.json", "haiku": "~/.claude/haiku.settings.json", "default": "~/.claude/settings.json" } diff --git a/install.sh b/install.sh index 4d423300..8df38f2a 100755 --- a/install.sh +++ b/install.sh @@ -60,26 +60,155 @@ fi echo "✅ Installation complete!" echo "" -echo "Next steps:" -if [[ ! -f "$HOME/.ccs.json" ]]; then - if [[ -f "$SCRIPT_DIR/.ccs.example.json" ]]; then - echo "1. Copy example config: cp $SCRIPT_DIR/.ccs.example.json ~/.ccs.json" + +# Smart setup: detect current provider and help create profiles +CLAUDE_DIR="$HOME/.claude" +CURRENT_SETTINGS="$CLAUDE_DIR/settings.json" +GLM_SETTINGS="$CLAUDE_DIR/glm.settings.json" +SONNET_SETTINGS="$CLAUDE_DIR/sonnet.settings.json" + +# Detect current provider +CURRENT_PROVIDER="unknown" +if [[ -f "$CURRENT_SETTINGS" ]]; then + if grep -q "api.z.ai" "$CURRENT_SETTINGS" 2>/dev/null || grep -q "glm-4" "$CURRENT_SETTINGS" 2>/dev/null; then + CURRENT_PROVIDER="glm" + elif grep -q "ANTHROPIC_BASE_URL" "$CURRENT_SETTINGS" 2>/dev/null && ! grep -q "api.z.ai" "$CURRENT_SETTINGS" 2>/dev/null; then + CURRENT_PROVIDER="custom" else - echo "1. Create config at ~/.ccs.json:" - echo " {" - echo " \"profiles\": {" - echo " \"glm\": \"~/.claude/glm.settings.json\"," - echo " \"sonnet\": \"~/.claude/sonnet.settings.json\"," - echo " \"default\": \"~/.claude/settings.json\"" - echo " }" - echo " }" + CURRENT_PROVIDER="claude" fi - echo "2. Edit ~/.ccs.json with your profile mappings" - echo "3. Run: ccs [profile]" -else - echo "1. Config already exists at ~/.ccs.json" - echo "2. Run: ccs [profile]" fi + +# Check for existing profile files +HAS_GLM=false +HAS_SONNET=false +[[ -f "$GLM_SETTINGS" ]] && HAS_GLM=true +[[ -f "$SONNET_SETTINGS" ]] && HAS_SONNET=true + +# Smart setup guidance +if [[ "$CURRENT_PROVIDER" != "unknown" ]]; then + echo "🔍 Detected current provider: $CURRENT_PROVIDER" + echo "" +fi + +# Offer to create missing profiles +if [[ "$HAS_GLM" == false ]] || [[ "$HAS_SONNET" == false ]]; then + echo "📝 Setup wizard: Creating profile files..." + echo "" + + # Create GLM profile if missing + if [[ "$HAS_GLM" == false ]]; then + if [[ "$CURRENT_PROVIDER" == "glm" ]]; then + echo "✓ Copying current GLM config to profile..." + cp "$CURRENT_SETTINGS" "$GLM_SETTINGS" + echo " Created: $GLM_SETTINGS" + else + echo "Creating GLM profile template at $GLM_SETTINGS" + # Preserve user's existing env vars if they exist + if [[ -f "$CURRENT_SETTINGS" ]] && command -v jq &> /dev/null; then + # Merge user's env with GLM essentials (atomic operation) + if jq '.env |= (. // {}) + { + "ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic", + "ANTHROPIC_AUTH_TOKEN": "YOUR_GLM_API_KEY_HERE", + "ANTHROPIC_MODEL": "glm-4.6" + }' "$CURRENT_SETTINGS" > "$GLM_SETTINGS.tmp" 2>/dev/null; then + mv "$GLM_SETTINGS.tmp" "$GLM_SETTINGS" + else + rm -f "$GLM_SETTINGS.tmp" + echo " ℹ️ jq failed, using basic template" + # Fallback to minimal template + cat > "$GLM_SETTINGS" << 'EOF' +{ + "env": { + "ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic", + "ANTHROPIC_AUTH_TOKEN": "YOUR_GLM_API_KEY_HERE", + "ANTHROPIC_MODEL": "glm-4.6" + } +} +EOF + fi + else + # Minimal GLM template + cat > "$GLM_SETTINGS" << 'EOF' +{ + "env": { + "ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic", + "ANTHROPIC_AUTH_TOKEN": "YOUR_GLM_API_KEY_HERE", + "ANTHROPIC_MODEL": "glm-4.6" + } +} +EOF + fi + echo " Created: $GLM_SETTINGS" + echo " ⚠️ Edit this file and replace YOUR_GLM_API_KEY_HERE with your actual GLM API key" + fi + echo "" + fi + + # Create Sonnet profile if missing + if [[ "$HAS_SONNET" == false ]]; then + if [[ "$CURRENT_PROVIDER" == "claude" ]]; then + echo "✓ Copying current Claude config to profile..." + cp "$CURRENT_SETTINGS" "$SONNET_SETTINGS" + echo " Created: $SONNET_SETTINGS" + else + echo "Creating Claude Sonnet profile template at $SONNET_SETTINGS" + # Preserve user's existing settings, remove GLM-specific fields + if [[ -f "$CURRENT_SETTINGS" ]] && command -v jq &> /dev/null; then + # Remove GLM-specific env vars, keep user's other settings (atomic) + if jq 'del(.env.ANTHROPIC_BASE_URL, .env.ANTHROPIC_AUTH_TOKEN, .env.ANTHROPIC_MODEL) | + if (.env | length) == 0 then .env = {} else . end' "$CURRENT_SETTINGS" > "$SONNET_SETTINGS.tmp" 2>/dev/null; then + mv "$SONNET_SETTINGS.tmp" "$SONNET_SETTINGS" + else + rm -f "$SONNET_SETTINGS.tmp" + echo " ℹ️ jq failed, using basic template" + # Fallback to minimal template + cat > "$SONNET_SETTINGS" << 'EOF' +{ + "env": {} +} +EOF + fi + else + # Minimal Claude template (uses default authentication) + cat > "$SONNET_SETTINGS" << 'EOF' +{ + "env": {} +} +EOF + fi + echo " Created: $SONNET_SETTINGS" + echo " ℹ️ This uses your Claude subscription (no API key needed)" + fi + echo "" + fi +fi + +# Auto-create ~/.ccs.json if missing (atomic operation) +if [[ ! -f "$HOME/.ccs.json" ]]; then + echo "Creating ~/.ccs.json config..." + cat > "$HOME/.ccs.json.tmp" << 'EOF' +{ + "profiles": { + "glm": "~/.claude/glm.settings.json", + "sonnet": "~/.claude/sonnet.settings.json", + "default": "~/.claude/settings.json" + } +} +EOF + # Atomic move only if file still doesn't exist (prevents race condition) + if mv -n "$HOME/.ccs.json.tmp" "$HOME/.ccs.json" 2>/dev/null; then + echo " ✓ Created: ~/.ccs.json" + else + rm -f "$HOME/.ccs.json.tmp" + echo " ℹ️ Config already exists" + fi + echo "" +fi + +echo "✅ Setup complete!" +echo "" +echo "Quick start:" echo "" echo "Example:" echo " ccs # Uses default profile"