> ## Documentation Index
> Fetch the complete documentation index at: https://docs.valarhq.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LiteLLM integration

> Run ValarCode through a LiteLLM proxy so Claude Code's per-engineer client id and routing still reach Valar

If you already run a [LiteLLM](https://docs.litellm.ai) proxy in front of your models, you can keep it and still use ValarCode. Claude Code points at LiteLLM, LiteLLM forwards to Valar, and Valar's per-engineer routing and attribution work as long as the client id makes it through.

This page covers Claude Code. **Pi** works the same way: it also sends the client id in an `X-Valar-Client-Id` header, so the LiteLLM config below applies unchanged. Just connect Pi with `valar pi on --endpoint <your-litellm-base-url> --api-key <litellm-virtual-key>` and restart Pi. Instructions for connecting Cursor through LiteLLM are coming soon (Cursor carries its client id as a token suffix rather than a header).

## How it fits together

```mermaid theme={"system"}
flowchart LR
  CC["Claude Code"] -->|"X-Valar-* headers"| L["LiteLLM proxy"]
  L -->|"forwards x- headers"| V["Valar gateway"]
  V --> RT["Route request<br/>Opus / Sonnet / Haiku / Fable to target model"]
  RT --> MS["Valar model serving"]
```

`valar claude on` writes three Valar headers into `~/.claude/settings.json`: `X-Valar-Client-Id` (attributes usage to an engineer, defaulting to their username), `X-Valar-Harness` (names the tool) and `X-Valar-Cli-Version`. All are `x-`-prefixed, so LiteLLM forwards them together — getting that hop right is the one thing that matters.

It matters more through a proxy than it does directly. LiteLLM makes its own request upstream, so the user agent Valar sees is LiteLLM's, not your harness's — the headers are the only signal left. Without `X-Valar-Harness`, everything on this path is recorded as Claude Code.

## Configure LiteLLM

Valar speaks the Anthropic Messages API at `https://api.valarhq.ai`, so LiteLLM routes to it as an `anthropic/*` model.

Two settings matter:

1. A **wildcard model entry** so any model string Claude Code requests (Opus, Sonnet, Haiku, or whatever it names across versions) is forwarded to Valar in Anthropic Messages format. Token and cost accounting still works, because every request maps to a known Anthropic model.
2. **Header forwarding**, so LiteLLM passes Claude Code's `x-`-prefixed headers (the `X-Valar-*` set) on to Valar. Without this, they are dropped at the proxy and per-engineer attribution is lost.

Add this to your LiteLLM config:

```yaml theme={"system"}
model_list:
  # Wildcard: any model string Claude Code requests is routed to Valar using the
  # Anthropic Messages format. Handles Claude Code changing its model names across
  # versions. Token/cost accounting works because these map to known Anthropic models.
  - model_name: "*"
    litellm_params:
      model: "anthropic/*"
      api_base: https://api.valarhq.ai
      api_key: os.environ/VALAR_API_KEY

general_settings:
  # Forward Claude Code's x- headers (the X-Valar-* set) to Valar.
  # NOTE: verify on first request that the header actually lands at Valar -- only
  # x-prefixed (and anthropic-beta) headers are forwarded; keep the "x-valar-" name.
  forward_client_headers_to_llm_api: true
```

Set `VALAR_API_KEY` to your **Valar coding key**, the `vlrcode_…` key you generated in the [Valar Dashboard](https://app.valarhq.ai). LiteLLM uses it to authenticate to Valar upstream.

<Note>
  The `X-Valar-Client-Id` header is `x-`-prefixed, which is exactly what LiteLLM's `forward_client_headers_to_llm_api` forwards. The header name matters: keep the `x-valar-` prefix. It is worth confirming on your first request (in Valar's request logs or the analytics dashboard) that the header actually arrives, since per-engineer attribution only works if it does.
</Note>

## Create a virtual key in LiteLLM

LiteLLM sits between Claude Code and Valar, so Claude Code no longer talks to Valar directly. Instead it authenticates to LiteLLM with a **virtual key** you create there.

In the LiteLLM admin UI (or via the LiteLLM API), create a virtual key that is allowed to reach the Anthropic models you just configured, i.e. the wildcard `*` entry that forwards to Valar. Copy the key; Claude Code will use it as its bearer token.

What flows through after this:

* Claude Code authenticates to LiteLLM with the **virtual key**.
* LiteLLM authenticates to Valar with your **Valar coding key** (`VALAR_API_KEY`).
* Claude Code's `X-Valar-*` headers are forwarded to Valar, so routing and attribution behave exactly as in the direct path.

## Connect Claude Code

Now point Claude Code at the LiteLLM proxy instead of Valar directly. Run `valar claude on` with `--endpoint` set to your LiteLLM base URL and `--api-key` set to the virtual key you just created:

```bash theme={"system"}
valar claude on --endpoint <your-litellm-base-url> --api-key <litellm-virtual-key>
```

For example, if LiteLLM is running at `https://litellm.example.com`:

```bash theme={"system"}
valar claude on --endpoint https://litellm.example.com --api-key sk-litellm-virtual-key
```

The CLI writes LiteLLM's base URL to `ANTHROPIC_BASE_URL`, the virtual key to `ANTHROPIC_AUTH_TOKEN`, and the Valar headers to `ANTHROPIC_CUSTOM_HEADERS` in `~/.claude/settings.json`, the same as the direct path but pointed at your proxy.

<Note>
  Claude Code appends `/v1/messages` to the base URL, so pass the host without a `/v1` suffix, the same way you would for the default Valar endpoint. If your LiteLLM proxy serves the Anthropic surface under a path prefix, include that prefix in `--endpoint`.
</Note>

## Verify it works

After the first few requests, check:

* **LiteLLM logs**: requests are arriving from Claude Code and being forwarded upstream.
* **Valar analytics dashboard**: the engineer shows up under their client id (their username by default) with attributed usage. If usage appears but is not attributed to an engineer, the `X-Valar-Client-Id` header is not making it through; re-check `forward_client_headers_to_llm_api` and the header name.

To stop routing through LiteLLM and restore Claude Code's previous settings:

```bash theme={"system"}
valar claude off
```

## Next steps

<CardGroup cols={2}>
  <Card title="Claude Code" icon="code" href="/valarcode/claude-code">
    The direct connect path and what the CLI writes to `settings.json`.
  </Card>

  <Card title="Model routing" icon="route" href="/valarcode/routing">
    How the client id drives cohort assignment and the split.
  </Card>
</CardGroup>
