How I Built a NotebookLM Podcast With an Audience of One
At 8:48 on Sunday night, August 30, 2026, I gave Codex a fairly loose request. There was a new Linux distribution called Omarchy that I wanted to understand. I asked Codex to find recent authoritative sources, interviews, Wikipedia background, and as much useful material as it could. Then I asked it to create a long audio overview, generate a separate debate, download both, and publish them to my podcast feed. Artwork would be a bonus.
I interrupted the run twice. First I suggested that it could collect artwork while doing the research. Then I asked, “What about YouTube?”
At 9:13, the job was done. Codex had built a notebook with 39 usable sources, including five YouTube transcripts, the official manual, release notes, security fixes, interviews, and independent reviews. It generated two audio programs, created separate cover images, uploaded everything, and verified the final RSS entries.
The AI-Powered Omarchy: Inside Linux Quattro 4.0 ran 47 minutes and 51 seconds. The $10 Million Omarchy Gamble: Linux’s Future or DHH’s Dotfiles? ran 45 minutes and 36 seconds.
They appeared in BeyondPod, the Android podcast application I already use while driving, walking, working around the house, and sometimes while working. I had finally built the personal NotebookLM podcast I wanted. I supplied a subject, and 25 minutes later two researched episodes arrived through RSS in the application where I already listened. Very little of that time required my attention. Most of it was Gemini Notebook generating the audio.
I did not set out to build an autonomous podcast producer. I kept removing the next manual step until describing what I wanted to learn was almost the only step left. Generating artificial podcast hosts is a neat demonstration. Getting a researched episode into the application I already use is what made it useful to me.
The first version involved editing XML by hand
I had been using Google’s NotebookLM, now called Gemini Notebook, to make audio overviews before this experiment. My first publishing process was manual.
I generated an audio file, downloaded it, opened the Azure Portal, and uploaded the file to Blob Storage. Then I edited feed.xml so the RSS feed pointed to the new file. I believe I wrote a small C# program to handle part of this process at some point, although I no longer have the code handy.
It worked, but I had to repeat the same upload-and-edit process for every episode.
The feed is called The Pigeon Whisperer’s Guide to the Galaxy. I do not submit it to podcast directories or advertise it. The RSS document and media files are publicly reachable because podcast clients need to fetch them, but I am not concerned if somebody happens across them. It is personal in the sense that I choose every subject and remain its intended audience. It is not a private feed with authentication.
I subscribe to it with BeyondPod. I also tested the feed with Apple Podcasts, where it worked, but BeyondPod is where I actually listen.
I built a website to stop editing the feed
On April 3, 2026, I built podcast-uploader, a Node and Express application that runs in Docker on my server. I used Claude Code for the initial build, then used it again when I added the REST documentation and MCP interfaces.
The uploader has a website, so I can publish an ordinary audio or video file whenever I want. That remains useful. I do not need every episode to begin as an AI research project.
The application moved the feed manipulation into code. When I upload an episode, the server extracts its duration and sends the media and optional artwork to Azure Blob Storage. It reads the existing RSS document, makes a backup, adds the new item, and writes feed.xml back to storage. Express serves the uploader website from the Docker container. Azure holds the published media, artwork, feed, waveform data, and feed backups.
The application exposes a REST API and an MCP endpoint. The REST publishing path includes endpoints for inspecting media metadata, uploading an episode, and reading the finished podcast feed. The MCP endpoint lets compatible agents discover several management operations directly.
By April, I no longer needed to upload blobs or edit XML through the Azure Portal. I still did the entire NotebookLM side myself. I created each notebook, collected the sources, generated the audio, waited for it, downloaded it, and then uploaded it through my website.
I had automated the part most likely to corrupt the feed. I was still standing between the two systems and carrying files from one to the other.
I stopped carrying files between NotebookLM and the podcast feed
That was where the project stood until the weekend of August 30. The uploader already had a REST API. On the other side, the unofficial notebooklm-py client could create notebooks, add sources, generate audio, and download the finished files. Codex could operate both of them. I had simply never asked it to take responsibility for the complete trip from a research question to a verified RSS entry.
The Omarchy request at the beginning of this article was my first attempt. There was no podcast-publisher skill yet. I described the entire job in one prompt and let Codex work through each handoff. It researched the topic, operated Gemini Notebook, downloaded the results, called my uploader API, and checked the feed.
Only after that one-off test published both Omarchy episodes correctly did I ask Codex to save the process as a reusable skill. The first run proved the pieces could work together. The skill made the same sequence repeatable without requiring me to describe every step again.
RSS connects the pieces
The exact services are less important than the handoffs between them. Reproducing this workflow requires:
- A Google account with access to Gemini Notebook
- An authenticated NotebookLM client that can create notebooks, add sources, generate audio, and download artifacts
- An agent such as Codex that can research the subject and operate the client
- Publicly reachable storage for the audio and artwork
- A publisher that can add each file and its metadata to a podcast RSS feed
- A podcatcher that accepts a custom RSS URL
Mine uses notebooklm-py, a Node uploader, Azure Blob Storage, and BeyondPod. None of those choices is mandatory. The RSS feed is the contract that lets each part change without requiring the others to know much about it.
The current flow looks like this:
I give Codex a subject
|
v
Codex researches the subject
and creates a Gemini Notebook
|
v
Gemini Notebook generates
an overview and a debate
|
v
Codex downloads the audio
and creates episode artwork
|
v
The uploader stores the files
and updates feed.xml in Azure
|
v
BeyondPod discovers the episodes
There is AI at the beginning of this system, but the publishing half is conventional. An RSS podcast item contains a title, description, publication date, globally unique identifier, duration, and an enclosure pointing to the media file. BeyondPod does not know or care whether two people recorded the episode in a studio or Gemini Notebook generated it from 39 sources. It sees an RSS enclosure and downloads the media.
That boring old interface is the reason the pieces fit together.
What Codex did during those 25 minutes
Google’s Audio Overview feature can generate several formats, including a deep dive and a debate. It also accepts instructions about focus, language, and length. More important for this workflow, it builds the discussion from the sources in the notebook. That makes the source set the main input I can control.
Codex uses the unofficial notebooklm-py client to operate Gemini Notebook. The package retains the old NotebookLM name. It can authenticate through a saved Google session, create notebooks, add sources, start audio generation, wait for artifacts, and download the result.
For the Omarchy test, Codex researched official documentation, release notes, interviews, independent reviews, Wikipedia, and YouTube transcripts. It created a dated notebook, added the sources, and waited to see which ones finished processing. Thirty-nine were usable.
It asked Gemini Notebook for a long overview covering the project’s origin, architecture, current release, installation, daily use, funding, security, drawbacks, and intended audience. The debate took a narrower position. Did Omarchy represent a useful direction for desktop Linux, or did it mainly package one developer’s preferences?
Codex waited for those exact generation tasks, downloaded both audio files, and created separate square covers. It prepared the titles, subtitles, descriptions, and other episode metadata before uploading each episode separately. Finally, it read the finished feed and checked the duration, title, author, explicit setting, media URL, and artwork.
The overview and debate are separate for a reason. An overview is useful for organizing the facts and explaining how the pieces fit together. A debate forces the same research through a disputed proposition. It gives the skeptical side a real case instead of reserving two sentences near the end for “drawbacks.”
The successful test became a Codex skill
At 9:40, after spending a few minutes looking at the result, I asked Codex if we could turn the workflow into a reusable skill. At 9:44, I had a personal notebooklm-podcast-publisher skill with the workflow instructions, a detailed reference, and a PowerShell publication script.
The skill is not simply the original request saved in a file. It records the operational details that keep a long workflow from quietly producing the wrong result.
It tells Codex to test authentication before creating anything. It counts sources only after Gemini Notebook reports them as ready. It keeps the exact task and artifact IDs rather than downloading whichever audio happens to be newest. It uploads the episodes sequentially because every upload rewrites the RSS document. If an upload returns an ambiguous error, it checks the feed for the expected filename before trying again. Finally, it rereads the feed and verifies the published fields.
The PowerShell script first submits the audio to /api/metadata. It then sends the audio, artwork, title, description, subtitle, author, episode type, and explicit setting to /api/upload. After the uploader returns the public media URL, the script calls /api/podcast and finds the episode with that exact URL. An HTTP 200 response is not enough. The entry has to exist in the feed with the metadata I intended.
It worked again
The next day, I used the new skill to research the 2026 software job market for someone with my background. Codex assembled 34 ready sources, including Atlanta employment data, current job descriptions, research papers, interviews, and YouTube material. It produced a 37-minute overview and a 38-minute debate about whether I should position myself as a staff engineer, architect, AI-focused builder, consultant, or manager.
Later that evening, I asked it to research the AI development methods people are actually using, including OpenSpec and BMAD, and what would be useful to discuss in an interview. That run used 40 ready sources and produced a 45-minute overview plus a 35-minute OpenSpec-versus-BMAD debate.
All three runs landed around 25 minutes. Most of the time went to audio generation rather than research or uploading. My active work was describing what I wanted and, in the Omarchy run, remembering halfway through that YouTube might contain some of the best interviews.
The unofficial dependency
The Notebook side depends on notebooklm-py, which is an unofficial client. Google can change the behavior it depends on, and its saved authentication can expire. That is a maintenance tradeoff I am willing to accept for a personal tool.
It goes where I already listen
I still upload ordinary audio through the website when I want to. The automated workflow did not replace the uploader’s original purpose. It added another way to publish.
It is also a concrete example of the long tail of bespoke software. The system is useful to me because it fits my specific habits. It does not need to become a product.
What changed is the amount of effort between finding a subject and having something useful to listen to. I can ask for an explanation of a new Linux distribution, a review of my job market, or a comparison of software-development methods. About 25 minutes later, an overview and a debate are in the same BeyondPod queue as everything else I listen to.
I did not need another AI application to remember to visit. I needed the result to arrive in the podcast application I was already using. RSS, which is considerably less fashionable than anything else in this system, turned out to be the part that made the AI useful.
AI assistance disclosure: OpenAI Codex assisted with research and drafting. I reviewed and verified the final article before publication.

