Why npx cc-safe-setup installed an outdated version for five months, and how to check what you have (Chapter 5)
Updated 2026-09-24. npm has caught up. 30.0.5 was published that day, latest points at it, and
npx cc-safe-setup and npx github:yurukusa/cc-safe-setup now install the same code. What follows
is the record of the five months when they did not — kept, because an install you made before that
date is still the old one, and nothing on your machine will tell you so. npx cc-safe-setup --outdated will: it lists the hooks you have that differ from the current ones.
This was the trap this book exists to remove, and it is the cleanest example in the book of a second kind of staleness: not a guard that stopped matching, but a distribution channel that stopped moving while everything it points at kept going.
Run --help and read the line in brackets:
1 Quick Start:
2 npx github:yurukusa/cc-safe-setup Install 8 safety hooks (30 sec)
3 npx github:yurukusa/cc-safe-setup --shield Maximum safety — one command
4 npx github:yurukusa/cc-safe-setup --doctor Diagnose hook problems
5 (npx cc-safe-setup now installs the same code; npm sat at 29.8.0 / 2026-04-20
6 for five months, so run --outdated if you installed before 2026-09-24)
For five months the npm entry sat at an old version. On 2026-09-03 I fired twenty-two command shapes at both versions of the three guards, feeding each the same JSON on stdin and running it with bash, which is the shell the installer names. Nine shapes that the current code refuses were allowed through by the version npm served then: four handled by destructive-guard (a deletion split over two lines, rm --recursive --force /, a base64 blob decoded into sh, and rm -rf "$HOME"), three by branch-guard (git push -uf, a force push after a separator, git -C /repo push --force) and two by secret-guard (git add .env after a separator, and the same split over two lines). Nothing went the other way, and two harmless controls were allowed by both.
The repository’s own README carries this table and a wider one. On the evening of 2026-09-14 I widened the set from twenty-two shapes to forty-one, and against that longer list the gap is twenty-five, not nine. The --help text above used to print that number; it does not any more, because the gap it described has closed, and a line in a tool that quotes a measurement goes stale the moment the measurement stops being current. The two numbers are the same finding measured against two different lists, not a disagreement: the original twenty-two still split nine and thirteen, and nothing goes the other way in either run. If a count in this chapter and a count in the tool’s own output ever look like they contradict each other, that is the first thing to check — which list each one was measured against.
I fired them again on 2026-09-14, the day before this edition went out, because two fixes landed in the current code that morning and a dated claim written in the present tense goes stale without anyone touching it. The same twenty-two shapes still split nine and thirteen: the frozen version cannot move. What moved is the list. Firing forty-one shapes instead of twenty-two — the original set plus the invocation forms the morning’s fixes were about, such as sudo git push --force origin main and git send-pack --force origin main — puts the gap at twenty-five, still with nothing going the other way. So the number in this chapter is not a constant and was never going to be. It is the distance between a package that stopped and a repository that did not, and the only direction that distance travels is wider.
That last sentence was wrong, and it is staying in. Ten days later the distance went to zero. The credential was never renewed; the problem was solved from the other end, with npm’s trusted publishing — the build proves its own identity to the registry, so there is no stored secret to expire and no second factor to reach for. The registry caught up in one afternoon. I had reasoned from I cannot fix this with what I have to this will keep getting worse, and that does not follow. Every measurement in this chapter was right on the day it was taken. The sentence that turned out to be false is the only one I did not measure.
Until 2026-09-24, the obvious install command, npx cc-safe-setup, was the one that got you the frozen version. It is shorter, it is what people type, and it is what a lot of documentation said, including this project’s own checklist until this book was written. That is why the gap outlived its cause: the copies installed during those five months are still on people’s machines, and the command that produced them now produces something else, so you cannot tell from what you typed. Run --outdated, or reinstall.
So: find out which one you have.
1 npx cc-safe-setup --outdated
It lists the hooks on your machine that differ from the current ones. And if you would rather not think about registries at all, installing from the repository is the one path that cannot lag, because there is no publishing step between the code and you — which is why it is the command the rest of this book uses:
1 npx github:yurukusa/cc-safe-setup
There is a general lesson under the specific one. A safety tool that is out of date is worse than no safety tool, because it moves you from “I am careful” to “I am covered”. Whatever you install, this or anything else, check what version you actually got, not what version exists.