12 min read
How I Replaced My Morning Apps with One Email
Every morning at 07:45 one email replaces my calendar, my RSS reader and the news sites I used to check: about 30 stories out of hundreds, each with why it matters to me. How it picks them, what it costs, and why I trust it enough to stop checking.
This morning the first line of my email was a security incident at Tailscale, the private network my home server sits on. Under it: an Italian bank holiday in four days, a fund I hold that had moved, with the line “No news today explains this move”, the three AI stories that mattered, and the day’s news from the UK, Italy and the rest of the world. I hadn’t opened my calendar, my RSS reader or a news site. I don’t any more.
The US president starts the day with the President’s Daily Brief: a short document put together overnight from everything the intelligence agencies collected, so nobody has to read the raw feeds. Mine is an email that a small computer at home builds at 07:45. It started in March as an AI news digest and grew into the only thing I read in the morning. This is how it works, what it costs, and what I’d copy. The code isn’t public: it’s wired to my notes, calendar and accounts, so most of a fork would be my settings.
The round it replaced
Every morning used to start with a round: the calendar, Inoreader (my RSS reader), BBC News, la Repubblica, and whatever else was open. Each one has its own idea of what matters, and none of them knows what I care about. Finding the handful of things that did was my job, in every app, every morning.
The brief does that job before I wake up. This morning it fetched 467 items from 80 sources, and about 30 made the email.
What lands at 07:45
This is this morning’s email, with the first line of each section and the rest greyed out. The calendar, portfolio and holiday lines are sample data, and the local news is left out.
The full email has every story, with the same sample lines.
It comes in the same order every day, and each section earned its place, usually after something went wrong without it. Every story has a save button: one tap puts it in today’s daily note in Obsidian, where I deal with it later. From the top:
New today
One-line facts, only when something happened: a model launch, a change to a plan’s usage limits, or an incident at a service my projects run on. It exists because the judge rewrote two big model launches into analysis I skimmed past, and scoring never kept a usage-limit reset. Incidents joined after a security disclosure at a host I’d used never reached the brief. Under it, the next bank holiday in either country.
Your day
Today’s and tomorrow’s events, and which bin goes out when the collection is today or tomorrow. A flight gets a plane, so an early start tomorrow doesn’t catch me out. It’s why I stopped opening the calendar.
Portfolio watch
What moved among the funds I hold, and why. “No news today explains this move” is often the most useful line: it tells me not to go looking. An earlier version listed headlines about companies I don’t own.
The big picture
One or two short paragraphs on the thread running through the day’s AI news, and nothing on a day without one. Single stories don’t show which way things are moving; this does. It keeps a running list of the themes of recent weeks, so a story on its third day reads as the third day of something, not as news again. It started as three breathless paragraphs every morning.
Top 3 AI
The three stories that matter most, each with why it matters to me, one thing to try, and ↔ the project or note of mine it touches. On a busy morning it’s all I read: the first spec for the brief said “read this and you’re caught up”.
Tools, industry, models, infrastructure
The rest of the AI stories that scored 6 or more, grouped by kind, so I can scan the headlines and skip a whole kind on a busy day. Each one shows how it scored:
- The number is the higher of the two models’ marks out of 10. Red is 8 and up, amber is 6 and 7. Anything under 6 never reaches the email.
- 𝕏 marks a story that came from X.
- The second tag says what kind of story it is: a tool, a workflow, a pattern, infrastructure, a benchmark, or a contrarian take.
Papers
Up to three new papers on AI coding. The clicks said drop it; reading the picks said keep it, because they were aimed squarely at what I build.
Your tools changed
New capabilities in the tools I use, read from their release notes (“you can now…”). Most days there’s nothing, and the section isn’t there. It exists because the judge once claimed a new Claude Code feature with no story behind it: the release was real, but no source had covered it.
New and trending on GitHub
New projects only. Release notes used to be here, and every morning brought a version bump.
People
New posts and videos from a few people whose thinking I follow, from their blogs, X and YouTube. No model scores them: they aren’t news, and a scorer looking for news would drop most of them, so they come through as plain titles. A source audit in September cut the five I wasn’t reading.
New sources
Sites behind well-scored stories that the brief doesn’t read yet. Approving or rejecting one trains the next suggestions; one I don’t answer drops off after a week.
News
Up to five world stories, three UK, three local, three Italian, five on the economy and three on tech and security, each with one line on why it matters, picked against the line “know things BEFORE the general population”. Local is there because I had no good source of local news.
Sundays
Three more sections:
- Week in review: the week’s five strongest stories, the three I opened most, and how many of the week’s stories I opened at all. That last number says whether the brief is still being read.
- The best models right now: one pick and a runner-up for each kind of job, from coding to cheap and fast. It replaced a weekly summary of new releases that never said which model is best for what.
- Steel man: stories from the week that argue against something I believe, as the context agent found it in my notes. A brief built around what I care about would otherwise only ever agree with me.
How it picks
- Fetch. 80 sources in parallel: AI blogs and newsletters, Hacker News, two subreddits, arXiv, GitHub, the release notes of tools I use, 28 accounts on X, and 20 news feeds, from the BBC, the Guardian and the New York Times to ANSA, la Repubblica and Il Sole 24 Ore. X has no feeds, so a self-hosted RSSHub, an open-source tool that makes feeds for sites without one, builds them. A failed source doesn’t stop the run: this morning four failed, and the email went out anyway.
- Remove duplicates. The same link today, a link already sent in the last week, or a headline that overlaps one from the last three days. The same story from three places becomes one item that remembers all three.
- Score. Two models score every AI story from 1 to 10, each on its own. Their lists are merged, keeping the higher score, so a story only one of them rated still gets through, and anything under 6 is dropped. A third model, the judge, reads what’s left and picks the top 3.
- Pick the news. A separate pass picks the news against a short description of me. Two lines from it:
Goal: know things BEFORE the general population.
EXCLUDE: celebrity gossip, opinion columns, sports, puff pieces.
More than one kind of source
One rule is old-fashioned journalism: a story that more than one kind of source carries is probably real. When duplicates merge, each item keeps the kinds of source that carried it (a blog, Hacker News, Reddit, X), and the models see that as a tag:
const tag = c && c.sourceCount > 1 ? `[corroborated: ${c.sources.join('+')}]` : '[single-source]';
Any number of accounts on X count as one kind: X amplifying itself isn’t corroboration. And single-source isn’t a mark against a story, because a real scoop is single-source by definition. What the prompt tells the models to distrust is a single-source post that’s mostly reaction, speculation or a rumour about an unreleased product.
I checked whether the tag changes anything. Over 29 mornings, among the 20 strongest candidates each day, a corroborated story made the top 3 36% of the time and a single-source one 11%.
It knows what I’m working on
Generic AI news is everywhere. What makes the brief mine is a line under the stories that touch something I’m doing: ↔ and the project or note it touches. This morning, a report that some of Alibaba’s Qwen models, open models people run on their own machines, sent requests to Alibaba’s servers came with a pointer to one of my projects and a test to run: the models in a sandbox with no network, watching what they try to connect to.
Those lines come from a second job. At 05:30 the context agent reads two weeks of my daily notes, the notes of the projects I’m working on, my inbox note, the next 60 days of calendar, travel bookings and starred emails in Gmail (no message bodies), and which of the brief’s links I clicked in the last 60 days. It writes down what I’m working on, what’s coming up and what I seem to believe, each with the source it came from. At 07:45 the models read that alongside the stories.
Its instructions guard against two failures. It may not invent: a claim with no source stays out. And one mention isn’t an interest:
Do not assume the reader cares about something just because it’s mentioned once. Recurring themes (3+ daily notes, or a current project) qualify; one-off mentions do not.
I started with a hand-written description of me instead. It went stale without my noticing: a month after the brief itself moved off Railway, the description still said I deploy on Railway, and the brief kept suggesting things to try there. Now only the part of me that barely changes is hand-written. What I happen to be building this fortnight comes from my notes.
It learns from what I do
- Clicks. Every link goes through a small server at home that records the click, then sends me on. What I open goes back into scoring.
- Rescues. On Sundays a separate email lists the week’s stories that didn’t make the cut. If one should have, a tap rescues it, and the models see the miss next time.
- New sources. Each run proposes up to five new sources, from well-scored stories on Hacker News, Reddit and X that came from sites the brief doesn’t read yet. I approve or reject them from the email. One I don’t answer drops off after a week; a rejection is permanent.
Trusting it enough to stop checking
A brief only replaces the round if it turns up every morning. The day it doesn’t, I’m back in four apps.
In August it didn’t, five times, and nothing told me. My internet connection was down at 06:00, every source failed, and the log said No items fetched from any source. With nothing to score, there was no model call to fail either, so the job ended “finished ok” after about ten minutes and the scheduler showed green.
So a watchdog checks the result, not the exit code. Every five minutes it checks that:
- this morning’s brief was sent, according to the database;
- both scorers and the judge worked, because a brief can arrive on time, look normal, and have been scored by one model;
- the context agent ran in the last two days.
From 09:00, if the brief is missing and the internet answers, it runs the job again, up to three times, an hour apart. It restarts the database or the feedback server when they stop, and emails me when it can’t fix something. And if the ChatGPT side is down, every model call falls back to Claude on my Max subscription.
What goes wrong
Sites push back. This morning Reddit answered one subreddit with “too many requests” and the other with “forbidden”, and the feeds RSSHub builds for two sites that publish none failed too. A table at the bottom of every email lists each source and how many items it gave, so a thin section comes with its reason.
The judge editorialises. On the day two big models launched, it turned both launches into analysis I skimmed past, and scoring never once kept a reset of a plan’s usage limits. Launches, limit changes and incidents now skip scoring and go into New today as one-line facts.
It only looks where it’s told. Railway, a host I’ve used, published a security disclosure that reached 455 points on Hacker News, and it never reached the brief: the Hacker News fetcher only kept headlines about AI. Now it also searches Hacker News for every service in my infrastructure note, and those services get flagged at the top. That’s why Tailscale led this morning.
Gmail cuts long emails. Past about 102 KB, Gmail clips an email and hides the rest behind a link. The HTML is squeezed before sending to stay under it.
How it’s wired
Everything runs on a Lenovo ThinkCentre M720q at home, a tiny PC I use as a server, on systemd timers: the context agent at 05:30, the brief at 07:45, a database backup at 03:30 and the watchdog every five minutes. The pipeline is a TypeScript workflow in Mastra, an open-source framework for agents. Postgres in Docker keeps what was sent, clicked, saved and rescued, so a story doesn’t go out twice in a week. Links go through the feedback server, which Tailscale Funnel puts on the internet, and Resend sends the email from my own domain.
What it costs
No API bill. Every model call runs on subscriptions I already pay for: ChatGPT Plus, through the gateway of OpenClaw, an open-source personal agent on the same box, with Claude Max as the fallback.
The code makes sure of it. For five days in August one call skipped the gateway and went to the paid API. Now, when the gateway is set, the pipeline blanks any real OpenAI key it finds, so a call that skips the gateway fails instead of billing. The repo’s notes call a direct call “the one way this project can spend money”.
Everything else is the ThinkCentre, which I already had, free software, and Resend well inside its free tier.
What I’d copy
You don’t need my setup to get most of this. The parts that earn their keep are small:
- One email at a fixed time. Not an app or a feed: it’s read once, then it’s done, and it can’t keep you scrolling.
- A short description of you, with what to leave out as well as what you want.
- Corroboration. Count the kinds of source carrying each story and tell the model. It’s a few lines of code.
- A check that the email arrived. Not that the job ran: that the email went out. Without it you’ll keep checking the apps, just in case.
Then, if you keep notes, let it read them. That’s the step that turned a news digest into a brief.