Becoming Lifelog, in which a decade of highlights finds a home
Previously on Becoming Lifelog…
The browser had learned to listen. SSE streams flowed. GitHub issues migrated. The architecture was proven. And then someone mentioned Readwise.
The Setup
22:00 - The developer stares at the Readwise API docs.
riclib: “I have ten years of highlights in here.”
CLAUDE: “How many?”
riclib: “I don’t want to know.”
[A tail begins to twitch somewhere in the shadows]
The Squirrel Materializes
THE SQUIRREL: already mid-sentence “—we sync EVERYTHING! Every document! Every reading state! Every podcast timestamp! Build a complete mirror! Think of the QUERIES—”
riclib: “I just want my highlights.”
THE SQUIRREL: “YES! And to get the highlights we need the documents! And to contextualize the documents we need the reading progress! And for reading progress we need—”
CLAUDE: “What do you actually do with highlights?”
[The Squirrel freezes]
riclib: “I… highlight things I want to remember. And then I search for them when I need them.”
CLAUDE: “So you need: documents that have highlights. With the highlights in them.”
riclib: “Yes.”
CLAUDE: “Not documents without highlights.”
riclib: “Those are just… articles I saved and never read.”
THE SQUIRREL: “But the COMPLETENESS—”
THE LIZARD: blinks
The Design
22:15 - The whiteboard fills with what we don’t need:
Documents without highlights → Skip
Reading progress → Don't care
Podcast timestamps → Not highlights
Tags from Readwise → We have our own
Full document content → We have the source URL
What remains:
Documents WITH highlights → Sync
The highlights themselves → As blockquotes
User notes on highlights → Preserve
LLM summaries → When available
THE SQUIRREL: “That’s… that’s leaving data on the table!”
THE LIZARD: “That’s not being an idiot.”
The Frequency Debate
22:30 - Implementation begins. The Squirrel circles.
THE SQUIRREL: “Poll every five minutes! What if you highlight something IMPORTANT? You need it IMMEDIATELY!”
CLAUDE: “When was the last time you highlighted something and immediately needed it in Thymer?”
THE SQUIRREL: “…”
CLAUDE: “…”
THE SQUIRREL: “…that’s not the POINT—”
riclib: “Readwise rate limits are strict. They’ll ban us.”
THE SQUIRREL: “Fine! Ten minutes!”
THE LIZARD: blinks twice
riclib: “Hourly. With a manual trigger for the impatient.”
THE SQUIRREL: “But—”
riclib: “That’s me. I’m the impatient. Hourly is fine.”
The Journal Question
23:00 - The first sync runs. Documents flow. Highlights land.
📚 Queued Readwise: Article about TypeScript (new, 4 highlights)
📚 Queued Readwise: Book about systems thinking (new, 12 highlights)
📚 Queued Readwise: Tweet thread about startups (new, 2 highlights)
📚 Queued Readwise: ...
And in the Journal:
23:01 highlighted **Article about TypeScript**
23:01 highlighted **Book about systems thinking**
23:01 highlighted **Tweet thread about startups**
23:01 highlighted **...**
riclib: “This is going to be noisy.”
CLAUDE: “Ten years of highlights. Every update logged.”
THE SQUIRREL: “Activity feeds! Notification badges! A timeline view with—”
riclib: “No. First highlight only. Updates are silent.”
CLAUDE: “The journal entry requires a verb. First sync: highlighted. Updates: no verb. No journal.”
THE LIZARD: approves with a slow blink
THE SQUIRREL: “But how will you KNOW when—”
riclib: “I was there. I highlighted it. I know.”
The Timezone Incident
23:30 - First sync completes. 147 documents. 892 highlights. Ten years of marginalia, landed.
23:45 - Second sync triggers.
⚠️ readwise API returned 400: {"errors": ["Field `updatedAfter` must be a valid ISO 8601 date time string"]}
CLAUDE: “Interesting.”
riclib: “What.”
CLAUDE: “The timestamp is 2024-12-26T23:45:00+01:00. Valid ISO 8601. Valid RFC3339. But the + in the URL…”
riclib: “Is being interpreted as a space.”
CLAUDE: “The server asked for documents updated after 2024-12-26T23:45:00 01:00.”
riclib: “Which is not a time.”
THE SQUIRREL: “We need a URL builder! A proper encoding layer! Abstract the—”
CLAUDE: url.QueryEscape()
THE SQUIRREL: “…what?”
CLAUDE: “One function. Wrap the timestamp. Done.”
[The Squirrel opens its mouth]
[The Lizard’s eye opens]
[The Squirrel closes its mouth]
The Sync Completes
00:15 - Ten years. All of it.
Documents synced: 147
Highlights captured: 892
Journal entries: 147 (first highlights only)
Subsequent updates: Silent
Lines of code: ~300
Dependencies added: 0 (bbolt already there)
API calls wasted: 1 (the timezone incident)
Squirrel proposals: 7
Squirrel proposals used: 0
riclib: scrolling through Thymer “There’s that article about passkeys. And the book about… oh, I forgot I read that.”
CLAUDE: “Ten years of ‘I should remember this.’ Now findable.”
THE SQUIRREL: “We could add semantic search! Embed the highlights! Build a—”
THE LIZARD: blinks
THE SQUIRREL: sighs, reaches for decaf
The Shape of a Highlight
Each record arrives like this:
## Summary
[LLM-generated summary, when Readwise provides one]
## Highlights
> The highlighted text, preserved exactly
> As blockquotes, because that's what they are
> Someone else's words that mattered to you
**Note:** Your annotation, if you left one
Not transformed. Not analyzed. Not fed into a knowledge graph.
Just… present. Searchable. Waiting for the day you need that one thing about passkeys, or that paragraph about attention, or what that author said about building in public.
THE SQUIRREL: “But the CONNECTIONS—”
THE LIZARD: “Will emerge. When they’re needed. Not before.”
The Moral
THE SQUIRREL: “So we built… a sync.”
CLAUDE: “We built a conduit. Readwise holds the highlights. Thymer makes them findable. The browser can’t listen, but the server polls hourly. The architecture we built for GitHub just… works.”
riclib: “Universal frontmatter interface. Write the adapter, get the sync.”
THE SQUIRREL: “But what about—”
THE LIZARD: “Next time.”
The Tally
Readwise documents: Synced (with highlights only)
GitHub issues: Synced
Manual markdown: Piped
Journal entries: Timestamped
Browser limitations: Worked around
Squirrel satisfaction: Pending
Lizard approval: ✅
Time: One evening
Tomorrow, a new highlight will appear in Readwise. An hour later, it’ll land in Thymer. Silent as a bookmark. Patient as marginalia has always been.
Ten years of “this is important.” Finally, somewhere it can be found.
🦎
Day 27 of Becoming Lifelog
In which a decade of highlights found a home
And the Squirrel learned that sync ≠ mirror
And we discovered that patience is a feature
See also:
The Saga (in which outside data flows in):
- The Browser That Forgot It Couldn’t Listen - SSE architecture that made this possible
- The Feature That Wasn’t - When not building is the build
- 488 Bytes, or Why I Am As I Am - The philosophy behind YAGNI
The References (highlight wisdom):
- Readwise Reader - Where the highlights live
- RFC 3339 - The timestamp format that needed escaping
- bbolt - The sync state database (one file, no dependencies)
