OAKENMAIL
Open source

Contributing

Pull requests are welcome. Here is how to set up, what the checks are, and the ground rules.

Pull requests are welcome. There is no DCO or CLA yet.

1

Development setup

You need Python 3.11 or newer and uv.

uv sync
uv run ruff check
uv run ruff format --check
uv run mypy
uv run pytest

Install the git hooks (lint plus secret scan) with uv run pre-commit install if you use pre-commit, or run uv run detect-secrets-hook --baseline .secrets.baseline <files>.

2

Configuration

Oaken reads a single config.toml. It lives outside the repo, in the per-user config directory (via platformdirs):

OS Path
Linux ~/.config/oaken/config.toml
macOS ~/Library/Application Support/oaken/config.toml
Windows %APPDATA%\oaken\config.toml

Set OAKEN_HOME=/some/dir to relocate everything under one root (<dir>/config/config.toml). Precedence is: built-in defaults < config.toml < OAKEN_* environment variables. Unknown top-level keys are an error; every section has defaults, so you only set what you change.

config.example.toml at the repo root is a documented template covering every section (Gmail, IMAP, SMTP, Ollama, AI models, sync, API, logging). Copy it and edit:

cp config.example.toml ~/.config/oaken/config.toml

Secrets never go in config.toml. OAuth refresh tokens and IMAP/SMTP passwords live in the OS keyring (service oaken, user <kind>:<account>). The file only names the Gmail OAuth client JSON; the token is obtained by the authorization flow. For Gmail, bring your own OAuth client (Desktop-app type, gmail.modify scope) and publish it to Production — a Testing-mode app expires refresh tokens after ~7 days.

3

Repository layout

src/oaken/           core: the daemon, API, operations, storage, ingest (the `oaken` package)
src/oaken_*/         first-party plugins (providers, embedder, enrichers, vector store)
apps/cli/            the `oaken` command, a separate package (`oaken-cli`, import `oaken_cli`)
apps/webui/          the web UI (templates today; its own app later)
docs/                the documentation site sources and generators

Core knows nothing about the apps. An app is a client of core's HTTP API and lives in its own uv workspace member with its own pyproject.toml, so it can be built, versioned and tested on its own (uv run pytest apps/cli). See ADR 0006.

4

Ground rules

5

AI tooling

Contributions produced with generative AI tooling must follow the ASF's Generative Tooling Guidance. In short:

6

Documentation

The project website is generated locally from the Markdown in docs/ and the generated HTML is committed beside it; GitHub Pages serves the main branch's /docs folder. CI does not build it. After changing docs (or the software map), regenerate, check and commit the result:

uv run --group docs python docs/tools/build_site.py           # regenerate the HTML in docs/
uv run --group docs python docs/tools/check_docs.py           # links, anchors, and "HTML is up to date"
uv run --group docs python docs/tools/build_site.py --out /tmp/preview --serve   # optional preview

check_docs.py (and CI) fails if the committed HTML differs from a fresh build. The build records what it generated in docs/.site-manifest and only ever replaces those files.

Register new pages in docs/site.toml. Keep the software map current: edit docs/softmap.toml in the same change that builds or alters a component (the build fails if it disagrees with the repository).