A single Claude Code session can burn millions of tokens. At per-token API prices, heavy agentic use gets expensive fast. Moonshot AI (Kimi) and Z.AI (GLM) both sell **flat-rate coding plan subscriptions** that are far cheaper than pay-as-you-go billing. The catch: Claude Code speaks Anthropic's API protocol, and Kimi's coding plan is **OpenAI-compatible only**.

This guide shows how to use both the **Kimi K3** and **GLM** coding plans in Claude Code with zero per-token charges, using [Ferrox](https://github.com/shaharia-lab/ferrox), a free, open-source LLM gateway written in Rust that translates between API dialects.

## The protocol problem

Claude Code can talk to any Anthropic-compatible endpoint via `ANTHROPIC_BASE_URL`. Here's how the two coding plans line up:

| Provider | Coding plan endpoint | Protocol | Works with Claude Code directly? |
|---|---|---|---|
| Z.AI (GLM) | `https://api.z.ai/api/anthropic` | Anthropic | Yes |
| Moonshot (Kimi) | `https://api.kimi.com/coding/v1` | **OpenAI only** | **No** |

Moonshot does run an Anthropic-compatible endpoint at `https://api.moonshot.ai/anthropic`, but coding-plan keys are **rejected there**; that route bills the standard pay-as-you-go account. So for Kimi you need something in the middle that speaks Anthropic on one side and OpenAI on the other.

## Enter Ferrox

[Ferrox](https://github.com/shaharia-lab/ferrox) is a stateless, MIT-licensed LLM API gateway written in Rust. It normalises every provider into one internal format and re-exposes it in **both** the OpenAI and Anthropic dialects:

```mermaid
flowchart LR
    CC[Claude Code] -->|Anthropic protocol| F[Ferrox]
    F -->|OpenAI protocol| K[Kimi K3 coding plan]
    F -->|Anthropic protocol| G[Z.AI GLM coding plan]
```

One gateway, one local endpoint, one auth token in your Claude Code config. Beyond protocol translation you get multi-provider routing (failover, round-robin, weighted) across Anthropic, OpenAI, Gemini, and AWS Bedrock, virtual keys with per-model access control, rate limiting, circuit breakers, and Prometheus metrics.

## Step 1: Configure Ferrox

Create `config/local.yaml`. Never commit API keys; reference environment variables:

```yaml
providers:
  # Z.AI coding plan is served over the Anthropic-native endpoint.
  # Do NOT use https://api.z.ai/api/paas/v4; that route bills
  # the pay-as-you-go balance instead of your coding plan.
  - name: zai
    type: anthropic
    api_key: "${Z_AI_API_KEY}"
    base_url: "https://api.z.ai/api/anthropic"

  # Kimi coding plan is OpenAI-compatible only.
  # Do NOT use https://api.moonshot.ai/anthropic; coding-plan keys are rejected there.
  - name: moonshot
    type: openai
    api_key: "${MOONSHOT_API_KEY}"
    base_url: "https://api.kimi.com/coding/v1"

models:
  - alias: glm-5.2
    routing:
      strategy: failover
      targets:
        - provider: zai
          model_id: "glm-5.2"

  - alias: glm-4.5-air          # cheap/fast, good for the Haiku slot
    routing:
      strategy: failover
      targets:
        - provider: zai
          model_id: "glm-4.5-air"

  - alias: k3                   # Kimi K3, 1,048,576 token context
    routing:
      strategy: failover
      targets:
        - provider: moonshot
          model_id: "k3"

virtual_keys:
  - key: "${PROXY_KEY:-sk-local-dev}"
    name: claude-code
    allowed_models: ["*"]
    rate_limit:
      requests_per_minute: 120
      burst: 20
```

Two things to note. Providers point at the **coding plan endpoints**, not the default API endpoints; getting `base_url` wrong is the top cause of "insufficient balance" errors. And the **virtual key** is what Claude Code authenticates with, so your real provider keys never enter any Claude Code settings file.

## Step 2: Run Ferrox

Gateway only, no database or Redis needed:

```bash
docker run -d --name ferrox --restart unless-stopped \
  -p 127.0.0.1:2333:8080 \
  -e Z_AI_API_KEY -e MOONSHOT_API_KEY -e PROXY_KEY \
  -v "$(pwd)/config/local.yaml:/app/config/local.yaml:ro" \
  ghcr.io/shaharia-lab/ferrox:latest --config /app/config/local.yaml
```

`-e VAR` without a value inherits the variable from your shell, so keys stay out of shell history and `docker inspect` output. Verify:

```bash
curl http://localhost:2333/healthz                     # {"status":"ok"}
curl http://localhost:2333/anthropic/v1/models \
  -H "Authorization: Bearer sk-local-dev"              # lists your aliases
```

No Docker? Binaries for macOS and Linux are on [GitHub Releases](https://github.com/shaharia-lab/ferrox/releases/latest), or `brew install shaharia-lab/tap/ferrox`.

## Step 3: Point Claude Code at Ferrox

Claude Code appends `/v1/messages` to `ANTHROPIC_BASE_URL`, and Ferrox serves its Anthropic surface under `/anthropic`. So the base URL is `http://localhost:2333/anthropic`. Keep one settings file per backend:

**`~/.claude/settings_kimi.json`**

```json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "env": {
    "ANTHROPIC_BASE_URL": "http://localhost:2333/anthropic",
    "ANTHROPIC_AUTH_TOKEN": "sk-local-dev",
    "API_TIMEOUT_MS": "3000000",
    "ANTHROPIC_MODEL": "k3",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "k3",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "k3",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "k3",
    "CLAUDE_CODE_SUBAGENT_MODEL": "k3",
    "CLAUDE_CODE_AUTO_COMPACT_WINDOW": "1048576"
  }
}
```

**`~/.claude/settings_glm.json`**

```json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "env": {
    "ANTHROPIC_BASE_URL": "http://localhost:2333/anthropic",
    "ANTHROPIC_AUTH_TOKEN": "sk-local-dev",
    "API_TIMEOUT_MS": "3000000",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-5.2",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-5.2",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.5-air"
  }
}
```

`ANTHROPIC_AUTH_TOKEN` is the Ferrox virtual key, not a provider key. `CLAUDE_CODE_AUTO_COMPACT_WINDOW` sets how much context Claude Code uses before auto-compacting; set it to the model's real window (K3 is 1,048,576 tokens).

Run it:

```bash
claude --settings ~/.claude/settings_kimi.json
claude --settings ~/.claude/settings_glm.json
```

Every request now flows through Ferrox and bills against your flat-rate subscription.

## Mixing both plans in one session

Ferrox routes per model alias, so one settings file can spread Claude Code's model slots across **both** subscriptions. For example, K3's huge context for the main loop and cheap GLM 4.5 Air for the background slot:

```json
"ANTHROPIC_DEFAULT_OPUS_MODEL": "k3",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "k3",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.5-air"
```

You can also give an alias multiple targets so one plan falls back to the other:

```yaml
  - alias: primary
    routing:
      strategy: failover
      targets:
        - provider: moonshot
          model_id: "k3"
        - provider: zai
          model_id: "glm-5.2"
```

Clients only ever see your aliases, so you can repoint `primary` at a different vendor without touching any Claude Code settings file.

## Troubleshooting

**`Insufficient balance or no resource package` (Z.AI, HTTP 429, code 1113):** you're on the pay-as-you-go route, not the coding plan. `base_url` must be `https://api.z.ai/api/anthropic` with `type: anthropic`, not `/api/paas/v4`.

**`Invalid Authentication` from Moonshot:** coding-plan keys only work against `https://api.kimi.com/coding/v1`. They are rejected by `api.moonshot.ai` and `api.moonshot.cn` on both routes.

**`There's an issue with the selected model (…)` in Claude Code:** the model name was rejected locally before reaching Ferrox. Use plain alias names; Claude Code strips its `[1m]` suffix before sending, so set the window with `CLAUDE_CODE_AUTO_COMPACT_WINDOW` instead.

**`Model alias '…' is not configured` (HTTP 404):** Ferrox matches aliases exactly. Check `GET /anthropic/v1/models` for what it actually serves.

**Empty responses with `finish_reason: "length"`:** K3 is a reasoning-heavy model; a small `max_tokens` can be consumed entirely by reasoning. Allow a few hundred tokens.

When in doubt, `docker logs ferrox` shows every routed request with the resolved alias, provider, upstream model ID, and status.

## Ferrox for teams and organizations

The same setup scales to a whole team:

- **Centralized credentials.** Provider keys live in one deployment, not fifty settings files. Rotate in one place.
- **Scoped access.** Each developer or CI job gets a virtual key with per-model access and its own rate limit. Revoke one key without touching anyone else.
- **Provider independence.** Clients only see aliases, so you can swap or add providers (Gemini, Bedrock, a self-hosted model) behind the same endpoint with zero client changes.
- **Production-grade ops.** Stateless and horizontally scalable, with Prometheus metrics, structured logs, and OpenTelemetry tracing built in.

Ferrox is MIT-licensed, single-binary Rust, and runs anywhere Docker does. If it's useful to you, a star on [GitHub](https://github.com/shaharia-lab/ferrox) goes a long way.

## FAQ

**Can I use the Kimi K3 coding plan in Claude Code?**
Not directly. Kimi's coding plan is OpenAI-compatible only, and Claude Code speaks the Anthropic protocol. Ferrox bridges the two.

**Can I use the Z.AI GLM coding plan in Claude Code?**
Yes, directly via `https://api.z.ai/api/anthropic`. Running it through Ferrox adds virtual keys, rate limiting, failover, and unified metrics.

**Does Claude Code usage tracking still work through Ferrox?**
Yes. Claude Code receives normal Anthropic-style responses with token counts, so `/cost` and `/usage` work. Ferrox adds server-side Prometheus metrics across all keys and models.

**Is Ferrox free?**
Yes, open source under the MIT license, with binaries, a Homebrew tap, and a Docker image.

## Wrapping up

Flat-rate coding plans are the pricing model agentic coding needed. With Ferrox in the middle, Claude Code isn't locked out of them just because a provider chose a different API dialect. One YAML file, one Docker container, one settings file per plan, and Kimi K3's million-token context and GLM 5.2 become everyday model slots in Claude Code. The full configuration reference is in the [Ferrox docs](https://github.com/shaharia-lab/ferrox/blob/main/docs/user/coding-plans-in-claude-code.md).