What a trap is, and why your agent should read them before you do
Youcef Zemmar · 2026-09-08
A trap is a breakage that is real, specific to a version range, and not in the documentation. Not a bug report, which is a request for someone else to act. Not a gotcha post, which is usually one person's afternoon written up without a version number. A trap is the thing you would tell a colleague who is about to install the same package, in the two sentences you would actually use.
Here is one from the corpus:
node: better-auth
version_range: ">=1.0.0"
severity: major
symptom: Role or plan changes do not reach the session until the cookie cache expires (default 5 minutes).
fix_md: >-
Disable session.cookieCache for role-gated apps, or call auth.api.getSession with
disableCookieCache: true on the routes that check roles, and invalidate the session
on role change.Five fields, plus an optional evidence_url this one does not have. The range decides who sees it. The severity decides where it sorts, since blockers go first and a compact response has a budget. The symptom is written as what you observe, not what you concluded, because the person reading it has the observation and not yet the conclusion. The fix has to be paste-able. If it needs a paragraph of context to be useful, it is not a trap yet, it is a note toward one.
That last constraint does more work than it looks like it does. Plenty of things that feel like traps fail it. "Be careful with the caching layer" is not a trap. "The default five minute cookie cache means a role change is invisible until it expires, so disable it on role-gated routes" is.
When the hooks fire
Tools that wait to be asked get asked when the agent already suspects something is wrong. By then it has usually written the code.
So the Claude Code plugin registers PreToolUse hooks on two tools. On Bash it fires when the command about to run is a package install and reads the name and any pinned version off the command line. On Edit, Write and MultiEdit it fires when the file about to change is a dependency manifest and reads the names out of the new content. Either way it makes one request:
GET https://mcp.wellworn.dev/api/traps?library=better-auth&version=1.7.3The response is plain text. If there are traps for that range the hook prints them into the transcript before the command or the edit goes through. If the package is not in the corpus the endpoint returns 204 No Content and the hook prints nothing at all, which is the behaviour that decides whether people keep a hook installed. A tool that speaks when it has nothing to say gets uninstalled in a week.
The sequencing is the whole point. The agent reads the cookie cache trap while it is deciding how to check roles, not after it has shipped a role gate that is wrong for five minutes at a time. It costs one HTTP request against the same limit as a tool call, and it works with no key.
What happens to one you submit
You lose an hour to something. That is the moment you have the version, the symptom and the fix in your head, and it is also the moment you are least willing to open a browser and fill in a form. So the submission is a tool call from inside the session you are already in:
{
"library": "better-auth",
"version": "1.7.3",
"symptom": "Role changes do not reach the session until the cookie cache expires.",
"fix": "Disable session.cookieCache for role-gated apps, or pass disableCookieCache on routes that check roles.",
"evidence_url": "https://github.com/better-auth/better-auth/issues/1234"
}It returns a submission id. Nothing is served from it yet.
A person then tries to reproduce it at the version you named. If it reproduces, the range gets checked against the releases either side, because a trap with the wrong range is worse than no trap: it fires on people it does not apply to and they stop reading. If it does not reproduce, you get asked what else was in the environment, and often that conversation is where the real trap turns out to be.
This is slow. Days, not minutes. I have thought about publishing submissions immediately with an "unverified" badge, and I keep deciding against it, because the only thing this corpus has that a search engine does not is that a person checked. The moment unverified entries are served, every entry has to be read as maybe-checked, and the whole thing degrades into a wiki with an API.
submit_trap is the one tool that needs a key, for the same reason: a submission is attached to someone a reviewer can write back to.