Day 1 of 9 · Sunday · Learning

Where your automation runs — and where failures goConcept

Four different things on your Mac can run code without you watching — and each one hides its failures in a different place. Today you learn which is which, and where to look when an expected output doesn't show up.

Catch-up progress
1/9
Why this matters to you

Three of the friction incidents in your session history were silent automation failures: the language email died twice, plan-day ran 34 minutes past its watchdog, and a build couldn't find the 'claude' binary. None of them announced themselves. If you can read where each runner logs and what proves it actually worked, you stop discovering failures by their absence.

There are four ways work runs without you in the loop, and they live at different layers. A LaunchAgent is macOS's own scheduler: a plist file in ~/Library/LaunchAgents that launchd fires on a clock or a file-change. Your daily plan (6:15am) and language email (10:00am) are LaunchAgents. cron is the older Unix scheduler — you don't really use it; macOS prefers launchd. /schedule (and its cousin remote agents) runs on Anthropic's servers, not your Mac — which is exactly why an earlier session couldn't find your language automation by searching local files and wrongly concluded it 'didn't exist.' And claude -p is a headless one-shot: a script starts Claude, hands it a prompt, and waits — that's how your LaunchAgents actually invoke skills like /plan-day.

The thing that bites you is that 'it ran' and 'it worked' are different claims. launchd will happily report a job exited 0 while the real work failed downstream — the email never reached Resend, the file never got written. The fix is to verify the side-effect, not the trigger: don't trust 'the LaunchAgent fired,' check that the email has a Resend ID, the commit landed, the Things task exists.

Each runner leaves its trail in a predictable place. LaunchAgent stdout/stderr go wherever the plist's StandardOutPath points (usually /tmp/…) plus whatever the script itself logs (your scripts write to PDB/logs/). Remote agents log on Anthropic's side — you check them with /schedule, not the filesystem. When an output is missing, the question is always 'which runner owned this, and where does that runner write?'

Worked example

Here's how to list every LaunchAgent you own and inspect one. Run these in a terminal:

# List your LaunchAgents (the jobs that run on YOUR Mac)
ls ~/Library/LaunchAgents/

# See whether one is currently loaded into launchd, and its last exit code
launchctl list | grep tom

# Read what a job actually did last time it ran
tail -30 /Users/tom/Claude/PDB/logs/language-lesson.log

# Inspect a job's schedule + where it logs (the plist is just XML)
cat ~/Library/LaunchAgents/com.tom.pdb-language-lesson.plist
▶ Do it now
  1. Run `ls ~/Library/LaunchAgents/` and read the list — these are every scheduled job on your Mac.
  2. Pick one (try com.tom.pdb-language-lesson), `cat` its plist, and find the StartCalendarInterval — confirm you can read what time it fires.
  3. `tail -20` that job's log under PDB/logs/ and find the most recent 'OK' or 'FAIL' line. That line — not 'the job ran' — is proof of the side-effect.

Gotchas

Go deeper: Your automation-hygiene rules · Apple: launchd.info
One-card takeaway

Don't ask 'did the job run?' Ask 'where's the side-effect, and what proves it landed?' The runner's exit code is a rumor; the Resend ID, the commit, the written file is the evidence.