Strategist · Designer · Operator

Launch
with Ben



Claude Code

Three Weeks of Claude Code on a Raspberry Pi 5. The Login Held. My Temp Folder Didn't.

The follow-up to my Raspberry Pi 5 Claude Code box. Does the subscription login survive weeks of cron? Do the jobs actually run? Yes, mostly. Here is what bit me instead.

The short version

Over three weeks on a Raspberry Pi 5, 2,088 of 2,165 headless claude --print calls worked on a subscription login. What failed was memory: /tmp lives in RAM and my leftover test folders filled it to 96%.

What you will learn

  • Whether a subscription login survives weeks of unattended cron
  • How to check that /tmp is memory-backed, and keep test runs from filling it
  • Why an hourly health check needs an agent wired to act on its alerts
  • Why pipes break a headless agent's allow-list

Who it is for

Someone running scheduled Claude Code jobs on a small always-on machine like a Raspberry Pi.

Skip it if

You have not read the setup post and want the install steps. You run jobs on a larger server with plenty of RAM.

You leave with

A three-line check for a RAM-backed /tmp and a set of rules for running headless jobs on 4GB.


Three weeks in, the Pi is still answering. The login was never the problem.

Three weeks ago I turned a Raspberry Pi 5 into a Claude Code box on my normal subscription, no API key. I ended that post with two things I didn’t know yet: whether the scheduled jobs actually run, and whether the login holds up with nobody touching it.

Both held. What bit me instead was memory, and a temp folder I didn’t know lived in RAM.

2,088of 2,165 headless claude calls worked
1,252of 1,254 scheduled jobs finished ok
88hours in one week the Pi was over its memory limits

The login held up

Every scheduled job that needs a model calls claude --print. The Pi logs each call. Over 21 days that’s 2,165 calls, on 17 different days, and 2,088 of them came back fine. The latest one ran today.

The 77 that failed were almost all one research script I was still building, failing in bursts on the days I was working on it. None of them was the login.

Honestly thought the login would be the weak spot. It wasn’t.

The CLI also reports what each call would have cost on the API. For the three weeks it adds up to $82. On the subscription that’s a notional number, not a bill, but it’s a fair picture of why I wanted this on a subscription in the first place.

The jobs run

The crontab line from the first post runs every fifteen minutes and kicks off whatever is due. Since 29 September that’s 1,254 jobs. Two failed.

To be clear, most of those are small. 1,032 of them are an eight-second check on a Shopify app that needs no model at all. The heavier ones, a daily alert digest, an SEO check and a weekly heartbeat, are in there too, and they finished.

So the Pi is fine as a box that wakes up, does a job and goes back to sleep. The trouble started when I asked it to do several things at once.

What bit me: four things, all about memory

1. Three heavy jobs at once rebooted it

On 7 October I had an install, a site build and a headless browser running at the same time. The Pi rebooted.

Heads up, I can’t prove it was memory: the system log didn’t survive the reboot. It keeps its log now. Since then I run one heavy job at a time, one install, build or browser while everything else waits, and it’s been up 12 days straight.

2. /tmp lives in RAM

This one I didn’t know. On Raspberry Pi OS here, /tmp is a 2GB tmpfs, so anything written there sits in memory.

My own test runs left a temp folder behind every time and never cleaned up. Eight days later there were 3,907 of them, about 1GB. /tmp hit 96%, swap hit 99%, and in the worst week the Pi spent 88 of 168 hours over its limits. Nothing crashed, it just got slow and tight.

This is the check I run now:

df -h /tmp          # "tmpfs" on the left means it's RAM
free -h             # watch the Swap line, not just Mem
ls -d /tmp/tmp* 2>/dev/null | wc -l

Receipt My /tmp is a 2GB tmpfs. Leftover test folders filled it to 96% and pushed swap to 99% before anything alerted me.

The fix was one line in the test runner: give each run its own temp folder and delete it when the run ends. The count stopped growing the same afternoon.

3. The health check only raised flags

I had an hourly health check running on the Pi, and it caught the right things: swap at 97%, /tmp over its limit. But without an agent wired to act on them, it just accumulated red flags. Three to five days of them.

So now an agent acts on them. When an alert stays open, the script hands it to a Sonnet agent:

  1. spots swap or /tmp over the limit
  2. looks at what’s actually filling it
  3. deletes only what it can prove is dead
  4. decides what else is safe to remove
  5. files the alert
  6. removes it through one guarded command
  7. re-measures
  8. writes up what it found
  9. emails me only if it’s still over

The agent can only delete inside /tmp, can’t touch anything a running process has open, and can’t kill anything. That’s enforced in the delete command itself, not just written in its instructions.

4. The first real run of that agent failed in 13 seconds

All my tests passed, because the tests swapped the model out for a stub. The first time the real agent ran, it gave up almost immediately and wrote: “Bash is denied in this session.”

It wasn’t, quite. In headless mode with --permission-mode dontAsk, a rule like Bash(du:*) allows du on its own. A command with a pipe, like du -sh /tmp/* | sort -rh, doesn’t match, so it’s refused. And /tmp is outside the working folder, so even a plain ls /tmp was refused until I added --add-dir /tmp. Both are in the CLI reference and the headless docs. I’d just never run into them.

The fix: one read-only script that gathers everything the agent needs in a single call, plus one line in its instructions. One plain command per call, no pipes, and try the plain form before deciding you’re blocked. The next real run cleared 344 dead folders, left everything in use alone, and wrote a clear report.

What still doesn’t fit on it

Some jobs are just too big for 4GB, and I’ve stopped trying:

JobWhat happens
astro dev on a 4,800-file sitekilled for memory at about 2.5GB, before it serves a page
a build that needs a 5GB heapcan’t start; it builds elsewhere now

One odd one that isn’t the Pi’s fault: about 1 in 4 calls to GitHub’s API time out from my network, while Cloudflare answers every time. A retry fixed it for the scheduled jobs.

The cooler from the first post earned its $11.99. Over the last week the Pi ran between 46°C and 60°C and never throttled.

How I run it now

Do

  • One heavy job at a time: install, build or browser
  • Check df -h /tmp as well as free -h. On a Pi, /tmp is memory
  • Give every test run its own temp folder and delete it at the end
  • An alert needs something that acts on it, or it’s just a log
  • Test the agent for real at least once, not only with a stub

Don't

  • Chain shell commands in a headless agent’s allow-list. Give it one script instead

Happy to answer questions about the setup, or share the scripts.

Related:

Sources

  • Claude Code CLI reference: --permission-mode, --allowedTools, --add-dir, read 2026-10-19.
  • Claude Code headless mode: running claude --print non-interactively with an allow-list, read 2026-10-19.
  • My own logs on the Pi, 2026-09-28 to 2026-10-19: every scheduled run, every headless call, and an hourly health log since 12 October.
Ben Peetermans

Ben Peetermans

I build MVPs and run ad campaigns with AI, and I write these notes from real projects. Twenty years shipping for the web. If you want someone who works with these tools every day to build yours, that is what I do.