Skip to content

Releases: Edmonds-Commerce-Limited/claude-code-hooks-daemon

v3.8.2 - Comprehensive Venv Resolver SSOT

22 Apr 13:43

Choose a tag to compare

Release v3.8.2 - Comprehensive Venv Resolver SSOT

Release Date: 2026-04-22
Type: Patch Release (hot fix for v3.8.0 / v3.8.1)

Summary

Version 3.8.2 completes the v3.7.0 → v3.8.x fingerprint-keyed venv migration. v3.7.0 moved the venv to untracked/venv-py{MM}-{fp}/ and auto-deletes the legacy untracked/venv/ after a successful upgrade. v3.8.0 fixed the skill wrappers. v3.8.1 added the fingerprint-mismatch scan-fallback. But many install, upgrade, QA, and diagnostic scripts still referenced the old path directly, so any script outside the skill surface — the installer's post-install validator, upgrade helpers, worktree tooling, QA runners — would false-fail with "Python venv not found" on any v3.7.0+ install where the agent's python3 differs from the installer's Python.

v3.8.2 introduces two new SSOT helpers — scripts/install/venv_resolver.sh for bash consumers and daemon.paths.resolve_existing_venv_python() for Python consumers — and migrates every remaining hardcoded consumer to use them. All four helpers now implement the identical 4-step precedence:

  1. $HOOKS_DAEMON_VENV_PATH (explicit override)
  2. untracked/venv-{current-fingerprint}/bin/python
  3. first matching untracked/venv-*/bin/python (scan-fallback)
  4. untracked/venv/bin/python (legacy fallback)

Highlights

  • No more "Python venv not found" false-fails on v3.7.0+ installs: Every script across install, upgrade, QA, and diagnostics now resolves the venv through the shared SSOT. The installer's own post-install validator, which previously reported every correctly-installed v3.7.0+ install as broken, now passes.
  • Four SSOTs in lockstep: Python (daemon.paths.resolve_existing_venv_python), install/upgrade bash (scripts/install/venv_resolver.sh), skill bash (skills/hooks-daemon/scripts/_resolve-venv.sh), and project-level bash (scripts/venv-include.bash) all implement the identical 4-step precedence. Parity is enforced by integration tests that exercise each helper side-by-side.
  • init.sh gets the v3.8.1 scan-fallback: The v3.8.1 fix for the skill resolver also applies to init.sh's _resolve_python_cmd(), which had the same latent bug. Now handled.
  • Upgrade guide template fixed: The generic CLAUDE/UPGRADES/upgrade-template/verification.sh checked the legacy path directly, so any future upgrade guide generated from the template would inherit the bug. Template now uses the shared scan-fallback pattern.

Changes

Fixed

  • Hardcoded legacy untracked/venv/bin/python paths across install, upgrade, QA, and diagnostic scripts: scripts/upgrade.sh, scripts/upgrade_version.sh, scripts/install/project_detection.sh, scripts/install/rollback.sh, scripts/install/validation.sh, scripts/validate_worktrees.sh, scripts/setup_worktree.sh, scripts/detect_location.sh, scripts/debug_hooks.sh, scripts/qa/run_all.sh, and scripts/qa/run_strategy_pattern_check.sh all now resolve the venv via the shared scripts/install/venv_resolver.sh SSOT helper.
  • client_validator.py reported "venv missing" on fingerprint-keyed installs: The installer's post-install validator now calls the Python-side SSOT daemon.paths.resolve_existing_venv_python() instead of checking untracked/venv/bin/python directly.
  • init.sh missed scan-fallback between fingerprint-match and legacy: _resolve_python_cmd() now scans untracked/venv-*/bin/python before the legacy fallback, matching the v3.8.1 skill-resolver fix.
  • CLAUDE/UPGRADES/upgrade-template/verification.sh hardcoded legacy path: The generic verification template now applies the scan-fallback pattern, so every future upgrade guide generated from it handles v3.7.0+ layouts correctly.

Added

  • scripts/install/venv_resolver.sh: Shared bash SSOT for install/upgrade/verify scripts. Implements the canonical 4-step precedence. Covered by 7 integration tests in tests/integration/test_install_venv_resolver.py.
  • daemon.paths.resolve_existing_venv_python(): Python SSOT for in-process consumers. Covered by unit tests in tests/unit/daemon/test_paths_resolve_existing_venv.py.

Breaking Changes

None. All changes are internal path-resolution refactors. Consumers that invoked the affected scripts continue to work identically; the fix is purely about where those scripts look for the venv.

Upgrade Instructions

Upgrading Existing Installations

/hooks-daemon upgrade

Or, from the daemon directory:

cd .claude/hooks-daemon
./scripts/upgrade.sh

New Installations

git clone -b v3.8.2 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

Verify

/hooks-daemon health
# Expected: "Daemon: RUNNING" — no "Python venv not found" message

Test Statistics

  • Total tests: 7,801 passing (4 skipped) — up from 7,778 in v3.8.1 (23 new tests for the two new SSOT helpers and their bash/Python parity)
  • Coverage: 95.0% (requirement: 95%)
  • QA gates: 10/10 passed

Contributors

  • joseph

Comparison

Full diff: v3.8.1...v3.8.2

v3.8.1 - Skill Resolver Fingerprint-Mismatch Fallback

22 Apr 12:24

Choose a tag to compare

Release v3.8.1 - Skill Resolver Fingerprint-Mismatch Fallback

Release Date: 2026-04-22
Type: Patch Release (hot fix for v3.8.0)

Summary

Version 3.8.1 is a hot fix for v3.8.0. The _resolve-venv.sh helper shipped in v3.8.0 recomputes the fingerprint from ${HOOKS_DAEMON_PYTHON:-python3}, but python3 on the agent's PATH may resolve to a different interpreter than the one the installer used when it built the venv (e.g. installer ran under /usr/bin/python3.13 → fingerprint py313-956ed987, but system python3 is 3.9 → fingerprint py39-3bb0ae3d). The resolver looked for the computed fingerprint, did not find it, and fell through to the legacy untracked/venv/ path — which v3.7.0 auto-deletes after a successful upgrade. Result: /hooks-daemon status, /hooks-daemon health, and /hooks-daemon init-handlers reported Python venv not found: …/untracked/venv/bin/python on v3.7.0+ installs even though the daemon itself was healthy and running.

The fix adds a scan-fallback to the resolver: after fingerprint-match fails, scan $DAEMON_DIR/untracked/venv-*/bin/python and use the first working venv. The venv's own bin/python symlink points to whichever base interpreter the installer chose, so the scanned venv is usable regardless of what python3 resolves to in the agent's current PATH. The same scan-fallback was added to scripts/venv-include.bash::_resolve_venv_dir() which has the identical bug.

Highlights

  • Skill wrappers find their venv when installer's Python differs from resolver's python3: /hooks-daemon skill invocations work again on systems where the installer picked a specific interpreter (e.g. python3.13) and the agent's PATH resolves python3 to a different version (e.g. python3.9).
  • Project-level venv-include.bash gets the same fix: Scripts sourcing venv-include.bash (QA helpers, install scripts) now tolerate the same mismatch.

Changes

Fixed

  • _resolve-venv.sh fingerprint-mismatch fallback: When the fingerprint recomputed at skill-invocation time does not match the venv directory the installer created, the resolver now scans for any existing untracked/venv-*/bin/python and uses the first one found, instead of falling straight to the legacy path. Precedence is now: $HOOKS_DAEMON_VENV_PATHuntracked/venv-{recomputed-fingerprint}/bin/python → first matching untracked/venv-*/bin/pythonuntracked/venv/bin/python (legacy fallback).
  • scripts/venv-include.bash fingerprint-mismatch fallback: Same scan-fallback added to _resolve_venv_dir() so that root-level helper scripts (QA runners, install scripts) tolerate the same mismatch.

Breaking Changes

None. The scan-fallback is purely additive — it runs only when the existing fingerprint-match and explicit-override paths fail.

Upgrade Instructions

Upgrading Existing Installations

/hooks-daemon upgrade

Or, from the daemon directory:

cd .claude/hooks-daemon
./scripts/upgrade.sh

The upgrade reinstalls the skill files, so the v3.8.0 resolver is replaced with the fixed v3.8.1 version automatically.

New Installations

git clone -b v3.8.1 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

Verify

/hooks-daemon health
# Expected: "Daemon: RUNNING" and handler count = 84

If /hooks-daemon health still reports Python venv not found after upgrading:

ls .claude/hooks-daemon/untracked/
# Expected: at least one venv-{fingerprint}/ directory present

Test Statistics

  • Total tests: 7,778 passing (4 skipped) — 3 new regression tests for the fingerprint-mismatch fallback
  • Coverage: 95.0% (requirement: 95%)
  • QA gates: 10/10 passed

Contributors

  • joseph

Comparison

Full diff: v3.8.0...v3.8.1

v3.8.0 - Skill Wrapper Venv Fix & gh_pr_comments

22 Apr 12:05

Choose a tag to compare

Release v3.8.0 - Skill Wrapper Venv Fix & gh_pr_comments Handler

Release Date: 2026-04-22
Type: Minor Release (hot fix for v3.7.0)

Summary

Version 3.8.0 is a hot fix for v3.7.0. The fingerprint-keyed venv refactor in v3.7.0 updated the daemon runtime paths but missed the three /hooks-daemon skill wrapper scripts (daemon-cli.sh, health-check.sh, init-handlers.sh), which continued to hardcode the pre-v3.7.0 path $DAEMON_DIR/untracked/venv/bin/python. On fresh v3.7.0 installs the legacy directory does not exist, so every skill invocation failed with Python venv not found: …/untracked/venv/bin/python and the skill was unusable.

This release ships a shared _resolve-venv.sh helper next to the wrappers that applies the same resolution precedence as init.sh's _resolve_python_cmd(), restoring the skill on v3.7.0+ installs without regressing the pre-v3.7.0 layout.

The release also folds in two items that had already landed on main since v3.7.0: a fix for list-venvs/prune-venvs path resolution in normal-install mode, and a new gh_pr_comments handler that mirrors the existing gh_issue_comments handler.

Highlights

  • Skill wrappers resolve the correct venv: /hooks-daemon status, /hooks-daemon health, and /hooks-daemon init-handlers work again on v3.7.0+ installs. A new shared _resolve-venv.sh helper is the single source of truth for wrapper venv resolution.
  • Venv cleanup & inspection consistent across install modes: list-venvs/prune-venvs and the post-install cleanup path now behave identically in normal-install and self-install modes.
  • gh_pr_comments handler: Block gh pr view <N> without --comments (priority 40, blocking). Prevents agents from missing review feedback that lives in comments rather than the PR body.

Changes

Fixed

  • Hooks-daemon skill wrapper scripts broken on v3.7.0+ installs: daemon-cli.sh, health-check.sh, and init-handlers.sh hardcoded $DAEMON_DIR/untracked/venv/bin/python. Replaced with source "$(dirname "$0")/_resolve-venv.sh" — a shared helper that resolves $HOOKS_DAEMON_VENV_PATHuntracked/venv-{fingerprint}/bin/pythonuntracked/venv/bin/python (legacy fallback). _resolve-venv.sh sources $DAEMON_DIR/scripts/install/python_fingerprint.sh (which ships with every install) to compute the fingerprint; if that helper is missing the resolver falls through cleanly to the legacy path. Covered by tests/integration/test_skill_scripts_venv_resolution.py (14 cases).
  • Venv cleanup and inspection broken in normal-install mode: list-venvs/prune-venvs and the post-install cleanup path resolved against self_install_mode defaults and failed silently in normal-install setups. Fixed path resolution so both modes behave identically.

Added

  • gh_pr_comments handler (PreToolUse, priority 40, blocking): gh pr view <N> without --comments is now denied with a guidance message. gh pr view <N> --comments and gh pr view <N> --json title,body,comments remain allowed. Mirrors the existing gh_issue_comments handler. Handler count rises to 84 across 13 event types.

Breaking Changes

None. The wrapper-script fix is fully backwards compatible — pre-v3.7.0 installs (where only untracked/venv/ exists) continue to work via the legacy fallback path in the new resolver.

Upgrade Instructions

Upgrading Existing Installations

/hooks-daemon upgrade

Or, from the daemon directory:

cd .claude/hooks-daemon
./scripts/upgrade.sh

The upgrade reinstalls the skill files, so the broken v3.7.0 wrappers are replaced with the fixed v3.8.0 versions automatically.

New Installations

git clone -b v3.8.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

Verify

/hooks-daemon health
# Expected: "Daemon: RUNNING" and handler count = 84

If /hooks-daemon health still reports Python venv not found after upgrading, confirm the skill files were re-deployed:

ls .claude/skills/hooks-daemon/scripts/
# Expected: _resolve-venv.sh present alongside daemon-cli.sh/health-check.sh/init-handlers.sh

Test Statistics

  • Total tests: 7,775 passing (4 skipped)
  • Coverage: 95.0% (requirement: 95%)
  • QA gates: 10/10 passed (magic values, format, lint, type check, tests, security, dependencies, error hiding, skill references, smoke test)

Contributors

  • joseph

Comparison

Full diff: v3.7.0...v3.8.0

v3.7.0 - Fingerprint-Keyed Venv Isolation

21 Apr 10:59

Choose a tag to compare

Release v3.7.0 - Fingerprint-Keyed Venv Isolation

Release Date: 2026-04-21
Type: Minor Release

Summary

Version 3.7.0 eliminates a class of silent venv corruption bugs caused by sharing the daemon's virtual environment across incompatible Python interpreters. The venv is now keyed by a fingerprint of the active Python environment — md5(sys.version | sys.base_prefix | platform.machine())[:8] — so a YOLO container (e.g. Fedora /usr/bin/python3) and the desktop host Python no longer clobber each other's binaries when opening the same project. Concurrent containers sharing the same image still share one venv. The legacy untracked/venv/ path remains a fallback for backwards compatibility and is auto-deleted only after the fingerprint-keyed venv is provisioned and the daemon is confirmed RUNNING.

Two new CLI subcommands (list-venvs, prune-venvs) give operators visibility into and control over the on-disk venv layout, including a --legacy mode to safely remove pre-v3.7.0 venvs after the upgrade.

Highlights

  • Fingerprint-keyed venv path: untracked/venv-py{MM}-{fp}/ isolates venvs per Python environment while still sharing across compatible containers.
  • Auto-bootstrap on first start: First daemon start in a new environment provisions the correct venv automatically via stamp-based invalidation; subsequent starts are zero-overhead.
  • Backwards compatible: Legacy untracked/venv/ is retained as a fallback if the fingerprint venv is absent. Auto-deletion happens only after the new venv is healthy and the daemon is confirmed RUNNING.
  • list-venvs / prune-venvs CLI: Inspect the venv layout and safely remove stale/legacy venvs with --dry-run, --force, --legacy, --stale, and --all-except-current selectors. The active-environment fingerprint venv is never deleted.
  • CI gate: HOOKS_DAEMON_SKIP_VENV_BOOTSTRAP=1 or CI=true disables bootstrap to keep CI jobs fast.

Changes

Added

  • Fingerprint-keyed venv layout (untracked/venv-py{MM}-{fp}/): The daemon now keys its virtual environment by a Python-environment fingerprint so concurrent containers sharing the same image reuse one venv while distinct Python environments (different version, prefix, or architecture) get their own isolated venv. Legacy untracked/venv/ is retained as a fallback.
  • Auto-bootstrap on first startup in a new environment: Stamp-based invalidation detects when the current Python environment has no matching venv. ensure_venv() provisions a fresh fingerprint-keyed venv automatically on first start; subsequent starts skip the check for zero-overhead operation.
  • Auto-deletion of legacy untracked/venv/ after successful upgrade: The installer and upgrader delete the pre-fingerprint untracked/venv/ once the fingerprint-keyed venv is provisioned and the daemon is confirmed RUNNING. Deletion is skipped if the daemon fails to start, ensuring safe fallback.
  • list-venvs CLI subcommand: Tabular or JSON listing of all venvs under the daemon's untracked directory, with current-environment marker.
  • prune-venvs CLI subcommand: Modes include --legacy, --all-except-current, and --stale. Requires --force to delete; --dry-run previews. The active-environment venv is never deleted.
  • cmd_repair retargeted to fingerprint-keyed path: repair now rebuilds at get_venv_path() for the active Python environment.
  • Fingerprint SSOT helpers (Python + bash): get_venv_fingerprint() and venv-include.bash provide a shared source of truth across Python code, shell scripts, and the installer.
  • init.sh lazy PYTHON_CMD resolution: init.sh sources venv-include.bash at runtime rather than at clone time.

Changed

  • Install and upgrade scripts use fingerprint-keyed paths: install.sh, upgrade.sh, and QA scripts (run_all.sh, run_tests.sh, etc.) resolve PYTHON_CMD via venv-include.bash / ensure_venv().

Breaking Changes

None. Legacy untracked/venv/ remains a fallback for backwards compatibility. Auto-deletion of the legacy venv only occurs after the fingerprint-keyed venv is proven healthy.

Upgrade Instructions

New Installations

git clone -b v3.7.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

Upgrading Existing Installations

cd .claude/hooks-daemon
git fetch --tags
git checkout v3.7.0
./upgrade.sh

The upgrade script provisions the fingerprint-keyed venv, restarts the daemon, and — if the daemon starts successfully — removes the legacy untracked/venv/. If the daemon fails to start, the legacy venv is left in place as a fallback.

Post-Upgrade Tasks

After upgrading, review CLAUDE/UPGRADES/v3/v3.6-to-v3.7/post-upgrade-tasks/ — it contains 1 recommended task:

  • 01-prune-legacy-venv.md: Verify that the legacy untracked/venv/ has been removed. If you opened the project in a mixed container/host environment before upgrading, the legacy venv may contain corrupted binaries; running prune-venvs --legacy --dry-run then --force confirms cleanup.

Testing

  • Tests: 7,721+ passing
  • Coverage: 95.0%
  • Type Safety: MyPy strict mode compliant
  • Security: Bandit scan clean
  • QA checks: 10/10 passing

Contributors

  • joseph

Full Changelog

Compare: v3.6.0...v3.7.0

v3.6.0 - Stash-by-Default and Auto-Commit CLAUDE.md

20 Apr 15:21

Choose a tag to compare

Release v3.6.0 - Stash-by-Default and Auto-Commit CLAUDE.md

Release Date: 2026-04-20
Type: Minor Release

Summary

Version 3.6.0 ships two improvements to daily development workflow. The git_stash handler now blocks stashing by default (previously advisory) — agents must supply an explicit reason via MUST_STASH_BECAUSE="<reason>" to proceed. The daemon also now auto-commits CLAUDE.md after regenerating handler guidance on restart, eliminating the unexplained dirty file that previously prompted agents to revert or stash it.

Highlights

  • Stash blocked by default: git stash is now denied unless prefixed with MUST_STASH_BECAUSE="<reason>", enforcing deliberate, explained stash operations.
  • MUST_STASH_BECAUSE escape hatch: Agents and developers can still stash when genuinely needed — the block message explains exactly how.
  • Auto-commit CLAUDE.md on restart: The dirty CLAUDE.md after daemon restart is now committed atomically and automatically, removing a persistent source of agent confusion.
  • Isolated single-file commit: The auto-commit uses git commit --only, touching nothing outside CLAUDE.md and leaving other staged changes untouched.

Changes

Added

  • git stash blocked by default with MUST_STASH_BECAUSE escape hatch: The git_stash handler default mode has changed from warn to deny. Stashing is now blocked unless the command is prefixed with MUST_STASH_BECAUSE="<reason>" (e.g. MUST_STASH_BECAUSE="switching branches for hotfix" git stash). An empty or missing reason does not bypass the block. The deny message explains the escape hatch. To revert to advisory-only behaviour, set handlers.pre_tool_use.git_stash.options.mode: warn in .claude/hooks-daemon.yaml.
  • Auto-commit CLAUDE.md after daemon restart injection: When the daemon restarts and regenerates the <hooksdaemon> guidance section in CLAUDE.md, the file is now automatically committed if dirty. This prevents LLMs from seeing an unexplained dirty CLAUDE.md and attempting to revert or stash it. The commit uses git commit --only for atomic single-file commits, touches no other staged files, and skips silently in non-git repos or when git operations fail.

Breaking Changes

None.

Upgrade Instructions

New Installations

git clone -b v3.6.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

Upgrading Existing Installations

cd .claude/hooks-daemon
git fetch --tags
git checkout v3.6.0
./upgrade.sh

Behaviour Change: git stash now denied by default

If your project relies on git stash being advisory (warn mode), you must explicitly restore the old behaviour after upgrading:

# .claude/hooks-daemon.yaml
handlers:
  pre_tool_use:
    git_stash:
      options:
        mode: warn

Without this override, any git stash command will be blocked. Agents and developers can bypass the block on a case-by-case basis with:

MUST_STASH_BECAUSE="<reason>" git stash

Testing

  • Tests: 7,666+ passing
  • Coverage: 95.0%
  • Type Safety: MyPy strict mode compliant
  • Security: Bandit scan clean
  • QA checks: 10/10 passing

Contributors

  • joseph

Full Changelog

Compare: v3.5.0...v3.6.0

v3.5.0 - Implicit Monorepo Support for Dependency Directories

16 Apr 10:50

Choose a tag to compare

Release v3.5.0 - Implicit Monorepo Support for Dependency Directories

Release Date: 2026-04-16
Type: Minor Release

Summary

Version 3.5.0 teaches the markdown_organization handler to treat vendor/ (PHP Composer) and node_modules/ (npm) as implicit monorepo roots. Each package inside these directories is now a sub-project where normal markdown rules apply — docs/ is allowed, random locations are blocked. Previously, any markdown write inside a dependency directory was unconditionally blocked unless allowed_markdown_paths was manually configured. The deny message now advises about allowed_markdown_paths and monorepo_subproject_patterns config options so users know how to unblock legitimate paths themselves.

Added

  • Implicit monorepo support for vendor/ and node_modules/: The markdown_organization handler now treats dependency directories as implicit monorepo roots. Normal per-package markdown rules apply within each package subtree — files in recognised locations such as docs/ are allowed, while files in unrecognised locations are blocked. Supports Composer two-level paths (vendor/{vendor}/{package}/), npm unscoped (node_modules/{package}/), and npm scoped (node_modules/@{scope}/{package}/).
  • Config advice in deny message: When the handler blocks a markdown write, the deny message now includes guidance about allowed_markdown_paths (for extra allowed paths) and monorepo_subproject_patterns (for sub-projects with their own docs/, CLAUDE/, etc.) in .claude/hooks-daemon.yaml.
  • Updated get_claude_md() guidance: Documents the dependency directory behaviour so agents understand why markdown in vendor trees is handled differently.

Install / Upgrade

# New installation
git clone -b v3.5.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

# Upgrade from v3.4.x
cd .claude/hooks-daemon && ./upgrade.sh

Test Stats

  • Tests: 7,656+ passing
  • Coverage: 95.1%
  • QA checks: 10/10 passing

Breaking Changes

None.

Comparison

Full diff: v3.4.0...v3.5.0

v3.4.0 - Hook-Registration Drift Detection

15 Apr 14:04

Choose a tag to compare

Release v3.4.0 - Hook-Registration Drift Detection

Release Date: 2026-04-15
Type: Minor Release

Summary

Version 3.4.0 extends the hook_registration_checker SessionStart handler with proactive drift detection for two failure modes that previously went unnoticed: hooks placed in settings.local.json (invisible to teammates and silently doubling up on events), and hook commands that bypass the daemon wrapper entirely by invoking custom scripts or inline Python directly. Both violations are now surfaced at session start with actionable remediation guidance. The cli health subcommand gains the same checks, so operators can validate hook configuration at install and upgrade time without waiting for a new Claude Code session.

Added

  • Hook-registration drift detection at SessionStart: The hook_registration_checker handler now detects and flags two additional policy violations beyond duplicate hooks: (1) any hooks entry present in settings.local.json is flagged as a policy violation (previously only duplicates of settings.json entries were flagged; now any hooks in settings.local.json are caught regardless of whether they duplicate settings.json); (2) any hook command that does not invoke the daemon wrapper (.claude/hooks/{event}) is flagged as a legacy-style bypass, with guidance to port the logic into a project-level handler via init-project-handlers.
  • cli health surfaces hook-registration drift: The health CLI subcommand now includes hook-registration validation in its output, giving operators an install-time and upgrade-time check for misplaced hooks and legacy-style commands without needing to start a new Claude Code session.

Install / Upgrade

# New installation
git clone -b v3.4.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

# Upgrade from v3.3.x
cd .claude/hooks-daemon && ./upgrade.sh

Test Stats

  • Tests: 7,649+ passing
  • Coverage: 95.1%
  • QA checks: 10/10 passing

Breaking Changes

None.

Comparison

Full diff: v3.3.1...v3.4.0

v3.3.1 - Restore Shipped-Broken Skill and Agent Frontmatter

14 Apr 15:54

Choose a tag to compare

Release v3.3.1 - Restore Shipped-Broken Skill and Agent Frontmatter

Release Date: 2026-04-14
Type: Patch Release (Dogfooding Fix)

Summary

v3.3.0 announced a fix for the markdown_table_formatter YAML frontmatter mangling bug — and then shipped a release artefact with 12 files still damaged by that very bug. This patch restores them.

Six SKILL.md files (hooks-daemon, release, acceptance-test, configure, mode, optimise) and six .claude/agents/*.md files had their frontmatter collapsed into a ## name: ... description: ... argument-hint: ... heading by the v3.1.0 batch-format commit (30db070), which ran the pre-fix mdformat across all project markdown. The v3.3.0 handler fix prevents new corruption, but files damaged on disk before the fix landed stayed damaged — and those damaged files were still committed. Every upgrade reached into client projects and re-deployed the broken skill/agent metadata, which is why Claude Code's skill-discovery system-reminders were showing release: --- instead of a real description line.

All 12 files have been restored from git history (30db070^, the parent of the corrupting commit). The v3.3.0 fix to markdown_table_formatter was verified via round-trip on a restored file: frontmatter is preserved byte-for-byte on subsequent Write/Edit operations.

This is exactly the scenario the v3.3.0 post-upgrade task 01-audit-markdown-frontmatter.md walks client projects through — and we should have run it against the daemon's own repo before tagging v3.3.0.

Fixed

  • 6 SKILL.md files: src/claude_code_hooks_daemon/skills/hooks-daemon/SKILL.md, .claude/skills/{release,acceptance-test,configure,mode,optimise}/SKILL.md — frontmatter restored; five wholesale-restored from 30db070^, release/SKILL.md had its frontmatter block surgically rebuilt to preserve the subsequent b38f5a6 UNRELEASED-task-move documentation edits.
  • 6 .claude/agents/*.md files: transcript-inspector.md, release-agent.md, qa-runner.md, qa-fixer.md, python-developer.md, code-reviewer.md — frontmatter restored from 30db070^ (none had post-corruption edits).

Install / Upgrade

# New installation
git clone -b v3.3.1 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

# Upgrade from any v3.x
cd .claude/hooks-daemon && ./upgrade.sh

Upgrading from v3.3.0 will overwrite the broken skill/agent files with the restored versions.

Test Stats

  • Tests: 7,621+ passing
  • Coverage: 95%+
  • QA checks: 10/10 passing
  • No source-code changes — restoration is content-only in .claude/skills/*/SKILL.md, .claude/agents/*.md, and src/claude_code_hooks_daemon/skills/hooks-daemon/SKILL.md

Acceptance Testing

Per RELEASING.md Step 12, PATCH releases with no handler-code changes skip the full acceptance suite. Targeted verification performed:

  1. Formatter round-trip on .claude/skills/mode/SKILL.md via format-markdown CLI — frontmatter preserved byte-for-byte; body re-aligned cleanly.
  2. Skill-discovery system-reminder confirmed all 6 restored skills now expose correct description: values instead of ---.

Comparison

Full diff: v3.3.0...v3.3.1

v3.3.0 - Markdown Frontmatter Fix + Post-Upgrade Task Convention

14 Apr 15:26

Choose a tag to compare

Release v3.3.0 - Markdown Frontmatter Fix + Post-Upgrade Task Convention

Release Date: 2026-04-14
Type: Minor Release

Summary

Version 3.3.0 fixes a silent file-corruption bug in the markdown_table_formatter PostToolUse handler and the format-markdown CLI subcommand, and introduces a generic post-upgrade-tasks/ convention that gives the release pipeline a formal mechanism for shipping post-upgrade instructions (audits, config migrations, workflow changes, notifications) to upgrading LLMs and humans.

The markdown fix is important on its own — any .md file whose first line was --- (notably Claude Code SKILL.md files, but also any Jekyll/Hugo/MkDocs content) was being silently rewritten so the opening --- became a 70-underscore thematic break and the YAML body was collapsed into a ## heading. The bug is now fixed, but files already damaged on disk remain damaged — the shipped post-upgrade task 01-audit-markdown-frontmatter.md walks an upgrading agent through detection and remediation.

Added

  • post-upgrade-tasks/ convention: Tasks are drafted in CLAUDE/UPGRADES/UNRELEASED/post-upgrade-tasks/ during the release cycle and moved into the versioned upgrade guide at release time. Each task is a self-contained .md file with a mandatory header (Type/Severity/Applies to/Idempotent) and sections Why/How to detect/How to handle/How to confirm/Rollback. Advisory only — nothing runs them automatically.
  • Release pipeline BLOCKING gate (Step 6): RELEASING.md and the /release skill now require moving every UNRELEASED task into the versioned upgrade guide before the Opus documentation review. Release ABORTS if any task file remains in UNRELEASED/ after Step 6. The Opus review checklist verifies the versioned guide's task index is populated and that release notes reference post-upgrade tasks when any are critical or recommended.
  • Per-release task index README: CLAUDE/UPGRADES/upgrade-template/post-upgrade-tasks/README.md template with the task-index table schema.

Fixed

  • markdown_table_formatter YAML frontmatter mangling: The handler and the format-markdown CLI now strip frontmatter before formatting and re-attach it byte-for-byte afterwards. Previously, mdformat (which does not understand frontmatter) rewrote the opening --- as a 70-underscore thematic break, collapsed the YAML body onto a ## heading, and lost the closing ---.

Post-Upgrade Tasks

After upgrading, review CLAUDE/UPGRADES/v3/v3.2-to-v3.3/post-upgrade-tasks/ — it contains 1 recommended task that may require action in your project: 01-audit-markdown-frontmatter.md walks through detecting and restoring any .md files damaged by the frontmatter bug during v3.0.0–v3.2.1. If the project has never been on v3.0.0–v3.2.1, skip this task.

Install / Upgrade

# New installation
git clone -b v3.3.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

# Upgrade from v3.2.x
cd .claude/hooks-daemon && ./upgrade.sh

Test Stats

  • Tests: 7,621+ passing
  • Coverage: 95%+
  • QA checks: 10/10 passing

Comparison

Full diff: v3.2.1...v3.3.0

v3.2.1 - Allow .github/ Markdown Files

10 Apr 13:22

Choose a tag to compare

Release v3.2.1 - Allow .github/ Markdown Files

Release Date: 2026-04-10
Type: Patch Release (Configuration)

Summary

Version 3.2.1 activates the allowed_markdown_paths configuration for the markdown_organization handler and adds .github/ as a permitted directory for markdown files. This enables writing markdown files under .github/ (e.g. issue templates, PR templates, triage prompt files) without being blocked by the handler.

Changed

  • Markdown organization allowed paths: Activated explicit allowed_markdown_paths configuration in hooks-daemon.yaml, adding ^\.github/.*\.md$ alongside all previously built-in default paths

Install / Upgrade

# New installation
git clone -b v3.2.1 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh

# Upgrade from v3.2.x
cd .claude/hooks-daemon && ./upgrade.sh

Test Stats

  • Tests: 7,622+ passing
  • Coverage: 95%+
  • QA checks: 10/10 passing

Comparison

Full diff: v3.2.0...v3.2.1