# Configuration (/configuration)



## Overview

QVAC configuration is loaded once during initialization from a `qvac.config.*` file and remains immutable for the lifetime of the SDK instance. To provide configuration, either set the `QVAC_CONFIG_PATH` environment variable or place a `qvac.config.*` file at the root of your project.

<Callout type="info">
  When using only the SDK, providing a configuration is **not required**. If you do not provide one, the SDK uses the default settings. *When using the HTTP server, however, providing a configuration **is required**.*
</Callout>

## File formats

The `qvac.config.*` format you can use depends on the JS environment where QVAC will run in:

| Format             | Node.js | Bare | Expo |
| ------------------ | ------- | ---- | ---- |
| `qvac.config.json` | ✅       | ✅    | ✅    |
| `qvac.config.js`   | ✅       | ✅    | ❌    |
| `qvac.config.ts`   | ✅       | ❌    | ❌    |

<Callout type="info">
  `qvac.config.ts` requires installing [`tsx`](https://www.npmjs.com/package/tsx) as a devDependency.
</Callout>

## Examples

Below are examples of `qvac.config.*` files. Values marked with `<placeholders>` should be replaced with your actual values.

<Tabs>
  <Tab value="json" label="JSON" default>
    <WrapCode>
      ```json title="qvac.config.json" lineNumbers
      {
        "plugins": ["<builtin_plugin_1>", "<custom_plugin_2>"],
        "loggerConsoleOutput": true,
        "loggerLevel": "info",
        "swarmRelays": ["<hyperbee_key_1>", "<hyperbee_key_2>"],
        "cacheDirectory": "</absolute/path/to/.qvac/models>",
        "httpDownloadConcurrency": 3,
        "httpConnectionTimeoutMs": 10000,
        "registryDownloadMaxRetries": 3,
        "registryStreamTimeoutMs": 60000,
        "deviceDefaults": [
          {
            "name": "Samsung Galaxy force CPU",
            "match": { "platform": "android", "deviceBrand": "samsung" },
            "defaults": { "llm": { "device": "cpu" } }
          }
        ],
        "bareRuntimeVersion": "<x.y.z>",
        "serve": {
          "models": {
            "<model_alias>": {
              "model": "<SDK_MODEL_CONSTANT>",
              "default": true,
              "preload": true,
              "config": {}
            }
          }
        }
      }
      ```
    </WrapCode>
  </Tab>

  <Tab value="js" label="JavaScript">
    <Callout type="warn">
      Supported on Node.js and Bare. Not supported in Expo — use JSON instead.
    </Callout>

    <WrapCode>
      ```js title="qvac.config.js" lineNumbers
      module.exports = {
        plugins: ["<builtin_plugin_1>", "<custom_plugin_2>"],
        loggerConsoleOutput: true,
        loggerLevel: "info",
        swarmRelays: ["<hyperbee_key_1>", "<hyperbee_key_2>"],
        cacheDirectory: "</absolute/path/to/.qvac/models>",
        httpDownloadConcurrency: 3,
        httpConnectionTimeoutMs: 10000,
        registryDownloadMaxRetries: 3,
        registryStreamTimeoutMs: 60000,
        deviceDefaults: [
          {
            name: "Samsung Galaxy force CPU",
            match: { platform: "android", deviceBrand: "samsung" },
            defaults: { llm: { device: "cpu" } },
          },
        ],
        bareRuntimeVersion: "<x.y.z>",
        serve: {
          models: {
            "<model_alias>": {
              model: "<SDK_MODEL_CONSTANT>",
              default: true,
              preload: true,
              config: {},
            },
          },
        },
      };
      ```
    </WrapCode>
  </Tab>

  <Tab value="ts" label="TypeScript">
    <Callout type="info">
      Supported on Node.js only, and requires installing [`tsx`](https://www.npmjs.com/package/tsx) as a devDependency.
    </Callout>

    <WrapCode>
      ```ts title="qvac.config.ts" lineNumbers
      import type { QvacConfig } from "@qvac/sdk";

      const config: QvacConfig = {
        plugins: ["<builtin_plugin_1>", "<custom_plugin_2>"],
        loggerConsoleOutput: true,
        loggerLevel: "info",
        swarmRelays: ["<hyperbee_key_1>", "<hyperbee_key_2>"],
        cacheDirectory: "</absolute/path/to/.qvac/models>",
        httpDownloadConcurrency: 3,
        httpConnectionTimeoutMs: 10000,
        registryDownloadMaxRetries: 3,
        registryStreamTimeoutMs: 60000,
        deviceDefaults: [
          {
            name: "Samsung Galaxy force CPU",
            match: { platform: "android", deviceBrand: "samsung" },
            defaults: { llm: { device: "cpu" } },
          },
        ],
        bareRuntimeVersion: "<x.y.z>",
        serve: {
          models: {
            "<model_alias>": {
              model: "<SDK_MODEL_CONSTANT>",
              default: true,
              preload: true,
              config: {},
            },
          },
        },
      };

      export default config;
      ```
    </WrapCode>
  </Tab>
</Tabs>

## Options

The following table lists all supported configuration options for `qvac.config.*`:

| Option                              | Description                                                                                                                                                                                                          | Type                                     | Required | Default                                                 |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | -------- | ------------------------------------------------------- |
| [`plugins`](/configuration/plugins) | Plugin specifiers to bundle (built-in and/or custom).                                                                                                                                                                | `string[]`                               | No       | [All built-in plugins](/configuration/plugins#built-in) |
| `loggerConsoleOutput`               | Enable or disable console output for SDK loggers.                                                                                                                                                                    | `boolean`                                | No       | `true`                                                  |
| `loggerLevel`                       | Global log level for all SDK loggers.                                                                                                                                                                                | `"error" \| "warn" \| "info" \| "debug"` | No       | `"info"`                                                |
| `swarmRelays`                       | Hyperswarm relay public keys (hex strings) for improved P2P connectivity (blind relays).                                                                                                                             | `string[]`                               | No       | —                                                       |
| `cacheDirectory`                    | Absolute path to the directory where models and other cached assets are stored.                                                                                                                                      | `string`                                 | No       | `~/.qvac/models`                                        |
| `httpDownloadConcurrency`           | Maximum number of concurrent HTTP downloads for sharded models.                                                                                                                                                      | `number`                                 | No       | `3`                                                     |
| `httpConnectionTimeoutMs`           | Timeout in milliseconds for HTTP connection establishment (applies to HEAD and GET requests).                                                                                                                        | `number`                                 | No       | `10000`                                                 |
| `registryDownloadMaxRetries`        | Maximum retry attempts for registry (P2P) downloads on timeout.                                                                                                                                                      | `number`                                 | No       | `3`                                                     |
| `registryStreamTimeoutMs`           | Timeout in milliseconds for stalled registry (P2P) download streams. Raise on slow or high-latency connections where the default triggers spurious retries.                                                          | `number`                                 | No       | `60000`                                                 |
| `deviceDefaults`                    | Override loaded model config for specific devices. First matching pattern wins. Use it to optimize for different hardware.                                                                                           | [`DevicePattern[]`](#devicepattern)      | No       | —                                                       |
| `bareRuntimeVersion`                | Bare runtime version used for native addon ABI verification during bundling (`qvac bundle sdk` / `qvac verify bundle`). When omitted, the bundler auto-detects it from `node_modules` (`bare-runtime`, then `bare`). | `string`                                 | No       | Auto-detected                                           |
| `serve`                             | Configuration for the [HTTP server](/cli/http-server).                                                                                                                                                               | [`ServeConfig`](#serveconfig)            | No       | —                                                       |

### `DevicePattern`

| Field      | Description                                                 | Type                                            | Required |
| ---------- | ----------------------------------------------------------- | ----------------------------------------------- | -------- |
| `name`     | Human-readable label for this pattern (used in logs).       | `string`                                        | Yes      |
| `match`    | Which device(s) to target. All specified fields must match. | [`DeviceMatch`](#devicematch)                   | Yes      |
| `defaults` | Model config overrides to apply when matched.               | [`DeviceConfigDefaults`](#deviceconfigdefaults) | Yes      |

#### `DeviceMatch`

| Field                 | Description                                                                                    | Type                 | Required |
| --------------------- | ---------------------------------------------------------------------------------------------- | -------------------- | -------- |
| `platform`            | Target platform.                                                                               | `"android" \| "ios"` | Yes      |
| `deviceBrand`         | Case-insensitive exact brand (e.g., `"samsung"`, `"google"`).                                  | `string`             | No       |
| `deviceModelPrefix`   | Case-sensitive prefix match on the device model (e.g., `"Pixel 10"` matches `"Pixel 10 Pro"`). | `string`             | No       |
| `deviceModelContains` | Substring match on the device model (e.g., `"Galaxy"` matches `"Samsung Galaxy S25"`).         | `string`             | No       |

#### `DeviceConfigDefaults`

Maps each model-type key to a model config object. For example (inside `DevicePattern.defaults`):

```json
{
  "llm": { "device": "cpu", "ctx_size": 1024 },
  "embeddings": { "device": "cpu", "flashAttention": "off" }
}
```

Model types (allowed keys): `llm` | `embeddings` | `whisper` | `parakeet` | `bci` | `nmt` | `tts` | `ocr`

<Callout type="info">
  **Important:** for the exact config fields supported by each model type (key), see [`modelConfig` — `loadModel()` at `@qvac/sdk` API reference](/reference/api#loadmodel).
</Callout>

### `ServeConfig`

| Field           | Description                                                                                                                                                                                                | Type                                   | Required | Default |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | -------- | ------- |
| `models`        | Map of model aliases to model entries (see [`ModelEntry`](#modelentry) below). Required when running the server.                                                                                           | `Record<string, string \| ModelEntry>` | Yes      | —       |
| `publicBaseUrl` | Externally reachable origin (e.g., `"https://api.example.com"`). Required for image `response_format=url`. Must start with `http://` or `https://`. The CLI flag `--public-base-url` overrides this value. | `string`                               | No       | —       |
| `openai`        | OpenAI-adapter–specific options. See [`OpenAIOptions`](#openaioptions).                                                                                                                                    | `OpenAIOptions`                        | No       | —       |

#### `ModelEntry`

The `serve.models` field is a map of model aliases to model entries. Keys are the **model aliases** — the names that HTTP clients use in the `model` field of their requests. Values can be either a **string** (SDK model constant name, e.g., `"QWEN3_600M_INST_Q4"`) or a `ModelEntry` object:

| Field     | Description                                                                                                                               | Type      | Required                                               |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------ |
| `model`   | SDK model constant name.                                                                                                                  | `string`  | Yes (unless using `src` + `type`)                      |
| `src`     | Explicit model source (URL or path).                                                                                                      | `string`  | Yes (if no `model`)                                    |
| `type`    | Model type: `llm` \| `embeddings` \| `whisper` \| `parakeet` \| `nmt` \| `tts` \| `ocr` \| `whispercpp-audio-translation` \| `diffusion`. | `string`  | Yes (if using `src`)                                   |
| `default` | Use as the default model for its endpoint category.                                                                                       | `boolean` | No (`false`)                                           |
| `preload` | Load model into memory on server startup.                                                                                                 | `boolean` | No (`true` for constant entries, `false` for explicit) |
| `config`  | Model config overrides (same as [`modelConfig` in `loadModel()`](/reference/api#loadmodel)).                                              | `object`  | No                                                     |

Example:

```json
{
  "serve": {
    "models": {
      "my-llm": {
        "model": "QWEN3_600M_INST_Q4",
        "default": true,
        "preload": true,
        "config": { "ctx_size": 8192 }
      },
      "my-embed": "GTE_LARGE_FP16"
    }
  }
}
```

#### `OpenAIOptions`

Optional OpenAI-adapter settings. Currently only `audio.speech` is configurable:

| Field                        | Description                                                                                                                                                                                                                                    | Type                     | Required | Default   |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- | --------- |
| `audio.speech.defaultVoice`  | Voice id used by `/v1/audio/speech` when the request omits `voice`. Set to `null` to make `voice` strictly required (otherwise the route returns `400 missing_voice`).                                                                         | `string \| null`         | No       | `"alloy"` |
| `audio.speech.voices`        | Map from OpenAI `voice` strings to `serve.models` aliases (case-insensitive keys). Lets clients keep using OpenAI voice names while the server routes them to QVAC TTS aliases. See [HTTP server — `POST /v1/audio/speech`](/cli/http-server). | `Record<string, string>` | No       | —         |
| `audio.speech.maxInputChars` | Hard cap on the `input` length (characters) accepted by `/v1/audio/speech`. Set to `null` to disable. Matches OpenAI's documented limit and bounds memory usage since the route buffers the full WAV before responding.                        | `number \| null`         | No       | `4096`    |

Example:

```json
{
  "serve": {
    "publicBaseUrl": "https://api.example.com",
    "openai": {
      "audio": {
        "speech": {
          "defaultVoice": "alloy",
          "voices": {
            "alloy": "tts-chatter-alloy",
            "echo": "tts-chatter-echo"
          },
          "maxInputChars": 4096
        }
      }
    }
  }
}
```
