I wanted a small research database to grow from one subreddit to ten communities where people talk about building with Claude Code and automation. Doing it properly was estimated at about $118. It cost about $34, and the corpus went from roughly 1,000 chunks to 5,846. Overnight, while I slept.
The scraping ran through a paid provider (Apify) that charges per delivered record. The cleaning, tagging and indexing were my own Python. Around all of it sat one PowerShell script, which Claude wrote for me. That script is what this post is about, because the agent isn't the hard part. Anyone can make an agent do something impressive while they're watching. The hard part is the wrapper that makes it safe to stop watching.
Three rules.
1. Every phase is resumable
The script keeps its own state: chunks before and after, spend at the start and end, what it recovered and what it couldn't. All of it is set before the work starts and read again at the end.
Scraping is the phase that fails. Reddit blocks a scraper that hits too many communities in one session, with a 403. My first version asked for all ten subreddits at once. Four listings came back empty, including every Claude community, and the run still said it succeeded.
The fix wasn't a smarter agent. It was batching: three subreddits at a time, and anything that comes up short goes into a retry queue and comes back on its own after a pause. All four blocked listings came back that way. Because the provider only bills for delivered records, the failed attempts cost nothing.
Everything after scraping (cleaning, tagging, indexing) can run again on the same input without doubling anything, and the paid tagging step skips whatever it has already done. That's what lets the script retry without asking me. If it needed my permission to re-run, I'd have to be awake.
2. Judge success by the provider's number, not yours
The obvious check: count your rows before the scrape, count them after, and if the number went up, it worked.
It's wrong, and it's wrong in a way that looks exactly like a failure. The pipeline deduplicates on the way in. A second pass over a community pulls the day's top posts, and many of those are already stored from the first pass. So the provider can deliver hundreds of good records while your database barely moves. A check on your side calls that a dead run and pays to scrape it again.
So success is the provider's delivered-record count, checked against a minimum I set for each community. My side can legitimately show no change and still be fine.
Money works the same way. Before every paid attempt, the script reads the account's actual spend for the month from the provider and stops at a hard cap. It doesn't keep its own estimate. If something in my pipeline miscounts, the budget check can't be fooled, because it isn't counting anything. It asks the account.
3. Write the report even if it crashes
The end of the script is a finally block. Whatever goes wrong above it (an error, a failed scrape, the provider going down), it still builds a coverage table, writes a status banner, saves the report and opens it in Notepad. One caveat: finally covers errors inside the script. If the whole process is killed, nothing runs.
The first real report said PARTIAL: one community, one listing not recovered, named, with the command to re-run it. Not a failure, a to-do. The mop-up the next day brought back 47 records, which was everything that community had that day.
When you're asleep for the whole run, silence is the worst output. Silence can mean everything worked, or that it died in the first 30 seconds, and from the couch those look the same. The report is what tells them apart.
What went wrong anyway
Two things, both the same lesson.
Headless Claude Code holds back its output. Launched from a script, it prints nothing until it exits unless you tell it to stream. So the log file sits at zero bytes for the whole run, and a healthy agent looks exactly like a dead one. I now judge an agent by the timestamps on the files it's writing and its CPU time climbing, never by the log.
My summary tables were one row long. The script that builds them had a nested database cursor that reset the outer loop after the first row. Every table came out formatted and plausible, and wrong. Now I count the rows I expect instead of eyeballing the top of the file.
A run that reports success and is wrong is scarier than a run that crashes. The crash tells you. The plausible report doesn't.
Get the script
The script is free on GitHub, with a header marking which lines to adapt:
https://github.com/lgcreativestudios/buildwithaihub/blob/main/scripts/v1/phaseC_overnight_orchestrator.ps1
It runs locally in PowerShell on Windows, reads your own Apify and OpenRouter keys from your user environment variables, calls those two services with them, and writes only local files. Read it before you run it.
Here's the 7-minute walkthrough, with the real report on screen:
I'm building the whole system in public. If you want the next pieces as they land, there's a waitlist: https://lgcreativestudios.github.io/buildwithaihub/
Drafted with Claude's help from the video script. The run, the code and the numbers are real.
Top comments (0)