Skip to content

Conversation

jookwang-park
Copy link

I'm a big fan of this project! I've implemented some features that I needed during my usage. I'd love to get your feedback and review.

Overview

Add --model CLI option to override the default model configuration at runtime

Objective

Currently, Claude Code Router uses the model configuration from config.json for all requests. Users need to manually edit the configuration file to use a different model temporarily. This PR adds a --model command-line option that allows users to override the default model for a specific ccr code execution without modifying the configuration file.

Solution

Implemented a model override mechanism by leveraging the existing auth token communication channel between the CLI client and server:

  1. CLI Argument Parsing (src/cli.ts):
    - Added parsing for --model option in the code command
    - Format: ccr code --model provider,model "prompt"
    - Updated help text with usage examples
  2. Inter-Process Communication (src/utils/codeCommand.ts):
    - Since CLI and server run in separate processes, embedded model override in auth token
    - Format: test:MODEL:{encoded_model} where commas are encoded as ___
    - This approach works reliably because Claude CLI forwards ANTHROPIC_AUTH_TOKEN
  3. Server-Side Handling (src/index.ts):
    - Added preHandler hook to extract model override from auth token
    - Decodes the model string and overrides the router configuration
    - Only affects the specific request, not global configuration

Usage Example

# Use a different model for a single request
ccr code --model openrouter,anthropic/claude-opus-4 "Write a function"

# Default model from config.json
ccr code "Explain this code"

@kierr
Copy link

kierr commented Aug 16, 2025

--model (and any other arg) is passed on to claude already. Since ccr supports /model... I would have this to work just fine...

@jookwang-park
Copy link
Author

--model (and any other arg) is passed on to claude already. Since ccr supports /model... I would have this to work just fine...

Specifically, if you understand how CCR works, you'll know why /model doesn't work. CCR spawns the Claude code, and the parameters are passed to it based on the settings in CCR's config.json. Therefore, if a parameter is not defined in CCR's configuration, it cannot be used by the Claude code. To solve this, I've created a feature to override the default model information in config.json and improved it so that it can be used within the Claude code.

@kierr
Copy link

kierr commented Aug 20, 2025

https://github.com/musistudio/claude-code-router?tab=readme-ov-file#-features

Dynamic Model Switching: Switch models on-the-fly within Claude Code using the /model command.

Does the README.md also not "understand how CCR works"?!

You've vibe coded a convoluted and overly complex feature, that is already built in...

❯ ccr code --model 'abcd,not/real'
╭───────────────────────────────────────────────────╮
│ ✻ Welcome to Claude Code!                         │
│                                                   │
│   /help for help, /status for your current setup  │
│                                                   │
│   cwd: /Users/user/Repos/github.com/herp-derp     │
│                                                   │
│   ─────────────────────────────────────────────── │
│                                                   │
│   Overrides (via env):                            │
│                                                   │
│   • API timeout: 600000ms                         │
│   • API Base URL: http://127.0.0.1:3456           │
╰───────────────────────────────────────────────────╯
╭──────────────────────────────────────────────────────────────────────╮
│                                                                      │
│  Select Model                                                        │
│  Switch between Claude models. Applies to this session and future    │
│  Claude Code sessions. For custom model names, specify with          │
│  --model.                                                            │
│                                                                      │
│     1. Default (recommended)  Use the default model (currently       │
│     Sonnet 4) · $3/$15 per Mtok                                      │
│    2. Opus                   Opus 4.1 for complex tasks · $15/$75    │
│    per Mtok                                                          │
│     3. Opus Plan Mode         Use Opus 4.1 in plan mode, Sonnet 4    │
│     otherwise                                                        │
│   ❯ 4. abcd,not/real          Custom model✔                          │
│                                                                      │
╰──────────────────────────────────────────────────────────────────────╯
 Enter to confirm · Esc to exit
 
> /model
  ⎿  Kept model as abcd,not/real

> test
  ⎿ API Error: 404 {"error":{"message":"Provider 'abcd' not
    foundError: Provider 'abcd' not found\n    at bt
    (/opt/homebrew/lib/node_modules/@musistudio/claude-code-router/
    dist/cli.js:74721:11)\n    at o0 (/opt/homebrew/lib/node_module
    s/@musistudio/claude-code-router/dist/cli.js:74745:17)\n    at
    Object.<anonymous> (/opt/homebrew/lib/node_modules/@musistudio/
    claude-code-router/dist/cli.js:74795:86)\n    at
    preHandlerCallbackInner (/opt/homebrew/lib/node_modules/@musist
    udio/claude-code-router/dist/cli.js:4522:28)\n    at
    preHandlerCallback (/opt/homebrew/lib/node_modules/@musistudio/
    claude-code-router/dist/cli.js:4494:9)\n    at next
    (/opt/homebrew/lib/node_modules/@musistudio/claude-code-router/
    dist/cli.js:3661:13)\n    at handleResolve
    (/opt/homebrew/lib/node_modules/@musistudio/claude-code-router/
    dist/cli.js:3676:11)\n    at process.processTicksAndRejections
    (node:internal/process/task_queues:105:5)","type":"api_error","
    code":"provider_not_found"}}

> /model humans,hallucinate/too
  ⎿  Set model to humans,hallucinate/too

> hi
  ⎿ API Error: 404 {"error":{"message":"Provider 'humans' not
    foundError: Provider 'humans' not found\n    at bt
    (/opt/homebrew/lib/node_modules/@musistudio/claude-code-router/
    dist/cli.js:74721:11)\n    at o0 (/opt/homebrew/lib/node_module
    s/@musistudio/claude-code-router/dist/cli.js:74745:17)\n    at
    Object.<anonymous> (/opt/homebrew/lib/node_modules/@musistudio/
    claude-code-router/dist/cli.js:74795:86)\n    at
    preHandlerCallbackInner (/opt/homebrew/lib/node_modules/@musist
    udio/claude-code-router/dist/cli.js:4522:28)\n    at
    preHandlerCallback (/opt/homebrew/lib/node_modules/@musistudio/
    claude-code-router/dist/cli.js:4494:9)\n    at next
    (/opt/homebrew/lib/node_modules/@musistudio/claude-code-router/
    dist/cli.js:3661:13)\n    at handleResolve
    (/opt/homebrew/lib/node_modules/@musistudio/claude-code-router/
    dist/cli.js:3676:11)\n    at process.processTicksAndRejections
    (node:internal/process/task_queues:105:5)","type":"api_error","
    code":"provider_not_found"}}


╭──────────────────────────────────────────────────────────────────────╮
│ >                                                                    │
╰──────────────────────────────────────────────────────────────────────╯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants