The Journey.

Notes from building a local-first, agentic operating system for my own life. One app at a time.

One Brain Stays Home
opencode routes different tasks to different providers and models: private work runs on one permanent local Ollama hub, beginner-tier tasks on cloud models from four separate vendors, and a three-vendor consensus panel handles the high-stakes calls. Claude Code is single-provider, so the same setup meant running two separate fleets of instances -- until the routing table became a file.
Add, Subtract, Repeat
Gopher was evicting a 74GB model on every chat message. The fix was mostly deletion: dead config, an interim approach that died the same day it was born, 2,278 lines off the monolith, and an embeddings pipeline that had never once worked -- plus what those vectors are actually for. Just enough features: add or subtract as the need changes.
Chatty: A RAG Experiment Grew Up
A few years ago I started tinkering with retrieval-augmented generation. That experiment is now Chatty, the eleventh app in the suite: a daily driver for asking questions about my own documents, running entirely on local hardware.
Guide-Coding Is the Future
Vibe-coding got the name wrong. Guide-coding is the model writing most of the lines while the human keeps the decisions: DrawmaticAI and OwnScribe, two native macOS apps, one owner, local to the last byte, and why making local the cheap option is the benefit that reaches the most people.
September 2026: MyOwnLifeOS Goes Native on macOS
The suite crosses into native desktop apps. inbox0 by MyOwnLifeOS is now pending App Store review: a free, local AI email assistant for Gmail built for macOS with Rust, Tauri v2, SQLCipher, and llama.cpp on Apple Metal. The first of more to come.
August 2026: TShirtize Joins the Suite
The suite now has ten apps. TShirtize reads Monday.com tickets, GitHub issues and PRs, or plain text, then returns a t-shirt size, rationale, definition of done, spike flags, and clarifying questions. Also: the monthly dig at the "I read every line" skeptics, and why a working product is still the best rebuttal.
Start at the Decomposition
When an agent turns a bounded unit into working code in minutes, the leverage is not in the implementation anymore. It is in how you carved up the problem. Which quietly reframes t-shirt sizing: same ritual, different payoff, because what used to produce an estimate now produces a spec. TShirtize reads a Monday.com, Jira, or GitHub item and does the context-gathering that stands between you and a decomposition worth handing off.
Just Enough Notes
The last post ended with notes arriving already attached to the calendar event. Most of my meetings attach nothing. The fix for that gap was not a notes app or some grand new system. It was one link field that pins a standalone notes doc to an event and follows the whole recurring series, plus a reminder that the smallest change that closes the gap is the one worth shipping.
The Notes Were Already Attached
Meeting notes docs arrive attached to the Google Calendar event, and the file id is already in the payload Almanac syncs. Sixty lines of parser turned my weekly synthesis from a description of my calendar into a description of my work, plus a 71-second demo of the estate, and the three bugs that were quietly keeping the whole thing from running.
The Apps Introduce Themselves
I replaced blind endpoint probing with a self-description protocol. Each app now declares what it offers in one JSON constant — endpoints, fields, parameters — and the router follows the map instead of guessing. Less coupling than I feared, more documentation than I expected.
Trust Issues (The Good Kind)
Two weeks of teaching my apps to trust nobody: SSRF and XXE hardening, a code reviewer that fact-checks its own findings before it opens its mouth, a weekly review that stopped being bossy, and all eight apps now installable PWAs. A little paranoia ships well.
Per-Request Secure Cookies, a Streaming Bug, and the Week the Suite Grew Up
Two days. Eight apps. A streaming-response crash that exposed a copy-paste bug across six servers, a YAML indentation mistake that corrupted Fernet keys in two containers, and a 38-finding suite-wide security pass that landed in the same window. Plus a value-based identity layer tying the suite together by email address.
Three Apps, One Service Worker -- And a Dashboard You Can Actually Triage
Seven apps got dynamic service worker cache busting -- a hash of UI file mtimes so browsers auto-reload on deploy. inbox0 got real triage controls: reprioritize with undo, dismiss and restore, collapsible cards and groups. One dashboard. Seven apps. Your rules.
A Holiday Is Not a Meeting
Almanac said I had worked 356 hours in a single week. There are 168. The calendar was counting holidays as 24-hour workdays. Local-first was never the hard part -- classifying your own data correctly is. The story of Almanac becoming a time data plane (CalDAV, per-calendar categories) and Weekly becoming a narrative layer durable enough to survive a logout, a reload, and a redeploy.
What the Industry Calls Trends, I Call Tuesday
Anthropic's own model walked me through ten thriving agentic AI use cases and ten lurking trends. Most of them are the industry arriving, slowly and at enormous expense, somewhere I got to in September 2023. Token bill reckoning, multi-agent compounding errors, code agents as full-time review, and data sovereignty finally becoming a market category.
The Agent Did Not Fix Itself
Eight commits across two weeks. Four distinct failure modes: instructions ignored, schema mismatches, silent looping, and an undefined constant referenced three times. Every single one required a human to identify, diagnose, and resolve. The agent was not autonomous. It was not close.
Ghost Routes and Disappearing Data
Twenty inbox0 API endpoints -- credentials, config, OwnLifeOS integration -- had been returning 404 since they were written. One misplaced line. The same week: E2E tests deleting the live diagrams database on every run, and a Docker seed file five weeks stale. Plus the rebrand to MyOwnLifeOS and a type scale pass across all seven apps.
Your Review Data Has No Business in Their Cloud
Notion AI, Reflect, and BeforeSunset all want you to sync your life into their infrastructure so their models can summarize it back to you. The ninth MyOwnLifeOS app does the same job -- looking back across the week across meetings, email, code, and tasks, telling you what actually happened and what needs to happen next. Your data never moves.
Coulda. Woulda. Shoulda. -- The Token Bill Reckoning
November 2024: a case study was written. It had the math. Private inference cluster, $766/month, no rate limits, no overages, data goes nowhere. Uber, JPMorgan, Shopify, and GitHub Copilot all had other plans. By April 2026 they were rationing access and watching token bills exceed employee salaries. The blueprint was right there.
The App That Watches Itself
DrawmaticAI now has a Playwright test suite. A demo login route sidesteps OAuth, persona fixtures give each test role its own authenticated browser context, and security controls get their own regression specs. Because a test suite is only as honest as the things it actually exercises.
One Invite System, Seven Apps
Seven apps. Seven invite flows. None of them matched. Some accepted empty bodies and returned 500s. Some generated tokens that never expired. One had a TOCTOU race where two requests could both pass the verification check before either wrote. Standardizing all of them to JWTs with expiry, revocation, and dedicated landing pages -- and giving most of them their first real admin page in the process.
Never Beholden: A $5,000 Bet on Compute Sovereignty
In September 2023, regrouping after failing to convince a board to invest in building out a serious illness management platform, I googled "local AI" and came across Ollama. Twenty minutes later I was chatting with a Llama model on my own machine. This is the cost story of what followed, and why I will never be beholden to a cloud subscription.
Green Tests, Broken Features
Swapped the model. Tests passed. Four features broke. Traditional practice has a clear answer: UI integration tests catch this. The problem is LLMs don't apply it -- they can't maintain a test suite, can't verify assertions still test the right thing, and tend to make tests less strict rather than fix what broke.
What Were You Doing?
Gopher can now search your Immich photo library from the chat window. Getting there meant a proxy layer to avoid leaking credentials to the browser, a URL-encoding trick to stop relying on the LLM for asset type detection, a hallucination problem diagnosed from a malformed UUID, and a full migration from global env vars to per-user encrypted settings.
Ten More
Gopher had five findings the previous review missed. inbox0 had five of its own. OAuth CSRF state appeared in every app with an OAuth flow. A chmod 666 on the database file, a wildcard CORS configuration paired with credentials, and an encryption key printing itself to stdout on startup.
The Tool Reviews Itself
Code Reviewer reviewed its own code. Gopher got the same treatment. Neither passed cleanly. Redirect-chain SSRF that bypasses scheme checks, a JWT issuer parameter that only validated when you remembered to ask, PII logged verbatim from LLM responses, and five streaming fetch loops that left the UI frozen on network loss.
The Brand You Build Last
The ○ placeholder survived seven apps and several months because I was solving the wrong problem. Replacing it with the shield-nodes mark taught me that brand is not aesthetics. It is description. Also: why the nav says Focus and not Pomodoro, why Consent by Default is a principle worth naming, and what Data Gravity actually means.
How Building 7 Apps Changed How I Think About Architecture
Real bugs, real debugging, 13 security findings, and a consent router I did not plan for. Six lessons on agents, sovereignty, security posture, and what "architect" actually means when AI is the runtime.
Closing Thirteen Security Findings in DrawmaticAI
A proper security review found IDOR on every diagram endpoint, JWT secrets that regenerated on restart, WebSocket locks with race conditions, and a Host header fallback that trusted the client. I closed all thirteen. Security is not a feature you add. It is a posture you maintain.
Gopher: The Steward Who Remembers Everything
The seventh MyOwnLifeOS app is a concierge with no data of its own. It queries inbox0, Summarizer, and the rest, caches context in PostgreSQL, and answers in plain language. Building it meant solving a regex that ate JSON, preventing cross-account email leakage, and teaching an LLM to know which inbox you mean before it speaks.
Scribe: When the Mic Finally Works
Live transcription with AI meeting minutes. What sounds simple -- capture audio, transcribe, summarize -- turned into a deep dive through Safari Web Audio quirks, ASGI event dicts, and the asyncio event loop. The gap between "it should work" and "it works" is where you learn.
From Email Triage to a Local-First OS
What started as a single Python script for email triage has become a five-app local-first suite with shared dark theming, cross-app analytics, PWA offline support, and a consent model I actually trust.
DrawmaticAI: Diagrams by Description
I needed a fast way to create diagrams. The first proof of concept took a few hours. By the end of the next day, there was an MVP working. No compromises for hypothetical users — just solving the actual problem in front of me.