npx skills add ...
npx skills add garrytan/gstack --skill freeze
Restrict file edits to a specific directory for the session. (gstack)
npx skills add garrytan/gstack --skill freeze
Blocks Edit, Write and NotebookEdit outside the allowed path. Use when debugging to prevent accidentally "fixing" unrelated code, or when you want to scope changes to one module. Use when asked to "freeze", "restrict edits", "only edit this folder", or "lock down edits".
Lock file edits to a specific directory. Any Edit, Write or NotebookEdit operation targeting a file outside the allowed path will be blocked (not just warned).
Ask the user which directory to restrict edits to. Use AskUserQuestion:
Once the user provides a directory path:
Set the user-selected boundary with the shared state writer. It resolves the physical absolute path and serializes replacement with investigation cleanup:
Only report success if the helper succeeds. On FREEZE_BUSY or unexpected state, preserve it and ask the user to inspect recovery after any active writer finishes; never write or delete the state file directly.
Tell the user: "Edits are now restricted to <path>/. Any Edit, Write or
NotebookEdit outside this directory will be blocked. To change the boundary, run /freeze
again. To remove it, run /unfreeze."
The hook reads file_path from the Edit/Write tool input JSON, or
notebook_path from a NotebookEdit (Jupyter notebook) call (shared
real-JSON extractor with /careful — one copy, sourced by both hooks), then
checks whether the path starts with the freeze directory. If not, it returns a
hookSpecificOutput payload with permissionDecision: "deny" to block the
operation (nested under hookSpecificOutput — Claude Code ignores a top-level
permissionDecision).
Polarity is fail-closed: a tool payload the hook cannot parse is DENIED, not
allowed — a boundary that fails open is not a boundary. A payload that parses
but has neither path field (a non-file tool) is allowed. A deny names the
tool, the path field, the boundary and /unfreeze. Symlinks are resolved
through their FINAL component, so an in-boundary symlink pointing outside the
boundary is checked against its target.
The freeze boundary persists until explicitly removed via the state file. The hook script reads it on every Edit/Write/NotebookEdit invocation. Boundaries containing spaces are supported.
/ on the freeze directory prevents /src from matching /src-oldsed or Set-Content can still modify files outside the boundary/unfreeze; ending or killing a conversation does not remove persisted statebash "$HOME/.claude/skills/gstack/freeze/bin/freeze-state.sh" set "<user-provided-path>"