Skip to content
← Work

Native application · Swift

The N.O.C.

A native client that turns one Mac into a home server for a knowledge vault — an editor, a CLI, and an MCP server all compiled from one core so three implementations of "what is a note" can never drift apart.

Editor, CLI and server from one core
Verification harness gates the build
18 MCP tools

In development · Swift 6 · TextKit 2 · libgit2 · SQLite FTS5 · Tailscale · MCP

Three programs, one definition of a note

The N.O.C. is a native client for a knowledge vault that also turns one Mac into a home server for it. There's an editor, a command-line tool, and a server that exposes the vault to other agent tools.

That's three separate programs that all need to know what a note is, where it lives, how it's indexed, and what happens when it moves. Written three times, those definitions would drift apart inside a week — and the failure would show up as data loss, not as a compile error.

So all three compile from one core. There is exactly one implementation of "what is a note," and the other two are thin surfaces over it.

Decisions worth stating

Three of these are written into the project's own documentation, and they're the ones I'd defend in an interview.

"@MainActor alone is not serialisation." Swift's main-actor annotation guarantees things run on the main thread. It does not guarantee they run one at a time in a predictable order — two operations can interleave at every suspension point. Tool calls that touch the vault therefore run through a FIFO gate, in order, one at a time. The annotation was never the safety property I needed; I'd assumed it was.

"An agent session is a real terminal, not a one-shot command." Running an agent through a simple non-interactive invocation is easier, and it silently changes the behaviour — hooks, skills and permission prompts don't act the same way. So sessions run in an actual pseudo-terminal. Harder, and it means what I test is what actually happens.

"Home is the absence of configuration." The role a machine plays defaults to home server when no configuration file exists. That inverts the usual pattern, and it means every "am I a client?" branch in the codebase has a safe default instead of an undefined one.

The harness

There is a 2,865-line verification script that runs 343 checks against a real vault before anything is considered working.

It doesn't test against mocks. It builds a throwaway vault and a bare git remote from scratch on every run, exercises the real push path against them, and tears them down — so the code that touches a repository is never tested against a pretend one, and development never points at the live vault.

That's the software version of the same sentence: a feature isn't done until it's tested and confirmed working.

Honest status

In development. An editor, a CLI and an MCP server compiled from one shared core, 18 tools exposed to other agent clients, and a build pipeline that produces a signed and notarised installer.

Every line was written by Claude Code. The architecture, the constraints, the order things were built in, and the definition of done are mine.