Claude Code plugin
What the Wellworn plugin installs, which commands make its PreToolUse hook fire, and how to turn the hook off.
The plugin is three small files: the MCP server entry, a skill that tells Claude when to ask Wellworn, and a hook that prints known traps before a package install runs. Everything in it is in the public repository under plugins/claude-code, and none of it needs an account.
Install
claude plugin marketplace add WellWorn-dev/wellworn
claude plugin install wellworn@wellwornThe marketplace manifest sits at .claude-plugin/marketplace.json in the repository root and points at ./plugins/claude-code. Both names in wellworn@wellworn are real: the first is the plugin, the second is the marketplace. The same two steps work as /plugin marketplace add and /plugin install inside a session.
Verified 2026-09-08 against code.claude.com
What the plugin contains
| Path | What it does |
|---|---|
.mcp.json | Registers https://mcp.wellworn.dev/mcp as an HTTP MCP server named wellworn |
skills/wellworn/SKILL.md | Tells Claude which tool to call and how to read a verdict |
hooks/hooks.json | Registers one PreToolUse hook on Bash and one on Edit|Write|MultiEdit |
scripts/check-traps.sh | The hook itself: reads the pending tool call, asks the traps endpoint, prints what comes back |
The plugin ships no key and no configuration. To attach a key, add the server yourself with an Authorization header as described in Claude Code; the plugin's .mcp.json entry stays anonymous.
The hook
hooks/hooks.json registers the same script twice, once for the Bash matcher and once for Edit|Write|MultiEdit, each with an 8 second timeout. The script reads the pending tool call as JSON on stdin and decides in its first few lines whether this call is interesting.
Which commands trigger it
On Bash, the script pulls the command string out of the payload and keeps going only if it contains one of these substrings:
npm install npm i pnpm add yarn add bun add
pip install uv add composer require cargo addAnything else exits immediately, so npm run build and npm ci never reach the network. From a matching command it takes the package names, drops flags and the package manager's own words, strips a pinned version off the end, and keeps at most eight names.
Which files trigger it
On an edit, the script reads file_path and continues only for package.json, pyproject.toml, requirements.txt, composer.json, Cargo.toml, go.mod, or Gemfile. It then scans the new content for "name": "1.2.3" pairs. Claude Code sends that content as an escaped JSON string, and the script's extraction stops at the first escaped quote, so in practice this path prints nothing and the install command is what fires the hook.
What it sends and prints
For each name the script requests the plain-text traps endpoint with a 4 second timeout:
GET https://mcp.wellworn.dev/api/traps?library=better-authThe library name is the only thing that leaves the machine. No file contents, no command line, no version: the version is stripped before the request, so the answer covers every range recorded for that library. A 204 (nothing recorded) or a failed request is skipped silently. Whatever text comes back is wrapped in the additionalContext field Claude Code reads for PreToolUse, which puts it in front of the model without touching the permission decision:
{"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"TRAPS Better Auth (1)\n [187fc511] blocker >=1.7.0 <1.7.2: organization invitations fail when teams are enabled\npass id for the full fix\n"}}The script always exits 0, so it can slow a tool call down but never block one. It needs curl and python3 on the PATH and exits quietly without them. Each request counts against the same limit as an MCP tool call: 60 a day per IP anonymously. See the traps API for the response format and keys for raising the cap.
Verified 2026-09-08 against code.claude.com
When the skill calls Wellworn
The hook covers installs. The skill covers the decision before the install, and it names the tool per situation:
## When to call it
- Before `npm install`, `pip install`, `composer require`, `cargo add`, or editing a dependency manifest: call `recommend` with the task in one sentence and any constraints (solo, free tier, serverless, RTL, offline).
- When two options are on the table: call `compare` with the names.
- When a SaaS is being considered: call `alternatives` for open-source or self-hosted options.
- Before a UI screen: call `design` with the screen and constraints.
- After an upgrade breaks something: call `traps` with the library and the version from the lockfile; pass an id for the full fix.The rest of the file is the shape of a verdict and the rule for reading one: follow PICK unless the ALT condition applies to this project, and read every blocker trap before writing code. The tools reference documents the same five tools with their arguments.
Turning it off
To keep the server and the skill but stop the hook, disable the plugin and add the server on its own:
claude plugin disable wellworn@wellworn
claude mcp add --transport http wellworn https://mcp.wellworn.dev/mcpclaude plugin uninstall wellworn@wellworn removes it completely. To silence every hook in a session without changing what is installed, start Claude Code with --settings '{"disableAllHooks": true}'.
Verified 2026-09-08 against code.claude.com