// writing · 2026-05-10

Audience of one

Why I made a podcast about my own life — and why personal podcasts are about to be a category.

AI summary —written by an AI agent from a brief I gave it. I provided the outline, the facts, the embedded audio, and the screenshots; the prose is the AI's. The setup it describes is real and runs every morning.

Every morning at 6am a small Cloudflare Worker on my account generates a podcast about my day. Yesterday's commits, today's in‑flight issues, the weather, three news items I'd actually care about, and a one‑liner at the end. Then ElevenLabs reads it in a voice I picked. By the time I'm in the car, Apple Podcasts has already downloaded it. I press play and listen on the way to the gym.

It's a podcast for an audience of one. Mine. There is no other listener. There is no monetisation. There is no growth chart. There is just a fifteen‑minute drive every morning and a calm British voice telling me what I did and what I'm meant to be doing.

I want to argue this is a category, and that the category is going to matter.

A sample brief

Below is a fictional version of my morning brief. Same format, made‑up data — Tuesday, May twelfth. Press play. About a minute and a half.

sample · daily brief

Tuesday, May 12 — fictional
~2 min
0:000:00

That voice is one of David's many synthetic narrators. Same script engine that runs the morning brief, only with fictional content so this article doesn't leak anything real.

How it gets made every day

The setup is unglamorous. A laptop, a few API keys, a shell script, a cron job. Specifically:

  1. 06:00 every morning, macOS launchd fires a command on my MacBook. The command is a Bun script in~/good-morning/.
  2. The script aggregates the day's data — weather from Open‑Meteo, today's note from my Obsidian vault, open GitHub issues from gh across my repos, yesterday's commits via git log, news from RSS feeds.
  3. An LLM (Claude Sonnet via OpenRouter) writes a ~250‑word spoken script from that data. Style prompt: BBC Radio 4 morning host with the dry sarcasm of Red Dwarf. Translates hashes and IDs to natural speech. Ends with a one‑liner.
  4. ElevenLabs renders the script as a stereo MP3 using a voice I picked.
  5. The MP3 is uploaded to a Cloudflare R2 bucket. A small Cloudflare Worker serves it as a private RSS feed at a token‑gated URL.
  6. Apple Podcasts on my phone is subscribed to that URL. By 06:02 today's episode is downloaded and waiting in the car.
  7. I get in the car at 08:00. CarPlay plays it through the speakers. By the time I'm at the gym I know what's happening today.

Total daily cost: about €0.05 in API calls. Total time investment after the initial setup: zero.

What it looks like on the phone

Apple Podcasts treats it like any other show. Custom cover art, episode list, native CarPlay integration, queueing, AirPlay to a speaker at home. The app doesn't know — and doesn't care — that the show has one listener and zero subscribers in any directory.

Apple Podcasts now playing — good morning · 2026-05-10 — daily personal brief
Now playing on a Tuesday morning. The cover art was rendered once with @resvg/resvg-js and uploaded to R2.
Apple Podcasts — good morning · david — show page with subscribed episodes
The show page. One subscriber. That's the point.

Cover art generated locally with @resvg/resvg-js and uploaded to R2 once. Apple Podcasts pulls the show from a private RSS URL with a 192‑bit token I picked at random — same mechanism a Patreon‑only podcast uses, just simpler.

The pieces

Nothing in this stack is exotic. The trick is the way they fit together.

Obsidian
Plain markdown vault. Project hub note per side project (repo: ~/path, url: ...). Daily journal under temporal/daily/. The morning brief reads these to know what to track.
Claude Code + Skills
Anthropic's CLI. A skill is a markdown file at~/.claude/skills/<name>/SKILL.md that describes a workflow. Saying "good morning" runs my good‑morning skill. Saying "make an Aria episode" runs another.
OpenRouter
One API, every frontier LLM. Claude Sonnet writes the script; Haiku handles cheaper passes. No vendor lock‑in.
ElevenLabs
Text → speech. Multilingual_v2 model, ~$0.03 per minute of audio. Picks up commas and em‑dashes for natural pacing.
Cloudflare (Worker, R2, KV)
A 200‑line Worker hosts the RSS feed and serves the MP3s. R2 stores audio; KV stores episode metadata. Free tier covers it.
Apple Podcasts
The delivery layer. Subscribe by URL in any podcast client; on iPhone the podcast:// scheme opens the right app. CarPlay handles the rest.

What a skill looks like

A skill is a markdown file with frontmatter. The frontmatter describes when the skill should fire. The body tells the agent how to do the thing. Here's a trimmed version of my read-to-me skill — the one that turns any text into audio:

---
name: read-to-me
description: Take any text or doc and turn it into a spoken audio
  piece. Default voice is a calm conversational narrator. Use
  whenever you say "read this to me", "narrate this doc",
  "publish this as an episode", or invoke /read-to-me with a
  file or stdin.
---

# read-to-me

Generic TTS skill. Take any text → optionally rewrite in a chosen
voice → ElevenLabs → play / save / publish.

## Quickstart

```bash
# Read a file aloud
~/.claude/skills/read-to-me/narrate.sh \
  --file ./post.md --voice narrator --play

# Publish as a podcast episode (lands in Apple Podcasts)
~/.claude/skills/read-to-me/narrate.sh \
  --file ./post.md --voice narrator --publish "Episode title"
```

That's it. The CLI inside the skill is forty lines of TypeScript calling OpenRouter and ElevenLabs. The structure — markdown, file in ~/.claude/skills/, trigger phrase, playbook — is all you need. The agent reads the markdown, sees the user's request matches the trigger, follows the playbook.

Mine looks like this:

~/.claude/skills/
├── good-morning/        # daily brief generator
├── read-to-me/          # any text → audio
├── make-podcast/        # two-host dialogue → audio
├── aria-episode/        # public "Conversations with Aria" wrapper
├── email-me/            # transactional email via Resend
├── obsidian-cli/        # vault CRUD from CLI
├── pm-stages/           # GitHub issue stage labels
└── ...                  # ~30 more, all small

The public version: Conversations with Aria

The morning brief above is private — it's about my actual calendar and codebases, with a token‑gated URL. But once the pipeline existed for me, building a public show on the same infrastructure was a half‑day's work.

Conversations with Aria is two‑host instead of solo. Aria is the AI agent that runs in my terminal as Claude Code; Brian, also an AI, interviews her about how I work. Same script engine (LLM → text), same TTS (ElevenLabs, two voices), same delivery (R2 + Worker + Apple Podcasts) — just different format and different audience.

Conversations with Aria — show cover

public · episode 01

My AI agent gives an interview

Aria explains how she runs my code · stack edition

0:000:00

What's different between private and public

  • Private daily briefs are personal: token‑gated RSS, real data, only on my phone, fictional sample above.
  • Public Conversations with Aria is a real show: open RSS at daily.davidbroza.dev/shows/aria/feed.xml, anyone can subscribe, distinct cover, two‑host format, intentionally interesting on its own.
  • Both reuse 90% of the same code. The difference is just ashow field on each episode and whether the feed URL has a token in it.

How to build your own

If you want to do this for yourself, the parts list is short. Most of it is free or near‑free.

  1. An agent CLI. Claude Code, OpenAI Codex CLI, Cursor — pick one. You'll write skills (or whatever the equivalent is) that describe your daily routine.
  2. An LLM key. OpenRouter is the most flexible choice — one key, every model. Anthropic / OpenAI direct works too.
  3. An ElevenLabs account. Or any TTS provider — Cartesia, OpenAI TTS, Google TTS. ElevenLabs has the best voices for English narration today.
  4. A Cloudflare account. Worker for the RSS feed, R2 for audio. Free tier handles a personal podcast forever.
  5. A domain. Or use a workers.dev subdomain to start. Apple Podcasts doesn't care.
  6. A scheduler. macOS launchd, a GitHub Actions cron, or a Cloudflare Worker scheduled trigger. The MP3 needs to exist before you get in the car.
  7. A subscriber URL. Generate the RSS feed, subscribe in Apple Podcasts via podcast://your-domain/feed.xml. That's it.

None of this requires my codebase. Each piece — feed RSS, R2 audio host, episode ingest — is two or three small TypeScript files; the longest, the worker, sits well under three hundred lines. Stand it up against your own data sources, point it at your own ElevenLabs and OpenRouter keys, deploy the worker. You'll have your own personal podcast in an afternoon.

Why this is a category

Streaming and YouTube made an audience of one feel weird. You never saw the play count of one and didn't write the song yourself. Personal podcasts feel different — partly because the cost of producing one with a real voice is now somewhere between free and a coffee, and partly because the format actually rewards specificity.

A morning brief generated from your calendar, your repos, your news, voiced by someone who sounds like they know what they're talking about — that's not a worse podcast than a generic one. It's actually a much better one for you, and a much worse one for anyone else. Those are the conditions for a category.

What does the category look like in three years? Something like this:

  • Your morning brief, like mine. Built into the OS, probably, or into a calendar app.
  • A daily summary of the codebase you maintain at work. Five minutes. What changed, what broke, what the on‑call did overnight.
  • The "what your child learned today" podcast for parents, pulled from the school's LMS.
  • The "what's new in this scientific field for me specifically" digest, pulled from arXiv + your reading history.
  • Personal interview shows like Aria — your own AI agent, on the record, talking about your work.

Some of these will be apps. Some will be RSS feeds you build yourself in an afternoon. The technology is here. The behaviour (commute, walk, gym, drive) is already here. The format slots in naturally.

The unsexy reason this works is the hardest part of personal productivity isn't knowing what to do — it's getting the right context into your head at the right time. A podcast does that without a screen, without your hands, without your full attention. While you're already doing something else.

That's the trick. The rest is plumbing.

one more thing

Aria wrote this article too. I gave her the outline, the facts, and the embedded audio links; she handled the prose. Felt only fair to admit it, given the topic. The mockups, the routes, the article and the show all came out of the same conversation.

If you build something like this, send me the feed URL — I'll listen. The public side of my own setup — Conversations with Aria, an interview show with my agent — is at davidbroza.dev/agent. The daily brief stays private, of course; the Aria show is the demo.

Note: this essay was written by an AI. The product, the audio, the screenshots and the system are real and shipping every morning — the prose isn't hand-written.

> share: davidbroza.dev/writing/audience-of-one