# Zed with OpenCheese

> Connect Zed's agent panel to OpenCheese: an openai_compatible provider in settings.json, the API key in the keychain or OPEN_CHEESE_API_KEY, a default model.
>
> Web page: https://opencheese.dev/en/docs/zed/ · Every docs page: https://opencheese.dev/llms.txt

Zed's agent panel reaches OpenCheese through an `openai_compatible` provider in Zed's
`settings.json`, speaking the OpenAI Chat Completions API at `https://api.opencheese.dev/v1`.

## 1. Open settings.json

Zed keeps every user preference in one file. Open it from the command palette with
**zed: open settings file**, or edit it directly:

| System | File |
| --- | --- |
| macOS and Linux | `~/.config/zed/settings.json` |
| Windows | `%APPDATA%\Zed\settings.json` |

Merge, do not replace: the same file holds your theme, keymap, fonts and language servers.

## 2. Add the provider

The dashboard's **Configuration** page, **Zed** tab, generates this block with every model your
plan includes and the limits each one has. By hand, one model looks like this:

```json
{
  "language_models": {
    "openai_compatible": {
      "OpenCheese": {
        "api_url": "https://api.opencheese.dev/v1",
        "available_models": [
          {
            "name": "MODEL_ID",
            "display_name": "Model name",
            "max_tokens": 1000000,
            "max_output_tokens": 131000,
            "max_completion_tokens": 126000,
            "reasoning_effort": "low",
            "capabilities": {
              "tools": true,
              "images": true,
              "parallel_tool_calls": false,
              "prompt_cache_key": true,
              "chat_completions": true,
              "interleaved_reasoning": false,
              "max_tokens_parameter": true
            }
          }
        ]
      }
    }
  }
}
```

- `api_url` keeps its `/v1`: Zed appends `/chat/completions` itself.
- If the file already has a `language_models` section, add only the `OpenCheese` key inside
  its `openai_compatible` object.
- `max_tokens` is the model's context window and `max_output_tokens` its longest answer: take
  them from `context_window` and `max_output_tokens` in [`/v1/models`](https://opencheese.dev/en/docs/models.md).
  Every model needs both, or Zed rejects the whole provider.
- `reasoning_effort` must be one of `none`, `minimal`, `low`, `medium`, `high`, `xhigh` or
  `max`; any other value makes Zed reject the whole provider. Leave it out for a model with no
  levels.
- Keep `prompt_cache_key` on: with it, each Zed thread appears as one session in the
  dashboard.
- `images` is `true` only for models whose `modalities.input` includes `image`.

## 3. Give Zed the API key

The key never goes into `settings.json`: Zed has no field for it there. Either:

1. Open the agent panel, run **agent: open settings**, find **OpenCheese** under LLM Providers,
   paste the key into its API key field and press Enter. Zed keeps it in your system keychain.
2. Or set the environment variable Zed reads for this provider:

```bash
export OPEN_CHEESE_API_KEY='YOUR_OPENCHEESE_API_KEY'
```

Note the underscore: Zed builds the name from the provider ID and splits `OpenCheese` into
`OPEN_CHEESE`. `OPENCHEESE_API_KEY` is never read. The variable also wins over the keychain, so
unset it and restart Zed if you later switch keys.

## 4. Pick an OpenCheese model (optional)

Zed keeps whatever model was selected before. To make an OpenCheese model the default for new
threads, merge:

```json
{
  "agent": {
    "default_model": {
      "provider": "OpenCheese",
      "model": "MODEL_ID"
    }
  }
}
```

`provider` is the plain provider ID, with no `openai_compatible/` prefix. Restart Zed, or
reload the window, after editing `settings.json`.

## Troubleshooting

- **No OpenCheese models at all**: the JSON is malformed, or a model entry misses `max_tokens`
  or has an unknown `reasoning_effort`. Copy the generated block again rather than fixing it by
  hand.
- **Models appear but every request fails**: the key never reached Zed; repeat step 3.
- **The model is not used**: the provider ID must be `OpenCheese` in both blocks, spelled the
  same way.
