install-hooks

star 1

Install or uninstall the adr-kit pre-commit hook in the current project. Copies templates/githooks/pre-commit into .githooks/pre-commit, makes it executable, and runs `git config core.hooksPath .githooks`. Idempotent. Used internally by /adr-kit:init and /adr-kit:upgrade; also exposed standalone for users who want to add or remove the hook independently.

rvdbreemen By rvdbreemen schedule Updated 6/12/2026

name: install-hooks description: Install or uninstall the adr-kit pre-commit hook in the current project. Copies templates/githooks/pre-commit into .githooks/pre-commit, makes it executable, and runs git config core.hooksPath .githooks. Idempotent. Used internally by /adr-kit:init and /adr-kit:upgrade; also exposed standalone for users who want to add or remove the hook independently. argument-hint: "[--uninstall]" disable-model-invocation: true allowed-tools: [Read, Write, Edit, Bash]

adr-kit install-hooks

You install or uninstall the adr-kit pre-commit hook in the project the user is currently in (pwd should be the project root).

Default behaviour: install

Step 1 — Resolve the plugin's hook template

ADR_KIT=$(ls -d ~/.claude/plugins/cache/rvdbreemen-adr-kit/adr-kit/*/ | sort -V | tail -1)
TEMPLATE="$ADR_KIT/templates/githooks/pre-commit"

If $TEMPLATE does not exist or is empty, exit with an error: the plugin install is broken; tell the user to reinstall via /plugin install adr-kit@rvdbreemen-adr-kit.

Step 2 — Detect existing hooks

Three cases:

  • No .githooks/pre-commit. Mkdir .githooks/, copy the template, chmod +x, set core.hooksPath. Done.
  • Existing .githooks/pre-commit is byte-identical to the template. No-op. Tell the user it's already installed.
  • Existing .githooks/pre-commit differs. Read both. Show the user the existing content (truncated to first 30 lines). Ask:
    • prepend adr-kit before existing — write a wrapper script that calls adr-kit then execs the original. Save the original as .githooks/pre-commit.adr-kit-saved.
    • replace — overwrite. Save the old hook as .githooks/pre-commit.backup-<timestamp> for safety.
    • abort — do nothing. Apply the user's choice.

Step 3 — Activate

Run git config core.hooksPath .githooks. Confirm with git config --get core.hooksPath. If the project already has core.hooksPath set to a different directory, do NOT overwrite — tell the user, ask whether to change the config or to symlink the hook into the existing hooks dir.

Step 4 — Confirm

Print:

Pre-commit ADR judge installed.
- hook: .githooks/pre-commit (mode 755)
- core.hooksPath: .githooks
- disable a single commit:  ADR_KIT_HOOK_DISABLE=1 git commit ...
- remove permanently:       /adr-kit:install-hooks --uninstall
- LLM pass is opt-in (off by default). Enable per-project: judge.llm_enabled:true in docs/adr/.adr-kit.json. Enable one commit: ADR_KIT_LLM=1 git commit ...
- ADR-suggest is opt-in too: suggest.enabled:true, or ADR_KIT_SUGGEST=1 for one commit.

Uninstall behaviour: --uninstall

When invoked as /adr-kit:install-hooks --uninstall:

  1. Read .githooks/pre-commit. Verify it is the adr-kit hook (look for the line # adr-kit pre-commit hook near the top). If it is NOT the adr-kit hook, refuse — tell the user the hook in place isn't ours and we won't touch it.
  2. Three paths:
    • No saved original (.githooks/pre-commit.adr-kit-saved does not exist). Remove .githooks/pre-commit. If .githooks/ is now empty, remove it too. Run git config --unset core.hooksPath.
    • Saved original exists. Restore: rename .githooks/pre-commit.adr-kit-saved.githooks/pre-commit. Leave core.hooksPath set to .githooks.
    • .githooks/pre-commit.backup-<timestamp> exists (from a prior replace install). Tell the user the backup is there and ask whether to restore that instead. Apply choice.
  3. Confirm with one line: Pre-commit ADR judge uninstalled. (restored prior hook | removed .githooks/ | unset core.hooksPath)

Guardian (SessionStart) hook — project-scoped install

The ADR Guardian has two registration paths (spec §7):

  • Plugin-level (default, frictionless): The adr-kit plugin declares a SessionStart hook in its manifest. It auto-registers in every Claude Code session when the plugin is enabled globally, and self-guards (exits silently when no docs/adr/ with ADRs is present). This is the recommended path.
  • Project-scoped (explicit): Adds the guardian's SessionStart entry directly to the project's .claude/settings.json. Contained to this project only. Use when the user wants explicit per-project control or does not enable the plugin globally.

Adding the project-scoped guardian hook

When the user asks to add the guardian hook to the project's .claude/settings.json:

  1. Read .claude/settings.json (create it as {} if missing).

  2. Check if hooks.SessionStart already contains an entry whose command contains the string adr-guardian. If yes: print "Already installed" and stop.

  3. If no SessionStart array exists: create it. Parse the JSON structurally — never do text substitution on a JSON file.

  4. Append the following hook object to hooks.SessionStart[0].hooks (create the array path if absent):

    {
      "type": "command",
      "command": "ADR_KIT=$(ls -d ~/.claude/plugins/cache/rvdbreemen-adr-kit/adr-kit/*/ 2>/dev/null | sort -V | tail -1) && [ -n \"$ADR_KIT\" ] && _PY=$(command -v python3 || command -v python || command -v py) && [ -n \"$_PY\" ] && \"$_PY\" \"$ADR_KIT/bin/adr-guardian\" check 2>/dev/null || true",
      "timeout": 10,
      "statusMessage": "Checking ADR health..."
    }
    
  5. Write the updated JSON back. The existing SessionStart hooks (if any) are preserved byte-for-byte — only the new entry is appended.

  6. Confirm: "Guardian hook added to .claude/settings.json. It will fire at the next session start."

Removing the project-scoped guardian hook

When the user asks to remove the guardian hook from .claude/settings.json:

  1. Read .claude/settings.json. Parse as JSON.
  2. Find entries in hooks.SessionStart[*].hooks[*] whose command contains adr-guardian. If none found: print "Guardian hook not found in .claude/settings.json" and stop.
  3. Remove exactly those entries. Leave all sibling hooks untouched.
  4. If the containing hooks array becomes empty after removal, remove the empty array (but keep the parent SessionStart entry if other entries exist in other groups).
  5. Write the updated JSON back.
  6. Confirm: "Guardian hook removed from .claude/settings.json."

Safety invariant: Never remove or modify any hook entry that does not contain adr-guardian in its command. This is the cozempic lesson — a remove that also clobbers unrelated hooks is worse than not removing at all.

Adding .adr-kit-state.json to .gitignore

After adding the guardian hook (project-scoped or as part of /adr-kit:init):

echo "docs/adr/.adr-kit-state.json" >> .gitignore

Verify it is not already present first (idempotent). The state file is per-machine and must never be committed.

Constraints

  • Never silently overwrite a pre-existing user hook. Always detect, show, ask.
  • Set core.hooksPath only when needed. If the user already has it pointing at a custom dir, propose a symlink rather than redirecting their config.
  • Idempotent in both directions. Re-running install when already installed is a no-op. Re-running uninstall when nothing is installed is a no-op (with a warning).
  • chmod +x the hook after writing — without the executable bit, git silently ignores it.
  • Do not commit the hook. The hook lives in .githooks/, which the project may or may not have in .gitignore. Don't add it to git here; the user decides whether to track it.
Install via CLI
npx skills add https://github.com/rvdbreemen/adr-kit --skill install-hooks
Repository Details
star Stars 1
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator