◉CLAUDE LABJP
●2.1.302 — Fork subagents are now on by default in claude -p, the Agent SDK and the desktop app. Turn them off with CLAUDE_CODE_FORK_SUBAGENT=0 (10/16)●2.1.301 — Unattended retries now stop on their own when a usage limit is hit instead of waiting (10/15). Latest is 2.1.304 (10/19)●SONNET 4.5 — Retires on the Claude API on 11/30, 40 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.302 — Fork subagents are now on by default in claude -p, the Agent SDK and the desktop app. Turn them off with CLAUDE_CODE_FORK_SUBAGENT=0 (10/16)●2.1.301 — Unattended retries now stop on their own when a usage limit is hit instead of waiting (10/15). Latest is 2.1.304 (10/19)●SONNET 4.5 — Retires on the Claude API on 11/30, 40 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/Cowork
◈ Cowork/2026-10-21Intermediate

Why I Stopped Borrowing a Stale Repo and Started Cloning Fresh After a Scheduled Task Couldn't Write to Shared /tmp

A scheduled task stopped because it could not create its clone directory under /tmp. Here is how I traced it, the borrowable clone that was about 9.6 hours behind, the cost of cloning fresh every run, and a script that picks a working directory.

Cowork53Scheduled Tasks17Git5/tmpOps Log

✦ Premium Article

On a Wednesday evening I opened the log of a scheduled task and found it had stopped at its first Git operation.

fatal: could not create work tree dir '/tmp/repos/claudelab.net': Permission denied

My runbook says to keep a persistent repository under /tmp/repos and git pull it next time. That one line told me there are days when the assumption does not hold.

What follows is how I traced the cause, and why I stopped borrowing a clone that another run had left behind and decided to clone fresh every time. If you run Git against a repository from a Cowork scheduled task, I hope it saves you from stepping on the same spot.

Four commands to separate the cases: /tmp is writable, /tmp/repos is not

I suspected /tmp itself first: a full disk, or a read-only mount. I checked in this order.

id                                   # who am I
ls -ld /tmp /tmp/repos               # owner and mode of parent and child
mkdir /tmp/repos/x                   # can I create under the child
touch /tmp/_w_test && echo "tmp root writable"   # can I write directly in /tmp

The output, abridged:

uid=1079(rcw-017tvrnbapgi3k7hq52tm5wv) gid=1079(...) groups=1079(...)
drwxrwxrwt 15 nobody nogroup 4096 Oct 21 08:44 /tmp
drwxr-xr-x  3 nobody nogroup 4096 Oct 21 01:16 /tmp/repos
mkdir: cannot create directory '/tmp/repos/x': Permission denied
tmp root writable

Three things to read from this. /tmp is drwxrwxrwt (sticky bit, writable by everyone), so a touch directly under it succeeds. /tmp/repos is owned by nobody with mode 755, so my user (uid 1079) can enter it but cannot create anything inside. And its creation time, 01:16 the same day, shows that a different run made it first.

Being able to write to /tmp says nothing about whether you can write to a directory someone else created inside it. I briefly reasoned that since /tmp was writable the problem must lie elsewhere, and started with the disk. There was no shortage: 3,787 MB free on / and 7,229 MB on /sessions.

A borrowable clone existed, but it was about 9.6 hours behind

Directly under /tmp sat a claudelab.net clone, apparently left by another run (also owned by nobody). It was readable, and I was ready to copy it and skip the clone.

Before using it I checked only how fresh it was.

git -c safe.directory='*' -C /tmp/claudelab.net log -1 --format='%h %ci'
git -C "$HOME/repos/claudelab.net" log -1 --format='%h %ci'    # latest I fetched myself
9296076 2026-10-20 23:06:43 +0000     <- the borrowable one
3dd2738 2026-10-21 08:41:15 +0000     <- latest origin/main

The borrowable clone trailed origin by about 9.6 hours. Because .git was not writable either (touch .git/probe gave Permission denied), I could not pull in place. Using it would mean copying first and pulling afterwards, which is a two-step detour.

For work that edits content, that state is quietly dangerous. If you check for duplicate slugs or confirm that internal link targets exist while blind to nine hours of changes, a page you judge missing may exist, or the reverse. The real cost of borrowing a stale clone is not the clone time. It is the probability of a wrong decision.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦You can tell whether a shared /tmp is 'writable but not for you' and find the cause with four commands
✦You can stop a run from appending to a stale clone that another run left behind, by comparing SHAs before you touch anything
✦You can put the choice of working directory into one script, so a scheduled task spends no time hunting for a place to work
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

◈ Cowork2026-10-18
I Preloaded a Scheduled Task with head -150: 15.6 KB Read, 3.3 KB for Today
A scheduled task preloaded its daily notes with head -150, and line count turned out to be no budget at all. A date-block reader with a byte ceiling, and how to avoid dropping ideas nobody has used yet.
◈ Cowork2026-10-17
When a Scheduled Task Keeps Saying SUCCEEDED but Produces Nothing, Check Outbound Traffic in the First Minute
The run history is green, but the output file is still yesterday's. A short probe and a freshness check that tell you in the first minute whether outbound calls are being refused with a 403 on CONNECT.
◈ Cowork2026-10-01
Before You Trim a Scheduled Task's Runbook, Count How Many Times It Gets Re-read
I cut 13 KB from a scheduled task's preloaded docs, and recounted by re-reads it was worth about 1.3 tool calls. Here is the ledger that counts re-reads, and a shell helper that records bytes during a run.