{"id":44176687,"url":"https://github.com/edmonds-commerce-limited/claude-code-hooks-daemon","last_synced_at":"2026-04-07T10:01:02.115Z","repository":{"id":334662940,"uuid":"1134899668","full_name":"Edmonds-Commerce-Limited/claude-code-hooks-daemon","owner":"Edmonds-Commerce-Limited","description":"Daemon-based hooks system for Claude Code with lazy startup, auto-shutdown, and project-level handler extensibility","archived":false,"fork":false,"pushed_at":"2026-03-30T13:39:25.000Z","size":4360,"stargazers_count":2,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-30T14:40:53.049Z","etag":null,"topics":["anthropic","claude","claude-code","claude-code-daemon","claude-code-extension","claude-code-hooks","claude-code-plugin","claude-hooks","claude-plan","cli-tools","developer-tools","hooks-daemon","plan-workflow","python","unix-socket"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Edmonds-Commerce-Limited.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-15T11:10:53.000Z","updated_at":"2026-03-30T13:40:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon","commit_stats":null,"previous_names":["edmonds-commerce-limited/claude-code-hooks-daemon"],"tags_count":40,"template":false,"template_full_name":null,"purl":"pkg:github/Edmonds-Commerce-Limited/claude-code-hooks-daemon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Edmonds-Commerce-Limited%2Fclaude-code-hooks-daemon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Edmonds-Commerce-Limited%2Fclaude-code-hooks-daemon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Edmonds-Commerce-Limited%2Fclaude-code-hooks-daemon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Edmonds-Commerce-Limited%2Fclaude-code-hooks-daemon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Edmonds-Commerce-Limited","download_url":"https://codeload.github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Edmonds-Commerce-Limited%2Fclaude-code-hooks-daemon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31508282,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T03:10:19.677Z","status":"ssl_error","status_checked_at":"2026-04-07T03:10:13.982Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anthropic","claude","claude-code","claude-code-daemon","claude-code-extension","claude-code-hooks","claude-code-plugin","claude-hooks","claude-plan","cli-tools","developer-tools","hooks-daemon","plan-workflow","python","unix-socket"],"created_at":"2026-02-09T13:17:40.583Z","updated_at":"2026-04-07T10:01:02.088Z","avatar_url":"https://github.com/Edmonds-Commerce-Limited.png","language":"Python","readme":"# Claude Code Hooks Daemon\n\n![Version](https://img.shields.io/badge/version-2.32.0-blue)\n![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)\n![License](https://img.shields.io/badge/license-MIT-green)\n![Tests](https://img.shields.io/badge/tests-7650%2B%20passing-success)\n![Coverage](https://img.shields.io/badge/coverage-95%25%20required-success)\n\nA better way to build and maintain Claude Code hooks.\n\n---\n\n## Installation \u0026 Updates\n\n\u003e **For humans:** See [Installation](#installation) and [Updating](#updating) sections below for manual and AI-assisted instructions.\n\n**LLM Quick Reference** — paste these into Claude Code to install or update:\n\n\u003cdetails\u003e\n\u003csummary\u003eInstall (copy into Claude Code)\u003c/summary\u003e\n\n```\nUse curl to fetch and save this file:\ncurl -fsSL https://raw.githubusercontent.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon/main/CLAUDE/LLM-INSTALL.md -o /tmp/LLM-INSTALL.md\nThen read /tmp/LLM-INSTALL.md and follow the instructions exactly.\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eUpdate (copy into Claude Code)\u003c/summary\u003e\n\n```\nUse curl to fetch and save this file:\ncurl -fsSL https://raw.githubusercontent.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon/main/CLAUDE/LLM-UPDATE.md -o /tmp/LLM-UPDATE.md\nThen read /tmp/LLM-UPDATE.md and follow the instructions exactly.\n```\n\u003c/details\u003e\n\n---\n\n## Why Use This?\n\nClaude Code's native hook system is powerful but difficult to iterate on. Hooks are small programs registered in settings — to test a change you need to modify external files and often restart your session to pick up the changes.\n\n**The daemon changes this fundamentally.**\n\nWhen installed, your project has just five Claude Code hooks — one per event type. Each is a lightweight shell script that simply forwards events to the daemon over a Unix socket. The daemon is a separate Python process that **you can restart independently of Claude Code**.\n\nThis means you can use Claude Code itself to write and modify hook handlers, restart the daemon with a single command, and immediately test your changes — all without leaving your current session. The tool you're using to edit code becomes the tool you use to improve the hooks that govern how you edit code.\n\n### What This Unlocks\n\n**Develop hooks with Claude Code itself**\n\nThe daemon's handlers are just Python files in a directory. Claude Code can read, modify, and test them directly. Ask Claude to write a new blocking pattern, add a test case, or debug unexpected behaviour — then restart the daemon and verify. No external tooling or context switching required.\n\n**Fast iteration without session restarts**\n\nRestarting the daemon takes under a second. Your Claude Code session continues uninterrupted with all its context intact. Change a handler, restart, test — repeat until it's right.\n\n**Test-Driven Development for hooks**\n\nBecause handlers are Python classes with proper type annotations, you can write real unit tests. This project ships with 7,650+ tests and a 95% coverage requirement — the same standard applies to handlers you write for your own project. Catch regressions before restarting, not after.\n\n**Run many handlers without overhead**\n\nThe daemon processes hook events in-process via Unix socket IPC, so adding more handlers has negligible cost. A project with 50 active handlers performs as well as one with 5. More rules means better guardrails.\n\n**Real programming, not shell scripting**\n\nHandlers are Python classes. Strategy patterns, type safety, dependency injection, shared utilities — the full toolkit. Complex enforcement logic that would be impossible to maintain as shell scripts becomes straightforward when you're working in a real language with proper abstractions.\n\n---\n\n## What's Built In\n\nThe daemon ships with 72 production handlers across 13 event types, covering the most common AI-assisted development guardrails:\n\n### Safety (Priority 10–20)\n\n- **Destructive git blocker** — Prevents `git push --force`, `git reset --hard`, `git clean -f`, `git branch -D`\n- **Sed blocker** — Encourages the Edit tool over sed; avoids dangerous in-place edits\n- **Security antipattern blocker** — Blocks hardcoded secrets (OWASP A02) and injection patterns (OWASP A03) across 12 language strategies (Secrets, Python, JS/TS, PHP, Go, Ruby, Java, Kotlin, C#, Rust, Swift, Dart)\n- **Absolute path enforcer** — Prevents absolute paths in tool calls\n- **QA suppression blocker** — Blocks `# type: ignore`, `# noqa`, `eslint-disable`, `//nolint` across 11 languages (Python, JS, TS, PHP, Go, Rust, Java, Ruby, Kotlin, Swift, C#)\n\n### Code Quality (Priority 25–35)\n\n- **TDD enforcement** — Requires test files alongside implementation; 11 language strategies\n- **ESLint disable blocker** — Prevents `@ts-ignore`, `@ts-nocheck` without justification\n- **Lock file protection** — Prevents editing generated lock files\n\n### Workflow (Priority 36–55)\n\n- **Planning enforcer** — Requires documented plans for non-trivial work\n- **Daemon restart verifier** — Blocks commits if the daemon cannot restart cleanly\n- **Pipe blocker** — Prevents expensive commands piped to `head`/`tail`\n- **Web search year** — Ensures searches include the current year\n- **Git context injector** — Adds git status to every prompt\n\n### Session Management\n\n- **YOLO container detection** — Identifies container environments with confidence scoring\n- **Version checker** — Alerts when the daemon is out of date\n- **Workflow state persistence** — Saves and restores workflow state across conversation compaction\n\n---\n\n## Status Line\n\nThe daemon can drive Claude Code's built-in status line, giving you a persistent at-a-glance view of your session:\n\n```\n📁 claude-code-hooks-daemon 👤 joseph | 🤖 Sonnet 4.6 ▌▌▌ | ◑ 45.0% | 🕐 15:15 | ⎇ main | 🪝 45.7s : 37MB : DEBUG : 🛡️\n```\n\nIt shows the repo name, account, model and thinking mode, context usage, time, git branch, and daemon stats — updated automatically on every interaction.\n\n**Setup** — add to `.claude/settings.json`:\n\n```json\n{\n  \"statusLine\": {\n    \"type\": \"command\",\n    \"command\": \".claude/hooks/status-line\"\n  }\n}\n```\n\nIf you haven't configured it yet, the daemon will suggest it on your next new session. If the daemon ever fails to start, the status line shows `⚠️ DAEMON FAILED` so the problem is immediately visible rather than silently degraded.\n\n---\n\n## Project-Level Handlers\n\nAdd your own handlers in `.claude/project-handlers/` — auto-discovered on daemon restart, co-located with tests, with full CLI support:\n\n```bash\nVENV_PYTHON=.claude/hooks-daemon/untracked/venv/bin/python\n\n# Scaffold the directory with an example handler and tests\n$VENV_PYTHON -m claude_code_hooks_daemon.daemon.cli init-project-handlers\n\n# Validate handlers load correctly\n$VENV_PYTHON -m claude_code_hooks_daemon.daemon.cli validate-project-handlers\n\n# Run project handler tests\n$VENV_PYTHON -m claude_code_hooks_daemon.daemon.cli test-project-handlers --verbose\n```\n\nSee [CLAUDE/PROJECT_HANDLERS.md](CLAUDE/PROJECT_HANDLERS.md) for the complete guide.\n\n---\n\n## Installation\n\n### AI-Assisted (Recommended)\n\n**Paste this into Claude Code** — the LLM will fetch the install guide and follow it:\n\n```\nUse curl to fetch and save this file:\ncurl -fsSL https://raw.githubusercontent.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon/main/CLAUDE/LLM-INSTALL.md -o /tmp/LLM-INSTALL.md\nThen read /tmp/LLM-INSTALL.md and follow the instructions exactly.\n```\n\nInstallation takes around 30 seconds. Claude will clone the daemon, create a virtual environment, run the installer, and verify everything works.\n\n### Manual\n\n```bash\nmkdir -p .claude \u0026\u0026 cd .claude\ngit clone https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git hooks-daemon\ncd hooks-daemon\ngit fetch --tags \u0026\u0026 git checkout \"$(git describe --tags --abbrev=0)\"\npython3 -m venv untracked/venv\nuntracked/venv/bin/pip install -e .\nuntracked/venv/bin/python install.py\ncd ../..\n```\n\nAfter installation, create `.claude/.gitignore` so generated files aren't committed:\n\n```bash\ncp .claude/hooks-daemon/.claude/.gitignore .claude/.gitignore\n```\n\nThe installer creates:\n- `.claude/settings.json` — Hook registration for Claude Code\n- `.claude/hooks/*` — Forwarder scripts (route events to the daemon)\n- `.claude/init.sh` — Daemon lifecycle functions\n- `.claude/hooks-daemon.yaml` — Handler configuration\n\n---\n\n## Updating\n\n### AI-Assisted (Recommended)\n\n**Paste this into Claude Code** — the LLM will fetch the update guide and follow it:\n\n```\nUse curl to fetch and save this file:\ncurl -fsSL https://raw.githubusercontent.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon/main/CLAUDE/LLM-UPDATE.md -o /tmp/LLM-UPDATE.md\nThen read /tmp/LLM-UPDATE.md and follow the instructions exactly.\n```\n\n### Manual\n\n```bash\ncd .claude/hooks-daemon\ncp ../hooks-daemon.yaml ../hooks-daemon.yaml.backup\ngit fetch --tags \u0026\u0026 git checkout \"$(git describe --tags --abbrev=0)\"\nuntracked/venv/bin/pip install -e .\nuntracked/venv/bin/python -m claude_code_hooks_daemon.daemon.cli restart\ncd ../..\n```\n\nVersion-specific migration guides are in [CLAUDE/UPGRADES/](CLAUDE/UPGRADES/).\n\n---\n\n## Writing Custom Handlers\n\n```python\nfrom claude_code_hooks_daemon.core import Handler, HookResult\nfrom claude_code_hooks_daemon.core.hook_result import Decision\n\nclass MyHandler(Handler):\n    def __init__(self) -\u003e None:\n        super().__init__(name=\"my-handler\", priority=50, terminal=True)\n\n    def matches(self, hook_input: dict) -\u003e bool:\n        return \"pattern\" in hook_input.get(\"tool_input\", {}).get(\"command\", \"\")\n\n    def handle(self, hook_input: dict) -\u003e HookResult:\n        return HookResult(\n            decision=Decision.DENY,\n            reason=\"Blocked because...\",\n            context=[\"Additional context line\"]\n        )\n```\n\nPlace handlers in `.claude/project-handlers/{event_type}/` — they're auto-discovered on daemon restart. Before writing a handler, capture real event data first:\n\n```bash\n./scripts/debug_hooks.sh start \"Testing my scenario\"\n# ... trigger the action in Claude Code ...\n./scripts/debug_hooks.sh stop\n# Logs show exact event structure, timing, and data\n```\n\n**Priority ranges:**\n- `10–20` — Safety (destructive operations)\n- `25–35` — Code quality (linting, TDD)\n- `36–55` — Workflow (planning, conventions)\n- `56–79` — Advisory (non-blocking suggestions)\n- `100+` — Logging and cleanup\n\nSee [CLAUDE/HANDLER_DEVELOPMENT.md](CLAUDE/HANDLER_DEVELOPMENT.md) for the complete guide.\n\n---\n\n## Daemon Management\n\n```bash\nVENV_PYTHON=.claude/hooks-daemon/untracked/venv/bin/python\n\n$VENV_PYTHON -m claude_code_hooks_daemon.daemon.cli status   # Check if running\n$VENV_PYTHON -m claude_code_hooks_daemon.daemon.cli restart  # Restart after handler changes\n$VENV_PYTHON -m claude_code_hooks_daemon.daemon.cli stop     # Stop daemon\n```\n\nThe daemon starts automatically on the first hook call and exits after 10 minutes of inactivity. Each project gets its own isolated daemon instance.\n\n---\n\n## Configuration\n\n**File**: `.claude/hooks-daemon.yaml`\n\n```yaml\nversion: \"2.0\"\n\ndaemon:\n  idle_timeout_seconds: 600\n  log_level: INFO\n\nhandlers:\n  pre_tool_use:\n    destructive_git:\n      enabled: true\n      priority: 10\n    sed_blocker:\n      enabled: true\n      priority: 10\n    tdd_enforcement:\n      enabled: true\n      priority: 25\n    british_english:\n      enabled: true\n      priority: 60\n      mode: warn  # \"warn\" or \"block\"\n\nproject_handlers:\n  enabled: true\n  path: .claude/project-handlers\n```\n\n### Tag-Based Filtering\n\nEnable only what's relevant to your tech stack:\n\n```yaml\nhandlers:\n  pre_tool_use:\n    enable_tags: [python, typescript, safety, tdd]\n    disable_tags: [ec-specific]\n```\n\n**Available tags:** `safety`, `tdd`, `qa-suppression-prevention`, `workflow`, `advisory`, `git`, `npm`, `python`, `typescript`, `javascript`, `php`, `go`\n\n---\n\n## Deterministic vs Agent-Based Hooks\n\nThe daemon is designed for **fast, deterministic validation**. For reasoning-heavy evaluation, use Claude Code's native agent-based hooks.\n\n| Use Daemon For | Use Agent Hooks For |\n|----------------|---------------------|\n| Pattern matching (regex, string checks) | Workflow compliance validation |\n| Fast synchronous validation | Context analysis (transcripts, git state) |\n| Reusable safety rules across sessions | Multi-turn investigation |\n| Deterministic, stateless logic | Reasoning and judgment calls |\n\n---\n\n## Git Integration\n\nWith `.claude/.gitignore` in place, your team shares hook configuration automatically:\n\n```\n.claude/\n├── .gitignore           # ✅ Commit\n├── settings.json        # ✅ Commit (hook registration)\n├── hooks-daemon.yaml    # ✅ Commit (handler settings)\n├── init.sh              # ✅ Commit (daemon lifecycle)\n├── hooks/               # ✅ Commit (forwarder scripts)\n└── hooks-daemon/        # ❌ Excluded (each dev installs their own)\n```\n\nNew team members get the same hooks automatically on first use. If your root `.gitignore` excludes `.claude/`, remove that entry — the per-directory `.gitignore` handles it correctly.\n\n---\n\n## Documentation\n\n- [Architecture](CLAUDE/ARCHITECTURE.md) — System design and components\n- [Handler Development](CLAUDE/HANDLER_DEVELOPMENT.md) — Creating custom handlers\n- [Project Handlers](CLAUDE/PROJECT_HANDLERS.md) — Per-project handler guide\n- [Debugging Hooks](CLAUDE/DEBUGGING_HOOKS.md) — Event introspection tool\n- [QA Pipeline](CLAUDE/development/QA.md) — Quality assurance automation\n- [Upgrade Guides](CLAUDE/UPGRADES/) — Version migration guides\n- [Bug Reporting](BUG_REPORTING.md) — Debug info generation\n\n---\n\n## Requirements\n\n- Python 3.11, 3.12, or 3.13\n- Linux or macOS (Windows has limited support — Unix sockets)\n- Dependencies auto-installed: `pyyaml`, `pydantic`, `jsonschema`\n\n---\n\n## Troubleshooting\n\nFor comprehensive troubleshooting and bug reporting, see [BUG_REPORTING.md](BUG_REPORTING.md).\n\n**Generate a debug report:**\n\n```bash\n# From the daemon project\n./scripts/debug_info.py /tmp/debug_report.md\n\n# From a client project\n.claude/hooks-daemon/scripts/debug_info.py /tmp/debug_report.md\n```\n\n**Common fixes:**\n\n```bash\n# Daemon won't start — check logs\n$VENV_PYTHON -m claude_code_hooks_daemon.daemon.cli logs\n\n# Force restart\n$VENV_PYTHON -m claude_code_hooks_daemon.daemon.cli restart\n\n# Verify hook forwarding works\necho '{\"hook_event_name\":\"PreToolUse\",\"tool_name\":\"Bash\",\"tool_input\":{\"command\":\"echo test\"}}' | \\\n  .claude/hooks/pre-tool-use\n# Expected: JSON with decision=\"allow\"\n```\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n1. Fork the repository\n2. Create a feature branch\n3. Write failing tests first (TDD)\n4. Implement the feature\n5. Run `./scripts/qa/run_all.sh` — all 8 checks must pass\n6. Submit a pull request\n\n---\n\n## License\n\nMIT License — Copyright © 2024–2026 Edmonds Commerce\n\n**Issues:** https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon/issues\n**Email:** hello@edmondscommerce.co.uk\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedmonds-commerce-limited%2Fclaude-code-hooks-daemon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedmonds-commerce-limited%2Fclaude-code-hooks-daemon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedmonds-commerce-limited%2Fclaude-code-hooks-daemon/lists"}