A local-first Notion alternative that runs in one Docker container — pages, databases, calendars, search, voice capture — with a local language model that pilots your project boards and has to prove what it did. No accounts, no cloud, no telemetry. The whole workspace is one SQLite file and an uploads folder on a volume you own.
Designed and built solo, 20 Jun – 2 Sep 2026 · 269 commits · 53 pull requests · 6 security audit rounds
The full build log, hurdles and corrections included →
$ docker compose up -d --build
→ http://localhost:3000 · 695 end-to-end tests green
Markdown shortcuts become real blocks as you type. A slash menu for everything else. Autosave with a status you can trust.
Watch for: “## ” collapsing into a heading and “/” opening the block menu. The same shortcuts work in every block — Tab indents, Ctrl+Z undoes across views, and edits flush to disk when you close the tab rather than being lost.
A page can be a database. Typed properties, relations, rollups and formulas underneath; table, board, calendar and gallery on top.
| Task | Status | Due | Owner | Est. |
|---|---|---|---|---|
| Split the agent-automation suite | Doing | 2 Sep | me | 2h |
| Board fairness — least-recently-served | Done | 30 Aug | me | 5h |
| Materials: audio previews in the library | Done | 29 Jul | me | 3h |
| GPU switch must actually evict | Done | 29 Aug | me | 6h |
| Planner reminders for any hour column | Todo | 4 Sep | me | 1h |
| Sign the lease in person | Needs you | 6 Sep | — | — |
The rows never move — only the lens does. Filters, sorts and hidden columns are saved per view, so a board and a table over the same data can disagree about what matters without either one editing the other.
A local model works the board. Done is unreachable unless a tool that produces something actually returned — and the evidence comes from the server's record, not the model's word.
Watch the second card. The model asks for Done twice and is refused twice — once because set_status cannot reach Done at all, once because reading is an input, not an outcome. It lands in Needs you, which is the status that makes the other three trustworthy. And a completion stays a claim until a person accepts it. — Drive this yourself, with the real gate logic →
Twelve parallel jobs on GitHub Actions, one per capability. A red job names a broken feature, not a shard number — and each posts to the project board the moment it finishes.
Real numbers from the last run on main. Note the long pole: agent-automation at 1:45 is nearly half the wall clock on its own, which is exactly why the most recent commit on the repo splits it further. The build refuses to start unless every spec file belongs to exactly one suite — a spec that silently stops running is the one failure a green build cannot show you.
A resident model holds ~3.9 GB of an 8 GB card whether or not anything is asking it anything. One switch stops the schedulers, refuses new calls with a reason, and evicts.
The first build of this reported success the instant Ollama acknowledged the unload — but its runner takes about twenty seconds to hand the memory back, so it told you the card was busy at exactly the moment you were deciding whether to launch a game. It now polls until the memory is really free and reports what it observed, or says it timed out rather than claiming a freedom it did not see.
Happy to walk through any of it — the evidence gate, the CI split, or the measurements that changed my mind. The application source is private; ask and I'll share it.