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

# Configuration

> Configure FERAL via settings files, environment variables, and the credential vault.

## Config File Location

FERAL reads its primary configuration from a JSON file at:

```
~/.feral/settings.json
```

You can override this path by setting the `FERAL_HOME` environment variable:

```bash theme={null}
export FERAL_HOME=/path/to/my/feral
```

When set, FERAL reads `$FERAL_HOME/settings.json` instead.

## Configuration Hierarchy

FERAL merges configuration from four sources, each overriding the previous:

<Steps>
  <Step title="User config (lowest priority)">
    `~/.feral/settings.json` — your global defaults.
  </Step>

  <Step title="Project config">
    `.feral/settings.json` in the current working directory — project-specific overrides.
  </Step>

  <Step title="Local config">
    `.feral/settings.local.json` in the current directory — personal overrides not checked into version control.
  </Step>

  <Step title="Environment variables (highest priority)">
    Any `FERAL_*` env var overrides the equivalent setting. See the [Environment Variables](/reference/environment) reference.
  </Step>
</Steps>

<Tip>
  Add `.feral/settings.local.json` to your `.gitignore` to keep personal overrides out of version control.
</Tip>

## Settings File Format

```json settings.json theme={null}
{
  "llm": {
    "provider": "anthropic",
    "model": "claude-sonnet-4-20250514",
    "temperature": 0.7,
    "max_tokens": 4096
  },
  "voice": {
    "enabled": true,
    "wake_word": "hey feral",
    "provider": "openai_realtime"
  },
  "autonomy": {
    "mode": "hybrid",
    "safe_categories": ["information", "media", "smart_home"],
    "risky_categories": ["email", "file_delete", "purchase"]
  },
  "ui": {
    "theme": "dark",
    "show_debug": false
  },
  "brain": {
    "port": 9090,
    "host": "127.0.0.1"
  },
  "access": {
    "pairing_mode": "localhost"
  },
  "memory": {
    "backend": "sqlite",
    "vector_store": "chroma",
    "path": "~/.feral/memory.db"
  },
  "hardware": {
    "ble_enabled": true,
    "home_assistant_url": null,
    "hup_port": 9091
  }
}
```

## Credentials Vault

Sensitive values (API keys, OAuth tokens) are stored separately in the encrypted **BlindVault**:

```
~/.feral/credentials.enc
```

The vault is encrypted at rest with **ChaCha20-Poly1305** (AEAD). The 32-byte master key lives in your OS keychain (macOS Keychain, GNOME Keyring, Windows Credential Manager) — there is no master password stored on disk; unlocking the vault requires the keychain entry to be present, so the brain decrypts transparently inside your OS account and refuses to start anywhere that entry is missing. At first boot FERAL prints a one-time **recovery code** (the master key, base32-encoded) you can use to recover the vault if the keychain entry is ever wiped; FERAL has no escrow. The decrypted credentials live only in process memory and the LLM never sees raw values — keys are injected at the HTTP layer at request time.

<Warning>
  Never commit `credentials.enc` to version control. The setup wizard creates it automatically and `pip install feral-ai` adds `~/.feral/` to your gitignore patterns when you run `feral setup`.
</Warning>

### Managing credentials

```bash theme={null}
feral setup                     # interactive wizard — sets keys and encrypts
```

You can also set credentials via environment variables, which always take precedence over the vault:

<CodeGroup>
  ```bash Anthropic theme={null}
  export ANTHROPIC_API_KEY=sk-ant-...
  ```

  ```bash OpenAI theme={null}
  export OPENAI_API_KEY=sk-...
  ```

  ```bash OpenRouter theme={null}
  export OPENROUTER_API_KEY=sk-or-...
  ```

  ```bash Ollama (local) theme={null}
  # No key needed — Ollama is auto-detected on localhost:11434
  ```
</CodeGroup>

## Key Settings Reference

| Setting Path           | Type   | Default       | Description                                                          |
| ---------------------- | ------ | ------------- | -------------------------------------------------------------------- |
| `llm.provider`         | string | `"ollama"`    | LLM backend: `anthropic`, `openai`, `openrouter`, `ollama`, `gemini` |
| `llm.model`            | string | `"llama3"`    | Model identifier for the chosen provider                             |
| `autonomy.mode`        | string | `"hybrid"`    | `strict`, `hybrid`, or `loose`                                       |
| `voice.enabled`        | bool   | `true`        | Enable voice pipeline                                                |
| `voice.wake_word`      | string | `"hey feral"` | Trigger phrase for hands-free activation                             |
| `brain.port`           | int    | `9090`        | Brain WebSocket/API port                                             |
| `brain.host`           | string | `"127.0.0.1"` | Bind host (`0.0.0.0` if you need LAN phone reachability)             |
| `access.pairing_mode`  | string | `"localhost"` | `localhost`, `local`, or `remote`                                    |
| `ui.theme`             | string | `"dark"`      | Web dashboard theme (`dark` or `light`)                              |
| `memory.backend`       | string | `"sqlite"`    | Storage backend for episodic memory                                  |
| `hardware.ble_enabled` | bool   | `true`        | Enable Bluetooth device scanning                                     |

## Example: Minimal Cloud Config

```json settings.json theme={null}
{
  "llm": {
    "provider": "anthropic",
    "model": "claude-sonnet-4-20250514"
  },
  "autonomy": { "mode": "strict" }
}
```

## Example: Fully Local Config

```json settings.json theme={null}
{
  "llm": {
    "provider": "ollama",
    "model": "llama3:70b"
  },
  "voice": {
    "provider": "whisper_local"
  },
  "autonomy": { "mode": "loose" }
}
```
