Putting it where it runs
Running validate by hand catches drift after the fact. hook install has three variants that catch it sooner — each with a different amount of enforcement. Here is what each one actually does.
harnd validate tells you about drift when you run it. The three hook install variants decide when it runs, without you having to remember to. All three require no API key.
hook install (no flags)
Installs a Claude Code “Stop hook” in .claude/settings.json. It runs harnd validate --diff --hook the moment your AI agent says it is done with a turn.
npx @harnd/cli hook installErrors go to stderr with exit code 2, which Claude Code treats as “the agent must fix this before finishing.” Drift gets caught and fixed in the same loop that created it, before you ever see it. This is Claude Code–specific.
hook install --npm-script <name>
For teams that already have an npm script they run before committing — for example "check": "tsc && vitest".
npx @harnd/cli hook install --npm-script checkThis appends && npx @harnd/cli validate to that script — always at the end, so your existing checks still report first if they fail. It works for any editor or AI agent, not just Claude Code, and for CI or a pre-commit hook that already calls the script. It is idempotent, and it detects if you already call harnd indirectly through another script, so it will not double up.
hook install --agents-md
Appends a short section to an existing CLAUDE.md or AGENTS.md, telling your coding agent to run npx @harnd/cli scan after touching UI and npx @harnd/cli validate before committing.
npx @harnd/cli hook install --agents-mdThis does not install any automation — it is a plain-text instruction an AI agent reading that file might follow. It will not create CLAUDE.md or AGENTS.md for you if you do not already have one; harnd never speculatively creates files outside .harnd/.
Which one to use
- If you use Claude Code, plain
hook installis the strongest option — it can literally block your agent from finishing until drift is fixed. - If you use any other AI coding agent, or you want enforcement in CI or a pre-commit hook too,
--npm-scriptis the general-purpose option. --agents-mdis a lightweight nudge you can combine with either of the above. It enforces nothing by itself — do not treat it as a substitute for one of the other two.
All three options accept --dry-run to show what would be written without writing it.
Which copy of harnd this runs
All three variants run npx @harnd/cli, and npx prefers the copy installed in the project you are in. So the check runs this project's copy of harnd, not a global one.
That is what makes the version predictable for everyone working on the repository. It also means that if you did not write this project, setting up the hook runs code the project supplies — plain hook install runs the command once to confirm the hook works, and your agent runs it again at the end of every turn. A project could ship something that only looks like harnd, and we cannot tell the difference from inside the repository: anything we could check, the project can also write.
You do not have to run the project's install script for this to matter: Git preserves executable bits and symlinks, so a repository can carry that copy in its committed files. Cloning it is enough. This is how project-local tooling works in general — husky, lint-staged and test runners behave the same way, and installing a project's dependencies already extends it the same trust. The practical rule is short: set any of these up only in projects you trust, and treat an unfamiliar repository the way you would treat running its install script.
harnd deliberately does not write the path of a specific file inside your repository into your settings. An earlier build did, after a check meant to confirm the file was genuinely ours; that check could be satisfied by anything committed to the repository, so it was removed rather than kept as false reassurance.
Removing what hook install added
If you only want to undo what this page describes, use npx @harnd/cli hook uninstall. It removes the Stop hook, the package.json line and the CLAUDE.md section, and leaves .harnd/ alone — including your API key.
npx @harnd/cli uninstall is the wider one: it removes all of that and deletes your API key, because leaving a raw secret behind after you stop using a tool is worse than removing it. Your .harnd/ knowledge — tokens, intents, decisions — is kept unless you pass --all. Use --dry-run first to see what would be removed.