For agents, on top of README.md, which they read first.
Notes for agents
Every folder has its own CLAUDE.md with the invariants of the code in it: the
questions and verdicts in crates/jevhooks-daemon/src/, the read-only filter in
crates/jevhooks-mod/src/, the mod's memory, $ calls and hook layering in
plugin/hooks/, running the plugin tests in plugin/tests/. What follows holds
everywhere.
Never make Jev's absence block anything. No key, a throttle, a timeout, an
unreachable daemon: all are Pass. The mod has its own 2.5 s limit on the daemon for
the same reason.
Run just mod after any change to crates/jevhooks-mod or jevhooks-events, and
just daemon after any change to the daemon. The plugin loads
plugin/hooks/jevhooks.js (wasm2js output, never edited by hand) and starts
plugin/bin/jevhooks (a copy, not a link into target/). A session started after a
rebuild replaces the running daemon by itself; to do it by hand,
plugin/bin/jevhooks stop and start a session, or op-env-run -- plugin/bin/jevhooks serve.
Never remove the [patch.crates-io] rmcp entry because "3.5.0 is the latest". rmcp
3.5.0 refuses every request after Claude Code's server/discover then initialize
opening, so the MCP server connects and lists no tools. The fix is on the private
deizel/rust-sdk fork (commit 1c69053, on top of the rmcp-v3.5.0 tag). Before
dropping it, confirm in a session that the status tool is listed.
Assume nothing about the machine. This is a plugin for anyone's machine, not for
the one it was written on: no host-specific helpers, no WSL, no systemd, no particular
host in the daemon or the mod. Where a figure is only knowable on some systems
(available memory is MemAvailable on Linux and nothing built in elsewhere), the
default is the generic one, a config key lets the user supply a command, and the
absence of both is a Pass, never a guess. A configured command is the only source
once set: do not fall back to the built-in figure when it fails, because the user set
it to say the built-in figure is wrong there.
The key is never written anywhere. Not in .mcp.json's env, an .envrc or a
file, and never printed; status says whether it arrived.
Build in the devshell, and check memory first. Crates' build scripts link with a
host cc even when the target is wasm32; mkShell supplies it. A release build of
the daemon uses several gigabytes: free -m before starting one.
The docs are a guide, chapter by chapter. Every folder with tracked files has a
README that is a chapter (# Chapter N: <name>, <subtitle>, an opening that teaches,
> **Aside.** detours, a > **Try it.**, then "For the people who maintain it" with
a file map) and a CLAUDE.md beside it starting @README.md. The last line of each
README is ← Previous: … · Up: … · Next: … →, and the chain is a depth-first
preorder of the folders in the order the root's table lists them; the lmjtfy site's
README viewer follows those lines. A new folder gets its chapter, and the chapters
after it are renumbered. Playful, never at the expense of a true fact: read the code
before describing it, and keep every relative link pointing at a tracked path.
The README must not claim a build works for outsiders. The rmcp patch is fetched
over SSH from a private repository, and Cargo resolves the whole workspace before
building any member, so without access every cargo command fails (measured
2026-10-02 with a fresh CARGO_HOME and SSH disabled). claude plugin test plugin
needs no Cargo and is the thing an outside reader can run.