---
title: Configuration
description: The config.toml schema — capture sources, filters, output, and retention.
---

Configuration lives in a single TOML file:

```
~/.config/tadoru/config.toml
```

Override the path per invocation with the global `--config <path>` flag. Helper commands:

```bash
tadoru config init   # create a fully commented template at the configuration path
tadoru config path   # print the config file path
tadoru config show   # effective configuration (defaults merged)
tadoru config edit   # open in $EDITOR
tadoru config set capture.text_content true
```

`tadoru config init` creates missing parent directories and writes the complete template shown
below. It never overwrites an existing file; if the destination exists, it reports that path and
exits with code 1. Use the global `--config <path>` option to initialize a non-default location.

Use [`tadoru config set`](/reference/cli#config) for the scalar `capture.text_content` and
`[output]` keys. Use [`tadoru filter`](/reference/cli#filter) for filter lists and `config edit`
for other arrays.

## Full example (defaults)

```toml config.toml
[capture]
sources = ["app", "window", "ui", "input", "browser"]
text_content = false            # content capture is an explicit opt-in

[filter]                        # capture-time filters — the privacy boundary (applied before the store)
exclude_apps = ["1Password", "Keychain Access"]   # deny list (bundle_id recommended); defaults ship built-in
include_only_apps = []          # non-empty switches to allow-list mode
exclude_websites = []           # browser.* URL hosts; dot-boundary suffix match (example.com also covers api.example.com)
include_only_websites = []      # allow list for URL hosts
redactors = ["email", "credit_card", "token"]     # scrubbing of captured values (second line of defense)

[output]
mode = "both"                   # stream | batch | both
batch_interval_s = 5
store = "sqlite"                # sqlite | jsonl
retention_hours = 48            # short-lived retention by default
```

There is no egress-related setting — external transmission does not exist as a feature.

## `[capture]`

| Key | Default | Description |
| --- | --- | --- |
| `sources` | `["app", "window", "ui", "input", "browser"]` | Which event families to capture. Removing a source also removes its permission requirement (see [permissions](/guides/permissions)) |
| `text_content` | `false` | Capture typed/field content (`ui.value`, `input.key`, clipboard contents). Off by default; see the [privacy model](/guides/privacy) |

## `[filter]`

Capture-time filters — matching events are discarded **before** being written. Semantics, matching rules, and precedence are documented in the [filters guide](/guides/filters); manage them with [`tadoru filter`](/reference/cli#filter) rather than editing by hand.

| Key | Default | Description |
| --- | --- | --- |
| `exclude_apps` | built-in defaults | Deny list of apps (`bundle_id` recommended; display names allowed) |
| `include_only_apps` | `[]` | Allow list; non-empty switches to allow-list mode |
| `exclude_websites` | `[]` | Deny list of URL hosts for `browser.*` events. Dot-boundary suffix match with no Public Suffix List handling: `example.com` covers `api.example.com` but not `evil-example.com`; a bare `com` would match every `.com` host |
| `include_only_websites` | `[]` | Allow list of URL hosts |
| `redactors` | `["email", "credit_card", "token"]` | Redaction rules applied to captured values |

The daemon watches the config file at roughly 2-second intervals, so filter changes apply within a few seconds — no daemon restart required.

## `[output]`

| Key | Default | Description |
| --- | --- | --- |
| `mode` | `"both"` | `stream` (emit events as they occur), `batch` (buffered writes), or `both` |
| `batch_interval_s` | `5` | Flush interval for batch mode |
| `store` | `"sqlite"` | Store backend: `sqlite` or `jsonl` |
| `retention_hours` | `48` | Events older than this are purged automatically |

## Change propagation

- `[filter]` changes are picked up by the daemon's config watch (roughly 2-second intervals) and apply within a few seconds — no restart needed.
- Other changes (e.g. `capture.sources`, `[output]`) take effect after a daemon restart: `tadoru stop && tadoru start`.

## Related paths

| Path | Purpose | Override |
| --- | --- | --- |
| `~/.config/tadoru/config.toml` | Configuration | `--config <path>` |
| `~/.local/state/tadoru/store.sqlite` | Event store | `--store <path>` |
