← All Claude Code tips
09

Loops, Background Jobs and Scheduled Agents

The last step is work that happens while you are not watching. Where that pays off, where it quietly burns money, and the rule that decides which.

In practice7 min read· Updated 8 Aug 2026

Everything so far assumed you are sitting there. This is about the work that is not interactive — and about being honest that it is the part with the worst effort-to-payoff ratio in the whole setup.

Background tasks: the easy win

The clearest case. A long-running command runs detached, you keep working, and you get notified when it finishes.

Test suites, builds, installs, migrations. Anything where you would otherwise watch a progress bar.

The reason this works so well is that it removes a specific waste — blocking on something that needs no supervision — without introducing any new risk. The command is one you would have run anyway. It runs the same way. You just stop staring at it.

One thing worth internalising: if a system notifies you when a background job finishes, do not also poll it. Setting a five-minute check on something that will announce itself is pure waste, and it is a surprisingly easy habit to fall into.

Loops: narrower than they look

A loop re-runs a prompt on an interval. The obvious use is polling something that changes on its own — a CI run, a deploy, a queue draining.

The judgement is the interval, and the rule is simple: match it to how fast the thing you are watching actually changes.

A CI pipeline that takes eight minutes deserves one check at around eight minutes, not eight checks at one minute. Seven of those are guaranteed to find nothing and cost the same as the one that finds something.

Where loops genuinely earn their place: external state that cannot notify you. A deploy on a platform without webhooks. A third-party API you are waiting to come back. A slow remote job with no callback.

Where they do not: anything inside your own machine that could just tell you when it is done.

Scheduled agents: be honest about value

Cron for AI sessions. A prompt runs at a set time whether or not you are there.

The compelling pitch is a morning briefing — check overnight CI, summarise new issues, flag failing monitors. It works. But the value depends entirely on one question: would you have checked anyway?

If yes, the scheduled version saves you five minutes. If no, you have automated the production of something you will not read, on a schedule, indefinitely.

I run very few of these, and the ones that survived have a property in common: they only speak up when something is wrong. A job that reports "all fine" every morning becomes wallpaper within a fortnight. A job that is silent for three weeks and then says "the staging certificate expires in six days" has justified itself entirely.

Silence as the default output is the design rule.

Two things that break unattended work

Both are unobvious until they bite.

Interactive auth disappears. Anything that authenticates through a browser may not exist in a headless or scheduled run. Automation built assuming a tool is present will fail at 3am in a way that looks like nonsense — the tool was there when you tested it interactively.

Check availability explicitly, or do not depend on such tools in scheduled work.

Nobody is there to say no. Everything from the permissions piece applies double. An unattended job cannot ask. So it either has permission to act — and will, on a misreading you are not there to catch — or it can only report.

Almost all of my scheduled work is in the second category. It observes and reports. It does not change things.

The rule

One line, and it is the reversibility axis again:

Automate what is reversible or read-only. Report on everything else.

A job that reads CI status and summarises it: reversible, in that it changes nothing. Automate freely.

A job that reads dependency updates and opens a PR: a PR is a proposal, not a change. Fine.

A job that reads dependency updates and merges them: not fine, whatever the test suite says. The failure mode is a broken production deploy at 4am with no human in the loop, and you have traded a small recurring saving for a large occasional disaster.

The asymmetry is the point. The upside of automating a decision is a few saved minutes. The downside is an outage. Those do not trade evenly.

What I actually run

Being concrete, and slightly deflating: background tasks constantly, loops occasionally for external state, and almost no scheduled agents.

That last one is not a failure of imagination. It is that most of what I do is project work, driven by what a client needs this week, and the useful moment to look at a codebase is when I am about to change it. A daily digest of a repo nobody is touching is noise dressed as diligence.

This piece is last in the series because it is genuinely the least valuable part. If you implemented only the CLAUDE.md rules and the memory vault, you would get most of the benefit of everything here.

Where to stop

The temptation with all of this is to keep going — automating the automation, building the system that maintains the system. It is enjoyable and it feels productive.

The check I use: has this saved more time than it took to build? Honestly, and including maintenance.

For background tasks the answer is obviously yes, within a day. For the memory vault it took weeks to break even and now compounds. For a couple of scheduled jobs I built and later deleted, the answer was never, and admitting that took longer than it should have.

Build the thing that removes today's friction. Be suspicious of the thing that removes friction you have merely imagined.


That is the series. The setup it describes will be different in six months, because every part of it exists because something went wrong first — and things will keep going wrong.

// ready?

Need a developer who ships fastwithout shipping mess?

I build and maintain WordPress, Laravel and Nuxt applications for businesses that care about performance and maintainability.