Crush Setup
Add QCode.cc as a custom provider in Charm Crush: type=anthropic plus base_url in crush.json, and use Claude from the terminal
On This Page
Last verified: 2026-09-18 · 📄 Per official docs (Crush v0.95.0, released 2026-09-16)
At a glance¶
| Item | Details |
|---|---|
| Models you can use | Claude ✅ (type: anthropic) · GPT ✅ · Chinese models ✅ (openai-compat) · Gemini ❌ (no Gemini route documented here) |
| Protocol & Base URL | Anthropic: https://api.qcode.cc/api · OpenAI: https://api.qcode.cc/openai/v1 |
| Where to configure | project-level crush.json / user-level ~/.config/crush/crush.json |
| Official docs | charmbracelet/crush |
| Crush is Charm's terminal-first AI coding agent (written in Go). It supports custom providers, so QCode.cc can be its upstream. |
Naming note: the repository was originally
charmbracelet/opencodeand is nowcrush(the old URL 301-redirects; upstream never stated the reason). It is a different project from OpenCode (opencode.ai) — and note that Crush also ships a built-in model upstream calledopencode, yet another Charm-side thing, not to be confused.
Which protocol¶
Crush's custom providers accept anthropic and openai-compat as type. For Claude, use anthropic — QCode's OpenAI endpoint does not accept Claude models (see Endpoints & API Paths).
| Model you want | type |
base_url |
|---|---|---|
| Claude | anthropic |
https://api.qcode.cc/api |
| GPT / the four Chinese families | openai-compat |
https://api.qcode.cc/openai/v1 |
Install¶
# Homebrew
brew install charmbracelet/tap/crush
# or download a prebuilt binary from Releases
# https://github.com/charmbracelet/crush/releases
Verify (trust the actual output, not a version number in any doc):
crush --version
Configure¶
Create crush.json in the project root, or user-level at ~/.config/crush/crush.json (= $XDG_CONFIG_HOME/crush/crush.json; note ~/.local/share/crush/ holds state files the official docs say not to edit). Newer upstream also promotes a crushrc (Bash DSL) format; JSON config is still read:
{
"$schema": "https://charm.land/crush.json",
"providers": {
"qcode": {
"type": "anthropic",
"base_url": "https://api.qcode.cc/api",
"api_key": "$QCODE_KEY",
"extra_headers": { "anthropic-version": "2023-06-01" },
"models": [
{
"id": "claude-sonnet-5",
"name": "QCode Sonnet 5",
"cost_per_1m_in": 2,
"cost_per_1m_out": 10,
"context_window": 1000000,
"default_max_tokens": 8192,
"cost_per_1m_in_cached": 0.2,
"cost_per_1m_out_cached": 2.5,
"can_reason": true,
"supports_attachments": true
},
{
"id": "claude-haiku-4-5",
"name": "QCode Haiku 4.5",
"cost_per_1m_in": 1,
"cost_per_1m_out": 5,
"context_window": 200000,
"default_max_tokens": 4096,
"cost_per_1m_in_cached": 0.1,
"cost_per_1m_out_cached": 1.25,
"can_reason": true,
"supports_attachments": true
}
]
}
}
}
Inject the key through the environment rather than writing it into the file:
export QCODE_KEY="cr_your_qcode_key"
| Field | Meaning |
|---|---|
type |
anthropic selects the native Messages protocol |
base_url |
Stop at /api — Crush appends /v1/messages itself |
api_key |
Supports $VAR environment expansion |
extra_headers |
The Anthropic protocol needs anthropic-version |
models[] |
Listing models lets you override cost / context parameters; omit it and Crush auto-discovers via <base>/v1/models (discover_models defaults to on). Each id must match qcode.cc/models character for character |
From mainland China, swap the host for
https://asia.qcode.cc/api(Asia node, nearest of Korea / Taiwan / Hong Kong); the key is unchanged.cost_per_1m_*(including the two*_cachedkeys the official schema requires) only affects Crush's own usage-estimate display, not actual billing — the sample numbers follow a typical cache ratio; adjust them to the real cached rates on qcode.cc/models.
Verify¶
crush run "reply with exactly: OK"
OK means you are connected.
To prove the traffic really goes to QCode, deliberately point base_url at a path that does not exist and run again. You should see an explicit 404 echoing the full URL:
404 Not Found {"error":"Not Found","message":"Route /api/xxx/v1/messages not found"}
That error proves Crush is composing base_url + /v1/messages and that your config took effect. (This is a negative control: a success alone does not prove your provider was used — Crush might have fallen back to another one.)
Everyday usage¶
# interactive
crush
# non-interactive
crush run "make this function async"
# pipes
cat README.md | crush run "make this clearer" > README.new.md
# specific directory with debug logging
crush --debug --cwd /path/to/project
# auto-accept every permission (use with care)
crush --yolo
Troubleshooting¶
model_not_available_on_endpoint¶
type is openai-compat while the model is a Claude one. Switch to type: "anthropic" with base_url = https://api.qcode.cc/api.
401 Invalid API key¶
The environment variable was not injected, or the key has stray whitespace. Check that echo $QCODE_KEY starts with cr_.
The model does not appear in the picker¶
Crush only shows models listed explicitly in models[]. Add an entry and restart.
Related¶
- Endpoints & API Paths — protocol × model-family table
- OpenCode Integration — a different terminal agent (not the same project)
- Chinese Models — GLM / Kimi / DeepSeek / Qwen