Settings, storage and the event log
Everything here is a command on the running core. It edits one table of config.toml and leaves your comments alone, tells you what a change needs before it takes effect, and never lets an environment variable quietly win.
Core settings
oaken settings # every section: value, default, where it came from, what a change costs
oaken settings ai # one section
oaken settings check ai chunk_tokens=128 # test a change; nothing is written
oaken settings set ai ask_context_tokens=2500
oaken settings set ai --unset ask_context_tokens # back to the default
oaken settings set ui mark_read_delay_ms=500 --reload # save, then reload core on it
Only some of core's settings are editable here. Anything that changes where data lives, which
address or port core listens on, or touches security ([api], [storage], token files, the model
and backend choices) is not, and settings says so (by hand in the list, a refusal if you try).
Plugin settings, including the models, are separate: see Plugins.
| Section | Table in config.toml |
What it holds |
|---|---|---|
index |
[index] |
Threading by subject; limits on a search query. |
retrieval |
[search] |
How keyword and vector results are merged; how much an answer reads. |
read_state |
[read_state] |
Automatic marking as read; audit batching. |
ui |
[ui] |
How long a message is open before it is marked read. |
sync |
[sync] |
Default interval, concurrency, backoff and batch size. The minimum interval is a floor you set by hand. |
ai |
[ai] |
Token thrift: how much of a message a model reads, and how chunks are cut. |
log |
[log] |
The log level and format. |
What a change costs
A saved change is in config.toml at once, and reaches the running core when it reloads. The answer
to check and set says what is needed:
- reload:
oaken reload(or--reloadonset). Core re-reads its configuration in place; no restart, and logging is reconfigured too, solog level=DEBUGtakes effect on a reload. - reload and rebuild-index: chunk size and overlap change how new mail is cut, so mail already
indexed follows only after
oaken rebuild-index. - restart: for a key a reload cannot apply. No key on today's list needs one, but if one ever does, it is reported the same way.
Safe by construction
- Only the one table is rewritten. Comments, other tables and your plugin settings are kept, and the previous file is saved beside it as a timestamped backup.
- The whole file is validated before anything is written, and each field's error names the key.
- A change that would not alter anything writes nothing and makes no backup.
- An environment variable such as
OAKEN_AI__CHUNK_TOKENSoutranks the file.settingsshowsenv (OAKEN_AI__CHUNK_TOKENS)as the source, and saving that key warns you that the variable wins. - No secrets pass through here: nothing on the list is one.
Storage
oaken storage # the two databases, their write-ahead logs, and the quarantine folder
oaken vacuum --wait # give back the space deleted mail left; shows the sizes before and after
Sizes are read from the files, not by scanning mail. vacuum rewrites raw.db and index.db, one
at a time, and refuses while an index rebuild runs or if the disk does not have about the larger
database's size free. While it works each database is write-locked: ingest waits and reads carry on.
The enrichment cache
oaken cache # entries, size, prompt versions, and how often it saved a model call
oaken cache clear --task triage # one task's answers; no --task clears all
The cache holds model answers keyed by what produced them, so clearing it costs only the calls it
had saved. Mail, the index and the usage record are untouched. Without a terminal, clear needs
--yes.
Watching a plugin or a job: the trace
oaken trace on # start recording (it holds mail text: off until asked for)
oaken trace -f plugin.triager.ai # follow one plugin, pushed as each event happens
oaken trace -f plugin.enricher.summary
oaken trace plugin.llm_backend.ollama -n 20
oaken trace --job 0192a7... # one job instance, and nothing else
oaken trace --message 0192a8... # everything that happened to one message
oaken trace off
The trace records, with the full text: every call into a plugin (its arguments and what it
returned, for every kind: providers, embedders, LLM backends, vector stores, caches, triagers and
enrichers); every model call core makes (the system text, each user part fenced as mail, the schema,
the response, the thinking a model returned, the backend's own token counts and timings, and the
tokens a cache hit saved); the jobs (queued, started, done, failed) and what each stored; and the
agent door (what an agent was handed on a claim, its heartbeats, the answer it committed, and any
thinking or tool calls it chose to report). Every event carries the plugin (plugin_kind,
plugin), the job (job_id, job_kind) and the message it happened under, so each of the filters
above is exact.
It is off by default, because it holds mail text. [log] trace = true turns it on at start-up;
oaken trace on|off changes it at run time. It goes to trace.jsonl in the data directory
(owner-only, rotated at trace_max_bytes, keeping trace_backups), is read only through the
authenticated API, is never shown on the console's token-free pages and is never offered over MCP.
A single text longer than trace_event_cap is cut and says so.
A plugin author gets the same view of their own code: every public async method on a plugin built
on a base class is traced under its kind and name, and self.trace("my.event", key=value) adds an
event of your own.
What happened: events and the audit log
oaken events --tail 20 # recent events, including from before core's last restart
oaken events --kind JobStateChanged --since 2026-10-24T09:00:00
oaken events --follow # the history, then the live stream
oaken audit --limit 20 # recent changes: who changed what, and whether it can be undone
oaken audit --all --since 2026-10-01
Core writes every event to events.jsonl in the data directory ([log] events_file; empty turns
it off), one JSON line each, owner-only, rotated at events_max_bytes and keeping events_backups
older files. Events hold ids, states and numbers, never mail text. audit pages with a cursor: the
last line of each page gives the command for the next, and --all follows them all.
Is it healthy?
oaken status says whether core is running and, when it answers, adds a line: accounts, messages
(and how many are indexed), the queue, healthy plugins, and anything that needs attention, such as a
stale index or sync schedules that are paused or failing.