Category

Tools & Dev Environment

The machine, agent environments, remote access, and alerting behind a one-person operation.

All posts

27
Two-panel diagram. Left shows pgrep -f matching the waiting shell's own command line, drawn as a circular arrow waiting on itself, with an already-finished job card beside it. Right shows the condition rewritten around results instead of process existence, listing an artifact file, an exact completion marker, and an API status.
Tools & Dev Environment3 min read

My Wait Loop Was Waiting for Itself

I added a one-line loop to wait for a long job to finish. That loop never ends: pgrep -f matches the full command line, and the waiting shell's own command line contains the string it's searching for.

#tooling#verification#macos#automation
A row of identical deploy-script icons all wearing a '--dry-run' badge, except one whose badge is greyed out and empty — and below it an arrow goes straight into a 'PRODUCTION' box.
Tools & Dev Environment4 min read

My `--dry-run` Shipped to Production

Every app has its own deploy script and they're nearly identical. Run with --dry-run first, and if the output looks right, drop the flag and run again. That day I ran it with --dry-run and the version shipped to production anyway. That script had no argparse.

#automation#android#gotchas#reality-check
Left: an interactive ssh session dying at zero bytes with Exit status 1 and a pty.Open device not configured log line. Right: 527 ttys pinned against the 511 ceiling and a list of claude/codex sessions alive for 20 days
Tools & Dev Environment5 min read

My SSH Died Because of 20 Days of Zombie Shells

An interactive tailscale ssh session exited instantly with zero bytes. The tailnet, the ACL, the host key, the version warning — all innocent. The real cause: CLI sessions nobody had touched in 20 days had consumed every PTY. And the thing holding each PTY wasn't claude — it was its parent shell.

#tailscale#ssh#macos#gotchas
The stub ignored `this` so a broken implementation passed; the test only fed ko-KR while the caller passes ko_KR; the self-check searched for a word the original body already contained, so it passed with no change at all.
Tools & Dev Environment4 min read

Three Ways My Own Tests Lied to Me

The stub was more forgiving than the real thing, the test input was cleaner than what the caller actually passes, and the self-verification check verified nothing. All three were green.

#testing#verification#gotchas#reality-check
Concept diagram: files whose logical size is normal but actual block count is 0 — APFS dataless. mv/rsync touching them triggers a synchronous per-file download. find -name '*.icloud' returns 0.
Tools & Dev Environment3 min read

Why moving files hung

Moving a git repo out of iCloud Drive to local disk with `mv`, hundreds of files wouldn't finish for over 10 minutes. iCloud files may not actually be on disk, and `mv` triggers a synchronous per-file download when it touches them. Worse, modern macOS uses APFS dataless files, not `.icloud` sidecars, so `find -name '*.icloud'` finds none of them.

#macos#icloud#git#gotchas
Concept diagram: in one directory create/delete/stat pass green while read/ls/append are blocked red. Full Disk Access is already granted. That asymmetry signals an EndpointSecurity extension, not TCC.
Tools & Dev Environment4 min read

The write-only directory

I could create and delete files but `open()` failed. `Operation not permitted`. Full Disk Access was already on, and the sandbox was irrelevant. The culprit wasn't TCC — it was an EndpointSecurity-based DLP agent, and the key to diagnosing it was the asymmetry: only files the current process just made were readable.

#macos#endpointsecurity#filesystem#gotchas
My one-person agent factory: the setup
Tools & Dev Environment3 min read

My one-person agent factory: the setup

34 web apps, a handful of paper-trading bots, and a multilingual video pipeline — all run from a 2017 Intel laptop that just stays on. Here's the whole setup and why the old hardware helped.

#setup#launchd#macos#automation