microlog.me: six years of designing a tracking system
A design document for a tracking system that needed an interpreter nobody had yet. When the interpreter arrived it contradicted the document's central bullet.
Motivation
The system started as a to-do list on paper, ticked off by hand, because bikeshedding over which app to use had kept me from starting a list at all. Choosing the container was displacing the thing the container was for, which is the failure the whole design is built against.
Sizing the unit of work
Paper produced a measurement within days that no whiteboard would have:
"I also realized that there is a sweet spot in the length of time between ticks -- I can't have a to-do list item that takes 2 hours long because it feels too intimidating to start."
Two things fall out of it:
- the unit of work has an upper bound somewhere under two hours
- the bound is about starting, not about finishing
Findings like that only come from running the system on yourself, which is the rule that governed the next four years:
"The reason why I am not executing on mlog is because right now, the idea is much too vague, and I need to develop a manual system before optimizing it into an app ("it must exist before you can optimize it.")."
Adjacent work: Getting Things Done
Three methodologies were on the list to research: Getting Things Done, Deep Work and Pomodoro. Only the first got worked through, and a single abstraction out of it was enough.
The open loop. Anything unresolved you are still holding in your head. Holding them is expensive: your mind is a place for having and combining ideas, and every unresolved thread takes room that combining needs. The method is a set of lists to move open loops out of your head, plus a weekly review to keep the lists from rotting.
Kept:
- the open loop
- the calendar
- the weekly review, because a system with no scheduled maintenance decays without anybody deciding to abandon it
Dropped: the two minute rule, which says do it now if the next action takes under two minutes. Not wrong, but it leaves the middle unhandled:
"doesn't provide guidance for how to manage granularity of next action. don't really want everything to become something actionable within 2 minutes, and also don't want to handle multiplicity of projects that are > 2 minutes."
Set against the paper finding, the two rules bracket a gap and neither covers it:
- two hours: too big to start
- two minutes: small enough to just do
- everything in between: unspecified, and that is where the whole design problem of a personal system lives
One platform, or many tools over a shared store
The first architectural fork, and the same document takes both sides. A goal statement:
"The ultimate goal of microlog.me is to make it so you can design your own workflow through code. EXPAND UPON THIS"
Then, under that marker, a question and its answer, which I did not treat as an answer:
"* what is the benefit of 1 productivity platform to run everything?
- i actually prefer a lot of individual tools but I prefer not to pay for them but I want some way such that all the data remains in sync"
Two different systems:
- One platform owns everything, and anything you want it to do has to be built into it.
- Many tools over a shared store asks one thing of every tool in it: a way for a program to read and write the data.
The bullet chose the second. The next six years of building went toward the first, and the distance between those two is what this design kept rediscovering.
The read-write constraint decided things long before I could argue for it. Trello with its API looked like the custom solution, weighed against microlog itself and against Notion, on the grounds of needing something simple enough to implement the system and stick to. Notion lost for not having an API, and it has had one since 2021, so that verdict is a fact about the month rather than about the product.
The rule underneath holds: in a system made of independent tools, a tool with no programmatic access is not a component, it is a destination.
The log model
Several tools over a shared store only works if they agree on what goes into it, which makes the entry format load-bearing and the tools the easy part. I had no formal definition and reasoned instead from two things that already worked:
"you can think of your life as a linear timeline of discrete, noteworthy events recorded chronologically. Similar to how logfiles record important events with relevant context, or how our banks/cryptowallets/finanical apps provide a transaction log, a "logfile for your life" would consist of timestamped chronological entries about the things important to you."
A program's log file and a bank statement share three properties:
- entries are timestamped
- entries are appended rather than edited
- each line carries enough context to be read on its own later
Those make the record honest. An append-only store cannot be quietly revised to match the story you would prefer, which is most of what makes a bank statement useful.
Two scope decisions came with it:
- an entry could be anything I cared about, including things I had no part in, like a world event or something that happened to a friend
- the integration contract put the translation on the developer: turn the behavior of their app into the language of logs and timestamped entries
The implicit runtime
Setting up a single integration takes four steps, and the order is the part that matters:
- install a Gmail integration
- authenticate, which produces a connection object inside the workspace
- use that connection to create a feed of new messages
- the feed runs a community contributed flow that makes one API call and returns a plain object
One implementation question has to be answered before any of that can be written:
"in which runtime / exec context does this POJO (which may include functions) exist"
No way to answer it without conceding something: if the object exists, something is running that it exists inside. So the workspace is a program that runs continuously like an event listener loop, the objects live on that program's execution context, and the transformations between them are operations in some evaluation order.
The concession is bigger than it looks. The ordinary parts of a programming language:
- values, the things you can hold: a number, a message, a connection
- storage, somewhere those values live while the program runs, which is what separates a value from a line in a file
- operations that take a value and produce another one
- evaluation order, so the second operation can depend on the first
All four are already specified by the tracking tool:
- the connection is a value
- the workspace is where it lives
- the flow that turns a connection into a feed of messages is an operation
- having to authenticate before the feed can exist at all is an evaluation order, sitting in my own setup story
"Ooh, this means that Microlog.me has a sort of implicit VM and semantics for a simplified log-flow oriented language."
Those are the parts in the literal sense, and all four were drawn without the word appearing once. Describe precisely how information moves through your thing and you have defined a small language.
Which runs into the problem that stops the whole design:
"While simplification / reduction of structured data models using the "log"-centric framework helps, the task of unifying the entire space of data structural patterns of infinite variety"
The missing primitive: inference
Unifying that structural variety is not a database problem or a framework problem. Something has to look at an entry and decide what kind of thing it is, and until something could, the format had no way to stay simple. August 2023:
"It is now possible to apply automation and superintelligence for inference that would've taken my time, attention, and additional knowledge I do not possess. Projects like MicrologMe are finally possible."
Inference was standing in for three things, and they are not the same kind of problem:
- my time. A task that takes too long gets automated. Better software fixes this.
- my attention. A task that takes too much attention gets asked fewer times a day. Better software fixes this too.
- knowledge I do not possess. A faster form still does not know whether the sentence I just typed describes a meal, a purchase, or both, and no amount of discipline on my part supplies a judgement the software cannot make.
For the first four years of this design, the only interpreter available was the person typing.
Something has to decide which parts of a sentence are events, when each happened, and which category they belong to. The only way to supply that in 2019 was to make the person do it, through a form whose fields were defined in advance, so every schema I drew was a way of moving that work onto the user. Once a model could read the raw sentence, in 2023, the schema stopped being the interface and became a description of the output.
The template I was filling in by hand in June 2020, with the contents stripped out:
Day 33/217 (184 days left)
Week 5/31
Mission
To do list
Habits
Journaling
Food Journaling
Expense Journaling
Fasting
Meditation
GYM
Bicep Curls
Shoulder Raise
Korean Learning
Highlights
Expenses
Food
Insights
Seven named sections, nine named habits inside one of them, every one decided in advance. To record that I ate something I had to know that Food was a section and that it was a different section from Expenses, even when one purchase produced an entry in both. The schema is the interface, so using the system means holding the schema in your head.
The same record now is one command that takes a sentence:
organs log "Ate: chicken, broccoli, okra (home cooked)"
organs log "Gym: bench DB 150x10, dips 3x8"
organs log "Weight 228.2"
organs log "Shipped tasks integration"Appending to a file that has no fields at all, only a timestamp and whatever was said:
# 2026-08-30 (Sunday)
## Morning
- [10:06] ...
- [10:24] ...
The categories did not go away. Food, exercise, weight and work are all still there and I can still ask for any of them. What moved is when the sorting happens.
- Write time, which the template requires, is the worst available moment to ask. I am standing in a kitchen with one hand free, thinking about the food and not about the schema, and the system wants a decision about Food versus Expenses before it will accept anything. Get it wrong and the record is wrong, quietly, forever.
- Read time, which the log allows, is a moment when I already know what I want, because wanting it is the reason I am there at all.
A system that asks its hardest question at the point of least attention gets abandoned, however good the question is.
What it cost
The version that ran, in 2025, produced the finding six years of design documents had not:
"I am stacking too many things on top of my tracking system -- arbitrary logs -- and no views on it, I wanted it to be a habit tracker, a source of context for my AI, automated logger etc, but it has been a shitty version of all of them"
It reads like a complaint about arbitrary logging, and it is not. Arbitrary logging was the part I had right: a single store that accepts anything is the correct foundation, the same append-only shape I had admired in a bank statement.
The failure is in the last four words. Three readings were asked of the store itself rather than built on top of it:
- habit tracker
- source of context for a model
- automated logger
Each is a different reading of the same data and each wanted its own narrow view. Which is the 2019 bullet again: many individual tools, one synchronized store.
A second finding sits underneath it:
"The intelligence is there, but it has to be parameterized with the proper amount of configuration, and the incredible span of the possible design space of prompts makes it very frustrating to do so."
The model could do the job. What it needed was configuration, and configuration cannot be derived at a desk, because the hard cases only appear when a real person puts real sentences in. Which is the 2019 rule arriving from the other end: a system's real parameters are only visible once something real is running through it, whether the thing running is a person with a pen or a model.