← 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.
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.
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.
Two questions decide everything else, and the Admin Console asks both when you first open it.
1. Who writes your briefing?
| A subscription | Your own AI key | |
|---|---|---|
| You need | Your subscription token, from catchupcast.com/app | A Gemini or Claude API key (Step 3) |
| Podcasts | Included — nothing else to set up | Also need Google Cloud and Cloudflare accounts (Steps 4 and 5) |
| Setup time | About 10 minutes, either way you get it | About 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.
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
chmod +x install-catchupcast-linux.sh
./install-catchupcast-linux.sh
On a headless box (a Raspberry Pi over SSH, say) this is the whole install — there's no desktop to double-click from anyway, so the terminal command above is the normal way to run it, not a fallback. If Docker isn't installed yet, you'll be asked for your sudo password partway through.
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:
docker group only takes effect on your next login, not the current shell session. The script detects this, tells you to log out and back in (or restart), and continues from there on the next run.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.
Gmail auth here is IMAP-based, not OAuth. Needed for both paths.
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.
AIza).sk-ant-).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.
Written from a completely empty account — skip to sub-step 5 if you already have a project with billing enabled.
This is a different key from your Gemini key in Step 3.
You should now have: Account ID, bucket name, public base URL, and Access Key ID/Secret Access Key.
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:
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.
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 cost | Basis | |
|---|---|---|
| A subscription | The plan's price, shown at catchupcast.com/app before you pay | Covers the AI, the voice and the podcast hosting. Nothing else to pay, and none of the rows below apply. |
| LLM (Gemini) | $3-6/month | Measured against a real twice-daily digest, 12-email batch. |
| Google Cloud TTS (full podcast) | Under $1/month, often $0 | Measured via live testing; the free tier (4M chars/month) covers typical usage. |
| Cloudflare R2 (full podcast) | $0-a few dollars/month | Estimated, based on the free tier against typical file sizes. |
| Claude, instead of Gemini | Broadly similar | Requires prepaid credit, no ongoing free tier. |
On your own keys, budget around $5/month — email and podcast cost about the same to run.
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.
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.
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.
| Mode | Reachable from | Needs |
|---|---|---|
| Local network | Devices on your home network | Nothing extra |
| Tailscale | Anywhere | A Tailscale account |
| Public domain | Any browser | A 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.
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.
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
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:
catchupgist/ folder, separate from CatchUpCast's. They must not share one — Docker names the data volume after the folder, so a shared folder means the two fighting over a single volume.http://127.0.0.1:5001, because CatchUpCast already uses 5000. If something else on your machine already has 5001, the installer picks the next free port and tells you which.secrets/ folder. It has its own Backup in its own Admin Console; CatchUpCast's backup does not cover it.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.
uname -m should say aarch64 or x86_64). Run install-catchupcast-linux.sh from Step 1 over SSH — it's the same script a desktop Linux user would run, no GUI required.network_mode: host in the compose file) works natively on Linux — nothing extra to enable.install-catchupcast-linux.sh says Docker isn't reachable, but it's installed. Usually means your user isn't in the docker group yet — the script detects this, adds you, and tells you to log out and back in (or run newgrp docker) before running it again.© 2026 P3 Digital Services LLC