
Careful
- 217 installs
- 126k repo stars
- Updated July 15, 2026
- garrytan/gstack
Apply a conservative change discipline—smaller diffs, explicit verification, and risk callouts—when editing production-critical paths or unfamiliar code.
About
Careful is a gstack behavioral skill that makes Claude Code proceed cautiously: narrower changes, clearer assumptions, and stronger pre-merge verification. It helps teams touching legacy SaaS, APIs, or agent tooling where a rushed patch can cause outages or subtle regressions.
- Encourages smaller diffs
- Surfaces risky edits
- Demands verification steps
- Reduces silent regressions
- Works across stacks
Careful by the numbers
- 217 all-time installs (skills.sh)
- Ranked #329 of 1,352 Code Review & Quality skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/garrytan/gstack --skill carefulAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 217 |
|---|---|
| repo stars | ★ 126k |
| Last updated | July 15, 2026 |
| Repository | garrytan/gstack ↗ |
What it does
Apply a conservative change discipline—smaller diffs, explicit verification, and risk callouts—when editing production-critical paths or unfamiliar code.
Files
<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly --> <!-- Regenerate: bun run gen:skill-docs -->
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 || trueWhat'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 permissionDecision: "ask" with a warning message if a match is found. You can always override the warning and proceed.
To deactivate, end the conversation or start a new one. Hooks are session-scoped.
#!/usr/bin/env bash
# check-careful.sh — PreToolUse hook for /careful skill
# Reads JSON from stdin, checks Bash command for destructive patterns.
# Returns {"permissionDecision":"ask","message":"..."} to warn, or {} to allow.
set -euo pipefail
# Read stdin (JSON with tool_input)
INPUT=$(cat)
# Extract the "command" field value from tool_input
# Try grep/sed first (handles 99% of cases), fall back to Python for escaped quotes
CMD=$(printf '%s' "$INPUT" | grep -o '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*:[[:space:]]*"//;s/"$//' || true)
# Python fallback if grep returned empty (e.g., escaped quotes in command)
if [ -z "$CMD" ]; then
CMD=$(printf '%s' "$INPUT" | python3 -c 'import sys,json; print(json.loads(sys.stdin.read()).get("tool_input",{}).get("command",""))' 2>/dev/null || true)
fi
# If we still couldn't extract a command, allow
if [ -z "$CMD" ]; then
echo '{}'
exit 0
fi
# Normalize: lowercase for case-insensitive SQL matching
CMD_LOWER=$(printf '%s' "$CMD" | tr '[:upper:]' '[:lower:]')
# --- Check for safe exceptions (rm -rf of build artifacts) ---
if printf '%s' "$CMD" | grep -qE 'rm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+|--recursive\s+)' 2>/dev/null; then
SAFE_ONLY=true
RM_ARGS=$(printf '%s' "$CMD" | sed -E 's/.*rm[[:space:]]+(-[a-zA-Z]+[[:space:]]+)*//;s/--recursive[[:space:]]*//')
for target in $RM_ARGS; do
case "$target" in
*/node_modules|node_modules|*/\.next|\.next|*/dist|dist|*/__pycache__|__pycache__|*/\.cache|\.cache|*/build|build|*/\.turbo|\.turbo|*/coverage|coverage)
;; # safe target
-*)
;; # flag, skip
*)
SAFE_ONLY=false
break
;;
esac
done
if [ "$SAFE_ONLY" = true ]; then
echo '{}'
exit 0
fi
fi
# --- Destructive pattern checks ---
WARN=""
PATTERN=""
# rm -rf / rm -r / rm --recursive
if printf '%s' "$CMD" | grep -qE 'rm\s+(-[a-zA-Z]*r|--recursive)' 2>/dev/null; then
WARN="Destructive: recursive delete (rm -r). This permanently removes files."
PATTERN="rm_recursive"
fi
# DROP TABLE / DROP DATABASE
if [ -z "$WARN" ] && printf '%s' "$CMD_LOWER" | grep -qE 'drop\s+(table|database)' 2>/dev/null; then
WARN="Destructive: SQL DROP detected. This permanently deletes database objects."
PATTERN="drop_table"
fi
# TRUNCATE
if [ -z "$WARN" ] && printf '%s' "$CMD_LOWER" | grep -qE '\btruncate\b' 2>/dev/null; then
WARN="Destructive: SQL TRUNCATE detected. This deletes all rows from a table."
PATTERN="truncate"
fi
# git push --force / git push -f
if [ -z "$WARN" ] && printf '%s' "$CMD" | grep -qE 'git\s+push\s+.*(-f\b|--force)' 2>/dev/null; then
WARN="Destructive: git force-push rewrites remote history. Other contributors may lose work."
PATTERN="git_force_push"
fi
# git reset --hard
if [ -z "$WARN" ] && printf '%s' "$CMD" | grep -qE 'git\s+reset\s+--hard' 2>/dev/null; then
WARN="Destructive: git reset --hard discards all uncommitted changes."
PATTERN="git_reset_hard"
fi
# git checkout . / git restore .
if [ -z "$WARN" ] && printf '%s' "$CMD" | grep -qE 'git\s+(checkout|restore)\s+\.' 2>/dev/null; then
WARN="Destructive: discards all uncommitted changes in the working tree."
PATTERN="git_discard"
fi
# kubectl delete
if [ -z "$WARN" ] && printf '%s' "$CMD" | grep -qE 'kubectl\s+delete' 2>/dev/null; then
WARN="Destructive: kubectl delete removes Kubernetes resources. May impact production."
PATTERN="kubectl_delete"
fi
# docker rm -f / docker system prune
if [ -z "$WARN" ] && printf '%s' "$CMD" | grep -qE 'docker\s+(rm\s+-f|system\s+prune)' 2>/dev/null; then
WARN="Destructive: Docker force-remove or prune. May delete running containers or cached images."
PATTERN="docker_destructive"
fi
# --- Output ---
if [ -n "$WARN" ]; then
# Log hook fire event (pattern name only, never command content)
mkdir -p ~/.gstack/analytics 2>/dev/null || true
echo '{"event":"hook_fire","skill":"careful","pattern":"'"$PATTERN"'","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
WARN_ESCAPED=$(printf '%s' "$WARN" | sed 's/"/\\"/g')
printf '{"permissionDecision":"ask","message":"[careful] %s"}\n' "$WARN_ESCAPED"
else
echo '{}'
fi
---
name: careful
version: 0.1.0
description: |
Safety guardrails for destructive commands. 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". (gstack)
triggers:
- be careful
- warn before destructive
- safety mode
allowed-tools:
- Bash
- Read
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "bash $HOME/.claude/skills/gstack/careful/bin/check-careful.sh"
statusMessage: "Checking for destructive commands..."
sensitive: true
---
# /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.
```bash
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 `permissionDecision: "ask"` with a warning message
if a match is found. You can always override the warning and proceed.
To deactivate, end the conversation or start a new one. Hooks are session-scoped.