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

# config.toml reference

> Every key the daemon reads, with defaults, straight from the source.

Configuration lives at `~/.config/rekody/config.toml`, created by the setup wizard and kept at mode `0600`.

```bash theme={null}
rekody config          # interactive settings TUI
rekody config edit     # open config.toml in $EDITOR
rekody config path     # print the config file location
rekody setup           # re-run the full wizard
```

Changes take effect the next time `rekody` starts.

## Core keys

| Key | Values | Default | What it does | |
| - | - | - | - | - |
| `activation_mode` | `"both"`, `"push_to_talk"`, `"toggle"` | `"both"` | How the hotkey starts and stops recording. `both` means hold for push-to-talk and quick-tap for a hands-free latch. Unrecognized values fall back to `both`. | |
| `trigger_key` | `"option_space"`, `"fn_key"` | `"option_space"` | Which key triggers dictation. `fn_key` requires System Settings, Keyboard, "Press globe key to" set to "Do Nothing". | |
| `stt_engine` | `"nemotron"`, `"local"`, `"groq"`, `"deepgram"`, `"gemini"`, `"cohere"`, `"custom"` | `"local"` when the key is absent | Speech-to-text backend. The setup wizard preselects `nemotron` (Rekody Streaming). Run `rekody engines` for the live list this build offers. See [Engines](/developers/engines). | |
| `whisper_model` | `"tiny"`, `"small"`, `"medium"`, `"turbo"`, `"large"` | `"turbo"` on Apple Silicon, `"small"` otherwise | Local Whisper model size. Only used when `stt_engine = "local"`. Turbo is fast only where the encoder runs on the Neural Engine; see [engines](/developers/engines). | |
| `stt_language` | BCP-47 code, e.g. `"en"` | unset (auto-detect) | Transcription language hint. Setting it slightly improves accuracy and speed when the language is known in advance. | |
| `injection_method` | `"clipboard"`, `"native"` | `"clipboard"` | How text is inserted: clipboard paste works everywhere; native sends keystrokes via CGEvent. | |
| `vad_threshold` | float, roughly `0.005` to `0.05` | `0.01` | RMS energy gate voice activity detection uses to split a continuously open microphone into utterances. It does not gate push-to-talk: a hold captures every frame and the whole recording goes to the engine at whatever level it came in. | |
| `record_all_audio` | `true`, `false` | `false` | Capture every frame even outside a recording window. A held key already captures everything, so this only affects an open microphone with no key held. | |
| `input_device` | device name, or an array of names | unset (system default) | Microphone to capture from, matched by case-insensitive substring. A single name pins that device; an array is an ordered fallback chain. See [Input device](#input-device). | |
| `max_recording_secs` | integer seconds, `0` = unlimited | `600` | Deadman switch: the longest a single recording can run. | |
| `llm_enabled` | `true`, `false`, or omit | omitted (auto) | LLM post-processing. Auto means on for every engine except Deepgram, whose `smart_format` already produces clean output. It stays on for `gemini`, which defaults to verbatim transcripts that still carry filler. | |
| `save_training_data` | `true`, `false` | `true` | Save each dictation's audio (FLAC) and transcript to `~/.local/share/rekody/training-data/` as a personal fine-tuning dataset. Local only. | Also selects the Gemini transcription mode: on means verbatim, off means smart. |
| `hud` | `true`, `false`, or omit | omitted (auto) | The floating pill. Auto shows it when the `rekody-hud` helper binary is found next to the daemon (or at `$REKODY_HUD_BIN`); `false` never shows it. | |

## Input device

`input_device` picks the microphone rekody captures from. Names are matched case-insensitively; any unique substring of the device name works. Omit the key (or set `"system"`) to follow the macOS default input, which jumps to whatever you connected last (AirPods being the classic offender).

```toml theme={null}
# One pin: use this mic when connected, otherwise the system default.
input_device = "Shure MVX2U"

# Ordered fallback chain: desk mic when it is connected,
# built-in mic when it is not.
input_device = ["Shure MVX2U", "MacBook Air Microphone"]
```

With a chain, each recording start walks the list in order and captures from the first connected device, so unplugging the desk mic needs no config change and no restart. If nothing in the chain is connected, capture falls back to the system default and the daemon logs a warning naming what it tried. An empty list behaves like the key being unset. `rekody doctor` shows the chain with each entry's status and which one would capture right now.

## Engine-specific keys

| Key | Default | What it does |
| - | - | - |
| `deepgram_api_key` | unset | Required when `stt_engine = "deepgram"`. Prefer the Keychain (below) over writing keys here. |
| `gemini_api_key` | unset | Required when `stt_engine = "gemini"`. The same Google key the Gemini LLM provider uses, under the same Keychain account. Prefer the Keychain (below). |
| `cohere_stt_port` | `8099` | Port of the local Cohere STT server, when `stt_engine = "cohere"`. |
| `custom_stt_base_url` | unset | Required when `stt_engine = "custom"`. API base URL, e.g. `"https://api.openai.com/v1"`. Must be https, or http on localhost. Rekody appends `/audio/transcriptions`. |
| `custom_stt_model` | unset | Required when `stt_engine = "custom"`. Model id the endpoint expects, e.g. `"whisper-1"`. |
| `custom_stt_api_key` | unset | Optional for `stt_engine = "custom"`. A vLLM or LM Studio server you run usually needs none. Prefer the Keychain (below). |

## LLM providers

Providers are tried in order; the first success wins, and failover is automatic. Local providers (`ollama`, `lm-studio`, `vllm`) need no API key.

```toml theme={null}
[[providers]]
name = "groq"
api_key = "gsk_..."
model = "openai/gpt-oss-20b"

[[providers]]
name = "ollama"            # local fallback, no key needed
model = "llama3.2:3b"
```

Each `[[providers]]` entry takes:

| Field | Required | What it does |
| - | - | - |
| `name` | yes | One of `apple`, `groq`, `cerebras`, `together`, `openrouter`, `fireworks`, `openai`, `anthropic`, `gemini`, `ollama`, `lm-studio`, `vllm`, or `custom`. |
| `model` | yes | Model identifier for that provider. |
| `api_key` | for cloud providers | Leave empty for local providers. |
| `base_url` | only for `custom` | Any OpenAI-compatible chat completions endpoint. Presets fill this in for named providers. |

<Note>
  Older configs may contain top-level `llm_provider`, `groq_api_key`, and `cerebras_api_key` keys. They still load and are migrated into the `providers` array at startup; use `[[providers]]` for anything new.
</Note>

## API keys and the Keychain

Keys belong in the macOS Keychain, not in the config file:

```bash theme={null}
rekody key set deepgram     # securely prompt and save
rekody key set groq
rekody key list             # show which keys are stored
rekody key delete groq
```

Keys are stored under the Keychain service `com.rekody.voice`. Agents can write one non-interactively:

```bash theme={null}
security add-generic-password -s "com.rekody.voice" -a "deepgram" -w "YOUR_KEY" -U
```

## A complete example

```toml theme={null}
activation_mode = "both"
trigger_key = "option_space"
stt_engine = "nemotron"
injection_method = "clipboard"
vad_threshold = 0.01
max_recording_secs = 600
save_training_data = true

[[providers]]
name = "apple"             # on-device cleanup, macOS 26+ with Apple Intelligence
model = "on-device"        # fixed; the wizard writes this value

[[providers]]
name = "ollama"
model = "llama3.2:3b"
```

<Note>
  If this page ever drifts from the code, the config struct in `crates/rekody-core/src/lib.rs` is the source of truth.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.