# Crush Setup

> **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](https://github.com/charmbracelet/crush)
[Crush](https://github.com/charmbracelet/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/opencode` and is now `crush` (the old URL 301-redirects; upstream never stated the reason). It is a **different project** from [OpenCode](/docs/ide/opencode) (opencode.ai) — and note that Crush also ships a built-in model upstream called `opencode`, 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](/docs/getting-started/endpoints-and-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

```bash
# 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**):

```bash
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:

```json
{
  "$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:

```bash
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](https://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 `*_cached` keys 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](https://qcode.cc/models).

## Verify

```bash
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:

```text
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

```bash
# 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](/docs/getting-started/endpoints-and-api-paths) — protocol × model-family table
- [OpenCode Integration](/docs/ide/opencode) — a different terminal agent (not the same project)
- [Chinese Models](/docs/usage/cn-models) — GLM / Kimi / DeepSeek / Qwen