Pro-workflow safe-mode
Prevent destructive operations using Claude Code hooks. Three modes — cautious (warn on dangerous commands), lockdown (restrict edits to one directory), and clear (remove restrictions). Uses PreToolUse matchers for Bash, Edit, and Write.
git clone https://github.com/rohitg00/pro-workflow
T=$(mktemp -d) && git clone --depth=1 https://github.com/rohitg00/pro-workflow "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/safe-mode" ~/.claude/skills/rohitg00-pro-workflow-safe-mode && rm -rf "$T"
skills/safe-mode/SKILL.mdSafe Mode
Three levels of protection against destructive operations during AI coding sessions.
Note: These hooks are skill-scoped — they only activate when you invoke
. The global/safe-modehook in hooks.json provides always-on alerting for dangerous commands. Safe-mode adds opt-in blocking and directory restrictions on top of that.permission-request.js
Modes
Cautious Mode
/safe-mode cautious
Intercepts Bash commands before execution. Warns on dangerous patterns but does not block — the user decides.
Flagged patterns:
| Pattern | Risk |
|---|---|
/ | Recursive deletion |
/ | SQL data loss |
| SQL data destruction |
/ | Remote history rewrite |
| Local history loss |
| Untracked file deletion |
/ | Discard all changes |
| World-writable permissions |
/ | Piped remote execution |
/ | Disk-level operations |
| Fork bombs |
| Elevated deletion |
What happens:
WARNING: Destructive operation detected Command: rm -rf ./build Pattern: rm -rf (recursive forced deletion) Risk: Permanently deletes ./build and all contents Proceed? The command will execute as-is if you continue.
The warning goes to stderr. Claude sees it and asks for confirmation before proceeding.
Lockdown Mode
/safe-mode lockdown <path>
Restricts Edit and Write operations to a single directory tree. Prevents accidental changes to unrelated code.
How it works:
- Set the allowed path (absolute or relative to repo root)
- Every Edit/Write call checks if the target file is inside the allowed path
- Operations outside the path are blocked with an explanation
LOCKDOWN ACTIVE: Edits restricted to src/api/ Blocked: Edit to src/utils/helpers.ts Reason: File is outside the lockdown path (src/api/) To edit files outside the lockdown, run: /safe-mode clear
Use cases:
- Focused refactoring of one module without touching others
- Bug fix in a specific directory while tests run elsewhere
- Junior developer guardrail — scope the blast radius
- Code review session — only edit the files under review
Scope: Session-scoped. Resets when the session ends.
Clear
/safe-mode clear
Removes all restrictions for the current session. Both cautious warnings and lockdown restrictions are disabled.
SAFE MODE: All restrictions cleared for this session.
Implementation
PreToolUse Hook — Bash (Cautious Mode)
The hook inspects
tool_input.command before every Bash execution:
const DANGEROUS_PATTERNS = [ { pattern: /\brm\s+(-[a-zA-Z]*[rf][a-zA-Z]*\s|--recursive|--force)/, label: "rm with -rf flags" }, { pattern: /\bDROP\s+(TABLE|DATABASE|INDEX|VIEW)\b/i, label: "DROP SQL statement" }, { pattern: /\bTRUNCATE\b/i, label: "TRUNCATE SQL statement" }, { pattern: /\bgit\s+push\s+(-[a-zA-Z]*f|--force)/, label: "git force-push" }, { pattern: /\bgit\s+reset\s+--hard\b/, label: "git hard reset" }, { pattern: /\bgit\s+clean\s+-[a-zA-Z]*f/, label: "git clean -f" }, { pattern: /\bgit\s+(checkout|restore)\s+\./, label: "git discard all changes" }, { pattern: /\bchmod\s+777\b/, label: "chmod 777" }, { pattern: /\bcurl\b.*\|\s*(sh|bash)\b/, label: "piped remote execution" }, { pattern: /\bwget\b.*\|\s*(sh|bash)\b/, label: "piped remote execution" }, { pattern: /\bsudo\s+rm\b/, label: "elevated deletion" }, ];
Match found → emit warning to stderr. No match → pass through silently.
PreToolUse Hook — Edit/Write (Lockdown Mode)
The hook checks
tool_input.file_path against the lockdown path:
function isInsideLockdown(filePath, lockdownPath) { const resolved = fs.realpathSync(path.resolve(filePath)); const allowed = fs.realpathSync(path.resolve(lockdownPath)); const rel = path.relative(allowed, resolved); return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel)); }
Inside lockdown path → pass through. Outside → block with explanation.
State
Mode state lives in a session-scoped temp file (keyed by session ID to avoid cross-session leaks):
$TMPDIR/pro-workflow/safe-mode-<sessionId>.json { "mode": "lockdown", "lockdownPath": "/Users/dev/project/src/api", "sessionId": "abc123", "activatedAt": "2026-03-28T10:00:00Z" }
Cleared by
/safe-mode clear. State persists until explicitly cleared or the temp file is manually removed. Each session has its own state file.
Combining Modes
Cautious and lockdown can run simultaneously:
/safe-mode cautious /safe-mode lockdown src/api/
Now you get:
- Bash command warnings for destructive operations
- Edit/Write restrictions to
onlysrc/api/
Clear removes both.
When to Use
| Situation | Mode |
|---|---|
| Working on production-adjacent code | Cautious |
| Focused refactoring of one module | Lockdown |
| Unfamiliar codebase, feeling cautious | Cautious |
| Pair programming, limiting AI scope | Lockdown |
| Done with restrictions | Clear |
Anti-Patterns
- Leaving lockdown on when you need to edit tests (update the path or clear it)
- Using safe-mode as a substitute for git branches (branches protect history, safe-mode protects the session)
- Ignoring cautious warnings repeatedly (if you always proceed, turn it off — false confidence is worse)