# Claude Code advanced

> Pin models, restrict permissions, run lifecycle hooks, and cap spend with the key quota when using Claude Code with MirAPI.

Claude Code is Anthropic's terminal coding agent, and it talks to MirAPI over the Anthropic Messages API (`POST /v1/messages`). This page covers what to configure once the connection works: pinning the model, restricting permissions, wiring lifecycle hooks, and capping spend. There is no OpenAI or Gemini variant to set up — Claude Code only speaks the Anthropic protocol.

**Prerequisites:** Claude Code configured with `ANTHROPIC_BASE_URL="https://api.mirapi.ai"` (the bare origin, no `/v1`) and `ANTHROPIC_AUTH_TOKEN` — see [Claude Code](/docs/integrations/claude-code).

## settings.json

Project settings live in `.claude/settings.json` in the project root. The keys you are most likely to touch:

| Key | What it does |
|---|---|
| `model` | Pins the MirAPI model for the project, e.g. `deepseek-chat` |
| `max_turns` | Caps the tool-use turns per task, bounding runaway loops |
| `permissions.allow` | Tools and patterns Claude Code may run without asking |
| `permissions.deny` | Tools and patterns to block or flag |
| `hooks` | Commands that run on lifecycle events (`Stop`, `Notification`, `PostToolUse`, …) |
| `env` | Per-project environment variables (an alternative to shell exports) |
| `statusLine` | A custom command for the statusline |

```json
{
  "model": "deepseek-chat",
  "max_turns": 40,
  "permissions": {
    "allow": [
      "Read",
      "Edit",
      "Bash(git:*)"
    ],
    "deny": [
      "Bash(rm:*)",
      "Bash(curl:*)"
    ]
  },
  "hooks": {
    "Notification": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "terminal-notifier -message 'Claude Code finished' 2>/dev/null || true"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "echo 'paused for input'"
          }
        ]
      }
    ]
  }
}
```

- `permissions` is the whitelist of what Claude Code may do without confirmation; anything else triggers an interactive prompt.
- `hooks` fire on lifecycle events and are the place for notifications, formatting, or guards.

## Switching models

Change `model` in `settings.json`, or pass `ANTHROPIC_MODEL` at launch:

```bash
ANTHROPIC_MODEL="deepseek-chat" claude
```

The model name must match an entry from `GET /v1/models` exactly. A model outside the key's whitelist returns **403**. Claude Code is optimized for Anthropic-style clients, so pick a model that supports tool calling for the best experience.

## Capping spend

The quota is enforced on the gateway side, so even a runaway session cannot exceed it:

1. In https://console.mirapi.ai → **API Keys**, set a **quota limit** (spend cap) on the key. Once the cap is reached, requests are rejected with **403** until you raise it.
2. Check usage at any time:

```bash
curl https://api.mirapi.ai/api/usage/token -H "Authorization: Bearer $MIRAPI_API_KEY"
curl https://api.mirapi.ai/api/log/token -H "Authorization: Bearer $MIRAPI_API_KEY"
```

`GET /api/usage/token` returns account-level totals; `GET /api/log/token` returns per-request detail.

## Billing

- Conversations are billed per token — input, output, and cache read are three separate prices per 1M tokens. Reasoning and thinking tokens count as **output**.
- Cache reads are cheaper than ordinary input.
- MirAPI draws from a prepaid balance: no subscription, no minimum, and the balance never expires.
- When the balance runs out, requests fail with **403**; topping up restores the same key immediately.

## Error handling

- **404** on `/v1/messages/count_tokens` — that endpoint is not implemented; Claude Code may call it at startup, and the error is harmless.
- **401** — the key is missing, malformed, or unknown. Fix `ANTHROPIC_AUTH_TOKEN`.
- **403** — the key is valid but the request was refused: balance exhausted, model not whitelisted, quota reached, or IP not allowed. Check the error message for the reason.
- **429** — rate limited. Retry with jittered exponential backoff (1s → 2s → 4s, capped around 30s). There is no `Retry-After` header, and the gateway does not retry for you.
- **500** — safe to retry idempotent requests.
- Every error message ends with a request ID — include it when you open a support ticket.

## Pitfalls

- Hook commands that print a lot of output slow the session down; keep them quiet.
- `permissions.deny` blocks matching commands but is not a hard security boundary — review the interactive prompts before approving anything risky.
- The Anthropic base URL stays bare (`https://api.mirapi.ai`); do not append `/v1`.

## Related links

- [Claude Code](/docs/integrations/claude-code)
- [Quickstart](/docs/quickstart)
- [Models & pricing](/docs/models)
- [Billing & top-ups](/docs/billing)
- [Authentication](/docs/api-reference/authentication)
- [Errors](/docs/api-reference/errors)