Build1 distinct publisher3 min readUpdated
A launchd job logged "no changes" and exited clean every Sunday while TCC blocked every write to ~/Documents. The success path and the total-failure path looked identical.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A weekly macOS backup job ran at 6:00 every Sunday, wrote "no changes" to its log, exited 0, and copied not a single file for three weeks running, according to a dev.to writeup by the person who built it [1]. The cause was macOS TCC: under launchd, the destination path under ~/Documents returned "Operation not permitted", every copy failed, and the sync target was moved to ~/.claude/config-snapshots/ on 2026-06-01 [2].
At one run per week, that is three consecutive scheduled executions that produced a clean log line and a zero exit status while doing nothing [11], leaving at least 21 days with no usable snapshot [13]. The job was not exotic. It was a launchd agent labelled com.shun.dotfiles-snapshot, weekly at 06:00, ProcessType Background, Nice 10, LowPriorityIO true [4], running a script at ~/.claude/scripts/dotfiles-snapshot.sh that rsyncs only config files out of ~/.claude into a separate directory and never modifies ~/.claude itself [3]. An explicit INCLUDE list is the canonical definition of what counts as config [9]. The design exists because ~/.claude is not under version control and putting the whole directory in git fails in practice: plugin cache, session history, telemetry and paste-cache balloon the repository to several GB and cannot rule out secrets landing in the cache [6]. What is worth keeping is real, though. settings.json, CLAUDE.md, hooks/, agents/, skills/auto/ and rules/ change in dozens of places every week [7].
The interesting part is the failure signature, not the permission. The script's documented behaviour is: if there is a diff, commit in conventional commits format; if there is no diff, write "no changes" to the log and exit [5]. That means the healthy quiet week and the week where the process could not write anywhere both terminate on the same line with the same status [12]. No alert fires because nothing failed, in the only sense the scheduler understands. This is the standard shape of macOS automation rot: TCC denies a file operation, the tool reports it as a copy that did not happen, and the wrapper interprets zero copies as zero changes.
The operator conclusion, which is mine and not the source's, is that exit codes are a liveness signal at best and never a health signal for anything that touches a protected directory. A job of this kind needs a proof-of-work assertion that is independent of the job's own reporting: check that the destination's newest file mtime is inside the expected window, or that the git repository has a commit or a verified clean tree from the last scheduled run, and treat "unchanged for N cycles" as a paging condition rather than a good week. If a backup cannot demonstrate that it read the source and wrote the destination, it has not demonstrated anything.
Two things to watch. The writeup does not say which TCC permission the launchd agent lacked or how consent was configured [14], so anyone copying the fix is copying a relocation, not a grant. And the snapshot job is deliberately kept separate from an existing SessionEnd auto-commit for ~/Documents/my-knowledge-base/ [8], which still sits inside the protected tree; that one runs from an interactive session today, and moving it under launchd would put it back on the same boundary. The reported side benefits of the git layer, tracing which change broke a hook with git log --oneline, spotting configuration drift, rebuilding on another machine [10], all depend on the snapshot actually happening.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The author's backup job ran every Sunday at 6:00 AM, logged "no changes", and exited 0; for three weeks straight it never copied a single file, macOS was blocking it, and nothing in the system reported the failure.
The old sync destination ~/Documents/claude-config-snapshots hit macOS TCC "Operation not permitted" when run under launchd and every copy failed, so the destination was relocated to ~/.claude/config-snapshots/ on 2026-06-01.
The script is ~/.claude/scripts/dotfiles-snapshot.sh; it rsyncs only the config files from ~/.claude to a separate directory and never touches ~/.claude itself, to avoid mixing with plugin cache noise.
The launchd job is labelled com.shun.dotfiles-snapshot, runs weekly on Sunday at 06:00, with ProcessType Background, Nice 10, and LowPriorityIO true.
Script behaviour: if there is a diff, commit it in conventional commits format; if there is no diff, write "no changes" to the log and exit.
~/.claude is not under version control, and putting the whole directory in git does not work in practice because plugin cache, session history, telemetry and paste-cache balloon the repository to several GB and cannot rule out secrets ending up in the cache.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Single first-party writeup with a plausible but undocumented mechanism
All claims come from one dev.to post by the operator of the system. The artefacts quoted (script header comment, plist excerpt, architecture diagram) are internally consistent and specific — label, schedule, destination path, relocation date — which supports the mechanical description. But there is no log excerpt of the failing runs, no error output beyond the phrase "Operation not permitted", no independent corroboration, and the writeup never identifies which TCC permission was missing, so the causal diagnosis rests on the author's assertion.
One self-reported personal deployment
Observed adoption is a single developer's machine: one launchd agent, one snapshot repository, one relocation event on 2026-06-01. No other users, teams, forks, downloads or reproductions are reported anywhere in the supplied material, so the pattern's uptake beyond the author is unknown rather than broad.
Framing slightly outruns the evidence supplied
The core insight — that a job whose no-diff path and whose blocked-write path both emit "no changes" and exit 0 cannot signal failure — is genuinely supported by the described script behaviour, so the piece is not badly inflated. The mild overstatement is generalisation and diagnosis: the headline presents a broad macOS rule ("launchd can't write to ~/Documents") from one unlogged case whose root permission was never identified, and the remedy demonstrated is path relocation rather than a verified TCC fix.
Personal developer writeup, no disclosed commercial stake
The single source is an individual's dev.to post describing their own tooling; no product, sponsor, vendor relationship, funding or pricing is being promoted in the supplied material, and the author reports a failure of their own automation rather than a success story. The residual incentive is ordinary developer-platform audience building — engagement-oriented framing such as a dramatic headline and a tidy architecture diagram.
Coherent single-source account with one unresolved gap
Confidence is moderate: the mechanical facts (paths, label, schedule, plist keys, relocation date, script branching) are quoted directly and hang together, and the logical conclusion about indistinguishable exit paths follows from them. It is held down by there being exactly one publisher and one first-party observer, no captured logs or error traces, no corroboration of the failure window, and no statement of the specific TCC permission at issue.
build
The 46GB Leak Your RSS Alert Cannot See: macOS Compressed Memory Breaks Threshold Monitoring1 distinct publisher
build
26 launchd jobs, one log directory: how scheduled automation rots quietly1 distinct publisher
build
41 queued tasks, zero ready to dispatch: the agent bottleneck was judgment1 distinct publisher
build
Your reviewing model is reading the diff when it should be reading the session1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 18, 2026