GnothiGnothi
SeriesFieldsCommunityPublishing
Sign inGet started free

9. The Digest That Runs While the Laptop Sleeps

Summary

Running the digest with the laptop shut

The enquiry digest only ran when the laptop was awake and the Claude Code app open, and a failed run told no one. The customer, dates and money remain the show's invented example and prove nothing about real demand.

The first fix is a cloud scheduled task, formerly called a routine and still a research preview, so check current documentation. The setup covers a self-contained prompt, a schedule, a GitHub repository and an environment. Cron times are read in UTC unless you add a time zone, and the shortest interval is an hour. Schedule a few minutes off the hour, well before the seven o'clock deadline.

The Google Drive server added on the laptop is invisible to the cloud run. Add it as a claude.ai connector or commit a .mcp.json file. Keep API keys out of environment variables by using network secrets and the environment's network access levels. A cloud run uses auto mode, so the read-only Drive scope and the Viewer share are the limits that still hold. Whether the laptop's prompt hook carries over is unconfirmed.

Detecting failed runs and avoiding duplicate sends

A Succeeded label in History only means no failure was reported. For headless runs, check the exit code, printed output, and MCP errors. Also check the result subtype and stop reason. The wrapper script that combines them is the show's own pattern, not an Anthropic script, so test each condition. Stop and StopFailure hooks can add a quality gate and alert logging. A separate check shortly after seven catches a run that never started.

For retries, each job gets a key from the customer's opaque identifier and the scheduled date, recorded in a small file in the repository. The digest is written to a fixed path, so a rewrite replaces the earlier copy. One gap remains: a crash after delivery but before the key is marked done. The owner's review before sending covers it during the trial. Stripe's idempotency keys solve the same problem, but keys may be discarded after a day. A GitHub Actions scheduled workflow can run the plain file checks, though it can delay or skip runs and does not prevent duplicates.

What to offer when the trial ends

The trial cost $135 for ten digests, so each delivered digest earns $13.50. With four delivered, $54 is earned and $81 is still owed in digests. The delivered count in the customer record should match the completed-runs record.

Claude Code drafts the offer from the scope file and price record only: an illustrative $270 a month, just over twice the illustrative floor of about $133. The trial agreement said it would not roll into a monthly charge, so billing starts only after written agreement. Without a yes, the trial ends. A discount toward $100 would earn less per digest than it costs. Before sending, the cloud task runs a clean week under watch.


Up to now the enquiry digest has had a weak point. It runs every weekday evening only if the laptop is awake and the Claude Code app is open. A run that fails tells no one. That was fine while you were testing. It is not fine once someone has paid for it. This chapter fixes both problems and then turns to the decision the trial is heading toward. The customer, dates and money are still the show's invented example. They show how the method works and prove nothing about real demand.

There are two answers. To run the digest with the laptop shut, move it into a Claude Code cloud scheduled task. To find out when a run didn't happen or went wrong, build an alert from the evidence the run leaves behind, and keep a small record of finished runs so a retry can't send the same customer the same digest twice. This is the first piece of the business that is meant to work with nobody watching. So the question changes from "did it work while I watched" to "how would I know if it didn't".

Moving the digest into a cloud scheduled task

A cloud scheduled task is a saved setup in Claude Code. It holds a prompt, one or more GitHub repositories and the connectors the job needs, and it runs on computers Anthropic manages, so it keeps going when your laptop is closed. Until recently it was called a routine. The old name still shows up in the web address, in a slash command alias, and in the programming interface, so don't be surprised to see both names. It is also a research preview. That means its behavior, limits and interface may change, so check the current documentation before you depend on any detail below.

You need a Pro, Max, Ultra, Team or Enterprise plan. As of November 2026 there is no separate price. Runs count against your normal subscription usage, the same as when you work in Claude Code yourself. On a Team or Enterprise plan, an Owner can switch the feature off, and that also stops tasks that already exist. Tasks belong to your own account, not to a shared team space.

Here is the setup, in the order you'll do it.

  1. Go to the Claude Code routines page on claude.ai and click New task.
  2. Write a prompt that stands on its own. The cloud run doesn't see your conversation, so the prompt has to say everything: read today's files from the customer's shared folder, write the digest using the evidence-checked-drafting skill, meet the five acceptance criteria, and save it to that customer's delivery folder.
  3. Choose a trigger. For the digest, pick Schedule, weekday evenings, early enough that the page is ready by seven.
  4. Under Advanced settings, select the GitHub repository that holds the Digest Prototype folder. If that folder's git history lives only on your laptop, push it to a private GitHub repository first. Then pick an environment, a model and the connectors.
  5. Click Create, then use Run now to test it once before relying on the schedule.

Two details about timing. Times you set on the web page are in your local time. If you write a cron expression instead, which is a short line of text describing a schedule, it is read in Coordinated Universal Time unless you start it with CRON_TZ= and your time zone. A heating engineer's evening in their own town is the time that matters. The shortest interval allowed is once an hour, so anything more often is rejected. And a run set exactly on the hour can start a little late, so for a seven o'clock deadline, schedule well before seven and a few minutes off the hour, say ten past six, rather than at six sharp. You can also create a schedule from inside a Claude Code session with the slash command schedule. It only works if you are signed in with a claude.ai subscription, not an API key or a cloud provider account.

Now the snag you will hit. Back in the read-only Drive chapter, the show registered the Google Drive server with claude mcp add. A server added that way lives on your laptop. The cloud task can't see it. You have two ways to fix this. One is to add Drive as a connector on your claude.ai account, because connectors are the account's integrations and the task can use them. The other is to commit a .mcp.json file describing the server into the repository, so the task finds it with the code. Either way, check that the connection still signs in as the test account and still offers only list and read.

Keys need care too. The task's environment has environment variables, and anyone who uses that environment can see them. For an API key, use network secrets instead. Anthropic's proxy attaches the key to outgoing requests from outside the virtual machine the run lives in, so Claude never sees the key at all. That gives the same protection as a limit enforced by software rather than an instruction to keep something private.

That point matters even more because of how a cloud run handles permissions. On the laptop, the trial run had only a few tools approved ahead of time: Drive list, Drive read, and writing to the delivery folder. A cloud run starts in auto mode instead. A separate classifier model decides whether each action is allowed or blocked. The run pauses if it reaches one of your ask rules or keeps getting blocked. No per-tool allowlist is documented, so you can't copy across the laptop's narrow list. What still holds is everything enforced outside Claude Code. The Drive OAuth scope is read-only, the customer shared the folder as Viewer, and the connection offers only list and read. A classifier can make a mistake. Google will still refuse a write. Network access works the same way. The default level is Trusted, and you can also choose Custom or Full. A request to a host that isn't allowed comes back as error 403 with the reason host_not_allowed. If the digest needs a host the default blocks, that error tells you exactly which one to allow.

Each run is a complete session. You find it under History on the task's detail page, with the transcript, any file changes, and the option to open a pull request. The digest goes wherever your prompt and connectors send it. For the trial, the show keeps the owner's review step: the run writes the page into the repository's delivery folder, and you read it before sending.

The laptop's UserPromptSubmit hook may not carry over. Hooks are part of the Claude Code configuration that runs, so check in the documentation whether your committed settings fire in the cloud before you count on that gate. If you can't confirm it, have the prompt run the counting script first and stop if it fails.

Knowing when a run failed, and not sending twice

Open History after the first scheduled run and you'll see the word Succeeded. Don't read too much into it. Succeeded only means the session ended without Claude Code reporting a failure. If the classifier blocked the Drive read and the run gave up politely, or if the work stopped halfway, that appears only in the transcript. A green label sitting on top of an empty digest is the most likely way this setup lets a customer down.

So judge a run by evidence, and send that evidence to yourself. If you run Claude Code headlessly, meaning from a script with no one at the keyboard, as you might from a scheduler you control, the command-line tool gives you four things to check. First, the exit code: zero means success and anything else means failure. A run killed by its supervisor exits with 143 and records no result at all, so a kill needs its own alert. Second, standard output, the text the run prints. A failure inside the run, such as missing authentication, is printed there as the result even when the process itself looks fine, so capture it. Third, the result's subtype. The Claude Agent SDK, Anthropic's library for running Claude Code from your own programs, describes this as the primary way to check how a run ended. It is either success or one of a few error values, such as running out of turns or budget, and only success carries a result. Even success has a trap: a run can be success with a stop reason of refusal, so check that separately. If you asked for structured output with a JSON schema and no valid output came back, that field is simply missing. Permission denials are listed in the final result. Fourth, MCP errors. A broken entry in the MCP configuration is skipped and the run still exits cleanly, which for the digest would mean no Drive access and no warning. Check the mcp_server_errors field.

Put those together in a small wrapper script. It runs the job, captures the exit code and the JSON result, and counts the run as failed if any of these is true: the exit code isn't zero, the JSON is invalid, the subtype is an error, the expected structured output is missing, or the stop reason is refusal or max_tokens. On failure it posts a short message to a webhook or an email address with the exit code, the subtype, the session identifier and the cost. The session identifier lets you resume the exact session and see what happened. To be clear, this wrapper is a pattern the show is putting together from documented pieces. It is not a script Anthropic publishes, so test each condition on purpose before you trust it. Claude Code hooks can help as well. A Stop hook that exits with code 2 blocks the session from ending, which makes it a quality gate. A StopFailure hook fires when a turn ends because of an API error, and since its output is ignored, use it only for logging or sending an alert. Hooks don't run when the command-line tool is started with its bare option. The exact input each of these hooks receives is something to check in the hooks reference before you write against it.

Add one more condition that has nothing to do with errors: lateness. Acceptance criterion five says the digest is in place by seven on a weekday, and a late day earns the customer a credit. Have a separate check look for today's digest file shortly after seven and alert if it's missing. It catches the run that never started, which no wrapper around the run can catch.

Alerts lead to retries, and retries lead to the second problem. Say Wednesday's run timed out after writing the page, you start it again, and now there could be two Wednesday digests, or you might send the page twice. The fix is a completed-runs record. Give each unit of work a key made from the customer's opaque identifier and the scheduled date, meaning the date the run was for, not the time it happened to start. A retry then produces the same key. Keep the record as a small file in the repository with one row per key. The run adds its key as started, skips the job if the key is already marked done, carries on if a started row has gone stale, and marks the key done at the end. Write the digest to a fixed path built from the same customer and date, so a second write replaces the first rather than adding a copy. Writing a file is safe to repeat. Sending isn't.

That leaves one gap to know about. Writing the record and doing the work are separate steps. If a run crashes after the page is delivered but before the key is marked done, the next attempt can't tell, and it may deliver again. For the trial, your review before sending covers that gap, because you send each date's page yourself and can see whether that date has already gone out. Payment systems handle the same problem with idempotency keys, a value you send with a request so a repeat returns the first response instead of acting again. Stripe stores the first response under each key, but may discard keys more than a day old, so a key on its own doesn't protect against a retry days later. Your own record has to.

One alternative is worth knowing. The plain checks, counting files and confirming today's page exists, don't need a model at all. They could run as a GitHub Actions scheduled workflow. That fits ordinary code well, but it only starts the job. It can delay or skip runs when GitHub is busy, it does nothing to prevent duplicates, its shortest interval is five minutes, it always runs from the default branch, and in a public repository the schedule switches itself off after sixty days with no activity. Use it for the steps that have one right answer, and keep the completed-runs record either way.

Deciding what to offer when the trial ends

With the digest running on its own, the money question comes next. Open the customer record. Say it shows four digests delivered so far. The trial cost a hundred and thirty-five dollars for ten weekday digests, so each delivered digest earns thirteen dollars fifty. Four delivered means fifty-four dollars earned. The other eighty-one dollars is cash you've received but still owe in digests, and it's only fully earned after the tenth. Make sure the delivered count in the customer record matches the completed-runs record. If they disagree, one of them is wrong, and the books depend on whichever you trust.

Have Claude Code draft the end-of-trial offer only from the scope file and the price record, using the same evidence-checked skill. The offer is the illustrative two hundred and seventy dollars a month. That's just over twice the illustrative floor of about a hundred and thirty-three, and both numbers are still invented. The trial agreement said it would not roll into a monthly charge, and the offer keeps that promise. A recurring charge starts only after the customer agrees to it in writing. Without a yes, the trial simply ends and nothing more is billed. Don't discount toward a hundred dollars: at that price each delivered digest would earn less than it costs to make.

Don't send it yet. First, let the cloud task run a full week while you watch the History page, the alerts and the completed-runs record, and check each page against the day's folder. Once that week is clean, send the offer. At that point you'll have a service that runs while you sleep, tells you when it doesn't, and is ready to ask for its first monthly customer.

Want a series of your own?

Gnothi wrote and narrated this chapter. Name a subject and it writes you a course, or a story that teaches it, one chapter at a time, delivered to your podcast app.

Get started free