Set up Oaken from scratch
This walks through a first setup on one machine: install, the config file, the local model, one mail account, the daemon, a first sync, and, if you want it, the MCP server. Each step says how to check that it worked.
Oaken is in beta. Everything below stays on your machine.
1. Install
You need Python 3.11 or newer and uv.
python3 -m pip install oaken-core # into a virtual environment you keep for it
oaken --help
To work on Oaken itself, use a checkout instead: git clone https://github.com/dfoulks1/oaken-mail,
uv sync, then run commands as oaken ... (or activate .venv to type oaken alone).
The commands below are written as oaken .... To check the install:
oaken --version
oaken help sync
2. Write config.toml
The file lives outside the repository, in your per-user config directory
(~/.config/oaken/ on Linux). Start from the documented template:
mkdir -p ~/.config/oaken
cp config.example.toml ~/.config/oaken/config.toml
Every section has defaults, so you only keep what you change. Never put a password or token in this file; step 5 stores them in your keyring. See Store credentials in your keyring if you have not used one before.
You do not have to copy anything: the first time core starts it writes a config.toml with every
setting shown at its default, commented out. Edit it in the console at /config (it tests a change
before saving and keeps a .bak), or with oaken config show, oaken config test FILE and
oaken config save FILE, then apply it with oaken config reload.
Where Oaken keeps its files
Set OAKEN_HOME=/some/dir to put everything (config, data, the runtime file) under one directory,
and put the line in your shell profile so every shell agrees. If it is unset, core warns, then uses
the last home it ran under, or the platform folders if there is none, and tells you the line to
add. Core cannot export a variable into your shell; it remembers the home in a small pointer file
outside the home instead.
Plugins that are not set up
A plugin that is installed but has no [plugins.<kind>.<name>] table (Gmail, IMAP, SMTP) is listed as
"not configured", not as an error. To turn one off for good, set enabled = false in its table.
Without restarting core: oaken plugins disable gmail, oaken plugins enable gmail, and
oaken plugins reload gmail to pick up a change to its table. oaken plugins config gmail shows
its settings and oaken plugins set gmail page_size=200 changes one (your comments in config.toml
are kept; reload to apply). Each plugin kind has a page or tab (Triage, Embed, Enrich, or a General tab) with an
enable switch and a Reload button.
3. Get the local models
Oaken runs a local Ollama by default. It never pulls models itself, so
pull the ones named in [ai] (these are the defaults):
ollama pull nomic-embed-text # the embedder
ollama pull qwen2.5:3b # the language model
To use a model you already have, set llm_model (and embed_model) under [ai] in config.toml.
4. Add an account
Pick the provider that matches the account:
- Gmail: Connect Gmail. You create your own Google OAuth client
(Desktop app,
gmail.modifyscope, published to Production) and save its JSON whereclient_secret_filepoints. - Any IMAP server: Connect any IMAP server.
- Sending through your own server: SMTP.
Then register the account. On a terminal this asks for the provider, an id, a display name and the provider's non-secret settings:
oaken admin account add
oaken admin account list
The account id (letters, digits, - and _) names the provider instance, gmail@<id>, and its
keyring entry.
5. Store the credential
oaken gmail auth --account-id <id> # opens Google's consent page and waits
oaken imap auth --account-id <id> # or: asks for the password, no echo
Each provider owns its own sign-in, so the command starts with the provider's name
(oaken smtp auth works the same way). The credential goes to the OS keyring and is never
printed. Add --check to test one that is already stored.
6. Start the daemon and check it
oaken start # in the background; --fg keeps it attached to this terminal
oaken status # prints the pid and the loopback port
oaken plugins # your account's provider row should say healthy
oaken admin account show <id> # a "problem:" line says why one is not
If oaken start fails (for example "core exited while starting"), run oaken start --fg. It stays
attached and prints the real error, such as a port already in use.
Core serves a small API on loopback only. Its token is the file api_token in the config
directory. The daemon and the local API explains the rest.
7. Sync and look
oaken sync --wait # every account on every provider; or add --account <id>
oaken search "invoice"
The first sync of a large mailbox takes a while by design. Mail is stored under your user data
directory (~/.local/share/oaken/ on Linux). A schedule then keeps the account current; see
Sync schedule.
8. Optional: connect an AI client
The MCP server is off until you turn it on. Add this to config.toml and restart core:
[api]
mcp = true
Then follow Connect an AI client to point Claude Desktop or another client at
oaken mcp. Changes made through it always ask for confirmation first.
If something fails
| Message | Likely cause |
|---|---|
no OS keyring is available |
The keyring is locked or not running. See the keyring page. |
client_secret_file is missing or is not a Google OAuth client JSON |
The file does not exist, or is a web client. It must be a Desktop-app client with an installed block. |
core is already running |
A daemon is up. oaken status shows where; oaken stop ends it. |
core_not_running from a tool call |
Start it with oaken start. |