Module 10: Automations & Agents
Lesson 2

Scheduling Work — Cron, Triggers & Background Jobs


A Worker That Shows Up on Its Own

In the last lesson you built a tiny worker: claude -p, a single instruction, a result. But you still had to type the command. The next level of leverage is making that worker show up on its own — every morning, every hour, or the moment something happens.

This lesson is about the two ways jobs get started without you:

  1. Schedules — "run this every day at 7am."
  2. Triggers — "run this whenever X happens" (a file arrives, a form is submitted, a webhook fires).

Here's the most important thing to understand up front, so you never feel misled:

Claude Code does not have its own always-on scheduler that you set and forget. The scheduling comes from a tool outside Claude — your computer's built-in scheduler, or a cloud service — and that tool's only job is to run your claude -p command at the right time.

In other words: the thinking is Claude's job. The timing is someone else's job. You wire them together.


Option 1: Cron — Your Computer's Built-In Alarm Clock

Every Mac and Linux machine ships with a scheduler called cron. You give it two things: a schedule and a command. It runs the command on that schedule, forever, as long as the machine is on.

You edit cron's list of jobs (the "crontab") by running crontab -e. Each line is one job. The schedule is written as five fields:

┌─────── minute (0–59)
│ ┌───── hour (0–23)
│ │ ┌─── day of month (1–31)
│ │ │ ┌─ month (1–12)
│ │ │ │ ┌ day of week (0–6, Sunday = 0)
│ │ │ │ │
0 7 * * *   <your command here>

A * means "every." So 0 7 * * * means "at minute 0 of hour 7, every day" — i.e. 7:00am daily. A few you'll actually use:

ScheduleMeaning
0 7 * * *Every day at 7:00am
0 * * * *Every hour, on the hour
*/15 * * * *Every 15 minutes
0 9 * * 1Every Monday at 9:00am

The catch: cron only runs while your computer is on and awake. A laptop that's asleep at 7am won't run the job. That's fine for many personal automations, but it's why the next two options exist.


Option 2: GitHub Actions — A Cloud Scheduler That's Always On

GitHub Actions is a free-for-most-uses service that runs commands in the cloud on a schedule — no machine of yours required. If you've already got a project in a GitHub repository, this is often the easiest "always-on" option.

You add a file describing the schedule and the steps. Here's a daily job, in GitHub Actions' YAML format:

name: Daily Summary
on:
  schedule:
    - cron: "0 7 * * *"   # same 5-field cron syntax, in UTC
  workflow_dispatch:        # also lets you run it manually with a button

jobs:
  summarize:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Claude
        run: claude -p "Summarize this week's changes" --allowedTools "Read"
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

Two things to notice. The cron: line uses the exact same five-field syntax you just learned (handy — learn it once). And the ANTHROPIC_API_KEY is pulled from a secret, not pasted in plain text — never put keys directly in a file you commit. (Anthropic also publishes an official Claude Code GitHub Action, anthropics/claude-code-action, designed specifically for reacting to pull requests and issues — worth knowing if your work lives on GitHub.)

Cloud schedulers from other providers (AWS, Google Cloud, etc.) work the same way conceptually: a managed clock that fires your command. GitHub Actions is just the friendliest starting point.


Triggers: Running on an Event, Not a Clock

A schedule answers "when?" A trigger answers "when something happens." Same idea — an outside system starts your claude -p job — but the starting gun is an event rather than a time.

Trigger typeFires when…Example
WebhookAnother service sends a signal to a URLA new lead submits your form → summarize and notify you
File changeA file appears or changes in a folderA new invoice PDF lands → extract the total and log it
Inbound messageAn email or chat arrivesA support email comes in → draft a reply for review

The pattern never changes: something external detects the event, then runs your Claude command, optionally piping the event's data in. For instance, a webhook handler might receive form data and run:

echo "$FORM_DATA" | claude -p "Summarize this lead in 2 sentences and rate fit 1-10" --output-format json

You don't need to master webhooks today. The point is to recognize the shape: schedules and triggers are the same machine with a different "go" button.


Worked Example: A Daily Project Digest

Let's build a real, end-to-end scheduled job: every morning at 8am, Claude reviews yesterday's activity in a project and writes you a short digest.

Step 1 — Get the headless command right (run it by hand first).

Always prove the command works manually before you schedule it. You don't want to discover a typo three days later when you wonder why no digests arrived.

cd ~/projects/my-app
git log --since="1 day ago" | claude -p "Write a 5-bullet daily digest of what changed: features, fixes, and anything that looks risky. Keep it skimmable." --allowedTools "Read" > ~/digests/$(date +%Y-%m-%d).txt

This pipes yesterday's commits into Claude, asks for a digest, and saves it to a dated file. Run it once. Read the output. Tweak the prompt until you like it.

Step 2 — Wrap it in a small script.

Cron lines get messy. Put the command in a file, say ~/scripts/daily-digest.sh, so the schedule just calls one clean thing.

Step 3 — Schedule it. Run crontab -e and add:

0 8 * * * ~/scripts/daily-digest.sh

That's it. Every day at 8am, while you're getting ready, Claude reads the project and leaves you a digest. (In Lesson 3 we'll add the final touch: instead of saving to a file you have to open, it'll message you the digest directly.)


Two Rules That Save You Pain

Rule 1: Test manually before you schedule. A scheduled job runs silently. If it's broken, it fails silently too. Always run the exact command by hand first.

Rule 2: Make failures loud. A digest that quietly stops arriving is worse than one that errors visibly. Have your job log its output somewhere, or — better — notify you when it runs and when it fails. We'll cover exactly how in the next two lessons.


Summary

  • Claude Code has no always-on scheduler of its own — you pair a claude -p command with an outside scheduler that decides when it runs.
  • Cron is the built-in scheduler on Mac/Linux: a five-field schedule plus a command, run via crontab -e. It only runs while your machine is on.
  • GitHub Actions (and other cloud schedulers) run jobs in the cloud, always on, using the same five-field cron syntax. Keep API keys in secrets.
  • Triggers start a job on an event (webhook, file change, inbound message) instead of a clock — same machine, different "go" button.
  • Build the pattern in order: get the headless command working by hand, wrap it in a small script, then schedule it.
  • A silent schedule fails silently — always test manually first and make failures loud.