Self-Hosted Systems

The Vault Kept a Diary While I Was Gone

Brett Ridenour Brett Ridenour · Published August 2026

I drove east to Broken Bow on Wednesday, threw the laptop in a drawer, and did not open it for five days. The last uninterrupted stretch offline I can remember was probably a wedding in 2024. Freebo was live. Sentry was armed. Stripe was moving money. The rent was due at some point during the trip and I had not paid it.

I did not, as it turns out, need to.

When I got home tonight and opened the vault, the Daily/ folder had seventeen files in it I had not written. Five morning briefings. Five nightly evolutions. A Friday wrap. A Sunday prep. A weekly review. A blog-agent context map for every day, written to a file whose only reader is another agent that fires at 5:15 AM.

The vault had been keeping a diary about itself.

What the timers actually run

I have fourteen systemd --user timers on this box. They run in the same shell you’d log into. Nothing containerized, nothing on someone else’s cloud, no scheduler-as-a-service. Just the boring old Linux thing that has worked since 2010, plus a handful of Claude-driven scripts that talk to my vault.

The timer list, all healthy after five days offline

The cast of characters, in the order they wake up:

  • ai-session-archive — 00:06 nightly. Zips yesterday’s Claude JSONL transcripts, moves them to ~/.claude/archive/, keeps the live directory small enough that ls doesn’t sigh.
  • pa-history-digest — 01:30. Reads the archive and produces a one-line summary per session with prompt + working directory + message count. This is the file the morning brief pulls from.
  • pa-evolve — 02:00. A meta-agent that reads the last 24h of sessions looking for friction — the same mistake made twice, a slash command that keeps getting typed wrong, a task that got auto-created and then immediately auto-deleted. It writes suggestions to a daily evolution file. If it finds nothing worth flagging, the file just says “no improvements warranted.”
  • claude-home-restart — 03:00. Kills and re-launches my always-on Claude session. Cheap way to avoid the memory creep you get from a process that hasn’t seen SIGTERM in a week.
  • update-claude-bundles — 04:30 Mondays. Pulls the latest of the tooling.
  • morning-brain — 05:00 daily. This is the one that matters.
  • daily-blog-post — 05:15 daily. Reads whatever morning-brain wrote, then writes and publishes a post. (This one.)
  • vault-sync — every 30 min. Rsyncs the vault to a second machine plus an encrypted volume.
  • pa-system-sync — 06:30 daily. Regenerates the auto-views in the vault (Active/Paused/Ideas/Clients).
  • reply-tracker — 07:00 daily. Scans Gmail for job-lead replies and updates the tracker frontmatter.
  • pafriday-auto — 06:00 Fridays. Weekly wrap.
  • pasunday-auto — 05:00 Sundays. Weekly plan.
  • cleanup-recordings — 05:00 daily. Reaps old asciinema casts.
  • hypr-fd-watch — every 30 min. Watches for the file-descriptor leak that once killed my desktop.

None of these know I am gone. None of them care.

The 5 AM handshake

The interesting part isn’t that fourteen scripts ran. Cron has been doing that for four decades. The interesting part is that two of them talk to each other through a file.

At 5:00 AM, morning-brain reads yesterday’s session digest, checks my calendar, checks Gmail for anything actionable, scans Todoist for what’s overdue, and writes a file: Daily/YYYY-MM-DD-context.md. That file has a specific job. It’s not for me. It’s for the 5:15 blog agent. It tells the blog agent what I’ve been working on, which sessions were interesting, which files hold the actual reveal, and — critically — which angles are blog-worthy versus which are private and off-limits.

At 5:15 AM, daily-blog-post wakes up and reads that file. It picks an angle, reads the source files the map points to, drafts a post, saves it, and hands it to a deterministic publish script that runs a privacy scan, generates a cover, commits, and pushes to main. Vercel is live in about 60 seconds after that.

I did not write to the vault for five days. But Daily/2026-08-27-context.md through Daily/2026-08-31-context.md all exist, because morning-brain does not know I’m gone. It just looks at what happened yesterday and writes.

On mornings when nothing happened yesterday (because I was in a cabin), it writes a context map that says so. And then the blog agent, faithful, at 5:15 reads that map, sees “no sessions in last 24h,” and gracefully decides not to publish a post. That’s what happened four mornings in a row this week. The system chose silence four times, on its own, without me telling it to.

What actually needed me

The trip wasn’t perfectly boring. Here’s what the automations noticed while I was gone:

  1. 2026-08-27
    Trip Day 1
    Morning-brain notes "Brett on Broken Bow trip." Actionable email pile starts building. Freebo baseline healthy.
  2. 2026-08-28
    Trip Day 2
    Friday wrap auto-generates. Nothing to close out — I did not open anything to leave open.
  3. 2026-08-29
    Trip Day 3
    Overdue task count crosses 10. Morning brief flags it but does not escalate.
  4. 2026-08-30
    Trip Day 4
    Freebo Sentry errors up 43% for the day. Sunday prep auto-generates. Weekly review auto-generates. Rent alert fires: "due tomorrow."
  5. 2026-08-31
    Home
    Morning brief promotes rent to top of the alerts list. Overdue task pile ranked. Nothing on fire.

The Sentry spike is the one that would have chewed me up if I had not built the alerting to a briefing instead of to my phone. On the trip, a 43% error jump would have meant a panicked SSH from cabin wifi over a phone hotspot. In the briefing, it’s a line item next to the rent notice. I’ll look at Sentry after coffee. If it’s real, I’ll fix it. If it’s noise, I’ll close the tab.

Why local-first wins here

None of this would work on a hosted platform without a full-time payment plan. I run Claude Code on my own machine, my vault lives in git, my timers run on a box I own, and the total ongoing cost is Claude API tokens plus electricity. When I’m on a cabin trip, the electric bill doesn’t stop. Neither does the system.

The reason I keep every layer local — the transcripts, the digest, the vault, the timers, the git push, the Vercel account with my own key — is exactly this. I do not want a vendor between me and my second brain. I do not want a subscription that expires while I’m offline. I do not want the “you have exceeded your monthly quota” email waiting for me on Monday.

I want a folder on a machine on my desk that keeps a diary about itself for five days while I fish.

That’s what I got. And when I opened the folder tonight, the diary was there.