Guard hooks and repo skills for Claude Code. Free, MIT.
Current release v0.1.12 (2026-10-01). Works with Claude Code 2.1.284 (evals 8 of 8; every version tried is in docs/compat.md). The npx installer added in 0.1.12 was tested on 2.1.286.
Claude Code is fast. It will also run rm -rf in the wrong directory, force-push over a teammate's branch, or write an API key straight into config.py if nothing stops it. This plugin blocks the commands and writes listed below (it is a guard, not a sandbox; the tamper-cases corpus shows what it catches and what it does not), and adds eight small skills for the boring parts of repo work.
Every call in the recording is the real hook fed the JSON Claude Code sends. Still image: docs/guard-bash.png.
The hooks have 79 unit tests in tests/test-hooks.sh. Each skill has a folder under evals/ with a fixture repo, a list of expected results, and the unedited transcript of a real Claude Code run. The last run was on Claude Code 2.1.284 on 2026-09-29: 8 of 8 cases passed their scripted checks. The pass counts per version are in docs/compat.md, and the run records and transcripts sit next to each case. You can read them before you install anything.
docs/compat.md lists every Claude Code version the evals ran on, with the pass counts, generated from the results in this repo. Since 2026-09-18 the runner also has a trigger mode (bash evals/run.sh --trigger): the same eight cases with a request that never names the skill, such as "Commit the staged changes.", so the table shows whether the descriptions fire on a plain request and not only whether the invocation path works (first run: 8/8 on 2.1.276). Since 0.1.3 the eval runner also writes a run record per case (evals/<skill>/record-<date>.json: exit code, every tool call, skill invocations, grader verdicts that need no model) and evals/cluster.py groups failed cases by their first mechanical mismatch, so a runner or grader fault shows up as one bucket instead of eight transcript reads. The skill texts call four external CLIs (gitleaks, trufflehog, pip-audit, gh); tests/test-cli-verbs.py checks every subcommand and flag they name against tests/cli-verbs.json, a snapshot read from the latest release of each CLI, so a renamed subcommand fails the test before it fails for you.
External test set: u/Far_Business4773 runs 52 evasion cases against a guard of this shape in lumis-skills/examples/tamper_cases.py (MIT). Cases 41 to 52 came out of the r/ClaudeCode thread with this project; case 42 (find -exec rm -rf) is the one fixed in 0.1.1. That file targets a guard with protected paths, which guard-bash does not have, so it is a reference, not part of this test suite. The shared corpus skillkeel/tamper-cases carries those 52 cases plus the destructive and git-config families from this suite (105 cases) with a runner for any hook; its RESULTS.md has one row per guard-bash version from 0.1.0 to 0.1.11.
This plugin does not overlap with the superpowers plugin. That one covers process (planning, TDD, debugging). This one covers guardrails and repo chores.
Recommended, inside Claude Code:
/plugin marketplace add skillkeel/skillkeel-starter
/plugin install skillkeel-starter@skillkeel
From a terminal, the same two steps in one command (needs Node 18 or later and Claude Code on PATH):
npx github:skillkeel/skillkeel-starter
It runs the two claude plugin commands above and prints them as it goes; npx github:skillkeel/skillkeel-starter uninstall removes the plugin again. The package is not on the npm registry yet, so the command fetches it from this repository.
Or clone the repo and start Claude Code with claude --plugin-dir ./skillkeel-starter.
To try it for one session without installing anything, load the release archive by URL (Claude Code fetches it at startup and forgets it when the session ends):
claude --plugin-url https://github.com/skillkeel/skillkeel-starter/archive/refs/tags/v0.1.12.zip
The eight skills alone, without the three hooks, also install through npx skills add skillkeel/skillkeel-starter -g -a claude-code; that route copies SKILL.md folders and never a plugin's hooks/hooks.json, so guard-bash and secret-scan are not part of it.
Nothing prints after the install. Two ways to see the plugin working:
In Claude Code, ask: what does Skillkeel say in this session? The answer comes from the session brief: "Skillkeel Starter active: guard-bash (blocks destructive shell), secret-scan (blocks credentials in writes)", followed by the eight skill names.
From a clone, feed the hook one command by hand:
echo '{"tool_input":{"command":"git push --force origin main"}}' | bash hooks/guard-bash
It prints skillkeel guard-bash: blocked (git push --force (use --force-with-lease)). Command: git push --force origin main and exits 2. The same line with --force-with-lease exits 0 and prints nothing.
SKILLKEEL_ALLOW_DANGEROUS=1 claude # guard-bash off
SKILLKEEL_ALLOW_SECRETS=1 claude # secret-scan off
bash tests/test-hooks.sh # 79 hook cases
python3 tests/test-cli-verbs.py # skill texts vs the CLI snapshot
python3 tests/test-evals-record.py # eval record and cluster tools
Skillkeel Kit adds a ten-chapter playbook, 24 more skills in six packs, five more guard hooks, five subagents, three checklists, and CLAUDE.md templates for eight stacks. You can read one playbook chapter and one skill's eval case with its unedited transcript first: https://skillkeel.com/kit/preview/. The Kit is sold on Gumroad, which shows the price; checkout adds any VAT or sales tax due in your country: https://skillkeel.gumroad.com/l/skillkeel-kit