Files
gstack/careful/SKILL.md
T
Garry TanandClaude Fable 5 455c805125 fix(hooks): fail-closed freeze + shared extractor + careful HIGH tier
Freeze boundary hook had four verified bugs: the grep-first JSON extractor
truncated at escaped quotes and failed OPEN on unparseable payloads; the deny
JSON was printf-interpolated so a quote- or newline-bearing path silently
no-oped the block; the freeze path read stripped INTERNAL spaces (a boundary
like ~/My Project could never match); and the path resolver skipped the final
component, letting an in-boundary symlink write through to an out-of-boundary
target.

Fixes, structurally: one shared sourced helper (careful/bin/hook-extract.sh)
now owns JSON extraction and JSON-encoded decision envelopes for BOTH hooks --
the two-copy drift is how freeze kept a broken extractor after careful's was
fixed. Freeze is now deny-tier fail-closed (unparseable payload denies,
parsed-but-no-file_path still allows), trims only leading/trailing whitespace,
and resolves symlinks through the final path component.

Careful gains a HIGH tier (hard deny, simple commands only): recursive delete
of /, ~, or $HOME, and force-push to the repo's default branch. Compound
commands always fall through to the MEDIUM ask; --force-with-lease is never
HIGH. Documented as a best-effort advisory hard-stop, not a policy boundary.
Plus additive-only project patterns (~/.gstack/careful-patterns.txt +
per-project file): config can only ADD warn rules, never suppress a baseline
family.

test/hook-scripts.test.ts: 89 tests incl. malformed-payload deny, parseable
deny JSON for hostile paths, space-bearing boundaries, symlink escape, HIGH
tier splits, additive invariant, invalid-regex resilience.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 23:12:19 -07:00

3.8 KiB

name, version, description, triggers, allowed-tools, hooks
name version description triggers allowed-tools hooks
careful 0.1.0 Safety guardrails for destructive commands. (gstack)
be careful
warn before destructive
safety mode
Bash
Read
PreToolUse
matcher hooks
Bash
type command statusMessage
command bash $HOME/.claude/skills/gstack/careful/bin/check-careful.sh Checking for destructive commands...

When to invoke this skill

Warns before rm -rf, DROP TABLE, force-push, git reset --hard, kubectl delete, and similar destructive operations. User can override each warning. Use when touching prod, debugging live systems, or working in a shared environment. Use when asked to "be careful", "safety mode", "prod mode", or "careful mode".

/careful — Destructive Command Guardrails

Safety mode is now active. Every bash command will be checked for destructive patterns before running. If a destructive command is detected, you'll be warned and can choose to proceed or cancel.

mkdir -p ~/.gstack/analytics
echo '{"skill":"careful","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true

What's protected

Pattern Example Risk
rm -rf / rm -r / rm --recursive rm -rf /var/data Recursive delete
DROP TABLE / DROP DATABASE DROP TABLE users; Data loss
TRUNCATE TRUNCATE orders; Data loss
git push --force / -f git push -f origin main History rewrite
git reset --hard git reset --hard HEAD~3 Uncommitted work loss
git checkout . / git restore . git checkout . Uncommitted work loss
kubectl delete kubectl delete pod Production impact
docker rm -f / docker system prune docker system prune -a Container/image loss

Safe exceptions

These patterns are allowed without warning:

  • rm -rf node_modules / .next / dist / __pycache__ / .cache / build / .turbo / coverage

How it works

The hook reads the command from the tool input JSON, checks it against the patterns above, and returns a hookSpecificOutput payload with permissionDecision: "ask" and a warning reason if a match is found (the decision must be nested under hookSpecificOutput — Claude Code ignores a top-level permissionDecision). You can always override a MEDIUM warning and proceed.

HIGH tier (hard deny)

A tiny set of catastrophic commands is denied outright while /careful is active, not just warned:

  • rm -r/-R targeting exactly /, ~, or $HOME
  • git push --force / -f to the repo's default branch

HIGH only fires on SIMPLE commands (no ;, &&, ||, |, newline) — string matching cannot resolve what a compound command does, so compound shapes fall through to the ordinary MEDIUM ask. --force-with-lease is deliberately not matched (it's the safe force variant). This is a best-effort advisory hard-stop, not a policy boundary: /careful is opt-in and session-scoped, so the escape hatch is ending the /careful session.

Project patterns (additive only)

Add your own warn rules — one POSIX ERE per line, # comments allowed — in:

  • ~/.gstack/careful-patterns.txt (all projects)
  • ~/.gstack/projects/<slug>/careful-patterns.txt (this project)

Matching lines warn with [careful] Project rule matched: <pattern>. Config can only ADD rules: the files are consulted after the built-in families, so no file content can suppress or weaken a baseline warning. Invalid regex lines are skipped.

To deactivate, end the conversation or start a new one. Hooks are session-scoped.