◉CLAUDE LABJP
●2.1.309 — Sandbox and permission checks are tighter, and hooks and PowerShell on Windows are fixed (10/22)●2.1.307 — Fixes MCP failing to reconnect after sleep or a keychain lock (10/21). 2.1.306 also fixed the false claude -p login message●SONNET 4.5 — Retires on the Claude API on 11/30, 37 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.309 — Sandbox and permission checks are tighter, and hooks and PowerShell on Windows are fixed (10/22)●2.1.307 — Fixes MCP failing to reconnect after sleep or a keychain lock (10/21). 2.1.306 also fixed the false claude -p login message●SONNET 4.5 — Retires on the Claude API on 11/30, 37 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-09-08Advanced

Until I planted a failing sample, my unattended checks had never once failed

A check running on an unattended schedule lost its exit code to a single pipe added for readable logs. I measured where the status disappears and built a small harness that checks the checker.

cowork16unattended4shell3quality gateautomation109

✦ Premium Article

I sat down to read three weeks of run records in one go. Every day was green. Not a single failure line.

That should have been a pleasant column to scroll through. Then I ran the same check by hand, plainly, and three violations were still sitting there. My hands stopped.

The check itself was fine. What was broken was the shape of the line calling it. A single | head -5, added so the logs would be easier to read, had stopped carrying the failure home.

A check earns unattended duty only after I've watched it fail on purpose. I keep that sentence in front of me now.

Green meant it had lost the ability to fail

Unattended run records almost always color themselves by one thing: whether the exit code was zero. However strict the check is inside, if the calling line returns zero, the record files it as a success.

The nasty part is that this failure mode still produces output. The violations were written into the log in full detail. Nobody opens a log that didn't fail. A defect that goes silent is easier to catch, in my experience, than one that keeps talking while nobody listens.

As an indie developer I run several websites, and the daily checks are handed to a Cowork schedule. Precisely because I designed the thing to run with no human watching, I never thought to question its capacity to fail.

Three places where the exit status disappears

Working through it one piece at a time, the leaks narrowed to three.

The first is the pipe. A shell reports the exit status of the rightmost command in a pipeline. Both head and tee finish with zero no matter what happened on their left.

The second is a local declaration inside a function. Write local out=$(cmd) and $? holds the result of the local builtin, not of cmd. Declarations succeed, so it is always zero.

The third is the || fallback. cmd || echo "failed" looks like "tell me if it breaks," but the moment echo succeeds the whole line is zero. Even with set -e in place, that line will not stop anything.

Every one of them came from wanting readability or wanting to be helpful. A character with no intent to break things had quietly disarmed the check.

✦

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'll be able to confirm today whether the checks you run unattended are actually capable of failing
✦You'll be able to find, inside your own scripts, the exact spots where pipes, tee, local, and fallbacks drop the exit status
✦You'll be able to stop weeks of false green from piling up by keeping a 40-line harness in front of every run
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-08-23
Not Every Unreachable Connector Means the Same Thing in an Unattended Run
When an unattended task cannot reach a connector, the cause splits into three states: still connecting, unauthenticated, or genuinely absent. Each demands the opposite response. Here is the resolver that tells them apart.
◈ Cowork2026-05-04
Why Cowork Scheduled Tasks Stop Mid-Run and How to Recover
Diagnose Cowork scheduled task failures using measured exit codes and real error output — why safe.directory delays failure instead of fixing it, how to pick a writable root before cloning, and how to structure logs with reason codes.
◈ Cowork2026-10-08
The Night I Halved the Instructions I Load Every Time: Three Drawers Before Any Cutting
The longer an instruction file grows, the more rules slip through. Here is how I sorted what gets loaded every time into keep, move, and delete, plus a small script that measures each heading.