Every night a scheduled job wakes up, reads a queue of pending work across my projects, and spawns one headless agent session per target to drain it. In the morning I read a report over coffee. That's the pitch, and scheduling it is genuinely the easy part, any cron line can do that. What took actual design is the policy around it, because an unattended agent with write access is a very fast way to wake up to a mess. Five laws came out of that design.
1. The runner owns the envelope, the child owns the work
A headless session cannot mind its manners, it won't maintain a lock, it won't notice a sibling, it dies without cleaning up. So the runner does all of that on its behalf. It takes the claim on the target before spawning the child, refreshes the heartbeat on a timer while the child runs, and releases it always, crash included. Manners stop being the child's job, which means they stop being a hope.
runner: take the claim on the target
│
├─▶ spawn the child, headless, in its own worktree
│ │ heartbeat renewed on a timer while it runs
│ ▼
│ child commits, or finds nothing, or dies, or hits the watchdog
│ │
└───────┴─▶ release the claim, always: exit, crash and kill alike
2. Skip, never fight
Five conditions make the runner walk away from a target, every one with a logged reason:
- a live interactive session on it
- a dirty tree
- someone else's claim
- an entry marked as needing me
- two failed attempts already tonight
The night never contends with the day. Contention is what mornings are for.
3. Nothing touches main
Children commit to their own trees, and where pushing is enabled at all, the runner pushes the night's work to an isolated per-night branch and restores whatever branch was checked out before. I review drained work the way I'd review a colleague's branch, not by discovering it merged.
4. Ceilings, set before the first run
Underneath it all, ceilings. A cap on children per night, a cap on retry rounds, a watchdog per child. I set them before the first unattended run, not after the first runaway, which I recommend as an ordering.
5. The report is unconditional
The rule I'd defend hardest. A report gets written even when there was nothing to do. This sounds trivial and it changes everything, because it converts silence into signal. An absent report can only mean the job died. Before this rule, a quiet morning meant either a quiet night or a broken scheduler, and I had to go check which.
- Automation you have to check up on is just unfinished automation.
The morning read is the acceptance test for the whole thing. The report's skeleton is three headings:
# Night report 2026-08-14
## what happened
## what was skipped, and why
## what needs me
If it can't fill those inside two minutes of my attention, the report is the bug. Five nightly reports in, the streak is young but every morning has had one waiting, and that is the property I refuse to lose. The coffee helps.
Top comments (0)