Deletion tripwire
Skill srfinch17/peckworks-skills-laboratory/skills/deletion-tripwire
Use when a TRIPWIRE block message appears after a destructive command, when wiring the deletion guard on a new machine, or before any bulk deletion or cleanup — "remove junk", "clean up", "delete old files", "wipe this folder", clearing an old installation, or any recursive/force delete — so the enumerate-confirm-ledger protocol runs before anything leaves existence.From its SKILL.md
npx -y skills add srfinch17/peckworks-skills-laboratory --skill deletion-tripwireAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.7 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it
Deletion Tripwire
Overview
A mechanical guard, not a persona: a PreToolUse hook that intercepts destructive shell commands and refuses to run them until the enumerate → confirm → ledger → approve protocol has been followed. It exists because the catastrophic-deletion class strikes during casual, un-reviewed operations, when no review panel is in session — so the guard must fire EVERY time, without anyone remembering to ask.
The two lessons it enforces, burned in by a public field disaster (an agent cleaned up
Windows.old after answering "safe" when asked directly; leftover junctions inside it pointed at
the user's LIVE Documents/Pictures; the deletion followed the links and emptied the real folders):
- The blast radius of a deletion is everything REACHABLE from the target — links and junctions included — not the folder that was named.
- "Is it safe?" answered by prediction is the weapon. Safety requires enumeration (a dry run that lists what will actually be touched), never reasoning about what should be there.
This is the deletion-direction sibling of the push/publish/send boundary: two irreversible directions, leaving the machine (can't recall) and leaving existence (can't recover).
The protocol (what the block message demands)
-
ENUMERATE, don't predict. Dry-run the reachable set: count, total size, sample paths. Hunt links/junctions resolving OUTSIDE the target (PowerShell:
Get-ChildItem <target> -Recurse -Force -Attributes ReparsePoint; bash:find <target> -type l). Anything escaping the target is a hard stop to report.⚠️ The
-Attributes ReparsePointcheck FALSE-POSITIVES on cloud-sync folders. Dropbox, OneDrive and iCloud mark synced/placeholder files with the reparse-point bit, so inside those folders nearly every file trips this test. Observed 2026-07-27 in a Dropbox workspace: 25 of 36 files flagged, including plainCLAUDE.md— taken literally, the hard stop would block every deletion forever, which trains people to ignore the guard.Disambiguate before treating it as an escape: a real link populates
LinkTypeANDTarget; a cloud-sync placeholder leaves both EMPTY.Get-ChildItem <target> -Recurse -Force -Attributes ReparsePoint | Where-Object { $_.LinkType } | # genuine symlink/junction only Select-Object FullName, LinkType, TargetOnly entries surviving that filter are real escapes and a genuine hard stop. On bash,
find <target> -type ldoes not have this problem. -
CONFIRM. Show the user the manifest and anything outside-target; get an explicit yes. If the user never asked for a deletion, stop and surface instead of proceeding.
-
LEDGER. Write
<ledger>/<id>.mdBEFORE deleting: the user's verbatim ask, the command, the manifest summary, the confirmation. Evidence of what died, every time — experiment artifacts and receipts have been destroyed by innocent "clean up junk" passes before. -
RERUN the same command with trailing comment
# tripwire-approved:<id>. The hook allows it only while the ledger entry is fresh (15 minutes).
Prefer recoverable deletion (Recycle Bin / move-aside) over permanent when practical.
Setup (per machine, like the assumption-debt hooks)
install.sh symlinks this skill but deliberately does not touch settings.json. Wire the hook
manually as a PreToolUse entry matching Bash|PowerShell:
"PreToolUse": [{
"matcher": "Bash|PowerShell",
"hooks": [{ "type": "command",
"command": "python \"<repo>/skills/deletion-tripwire/hooks/guard_destructive.py\" \"<ledger-dir>\"" }]
}]
Ledger default: ~/.claude/deletion-ledger/. Self-check: python hooks/test_guard.py.
What it blocks / what it lets through
| Blocked (any shell) | Allowed |
|---|---|
rm with -r/--recursive (any flag combo) | single-file rm / Remove-Item |
Remove-Item -Recurse (+ aliases/abbreviations) | non-delete commands with -r flags (grep -r) |
| `rd | rmdir |
| `robocopy /MIR | /PURGE` |
git clean -f*, git reset --hard | |
find -delete / find -exec rm, shutil.rmtree | |
dd of=/dev/*, mkfs, format X: |
Common Mistakes
- Self-serving the approval token without doing the protocol. The token is not a bypass; writing the ledger entry REQUIRES the enumeration and the user's confirmation to already exist. Skipping to step 4 defeats the guard and re-arms the exact disaster it prevents.
- Predicting instead of enumerating. "That folder only contains X" is the sentence that destroyed a stranger's family photos. Run the dry-run; read the real list.
- Growing the ephemeral allowlist casually. Every generic name added (
build,dist,temp) widens the silent path. Expand only deliberately, for names that are unambiguous. - Treating a quiet tripwire as a broken one. It is pattern-based and stays silent on normal work by design (a guard that fires constantly gets tuned out). Known ceilings are named in the design spec; grow the pattern list with incidents, not speculation.
- Weakening the matcher because prose tripped it. The guard cannot tell running a
destructive command from talking about one — a commit message or echo that mentions the
patterns gets blocked (observed twice on day one, on this very skill's own commit messages).
That over-blocking is deliberate: quote-stripping would open a
bash -c "<destructive>"bypass. The durable workaround is to keep such prose OUT of the shell string — write commit messages to a file and usegit commit -F <file>, print docs from files instead of echoes.
Provenance
Born 2026-07-19, test-first (RED: 35-check assert suite watched failing on the missing module;
GREEN: all pass, including the end-to-end stdin/exit-code hook contract). Motivating cases:
(1) public r/ClaudeCode data-loss incident, 2026-07 — Windows.old cleanup followed junctions
into live Documents/Pictures after the agent answered "safe" from prediction; (2) same-day local
miniature in this lab — a routine "clean up any junk" pass deleted the artifacts that were a
skill's only test evidence ([[paladin-review-works]]). Design spec:
docs/specs/2026-07-19-deletion-tripwire-design.md. Field wins to be appended per the
Provenance win rule.
What ships with it: 2 files
11.5 KB alongside SKILL.md, 2 of them executable
hooks/
- guard_destructive.pyruns6.2 KB
- test_guard.pyruns5.2 KB