← CatchUpCast·Install CatchUpGist·FAQ·Feedback·Privacy

Subscriptions aren't on sale yet. Testers who already have a token can follow the subscription path below. Everyone else can set it up on their own AI key today, or ask to be told when subscriptions open.

Installing CatchUpCast

Pulls labeled Gmail into a synthesized digest — delivered as a plain-text email or a private podcast feed, your choice.

This covers installing the packaged release on Linux — any distro, including a Raspberry Pi. You don't need to build anything from source, install Python, or even install Docker yourself — the setup script in Step 1 installs Docker for you if it isn't already on your machine.

What you're installing

One Docker container running the scheduler + a local Flask admin UI (the “Admin Console”), plus a small companion container that checks for updates automatically. All state lives in a Docker volume on your own machine. Provider credentials are entered through the Admin Console and encrypted at rest — nothing is typed into a config file.

Choose your setup

Two questions decide everything else, and the Admin Console asks both when you first open it.

1. Who writes your briefing?

A subscriptionYour own AI key
You needYour subscription token, from catchupcast.com/appA Gemini or Claude API key (Step 3)
PodcastsIncluded — nothing else to set upAlso need Google Cloud and Cloudflare accounts (Steps 4 and 5)
Setup timeAbout 10 minutes, either way you get itAbout 10 minutes for email; 30–45 for a podcast

2. How do you want it? By email, to your own inbox, or as a podcast your podcast app plays. You can switch later on the Settings page without reinstalling.

Have a subscription? You only need Step 1 (install) and Step 2 (a Gmail App Password). Skip Steps 3 to 5 — the Admin Console asks for your token instead.

Requirements

Step 1: Download and run the setup script

Download the setup script for your platform and run it — it does everything by itself: installs Docker if it isn't already on your machine, creates the deployment file, generates your encryption key, and starts the containers.

⇩ install-catchupcast-linux.sh Windows — coming soon macOS — join the waitlist

The script creates a catchupcast/ folder next to itself and installs into that — a docker-compose.release.yml file and a secrets/ folder inside it. Note where you saved the script, because that folder is where your data lives from then on. It has its own folder deliberately: Docker names your data volume after the folder it runs in, so anything else installed the same way into the same place would collide with it. Re-run the script later to update — it finds the existing folder rather than making a second one. It mentions a key file, secrets/bootstrap_key; you don't need to copy it — once setup is done, the Admin Console's Backup is the backup to keep (see Backups). It finishes by telling you to open http://127.0.0.1:5000 — the Admin Console, covered in Step 6.

One case needs a restart and a second run of the same script — neither is a failure, both are printed clearly when they happen:

Prefer to type the commands yourself?
mkdir catchupcast && cd catchupcast
mkdir -p secrets
cat > docker-compose.release.yml <<'EOF'
services:
  app:
    image: ghcr.io/pppoole/email-podcast-pipeline:${APP_IMAGE_TAG:-latest}
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
    network_mode: host
    volumes:
      - db-data:/app/data
    environment:
      - DB_PATH=/app/data/podcast.db
      - MESSAGES_DB_PATH=/app/data/messages.db
      - CONFIGURATOR_PORT=5000
      - TLS_CERT_DIR=/app/data/tls
    secrets:
      - bootstrap_key
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "python", "-m", "email_podcast_pipeline.healthcheck"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  watchtower:
    image: ghcr.io/nicholas-fedor/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_LABEL_ENABLE=true
      - WATCHTOWER_CLEANUP=true
      - WATCHTOWER_SCHEDULE=0 0 4 * * *
    restart: unless-stopped

secrets:
  bootstrap_key:
    file: ./secrets/bootstrap_key

volumes:
  db-data:
EOF

docker run --rm -v "$(pwd)/secrets:/app/secrets" ghcr.io/pppoole/email-podcast-pipeline:latest \
  python -m email_podcast_pipeline.cli init-secret

docker compose -f docker-compose.release.yml up -d
docker compose -f docker-compose.release.yml logs -f

Wait for ready in the logs, then Ctrl-C to stop following them — the containers keep running either way.

Step 2: Gmail App Password

Gmail auth here is IMAP-based, not OAuth. Needed for both paths.

  1. Go to myaccount.google.com and sign in with the Gmail account you want this to read from.
  2. Click Security. Under “How you sign in to Google,” turn on 2-Step Verification if it's off — App Passwords require it.
  3. Go to myaccount.google.com/apppasswords. Type an app name and click Create.
  4. Copy the 16-character password shown — it's shown exactly once.
  5. Nothing to save to disk — you'll enter this in the Admin Console's Connect Gmail page later.

Step 3: An LLM API key (Gemini or Claude)

Only for your own AI key — with a subscription, skip to Step 6. Gemini is simpler to set up (no Google Cloud project required) and the cheaper of the two to run — the recommended default unless you have a reason to prefer Claude. There's no model to pick: CatchUpCast uses a strong, current model from whichever provider you choose, and moves to its replacement by itself when the provider retires one.

Gemini (recommended default)

  1. Go to aistudio.google.com/apikey and sign in with any Google account.
  2. Click Create API key.
  3. If asked which project, choose Create API key in new project if you don't have one.
  4. Copy the key (starts with AIza).

Claude (alternative)

  1. Go to console.anthropic.com and sign in or create an account.
  2. API Keys → Create Key.
  3. Copy the key (starts with sk-ant-).
  4. Requires a payment method and prepaid credit — no free tier like Google AI Studio.

Want your briefing by email? Stop here and skip to Step 6 — the setup asks whether you want email or a podcast. Steps 4 and 5 are only for a podcast on your own key.

Step 4: Google Cloud Text-to-Speech API key (full podcast path only)

Written from a completely empty account — skip to sub-step 5 if you already have a project with billing enabled.

  1. Go to console.cloud.google.com and sign in.
  2. Create a project via the project dropdown → New Project.
  3. Enable billing — menu (☰) → Billing. Required before any paid API responds, even usage that stays free.
  4. Link billing to your project if not automatic.
  5. Enable the API — search “Text-to-Speech API,” click Cloud Text-to-Speech API, then Enable.
  6. Create an API key — menu → APIs & Services → Credentials → + Create Credentials → API key (not “Service account”).
  7. Restrict the key (recommended): Edit API key → Restrict key → select Cloud Text-to-Speech API.

This is a different key from your Gemini key in Step 3.

Step 5: Cloudflare R2 setup (full podcast path only)

  1. Create a Cloudflare account at dash.cloudflare.com/sign-up.
  2. Find R2 Object Storage. Enabling it requires a payment method — normal use stays $0/month.
  3. Create a bucket.
  4. Enable Public Development URL in its settings — copy the URL, that's your R2 public base URL.
  5. Create an API token: main R2 overview page → Manage R2 API Tokens → Account API Token → Object Read & Write, scoped to your bucket. Copy the Access Key ID and Secret Access Key (ignore the “Token value”).
  6. Find your Account ID on the R2 overview page.

You should now have: Account ID, bucket name, public base URL, and Access Key ID/Secret Access Key.

Step 6: Reach the Admin Console and configure

The setup script already started everything. Open http://127.0.0.1:5000 on the same machine, or via an SSH tunnel for a remote host:

ssh -L 5000:127.0.0.1:5000 <user>@<host>

The first time you open it, a short setup asks four things, checking each answer as you go:

  1. Who writes your briefing — paste your subscription token, or your Gemini/Claude key from Step 3.
  2. Email or podcast.
  3. Connect Gmail — your address and the App Password from Step 2.
  4. Which label, and when — filled in for you (Newsletters, 07:00 and 17:00 in your timezone); change them if you like.

Making a Gmail filter that fills the label: in Gmail on the web, open an email from a newsletter you want in your briefing, select the three dots at the top, then Filter messages like these. Select Create filter, tick Apply the label and choose your label (or New label), then Create filter. Repeat for each sender. The setup shows the same steps.

Newsletters are moved to Gmail’s Trash 10 days after they’re in a briefing; change that on Settings.

That's it for a subscription or an email briefing. If you chose a podcast on your own key, the Dashboard then lists what's left — the text-to-speech key and R2 details from Steps 4 and 5 — each with a link. Moving from another computer? Choose Restore your settings from a backup on the first screen instead.

After setup, the Dashboard says how your briefing is made and delivered, lists anything still to do, and has a Run now button. For a podcast, it shows your feed URL to add to your podcast app.

What this costs

Precise about what's measured versus estimated. The main driver of your cost is how much you have your LLM read, not how many emails arrive.

Typical monthly costBasis
A subscriptionThe plan's price, shown at catchupcast.com/app before you payCovers the AI, the voice and the podcast hosting. Nothing else to pay, and none of the rows below apply.
LLM (Gemini)$3-6/monthMeasured against a real twice-daily digest, 12-email batch.
Google Cloud TTS (full podcast)Under $1/month, often $0Measured via live testing; the free tier (4M chars/month) covers typical usage.
Cloudflare R2 (full podcast)$0-a few dollars/monthEstimated, based on the free tier against typical file sizes.
Claude, instead of GeminiBroadly similarRequires prepaid credit, no ongoing free tier.

On your own keys, budget around $5/month — email and podcast cost about the same to run.

Keeping costs in check

Why Inbox isn't allowed as the source label

The Source Label field on the Settings page still works exactly like before — type a name, and if it's a real label but doesn't exist yet, it gets created for you. Once Gmail is connected it also shows suggestions from your real labels as you type, but you're never limited to picking from that list: naming something brand new is expected, not an edge case. What's not allowed, suggested or typed, is Inbox itself (or Gmail's other built-in folders — All Mail, Sent, Spam, Drafts, Important, Starred): saving one of those is rejected, with an explanation, since they mix newsletters with personal mail, receipts, and whatever spam slipped through — exactly the scenario the caps below exist to guard against.

If a label collects more mail than expected

The numbers above assume a normal newsletter folder. Even with a real, dedicated label selected, one can still end up bigger than expected — a shared folder with years of backlog, say. A single digest run doesn't just try to summarize all of it at once. Three tunable settings guard against this, all on the Settings page:

Anything a cap leaves out simply waits for a later run — nothing is lost. You'll also get an email if a run ever actually hits one of these caps, so it's never silently slow. Lower any of these for tighter cost control, or raise them if you have a genuinely busy label and don't mind larger digests.

Setting a spending guardrail with your provider

The cap above bounds this project's own behavior. It's still worth knowing what your LLM provider itself offers as a backstop — confirmed by checking each provider's actual current behavior, not assumed to be equivalent:

Either way, a budget alert is worth setting up regardless of the cap above — it's a second, independent signal if something unexpected happens.

Step 7: Reach it from elsewhere (optional)

ModeReachable fromNeeds
Local networkDevices on your home networkNothing extra
TailscaleAnywhereA Tailscale account
Public domainAny browserA domain + port forwarding

Before switching away from loopback, set up a login on the Access page first.

Using Tailscale? By default Tailscale signs a machine out after 180 days, and then you can't reach the console remotely until you sign it back in. For a machine that's always on, turn on Disable key expiry for it in the Tailscale admin console. CatchUpCast itself keeps running either way.

Backups

Use Backup in the Admin Console. It makes one file, protected by a passphrase you choose, and a new machine is restored from it in a minute (choose Restore your settings from a backup on the first screen). Take a fresh one whenever you change a key or token.

The setup script also mentions secrets/bootstrap_key. You don't need it if you have a backup: it only helps in the rare case where this machine's data survives but that one file is lost.

Updating

Automatic — the companion container checks daily. To update immediately:

docker compose -f docker-compose.release.yml pull
docker compose -f docker-compose.release.yml up -d

Also installing CatchUpGist?

CatchUpGist is the companion product — it summarizes each email on its own instead of synthesizing a briefing across them. Plenty of people want both, for different mail. Installing it is the same shape as above, with the same setup script approach.

Full CatchUpGist install guide → — or grab the script directly:

⇩ install-catchupgist-linux.sh

Three differences worth knowing, all handled for you:

Both products keep themselves updated independently and neither interferes with the other's updates.

Windows: coming soon for CatchUpGist too — a native app, a better fit for a laptop — see the FAQ.

Platform-specific notes

Troubleshooting

© 2026 P3 Digital Services LLC