back to portfolio

Systems

Systems I run on my own machine

Local-first tools I built for my own workflow, each with a number I can defend. Most of these repos are private because they hold my own calls, notes and applications, so they are described here, not linked.

screen-tutor

private repo

A voice that watches my screen, explains it, and points at what it is talking about.

The model never gets a move-the-cursor tool. It appends one text tag to its spoken answer and the host parses it with a single regex; on a structured surface the coordinate becomes an element id, which is what stops a pointer being hallucinated. I measured three architectures before keeping one, and the whole loop now runs locally: a streaming ASR ear, a long-lived headless Claude process, a neural TTS on the Neural Engine. The silence after a question is covered by a resident small model that speaks a six-word acknowledgement and is guarded so it can never state a fact, a promise or a number. An end-of-turn model replaced the fixed silence timeout, so a finished question is answered at once and a sentence that stopped on "the" is held. Evaluated without me in the room: a harness drives it with typed turns and a silent fake device, which is what caught every answer starting at exactly 2.2 s.

p50 906 msopener, vs 2.7 s fresh process
1.4-1.6 sfirst word after I stop, from 2.4-3.3 s
0.14-0.3 sTTS per clause, warm
600+tests
NodeSwiftPythonParakeetKokoro-82MClaude Code headless

meeting-recorder

private repo

On-device call and interview recorder with speaker identification. Nothing leaves the machine.

Hosted note-takers upload the audio, which is not an option when the calls are under NDA. So it records two tracks, my mic and the call's own audio, through a signed Swift CLI on Core Audio process taps, which means self-attribution is exact by construction and voice ID only has to run on the other side. The virtual-driver route it replaced produced a silent call track whenever a Bluetooth headset shifted the channel map by one; I proved that by playing a 19 kHz tone into each device and measuring per-channel levels. It checks its own audio now (a dropout detector found a 119.9-holes-per-minute recording in about a second, where I had found it days late by hand), live captions are scheduled on audio-seconds rather than requests so neither track starves, and the filed archive is a read-only MCP server scoped to one company at a time.

48.4 s to 17.5 smedian caption lag on a busy stretch
52 to 19repetition markers across 3 code-switched calls
2-4 swho-said-what after each utterance, live
~1 sto locate a 4-minute capture loss
NodeSwiftPythonwhisper.cppsherpa-onnxMCP

brain-ops

private repo

Local long-term memory over everything I write and build, served to every agent session over MCP.

Hybrid retrieval in one SQLite file: FTS5 keyword search, bge-small embeddings and a link graph, ranked with Personalized PageRank. Recall understands time ("last week", "in September") and intent ("what did I decide"), memories carry an FSRS-style strength that fades unless used, and confidence is calibrated so "low" means "I don't remember" rather than a guess. One shared server on a Unix socket holds the graph and the model for every session instead of ~500 MB each. Privacy is an allowlist in code: the most private repos and secrets are refused at index time. Adding a 535-chapter book library as a source took recall@5 to 1.0, and I damped it to 0.4 because 0.6 pushed my own note out of the top 5 on a question it should have won.

0.929 to 1.0recall@5 on my own eval set
~30 mswarm retrieval
127 to 229 mswarm p95, the cost of the library
44tests
NodeSQLite FTS5transformers.jsMCPlaunchd

agent-memory

private repo

A store for what an agent session finds out while working. Git-shaped, for five specific reasons.

Four records already existed on this machine and none of them owned experience: git holds what changed, the event log holds what was built, CLAUDE.md holds the contract. I measured the baseline before writing anything, and that number is the argument for the whole repo. Entries are content-addressed, so the same lesson learned in six sessions becomes one entry seen six times, and that count is what the digest ranks on. Merge, three-way diff and packfiles are deliberately absent, and the repo says why. The read path is the half that decides whether any of it is worth it: a 35-line budget enforced in code, open loops first, and three guards between a memory and a session that would believe it. Nothing can be pinned fresh by hand; reconfirmation by use is the only honest signal.

246 of 246sessions that left nothing behind, before
35 linesread budget, enforced in code
10 writersconcurrent, one linear chain, no forks
53tests
NodeJSONLlaunchdClaude Code skills

JobOps

private repo

A job-application pipeline built as an agent system with a hard human gate.

It researches, drafts and scores; nothing is sent or submitted automatically, except one deliberately carved-out lane for the lowest grade of lead. The measurement half came out of an audit of where the leads were coming from: five new sources, a shared geo filter backtested against history, and word-boundary keyword matching to kill silent substring hits (defi was matching undefined, rag was matching storage). Then its own record-keeping got the same treatment. Four stores recorded the same company at different moments with nothing reconciling them, so I wrote a join that derives one canonical status per company and surfaces every disagreement as drift instead of resolving it quietly. That join caught two parser bugs that had been dropping real applications from every view.

138 of 178leads from a single source, pre-audit
0 false dropsgeo filter, across 20 historical A/B leads
80 issuesclosed by hand before the drift join existed
1 in 4low-grade leads that clear all five gates
NodeChrome extensionGitHub Actionswhisper.cppheadless Chrome

ops-center

private repo

One command centre across every repo, with a push-to-talk orb in front of it.

Built after an audit said a third copy of the per-repo board was the wrong fix, because N copies means N heartbeats to keep alive. It is a window and a launcher, never an owner: every fact on screen is read through its source repo's own parser, so deleting it would lose nothing. The first build put every data source on the page at equal weight; rebuilt around a ranking engine that clusters and picks one hero. The slow poll was not slow git either: each git call ran under 40 ms, the cost was 36 subprocess spawns, so reading .git/HEAD directly fixed it. The voice path keeps no LLM in the loop by design, a fuzzy grammar over 14 repos and roughly 100 skills, with a two-second editable box before anything reaches a session, so a misheard word is corrected first.

229 to 12things on the page (153 to 8 clickable)
1483 ms to 10 msstatus poll across twelve repos
0.5 sfirst word of streamed speech, 82 ms per slice
2297 to 44words on the page
NodeSwiftParakeet via FluidAudioiTerm2 automation

lifelog

private repo

An append-only event log in Go that keeps every system describing me current from evidence, not memory.

One ordered JSONL stream and a cursor per consumer, so a consumer added later replays all history into itself and nothing is ever applied twice. Commits log themselves through a single global git-hooks dispatcher covering every repo on the machine, including ones cloned later. Summaries are extracted deterministically (conventional type and scope, file churn, languages, dependency diffs) with no model in the loop. Corrections are appended as events and resolved on read rather than mutating the log, project status decays on its own, and salience ranking means the digest ranks commits instead of dumping them. It ships its own macOS integration: launchd agents, a code-signed app bundle, and a global-hotkey capture panel in Objective-C. It is the source every other system on this page reads from.

1 cursorper consumer, replay-safe
6manifest formats diffed for dependency changes
0 modelsin the summariser
GoObjective-CJSONLlaunchdgit hooks

Want this kind of work inside your tools?

I do fractional work: agents and integrations built inside a customer's own systems, measured before and after.

Fractional work

Numbers on this page are measured on my own machine and my own data. They are what I got, not a benchmark.