My bank knows what I spend. Apple knows how I slept last night. Google’s sitting on years of my email. Somewhere my carrier has a log of every call I’ve ever made.
Each one hands me its own little dashboard, behind its own login, and not one of them will let me ask the question I actually care about: how do these things move together? Do I spend more the weeks I sleep worse? Do I text less on days I walk more?
So a while back I started pulling it all down myself, into one SQLite file on my own machine. I named it life.db, which isn’t clever, but it’s honest. It’s a two-megabyte file on my laptop that knows more about my year than anything I pay a subscription for.
That’s the whole idea. Everything else is plumbing.
It was mostly a treasure hunt
Nobody tells you this, but most of your life is already sitting on your Mac as SQLite databases. Apple just hides them.
Your texts live in chat.db under ~/Library. Turn on Full Disk Access and you can count every message you’ve ever sent. Call history is in another one. Screen Time keeps its own little database that Apple rearranges every OS update, apparently just to keep me humble. Bank data came from an API, email from Gmail, steps from a phone app that quietly POSTs to a server I leave running.
Every feed is a dumb little Python script on a timer. Each one logs whether it worked, and if something breaks it pings me on Discord. (Hold onto that. It matters later.)
It all lands in one SQL view — daily_summary, one row per day, one column per thing I track. “Do I text less when I walk more” stops being a shower thought and turns into a query.
Then I built a lock-screen widget for my phone that reads it over a private VPN: spend, texts, steps, and a one-line note an LLM writes me every morning, all served off my own laptop. First iOS thing I’ve ever made. I was insufferable about it for a week.
Then I broke my own data
In May I moved my phone to GrapheneOS. Privacy reasons. Felt great about it.
It also silently killed my health data, because the little app feeding steps into life.db was iOS-only. I didn’t notice for weeks. The number just stopped, and my precious self-surveillance rig had a dead limb I walked past every single day.
Two feeds died quietly that spring. Screen Time had been broken for seven weeks and I had no idea. Which is when it clicked: a pipeline you’re not watching isn’t a pipeline. It’s a rumor.
The ring, and me being a hypocrite
To fix the health hole I bought a cheap little smart ring — a Colmi R02 — specifically because you can read it over Bluetooth with open-source code. No app, no account, no cloud.
Then I started researching accurate rings and hit a wall. Every good one — Oura, Ultrahuman, all of them — is accurate because it phones home. The nice sleep numbers get computed on their servers. You literally cannot buy the accuracy without the round-trip to the cloud.
I sulked about that for a day before realizing I was being ridiculous. My bank data comes from a cloud aggregator. My email is Google’s. The entire project is “pull from other people’s clouds into a file I own.” The ring was the one feed I’d decided had to be pure — and I don’t even care about perfect sleep scores, I care about the trend over months. For that? The cheap open ring is exactly right. I’d been a snob about it for no reason.
Round two
life.db moved off my laptop onto a small Fedora desktop that never sleeps. The ring got a whole supply chain: ring → a Pixel running Gadgetbridge that talks to it over Bluetooth → the Fedora box, which reaches over and grabs the data every fifteen minutes. Messages come through an open-source iMessage server now. Calls come through a tiny service I run on an old MacBook that never gets its lid closed.
The display is my favorite part. I’d had one of those MagicMirror setups on a Raspberry Pi — a screen behind a two-way mirror — and it froze constantly. Since I already owned all the data, I just built my own page: clock, weather, tonight’s schedule, what’s on Spotify, my live stats. Then I set that same page as the Fedora box’s screensaver, so when it goes idle my resting heart rate and last night’s sleep fade up on the monitor. Touch the mouse and they vanish. The first time it kicked in I said “holy shit” out loud to an empty room.
Then I got greedy and turned the weather corner into a status board: green and red dots for my work servers, my phone backups, and every one of these data pipelines. A database that grew up into a control panel for my whole house.
The bugs were the good part
A few that ate real evenings:
The ring stopped updating for six days. My timer was set to fire “fifteen minutes after the last successful sync” — so the moment my phone went unreachable and the syncs started failing, there was no success to count from, and it just quietly stopped scheduling itself. Forever. Great feature.
Another night I was dead certain an export was stale. Both files were exactly 811,008 bytes, so they had to be identical, right? Nope. SQLite holds onto emptied pages, so two files can be byte-for-byte the same size and hold completely different data. File size lied to me for three hours.
And Gadgetbridge refused to talk to my ring because it matches device names against “R02_” and mine announces itself as “COLMI R02_…” One extra word. Half a day.
Every single time I was positive the code was broken, it was a device asleep, a phone on the wrong Wi-Fi, or a filename with a capital letter. That’s the tax for building things that live in your actual house instead of a clean rack in a data center.
What I actually do with it
Turns out: a lot — and almost none of it is me opening the database.
It lives on a HUD in my kitchen with my AI assistant. Coffee’s going and there it is on the wall — resting heart rate, last night’s sleep, what I spent, today’s calendar, whatever’s on Spotify, my AI assistant ready to transform the data into real insights.
That assistant is the part I’m proudest of. Every morning it queries life.db on its own and goes looking for anything off — heart rate creeping up, a sleep dip, a spending week that doesn’t match the rest — and writes me a briefing. Not four hundred numbers. More like: you slept worse all week and your resting HR is up, keep an eye on it. It reads the data so I don’t have to.
And when I’m not looking at any of it, the same stats are the screensaver on my Linux desktop, fading up whenever the machine goes idle.
So no, I don’t sit and run queries by hand. I built the warehouse, then I built something to watch it for me, and now the whole thing just runs in the background of my actual life — on the kitchen wall, on my monitor, in a briefing that’s waiting when I wake up.
It’s a two-megabyte file that knows me better than my bank does. The difference is mine actually tells me what it sees.