From permitcrab
Test harness invoked by permitcrab:setup to verify that a candidate permissions block produces the intended approve / passthrough / deny outcomes. Replays each case in test-plan.json against the same resolver script that the live PermissionRequest hook runs, passing this skill's own directory as the resolver's explicit skill-dir argument. Not for general use; setup writes the test plan and permissions block into this skill before invoking it.
How this skill is triggered — by the user, by Claude, or both
Slash command
/permitcrab:setup-testThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill is a controlled test harness. The `permitcrab:setup` skill writes:
This skill is a controlled test harness. The permitcrab:setup skill writes:
${CLAUDE_PLUGIN_ROOT}/skills/setup-test/test-plan.json.Then it invokes this skill. When invoked, this skill executes each test case in the plan and reports whether the observed outcome matched the expectation.
Run the runner:
${CLAUDE_PLUGIN_ROOT}/skills/setup-test/scripts/run-test-plan.js
The runner reads test-plan.json, replays each case by piping a synthetic tool-use JSON payload to the resolver script (the same script that runs from the PermissionRequest hook), passing this skill's own directory as the resolver's explicit skill-dir argument so the resolver loads the candidate permissions injected above. The argument bypasses transcript lookup, which is how the live hook normally derives the active skill. It prints a structured report to stdout.
After printing the report, the runner writes a machine-readable copy to ${CLAUDE_PLUGIN_ROOT}/skills/setup-test/last-report.json for setup to consume.
Do not call the restore script from here. setup calls setup-test-restore.js after reading the report so that, if a run is interrupted, the next invocation of setup still has a known starting state to clean up.
The runner invokes the resolver directly with the same arguments and stdin shape the PermissionRequest hook uses. It does not exercise the PreToolUse auto-deny-dangerous.js hook, so dangerous-command denials produced by that hook are not covered here. Use permitcrab:audit and permitcrab:doctor to cover hook-wiring concerns.
The runner prints one line per case:
case <id>: tool=<Tool> expected=<approve|deny|passthrough> observed=<...> -> PASS|FAIL
Followed by a summary line:
setup-test: N passed, M failed, K untestable
last-report.json has the shape {passed, failed, untestable, cases: [{id, tool, expected, observed, outcome, reason?}]}. Exit code is 0 if every testable case passed, non-zero otherwise. Untestable cases (e.g., bash patterns with no literal anchor) count as warnings, not failures.
Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub brennacodes/utilitry --plugin permitcrab