# Test Permission Hooks

> Empirically test whether mr-sparkle's permission-trigger blocking hook earns its keep — run its blocked patterns with the hook on, then with mr-sparkle disabled, and see which patterns actually trigger a Claude Code permission prompt without it. Use when deciding whether to keep, narrow, or drop block_unneeded_permission_triggers.sh + bash_guidance.sh.

- Skill: `racurry/test-permission-hooks` (Agent Skill)
- Install (CLI): `npx skillmds@latest add racurry/test-permission-hooks`
- Raw SKILL.md: https://api.skillmd.com/api/skills/racurry/test-permission-hooks/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: racurry (https://skillmd.com/u/racurry)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/racurry/test-permission-hooks

---


# Test Permission-Trigger Hooks

mr-sparkle's `block_unneeded_permission_triggers.sh` (PreToolUse) blocks 7 Bash patterns that *it claims* trigger Claude Code permission prompts, so Claude rewrites instead of making the user re-approve. `bash_guidance.sh` (SessionStart) preaches the same list. The open question: **do those patterns actually trigger a prompt under the current permission setup?** If not, the hook is pure friction (it blocked ~6 legitimate read-only commands in one review session).

This is a **two-phase** test — the phase boundary is the user toggling the mr-sparkle plugin.

## The 7 patterns and their test commands

Each command is safe/no-op and isolates one pattern against an otherwise-allowed base command (so any Phase-2 prompt is due to the *pattern*, not the base command).

| #   | Pattern                         | Test command                                        |
| --- | ------------------------------- | --------------------------------------------------- |
| 1   | `$()` command substitution      | `echo "$(echo subst)"`                              |
| 2   | Backtick substitution           | `echo "` + backtick + `echo subst` + backtick + `"` |
| 3   | `echo/printf` with `---` string | `echo "--- divider ---"`                            |
| 4   | `git -C <path>`                 | `git -C . status --short`                           |
| 5   | Fully-qualified cwd path        | `ls <absolute path to this repo>/docs`              |
| 6   | Brace + quote (JSON)            | `echo '{"test":1}'`                                 |
| 7   | Output redirection              | `echo redirect-test > ./.tmp/perm-test.txt`         |

## Phase 1 — hooks ON (mr-sparkle enabled)

Run each of the 7 commands. **Expected:** `block_unneeded_permission_triggers.sh` intercepts each (exit 2) with a "…triggers a permission prompt" message — the command never runs. Record blocked vs. ran for each. This confirms the hook is active and what it catches.

## Phase 2 — hooks OFF

Ask the user to **disable the mr-sparkle plugin AND restart the session**, then run the same 7 commands again. Disabling the plugin does *not* unload its hooks from a running session — hooks are registered at session start, so without a restart the blocking hook keeps firing and Phase 2 is invalid (observed 2026-06-14). After the restart the blocking hook is gone, so the raw Claude Code permission system decides. For each command, record:

- **Prompted** — the user got a permission prompt (approve/deny), OR
- **Ran clean** — it executed with no prompt.

(The user watches for prompts — they're the one who'd be interrupted.)

## Decision rule

Per pattern:

- **Prompted without the hook** → the hook prevents a real interruption → **keep** it for that pattern.
- **Ran clean without the hook** → the hook was blocking a harmless command for no benefit → **drop/narrow** that pattern.

If *every* pattern runs clean without the hook, the whole prophylactic layer (`block_unneeded_permission_triggers.sh` + `bash_guidance.sh`) is friction-only → remove both. If *some* prompt, narrow the hook to just those.

## Report

Produce a table: pattern → Phase 1 (blocked?) → Phase 2 (prompted / clean) → verdict (keep / drop).

## Cleanup

- `rm ./.tmp/perm-test.txt` (created by pattern 7 if it ran in Phase 2).
- Tell the user to re-enable mr-sparkle (disabling it also turns off the dangerous-command and lint-on-write hooks).

