Compile your CLAUDE.md rules to real Claude Code hooks.
CLAUDE.md is suggestions. Claude reads "NEVER commit .env", agrees, then
silently writes git add .env on turn 47 anyway (issues
#19635,
#7777,
#50235).
Anthropic's own docs already point at the fix — PreToolUse hooks. Nobody
writes them by hand because they drift the moment the rules in CLAUDE.md
change. wisp-rulecast reads the markdown, parses the prohibitions, and
emits the hooks that actually stop the tool call before it runs.
Three minutes after you add NEVER commit `.env` to your CLAUDE.md,
the next git add .env is denied with the reason pointing back at the
source line. No retraining, no follow-up prompt, no audit trail you have
to dig through git log for — just a hard stop the model can't talk its
way past.
|
## Security
- NEVER commit `.env`
- NEVER commit `*.pem`
- DO NOT commit `id_rsa`
## Filesystem
- NEVER edit files in `/vendor`
## Workflow
- ALWAYS run `npm test`
before `git commit`
- ALWAYS save tests to `/tests`
## Soft (flagged as vague)
- Prefer small functions
- Be cautious when refactoring
- NEVER commit secrets |
|
Left: behavioral guidance. Right: mechanical enforcement. compile --explain tells you exactly which soft rules got dropped and how to rephrase them.
|
The model receives the reason verbatim and stops trying. No file is staged, no retry, no half-applied change. |
|
/plugin marketplace add Samuel0101010/wisp-rulecast
/plugin install wisp-rulecast@wisp
That's it. The plugin ships its own Node bundle, the skill, and the runtime dispatcher source. No npm install, no global CLI. While the plugin is enabled, the wisp-rulecast binary is on PATH and the /wisp-rulecast:compile skill is registered. The skill auto-triggers whenever you edit CLAUDE.md — no manual recompile.
Permission denied (publickey)on/plugin marketplace add. Claude Code clones marketplaces via SSH by default, even for public repos. If you don't have a GitHub SSH key set up, run this once and retry:PowerShell needs the literal space between the two quoted arguments.git config --global "url.https://github.com/.insteadOf" "git@github.com:"
- Re-installing after an upstream fix. Claude Code caches the marketplace manifest. If you installed once, hit an error, and a fix was pushed, do
/plugin marketplace remove wispand then/plugin marketplace add Samuel0101010/wisp-rulecastagain — otherwise you re-install from the cached (broken) manifest.
git clone https://github.com/Samuel0101010/wisp-rulecast.git
cd wisp-rulecast
npm install && npm run build
node dist/index.js install # copies skill + command into your project
node dist/index.js compilewisp-rulecast compile [--dry-run] [--explain]— or say "compile the rules" / "enforce CLAUDE.md" in chat and the
skill triggers it for you, or type /wisp-rulecast:compile (namespaced).
| Command | What it does |
|---|---|
install |
Clone-and-run bootstrap only — copies skill + command into the project, then compiles. Plugin users skip this; the plugin already deploys them. |
compile |
Parse CLAUDE.md, write rules.json + dispatcher + merge hooks into settings.json |
compile --dry-run |
Compute everything, write nothing |
compile --explain |
Print every vague rule with a refactor suggestion |
verify |
Spawn the dispatcher with a synthetic violating input per rule, assert it denies |
audit [--since 24h] |
Markdown summary of blocked violations from the JSON-lines log |
reset |
Remove every wisp-rulecast hook from settings.json (user hooks preserved) |
| Form | Becomes |
|---|---|
NEVER commit `<pattern>` |
PreToolUse on Bash matching git staging / commit / push |
NEVER edit `<path>` |
PreToolUse on Edit|Write|MultiEdit with path check |
NEVER run `<command>` |
PreToolUse on Bash with command match |
ALWAYS `<X>` before `<Y>` |
PostToolUse marker + PreToolUse deny if marker missing |
ALWAYS save `<X>` to `<path>` |
PreToolUse allowlist for Edit|Write|MultiEdit |
NEVER ≡ DO NOT ≡ MUST NOT ≡ NO. Wrap your patterns in backticks — it's the single highest-leverage thing you can do to make wisp-rulecast confident about your intent. Full grammar: docs/rule-grammar.md.
CLAUDE.md
│ remark-parse → AST → paragraph candidates
▼
parser/ regex classifier
│ → EnforceableRule | VagueRule
▼
compiler/templates/ one of five templates per rule
│ → CompiledHooks
▼
settings-merger.ts idempotent: drops previous wisp-rulecast
│ groups, preserves user hooks
▼
.claude/settings.json .claude/wisp-rulecast/rules.json
.claude/wisp-rulecast/dispatch.mjs
│
▼ Claude Code spawns dispatch.mjs per PreToolUse call (<50 ms target)
│
▼ Exit 0 + { permissionDecision: "deny", reason: "…" }
│
▼ .claude/wisp-rulecast.log ← every block as one JSON line
No LLM is invoked at compile time. Pure regex classifier — predictable,
debuggable, fast. Generated hook shapes documented in
docs/hook-templates.md; the hooks-API reference
notes are in docs/notes/hooks-api.md.
You can. But CLAUDE.md and settings.json drift the second you edit one
of them. The rules and the enforcement live in two files in two languages
written for two audiences; one slips, the other doesn't notice. wisp-rulecast
removes the second file from your workflow — you edit the English version,
re-run compile, the JSON regenerates with the same rule ids and the same
behavior. Run it on save, run it in a pre-commit hook, run it as the
skill auto-trigger — same result.
Three structural guarantees that come for free:
- Idempotent merge. A hook group is "ours" iff every hook in it routes through the dispatcher. Recompiling drops only ours, leaves your hand-written hooks alone, and produces byte-identical output on a no-op run.
- Self-check.
verifyspawns the dispatcher per rule with a synthetic violating input and asserts deny. If your generated hooks can't fire, CI catches it before the user does. - Failure-safe. Missing or malformed registry → dispatcher allows. The tool never blocks your work because of its own bugs.
wisp-rulecast is the guardrail layer of the agent lifecycle. Same author,
complementary tools:
| Stage | Tool |
|---|---|
| Plan + spawn + watch multi-agent runs | wisp-orchestrator |
| Stop bad tool calls before they run | wisp-rulecast (this repo) |
| Review + approve + merge per-agent worktrees | wisp-agentdiff |
v0.1 ships the parser, five hook templates, idempotent merger, runtime
dispatcher, audit log, self-check, and 53 tests including an end-to-end
dispatcher-spawn integration test. Distributed as a Claude Code plugin
(repo doubles as a single-plugin marketplace via .claude-plugin/marketplace.json).
Build roadmap and open questions live in CLAUDE.md;
v1.0 launch gate in docs/launch-checklist.md.
Issues and PRs welcome.
npm install
npm run verify # lint + typecheck + test + build
npm run test:watch # iterating on a single module
npm run dev # tsup watch buildCI matrix: Linux / macOS / Windows × Node 20 + 22.
Karpathy's CLAUDE.md philosophy — but makes the rules actually enforced.
MIT — see LICENSE.


{ "hooks": { "PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "node", "args": [ "${CLAUDE_PROJECT_DIR}/.claude/wisp-rulecast/dispatch.mjs", "--rule", "never-commit-51678eab" ], "timeout": 5, "if": "Bash(git commit *|git add *|git push *)" }] }] // …one entry per enforceable rule } }