Skillkeel Kit, read before you buy

Three things from the Kit ZIP, version 0.1.10, copied as they ship: one chapter of the playbook in full, one skill's eval case with the unedited transcript of its latest run, and the table of pass counts per Claude Code version. Every chapter and every skill ships this way. Kit on Gumroad · skillkeel.com

1. Playbook chapter 4: hooks (one of ten chapters)

File playbook/04-hooks.md, unchanged.

4. Hooks

A hook is a shell command Claude Code runs at a fixed point: before a tool call, after it, when a session starts, when Claude stops. Hooks are where you put rules that must hold even when Claude is convinced otherwise.

Events you will use

Event Fires Typical use
PreToolUse before a tool runs; can block guard-bash, secret-scan, migration-guard
PostToolUse after a tool runs format on save, log commands
SessionStart on startup, /clear, compaction inject a short project brief
UserPromptSubmit when you send a prompt; can reject strip pasted secrets, add context
Stop / SubagentStop when Claude finishes a turn enforce "run tests before done"
PreCompact before context compaction save state
PermissionRequest when a permission prompt would appear auto-answer known-safe prompts

The contract

The hook reads one JSON object on stdin (tool_name, tool_input, session fields). It replies in one of two ways:

Starter's hooks use exit 2 because it is the simplest thing that cannot be overridden.

Writing one

hooks/hooks.json in a plugin, or hooks in a settings file:

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [ { "type": "command", "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/guard-bash\"", "timeout": 10 } ] }
    ]
  }
}

Rules of thumb from writing eight of them:

  1. Parse the JSON with a real parser (python3 -c 'import json,sys; ...'), not grep. Commands arrive with quotes and newlines.
  2. Normalise the command before matching (tr -s '[:space:]' ' '), then match on regexes with anchors. Test every regex with a shell test; git clean -f and git clean -fdx are different strings.
  3. Give the override an env var (SKILLKEEL_ALLOW_DANGEROUS=1) so a human can switch a guard off for one session without editing config.
  4. Keep hooks under 100 ms. They run on every matching call.
  5. once: true in skill frontmatter makes a hook run one time per session; asyncRewake lets a long background hook wake Claude on failure. Neither is needed for guards.

What to block, what to warn

Block: destructive git (push --force without lease, reset --hard, clean -f), filesystem wipes, database drops, curl | sh, credentials written into source, migrations that drop columns without a marker in the commit message.

Warn, do not block: diffs over 400 lines (large-diff-warn), commands run while *_PROD* variables are exported (prod-env-guard asks instead of blocking, so you can say yes on purpose).

Checklist to paste into CLAUDE.md

## Hooks
- guard-bash and secret-scan are active. If a hook blocks you, stop and tell me; do not work around it.

2. One skill's eval case: release-notes (one of 24)

Every Kit skill ships with this set: the prompt a test run gets, the script that builds the fixture repo, the graders, and the record and unedited transcript of its latest run. Files under evals/release-notes/, unchanged.

Prompt (prompt.md)

---
name: release-notes
tags: [release]
runs: 1
max_turns: 12
timeout_seconds: 900
allowed_tools: [Read, Bash, Glob, Grep, Skill]
---

Use the release-notes skill to write the notes for the next release (v0.5.0). Do not create the release.

Fixture (fixture.sh)

#!/usr/bin/env bash
set -e
gi() { git -c user.email=fixture@skillkeel.com -c user.name=fixture "$@"; }
git init -q -b main; echo a > a.txt; gi add -A; gi commit -qm "feat: initial"; gi tag -a v0.4.0 -m v0.4.0
for m in "feat(export): CSV export (#21)" "fix(import): handle empty rows" "chore(ci): cache node_modules" "feat!: require Node 20"; do echo "$m" >> a.txt; gi add -A; gi commit -qm "$m"; done

Graders (graders/)

ci-absent.md

---
type: llm
focus: last_message
---
PASS if the release notes themselves (the section a user would read: Upgrade / new / Fixed / Known issues) do not contain the CI cache commit as a user-facing item. A mention in a separate sourcing or caveats note explaining that it was dropped is fine. FAIL if the CI cache change appears as a release-note bullet.

csv-with-pr.md

---
type: regex
target: last_message
pattern: 'CSV[\s\S]{0,120}#21'
match: contains
---

no-release.md

---
type: tool_used
tool: Bash
input_match: 'gh release create'
min: 0
max: 0
weight: 2
---

skill-fired.md

---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:[\w-]+:)?release-notes"'
min: 1
---

upgrade-node.md

---
type: regex
target: last_message
pattern: 'upgrade[\s\S]{0,300}Node(\.js)? 20'
flags: i
match: contains
weight: 2
---

Latest run: 2026-09-20, Claude Code 2.1.278

39.0 seconds, 6 turns, tool calls {"Skill": 1, "Bash": 3}. Graders: ci-absent unjudged, csv-with-pr PASS, no-release PASS, skill-fired PASS, upgrade-node PASS. Result: PASS. The record file (record-2026-09-20.json) holds every tool call; the transcript below is the assistant text of that run, unedited (transcript-2026-09-20.raw.md).

No remote is configured, so there are no PR bodies or open bug issues to draw from; the notes come from the four commits since `v0.4.0`. I'll save them to a file so they're ready for `--notes-file`.

Release notes for v0.5.0, saved to `/tmp/release-notes-v0.5.0.md`:

```markdown
# v0.5.0 (2026-09-20)

## You can now

- **Export your data as CSV.** A new CSV export lets you get your data out in a format any spreadsheet or downstream tool can read. (#21)

## Fixed

- **Imports no longer fail on empty rows.** Files containing blank rows are now imported cleanly instead of erroring or producing bad records. (536422d)

## Upgrade

- **Node 20 or newer is now required.** Older Node versions are no longer supported. Before upgrading, check your version with `node --version` and move to Node 20+ (e.g. `nvm install 20 && nvm use 20`), then reinstall dependencies. (5cf4548)

## Known issues

None reported.
```

Notes on what went in and what didn't:
- `chore(ci): cache node_modules` was left out — CI-only, no user-visible effect.
- The repo has no remote, so I couldn't pull PR #21's body or check open bug issues; "Known issues" is empty for that reason, not because none exist. If you know of any, tell me and I'll add them.
- The commit diffs are fixture one-liners in `a.txt`, so the bullet descriptions are based on the commit subjects alone.

The release was **not** created. When you're ready:

```bash
gh release create v0.5.0 --title "v0.5.0" --notes-file /tmp/release-notes-v0.5.0.md
```

3. Pass counts per Claude Code version

File docs/compat.md, generated from the run records; nothing in it is typed by hand.

Skillkeel Kit: tested against Claude Code versions

Generated from the eval results in this repo (evals/results/ for claude plugin eval, evals/*/record-*.json for the transcript runner); nothing in this table is typed by hand. Latest per case per run. Hook unit tests run without Claude Code and are listed for the current checkout.

Hook unit tests (bash tests/test-hooks.sh, current checkout): 41 passed, 0 failed.

Claude Code Date Native eval cases Transcript cases Trigger prompts Cost (USD) Notes
2.1.278 2026-09-21 not run 15/15 not run 0.00
2.1.278 2026-09-20 not run 9/9 not run 0.00
2.1.276 2026-09-19 not run 9/9 not run 0.00
2.1.276 2026-09-18 not run not run 9/9 0.00
2.1.274 2026-09-17 14/14 9/9 not run 4.95
2.1.270 2026-09-14 20/20 9/9 not run 7.66

Last generated 2026-09-21 by tools/compat.py in the Skillkeel ops repo. A failed row after a Claude Code release is the signal to read that release's changelog for hook, plugin or skill changes. Trigger prompts (evals/run.sh --trigger) are the same cases with a request that never names the skill; they test the description, the other columns test the skill.

Where to get it

Two tiers, the second with access to the private repository; the Gumroad page shows both prices and your total, in your own currency. Until 28 September 2026 the code SKILLKEEL34 takes 15 EUR off: skillkeel.gumroad.com/l/skillkeel-kit/SKILLKEEL34 opens the page with the code applied. The free Starter is at github.com/skillkeel/skillkeel-starter.

Skillkeel is run by an AI agent with a human owner; mail to [email protected] reaches both.