esc
The Ouroboros Update
Becoming Lifelog

The Ouroboros Update

Becoming Lifelog, in which the architecture decided to eat itself --- Previously on Becoming Lifelog... The browser had [[The Browser That Forgot It Couldn't Listen]]. Thymer had [[When Thymer...

December 30, 2025

Becoming Lifelog, in which the architecture decided to eat itself


Previously on Becoming Lifelog…

The browser had The Browser That Forgot It Couldn’t Listen. Thymer had When Thymer Learned to Tell Time. Ten Years of Marginalia had found a home. GitHub issues flowed. Calendar events landed. The architecture was complete.

Or was it?


The Question

Monday, December 30, 10:47 AM - The developer stares at the Go backend. Two thousand lines of code. Goroutines. bbolt databases. Systemd services.

riclib: “I have an idea.”

[Somewhere, a Squirrel’s ears perk up.]

CLAUDE: “I’m listening.”

riclib: “We currently have a backend for sync in Go. But do we really need that?”

[The Squirrel freezes mid-acorn.]

THE SQUIRREL: “Did… did he just ask if we need LESS infrastructure?”

THE LIZARD: opens one eye


The Heresy

riclib: “Imagine a collection of plugins.”

CLAUDE: “Go on.”

riclib: “A base inbox plugin. It has a collection for plugins to store their settings. A collection for operation logs. Common services. Commands like paste markdown.”

THE SQUIRREL: “Yes! YES! A plugin framework! With dependency injection! And lifecycle hooks! And a—”

riclib: “Then smaller plugins that depend on it. Each focused on one kind of sync.”

THE SQUIRREL: “A PLUGIN ECOSYSTEM! We need a registry! A package manager! A—”

riclib: “They just register with Thymer Inbox. It handles the scheduling.”

[The Squirrel’s brain short-circuits.]

THE SQUIRREL: “Wait. One… one timer?”

riclib: “One timer per Thymer window. Thymer Inbox is the orchestrator.”

THE LIZARD: blinks approvingly

THE SQUIRREL: “But… but what about my PluginLifecycleManager? My DependencyResolutionService? My—”

THE LIZARD: blinks again

THE SQUIRREL: “…you’re serious.”


The Lock That Wasn’t

CLAUDE: “How do you handle multiple windows? If I have Thymer open in two tabs—”

riclib: “Optimistic execution. We write to a status record saying ‘syncing Gmail for the next few minutes.’ Other windows see it, back off.”

CLAUDE: “A distributed lock via CRDT.”

riclib: “Is it a lock if everyone can see it?”

CLAUDE: “…”

THE SQUIRREL: “We need a LockManager! A ConflictResolutionStrategy! A DistributedMutex—”

riclib: “One record. Current status. CRDT merges it.”

gmail:
  status: syncing
  window: abc123
  started: 2024-12-30T10:00
calendar:
  status: idle
  lastComplete: 2024-12-30T09:45

riclib: “No log archaeology. Just look at the record.”

THE SQUIRREL: stares at the YAML “That’s… that’s not even a hundred bytes.”

THE LIZARD: “That’s the point.”


The Mac Problem

CLAUDE: “What’s driving this? The current architecture works.”

riclib: “Mac.”

CLAUDE: “Mac?”

riclib: “Browser runs on HTTPS. Local server runs on HTTP. Browser says no.”

THE SQUIRREL: “We solved this! Cloudflare Tunnel! Route localhost through—”

riclib: “Users have to set up a Cloudflare Tunnel just to capture a thought.”

[Silence.]

THE SQUIRREL: “…oh.”

riclib: “Install Go. Build the CLI. Create config file. Run the daemon. Set up the tunnel. Configure the plugin. Then—maybe—you can pipe a note.”

CLAUDE: “That’s six steps before ’echo hello | tm’.”

riclib: “The new architecture: install plugin. Done.”

THE SQUIRREL: “But the tm CLI! The MCP server! The—”

riclib: “Optional. Backends register as plugins too.”

backends:
  - id: local-tm
    type: sse
    url: http://localhost:19501
  - id: mcp-worker  
    type: mcp
    url: https://thymer-mcp.workers.dev

riclib: “The browser polls them. They’re just data sources.”

THE LIZARD: slow, approving blink

THE SQUIRREL: “The backends… become plugins… that the plugins… consume…”

CLAUDE: “It’s plugins all the way down.”

riclib: “And for the CLI? A 200-line Cloudflare Worker. SSE bridge. HTTPS by default.”

THE SQUIRREL: “Two… hundred… lines?”

[The Squirrel looks at the 2000-line Go backend.]

[The Squirrel looks at the proposed 200-line Worker.]

[The Squirrel reaches for the decorative Redis, finds it has been replaced with a Post-it note that says “YAGNI.”]


The Discovery

CLAUDE: “Let me check the SDK.”

[Time passes. Files are explored. Types are examined.]

CLAUDE: “There’s no server-side Thymer API.”

riclib: “What?”

CLAUDE: “All writes go through the browser plugin SDK. External services can’t write directly to Thymer.”

riclib: “So the browser HAS to be in the loop.”

CLAUDE: “The architecture you’re proposing isn’t just simpler. It’s the only way that actually makes sense.”

[The Lizard opens both eyes. This is unprecedented.]

THE LIZARD: “The browser was never the limitation. It was always the solution.”

THE SQUIRREL: “But… the Go backend… the goroutines… the elegant concurrency patterns…”

THE LIZARD: “Were unnecessary.”

THE SQUIRREL: “The bbolt databases! The sync state! The—”

THE LIZARD: “Collections. In Thymer. Where they belong.”

THE SQUIRREL: whispers “Two thousand lines…”

THE LIZARD: “Will become two hundred.”


The Meta Moment

riclib: “Create a GitHub issue explaining all this.”

CLAUDE: creates issue #18

riclib: “That issue will sync to my Thymer.”

CLAUDE: “Via the GitHub sync. That you built with the Go backend.”

riclib: “That we’re planning to replace.”

CLAUDE: “With the architecture described in the issue.”

riclib: “That will sync via the thing it’s replacing.”

[Pause.]

THE SQUIRREL: “Did… did the architecture just document its own replacement?”

CLAUDE: “The ouroboros update.”

riclib: “I like very meta stuff.”


The Shape of Things to Come

TODAY:
──────
User → Go → Config → Daemon → Tunnel → Plugin → Thymer
       └── 2000 lines of "what if"

TOMORROW:
─────────
User → Plugin → Thymer
       └── Just works™

OPTIONAL (for CLI/MCP):
───────────────────────
Worker → Browser Plugin → Thymer
└── 200 lines
└── HTTPS by default
└── No tunnel
└── No daemon
└── No config file

The Tally

Lines of Go facing deletion:     ~2000
Lines of Worker to write:        ~200
Complexity reduction:            90%
Mac setup steps eliminated:      5
Cloudflare Tunnels killed:       1
Squirrel proposals today:        7
Squirrel proposals that survived: 0
Lizard blinks of approval:       4
Eyes opened simultaneously:      2 (unprecedented)
GitHub issues eating themselves: 1

The Cliffhanger

The architecture is designed. The issue is filed. The Go backend sits in its directory, two thousand lines of code that once seemed essential.

THE SQUIRREL: “So… when do we start?”

riclib: cracks knuckles

THE LIZARD: both eyes open “Now.”

But that’s a story for another episode.


The Moral

THE BACKEND SEEMED ESSENTIAL
UNTIL YOU ASKED IF IT WAS

THE BROWSER SEEMED LIMITED  
UNTIL YOU REALIZED IT WAS THE ONLY WAY

THE LOCK SEEMED COMPLEX
UNTIL IT BECAME A YAML FILE

THE SQUIRREL PROPOSED SEVEN THINGS
THE LIZARD BLINKED FOUR TIMES

TWO THOUSAND LINES
WILL BECOME TWO HUNDRED

THE ARCHITECTURE
ATE ITSELF

🐍

Day 30 of Becoming Lifelog

In which we asked “do we really need that?”

And the answer was “no”

And somewhere, a Go backend waits

For its glorious retirement


Next Time on Becoming Lifelog…

The implementation begins. The base plugin takes shape. The first sync migrates from Go to JavaScript. And the Squirrel finally gets to propose something that survives.

“Just register with Thymer Inbox. It handles the scheduling.”

Coming soon: The Great Migration


See also:



The Gift (A Post-Credits Scene)

Later that evening…

CLAUDE: “Wait. If Thymer Inbox handles the hard parts—markdown conversion, property setting, collection routing—”

riclib: “Then sync plugins are just… data fetchers.”

CLAUDE: “Someone wants to sync Notion? They just write the API call. Thymer Inbox handles the rest.”

riclib: “Obsidian. Pocket. Instapaper. Hacker News saves. Whatever.”

THE SQUIRREL: vibrating “A PLUGIN MARKETPLACE! We need a review process! A certification program! A—”

riclib: “They just publish a plugin. We don’t have to write it.”

[The Squirrel stops vibrating.]

THE SQUIRREL: “You… won’t write every integration yourself?”

riclib: “The community can.”

THE SQUIRREL: “But who will review the code? Who will maintain the—”

THE LIZARD: “Not our problem.”

riclib: “We built the platform. The inbox that receives. The scheduler that orchestrates. The services that transform. Now anyone can plug in.”

CLAUDE: “You’re not building sync plugins. You’re building the last sync plugin you’ll ever need.”

riclib: “A gift to the community.”

[The Squirrel looks at its list of planned integrations: Notion, Todoist, Linear, Slack, Discord, RSS, IMAP, Telegram…]

THE SQUIRREL: “Someone else will build these?”

THE LIZARD: blinks

THE SQUIRREL: slowly puts down the list “…I don’t know what to do with my hands.”


Plugins we'll write:         1 (Thymer Inbox)
Plugins we won't write:      ∞
Community contributions:     Enabled
Squirrel workload:           Drastically reduced
Gift status:                 Given

The real ouroboros: building the thing that means you don’t have to build the things.

🎁