# Environment variables

Speedwave reads a small set of environment variables. Some you set on the host before launching Speedwave. Others Speedwave sets inside containers itself, derived from your configuration. A host variable comes from your shell. A container variable is one Speedwave sets for you; you never set it yourself.

This table uses the same format as the [config keys reference](/docs/reference/config-keys/), which covers the JSON settings Speedwave reads instead.

## All variables

| Variable | Scope | Description |
| --- | --- | --- |
| `SPEEDWAVE_DATA_DIR` | host | Overrides the default `~/.speedwave/` data directory. Must be an absolute path. Its basename isolates a whole instance. |
| `SPEEDWAVE_RESOURCES_DIR` | host | Points the CLI at Desktop's bundled resources directory. Falls back to a marker file when unset. |
| `SPW_TOKENS_DIR` | container | Overrides the in-container path where the proxy reads mounted provider key files. Defaults to `/tokens`. |
| `RUST_LOG` | host | Filter for the CLI and proxy container logger. Defaults to `info` when unset. |
| `ANTHROPIC_MODEL` | container | Pins a specific Claude model for Claude Code in the container. |
| `SPW_KEY_<ID>` | container | Name (not value) of a provider API key passed to the proxy. `<ID>` is the provider id uppercased with `-` replaced by `_`. |
| `SPEEDWAVE_PLUGINS` | container | Comma-joined list of enabled plugin slugs, set in the Claude container. |
| `WORKER_<SLUG_UPPER>_URL` | container | Discovery URL for a third-party MCP plugin worker, derived from its `service_id`. |
| `WORKER_SLACK_URL`, `WORKER_GITHUB_URL`, `WORKER_GITLAB_URL`, `WORKER_ATLASSIAN_URL`, `WORKER_REDMINE_URL`, `WORKER_SHAREPOINT_URL`, `WORKER_OFFICE_URL`, `WORKER_PLAYWRIGHT_URL` | container | Discovery URLs for the built-in integration workers. Fixed constants, not derived at runtime. |

## SPEEDWAVE_DATA_DIR

`SPEEDWAVE_DATA_DIR` overrides the default `~/.speedwave/` data directory. Unset or empty, Speedwave falls back to `~/.speedwave/`. The value must be an absolute path; a non-absolute value stops the process.

The basename drives instance isolation, so Speedwave constrains it. After stripping any leading dots, the basename must match `^[a-z][a-z0-9-]{0,63}$`: it starts with a lowercase letter, contains only lowercase letters, digits, or hyphens, and runs at most 64 characters. An invalid basename, or a non-absolute path, aborts the process rather than falling back to a default.

That basename is more than a folder name. Speedwave derives both the Lima VM name and the compose project prefix from it, so a single `SPEEDWAVE_DATA_DIR` value isolates an entire instance: its VM, its containers, and its data all key off the same name. `.speedwave-dev` derives the name `speedwave-dev`, which is why Speedwave's own dev builds run alongside an installed app without sharing a VM, containers, or data.

```bash title="shell"
export SPEEDWAVE_DATA_DIR=/opt/speedwave-ci
```

## SPEEDWAVE_RESOURCES_DIR

`SPEEDWAVE_RESOURCES_DIR` tells the CLI where to find Desktop's bundled resources directory (for example `/usr/lib/Speedwave`). Desktop sets it when it launches the CLI.

Running the CLI standalone, outside Desktop, the variable is usually unset. The CLI then falls back to a marker file at `~/.speedwave/resources-dir`: it reads the file, trims the content, and ignores it if empty. Once resolved, the value is exported into the process environment so the rest of the CLI can read it like any other variable.

Self-update's rebuild step clears this variable before re-executing the CLI binary, so the freshly re-exec'd process re-reads the marker file instead of inheriting a stale path.

## SPW_TOKENS_DIR

The proxy container reads provider API keys from files mounted at `/tokens` by default. `SPW_TOKENS_DIR` overrides that in-container path, so the proxy looks for the mounted key files somewhere else instead.

## RUST_LOG

`RUST_LOG` sets the verbosity of the Speedwave CLI logger, and the same variable sets the proxy container's log level. Both default to `info` when the variable is unset. See [Logs and diagnostics](/docs/guides/logs-and-diagnostics/) for where that verbosity shows up.

## ANTHROPIC_MODEL

`ANTHROPIC_MODEL` pins a specific Claude model, passed to Claude Code inside the container. Two settings can populate it, and `claude.llm.model` wins: Speedwave writes `claude.env.ANTHROPIC_MODEL` into the compose file first, then writes the value derived from `claude.llm.model` afterward, overwriting the earlier one by key.

## Provider keys: SPW_KEY_&lt;ID&gt;

Provider API keys reach the proxy container by name only, never by value. The env name is the provider id uppercased with `-` replaced by `_`, so the provider id `openrouter` becomes `SPW_KEY_OPENROUTER`. The proxy reads the actual key value from a mounted file, not from the env value; see `SPW_TOKENS_DIR` above for where it looks.

## Plugin discovery: SPEEDWAVE_PLUGINS and WORKER_&lt;SLUG_UPPER&gt;_URL

`SPEEDWAVE_PLUGINS` is set in the Claude container to the comma-joined list of enabled plugin slugs.

For each enabled MCP plugin, Speedwave injects a `WORKER_<SID>_URL` variable, keyed on the plugin's `service_id` (which defaults to the plugin slug when the manifest omits it) uppercased with `-` replaced by `_`. So a plugin `example-plugin` gets `WORKER_EXAMPLE_PLUGIN_URL`, and `crm` gets `WORKER_CRM_URL`.

That derivation applies only to third-party plugin workers. The built-in integration workers instead use fixed, hardcoded URL variables: `WORKER_SLACK_URL`, `WORKER_GITHUB_URL`, `WORKER_GITLAB_URL`, `WORKER_ATLASSIAN_URL`, `WORKER_REDMINE_URL`, `WORKER_SHAREPOINT_URL`, `WORKER_OFFICE_URL`, and `WORKER_PLAYWRIGHT_URL`. These are constants Speedwave ships with, not values it computes from a plugin's `service_id` at runtime.

See [Using plugins](/docs/plugins/using-plugins/) for how the plugin hub uses these URLs, and the [config keys reference](/docs/reference/config-keys/) for the JSON settings that populate several of the variables above.