Hooklint — Development skill for Claude Code
Offline linter for the agent config that actually executes: hooks, skills, MCP entries, permission rules.
How to install Hooklint
This entry records only its repository, not the path inside it, so there is no
exact command to give. Open ethan-haas/hooklint and copy the folder into
~/.claude/skills/, or the file into ~/.claude/agents/.
What Hooklint does
Offline linter for the agent config that actually executes: hooks, skills, MCP entries, permission rules. Catches the hook that can never fire and the hook that splices agent-controlled text into a shell command unquoted.
Alternatives in Development
- Domxss — Confirm DOM XSS in a real headless browser — injects canary payloads into params + URL fragment and only repor 4.5k ★
- Sandbox-agent (Rivet) — Run Claude Code and other coding agents in sandboxes controlled over HTTP 1.2k ★
- Fable OS — An agentic operating system where the kernel is controlled directly by Claude 324 ★
README
hooklint
You pasted a hook out of a 53,000-star awesome-list into a tool that executes shell on your machine. Two failure modes look identical in the config file: a hook whose matcher can never fire, and a hook that splices tool-output or fetched content into a shell command unquoted. `hooklint` finds both, and six more, anchored to a JSON Pointer into the offending file. It parses; it never executes a hook.
$ hooklint .claude/settings.json
ERROR .claude/settings.json /hooks/PreToolUse/0/matcher [dead_matcher]
PreToolUse hook #0: matcher 'Bahs' matches none of the declared tool names; this hook will never fire
evidence: 'Bahs'
hooklint: scanned 1 file(s), 1 finding(s), 0 parse error(s), unknown_rate=0.0000 (0/9)
That's a typo (`Bahs` for `Bash`) that JSON-validates fine and silently does nothing, forever. Here's the other failure mode, from a generic YAML hook manifest:
$ hooklint agent-hooks.yaml
ERROR agent-hooks.yaml /hooks/pre_tool_use/0/run [unquoted_interpolation]
unquoted/double-quoted shell expansion '$USER_MESSAGE'; if the expanded value is tool output or fetched content this is command injection
evidence: $USER_MESSAGE
hooklint: scanned 1 file(s), 1 finding(s), 0 parse error(s), unknown_rate=0.0000 (0/6)
That one runs. It just runs whatever `$USER_MESSAGE` happens to contain, unquoted, in a shell.
Why this one
| what exists | stars |
|---|---|
hesreallyhim/awesome-claude-code |
53.4k |
PatrickJS/awesome-cursorrules |
40.7k |
wshobson/agents |
39.4k |
| any linter for these configs | 63 |
The ecosystem produced collections, not verification.
Install
pipx run hooklint /path/to/repo
No account, no API key, no network, no client installed. Or:
pip install hooklint
hooklint . # scan the current directory
hooklint --json . # machine-readable
python -m hooklint . # also works
What it checks
Hook commands are parsed as **s
Related Skills
PDF Text Router
A Claude Code hook that routes each Read on a PDF to the path that actually works: text layer to UTF-8 text, s
Executing Plans
Use when partner provides a complete implementation plan to execute in controlled batches with review checkpoi
Claude Linter
Lints Claude Code config, CLAUDE.md, hooks, MCP, settings, permissions for silent conflicts, dead references,
Skillopt
Run the SkillOpt process-skill optimizer (offline, local). Default prints the exact bare-terminal command (saf
Sota Resume
Find and finish the open work in this project — inventory every tracker, checkbox and marker with a controlled
Agentcompat
Which agent extension features actually work on which agent. A compatibility matrix for skills, hooks, MCP and
Related Agents
Claude Code Hook Agent
Plays agent-specific sounds for the 6 hooks that actually fire in agent sessions
Light Security ClaudeSettingsAudit
Audit Claude Code config files (settings.json, settings.local.json, .mcp.json) for unsafe or malicious content
Gaia System
Use when building, modifying, or auditing Gaia's own machinery — agents, skills, hooks and hook modules, routi