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

# Pi

> Connect Pi to RunInfra, or configure its Chat Completions provider and default model manually.

Use RunInfra models in Pi through the OpenAI-compatible Chat Completions API.

## Connect Pi

Use Node 20 or newer, an installed Pi with first-time setup complete, a workspace API key, and available RunInfra credits.

```bash theme={"dark"}
npx @runinfra/connect pi
```

In an interactive terminal, Connect starts login if needed. Review and approve the proposed changes. Connect saves a snapshot, writes the provider settings and model selection, and makes a real Chat Completions request that uses credits. Follow the printed restart hint before using Pi.

To choose a model during setup:

```bash theme={"dark"}
npx @runinfra/connect pi on --model deepseek-v4-flash
```

See [Connect](/docs/tools-sdks/connect) for key placement, status, diagnostics, and restore behavior. Run `on` again to refresh the saved model list.

## Configure manually

Load your workspace API key into `RUNINFRA_API_KEY` through your secret-management workflow. Keep it in the environment that launches Pi.

### Add the provider

Back up `~/.pi/agent/models.json`, then merge this `providers.runinfra` entry into it. Custom provider definitions belong in this user-level file, not a project-level `models.json`.

```json theme={"dark"}
{
  "providers": {
    "runinfra": {
      "baseUrl": "https://api.runinfra.ai/v1",
      "api": "openai-completions",
      "apiKey": "$RUNINFRA_API_KEY",
      "compat": {
        "supportsDeveloperRole": false
      },
      "models": [
        {
          "id": "deepseek-v4-flash",
          "name": "DeepSeek V4 Flash",
          "contextWindow": 1048576,
          "maxTokens": 32768,
          "input": ["text"]
        }
      ]
    }
  }
}
```

`openai-completions` is Pi's name for the Chat Completions API, not the legacy `/v1/completions` endpoint. `apiKey` uses Pi's `$VARIABLE` interpolation, so the key itself stays out of this file.

<Warning>
  Keep `compat.supportsDeveloperRole` set to `false`. This prevents Pi from sending its default `developer` role with this configuration.
</Warning>

Use the selected model's context window and an output budget that fits it. If you add thinking-level controls, configure a per-model `thinkingLevelMap` matching the model's supported effort values; effort names are not interchangeable across models.

### Select the default model

Back up `~/.pi/agent/settings.json`, then merge these settings:

```json theme={"dark"}
{
  "defaultProvider": "runinfra",
  "defaultModel": "deepseek-v4-flash"
}
```

Project settings in `.pi/settings.json` can override these defaults after you trust the project. If you use an `enabledModels` filter, include `runinfra/*` without removing other providers you still use.

Start Pi with an explicit selection:

```bash theme={"dark"}
pi --provider runinfra --model deepseek-v4-flash
```

Pi also reloads `models.json` when you open `/model`. A credential saved in Pi's `auth.json` takes precedence over `apiKey` in `models.json`, so check it if Pi uses a different key than you expect.

## Verify

Load the same workspace key into `RUNINFRA_API_KEY` in your terminal. This request uses credits and reads `usage.prompt_tokens_details.cached_tokens`. The macOS and Linux example uses `jq`.

<Tabs>
  <Tab title="macOS and Linux">
    ```bash theme={"dark"}
    curl --silent --show-error --fail-with-body https://api.runinfra.ai/v1/chat/completions \
      -H "Authorization: Bearer $RUNINFRA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"Say hello."}],"max_tokens":16384}' \
      | jq '.usage.prompt_tokens_details.cached_tokens'
    ```
  </Tab>

  <Tab title="PowerShell">
    ```powershell theme={"dark"}
    $body = '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"Say hello."}],"max_tokens":16384}'
    $response = $body | curl.exe --silent --show-error --fail-with-body https://api.runinfra.ai/v1/chat/completions `
      -H "Authorization: Bearer $env:RUNINFRA_API_KEY" `
      -H "Content-Type: application/json" `
      --data-binary '@-' | ConvertFrom-Json
    $response.usage.prompt_tokens_details.cached_tokens
    ```
  </Tab>
</Tabs>

A count of `0` is valid; a successful request does not guarantee a cache hit. This tests the API, not whether Pi inherited the key environment. Restart Pi from that environment and select the model with `/model`.

## Revert

If you used Connect:

```bash theme={"dark"}
npx @runinfra/connect pi off
```

This restores the snapshot from immediately before the most recent `on`, which may already contain RunInfra settings. If a managed file changed afterward, Connect refuses to overwrite it. Back up and review those edits before proceeding.

For manual setup, restore the previous `providers.runinfra` entry in `models.json`, or remove it if you added it for this setup. Restore `defaultProvider`, `defaultModel`, and any `enabledModels` filter you changed in user or project settings. If you saved a RunInfra credential in Pi, use `/logout runinfra`. Open `/model` to reload the provider list and select your previous model.

Connect's `logout` removes only its saved credentials. It does not restore agent settings or revoke the workspace key. Revoke an unwanted key in the dashboard.

## Related

<Columns cols={3}>
  <Card title="Connect" icon="plug" href="/docs/tools-sdks/connect">
    Set up, inspect, and restore your coding agent.
  </Card>

  <Card title="Chat completions" icon="braces" href="/docs/api-reference/chat-completions">
    Read the request contract and cache usage fields.
  </Card>

  <Card title="Models" icon="list" href="/docs/api-reference/models">
    Find model ids and context windows.
  </Card>
</Columns>
