From 6612cd91632c2712ffe388b31297f8278e4c7284 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Sun, 26 Jul 2026 12:06:29 +0700 Subject: [PATCH] fix(hooks): configure via settings.local.json not plugin hooks.json Skills-dir plugins (~/.claude/skills/) may not execute hooks from hooks/hooks.json. Per documentation, hooks need to be in settings files. - install.sh: add hook registration in ~/.claude/settings.local.json - Hooks use absolute paths to hub-guide scripts - SessionStart matcher: startup|resume|compact - PreToolUse matcher: Write|Edit - Remove hooks/hooks.json from plugin (redundant for skills-dir) --- hooks/hooks.json | 31 ------------------ install.sh | 85 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 69 insertions(+), 47 deletions(-) delete mode 100644 hooks/hooks.json diff --git a/hooks/hooks.json b/hooks/hooks.json deleted file mode 100644 index 9c41490..0000000 --- a/hooks/hooks.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "hooks": { - "SessionStart": [ - { - "matcher": "startup|resume|compact", - "hooks": [ - { - "type": "command", - "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/scripts/detect-project.sh\"", - "shell": "bash", - "timeout": 10, - "async": false - } - ] - } - ], - "PreToolUse": [ - { - "matcher": "Write|Edit", - "hooks": [ - { - "type": "command", - "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/scripts/detect-file-type.sh\"", - "shell": "bash", - "timeout": 10 - } - ] - } - ] - } -} diff --git a/install.sh b/install.sh index 8d77f2c..0b2a2e9 100755 --- a/install.sh +++ b/install.sh @@ -1,33 +1,32 @@ #!/bin/bash # install.sh — hub-guide installer for Claude Code -# -# Installs the entire hub-guide directory as one unit into ~/.claude/skills/. -# Claude Code auto-discovers skills from ~/.claude/skills//skills//SKILL.md -# +# Installs skills to ~/.claude/skills/ + configures hooks in settings.local.json # Usage: -# ./install.sh # Copy hub-guide to ~/.claude/skills/ -# ./install.sh --link # Symlink (edits live) -# -# Requires: Claude Code +# ./install.sh # Copy + hooks +# ./install.sh --link # Symlink (edits live) + hooks +# ./install.sh --no-hooks # Skills only, no hook setup +# Requires: Claude Code, python3 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SKILLS_DIR="${HOME}/.claude/skills" LINK_MODE=false +NO_HOOKS=false for arg in "$@"; do case "$arg" in --link) LINK_MODE=true ;; + --no-hooks) NO_HOOKS=true ;; --*) echo "Unknown: $arg"; exit 1 ;; esac done -echo "📐 hub-guide installer" -echo " Target: ${SKILLS_DIR}/hub-guide/" -echo " Mode: $([ "$LINK_MODE" = true ] && echo 'symlink' || echo 'copy')" -echo "" +echo "hub-guide installer" +echo " target: ${SKILLS_DIR}/hub-guide/" +echo " mode: $([ "$LINK_MODE" = true ] && echo 'symlink' || echo 'copy')" +# --- install skills --- mkdir -p "$SKILLS_DIR" DST="${SKILLS_DIR}/hub-guide" @@ -39,10 +38,64 @@ else cp -r "$SCRIPT_DIR" "$DST" fi -echo "✅ hub-guide installed to ${DST}/" +echo " skills installed to ${DST}/" if [ "$LINK_MODE" = true ]; then - echo " (symlink — edits in this repo are live)" + echo " (symlink)" fi + +# --- configure hooks in settings.local.json --- +if [ "$NO_HOOKS" = false ]; then + HOOKS_DIR="${DST}/hooks" + SETTINGS_FILE="${HOME}/.claude/settings.local.json" + + python3 << PYEOF +import json, os + +dst = "${DST}" +settings_file = os.path.expanduser("${SETTINGS_FILE}") + +# Read existing settings or create empty +settings = {} +if os.path.exists(settings_file): + with open(settings_file) as f: + settings = json.load(f) + +# Ensure hooks key exists +if "hooks" not in settings: + settings["hooks"] = {} + +hooks_config = { + "SessionStart": [{ + "matcher": "startup|resume|compact", + "hooks": [{ + "type": "command", + "command": "bash \"" + dst + "/hooks/scripts/detect-project.sh\"", + "timeout": 10, + "async": False + }] + }], + "PreToolUse": [{ + "matcher": "Write|Edit", + "hooks": [{ + "type": "command", + "command": "bash \"" + dst + "/hooks/scripts/detect-file-type.sh\"", + "timeout": 10 + }] + }] +} + +# Merge hooks into settings (update existing, don't overwrite unrelated hooks) +for event, handlers in hooks_config.items(): + settings["hooks"][event] = handlers + +os.makedirs(os.path.dirname(settings_file), exist_ok=True) +with open(settings_file, 'w') as f: + json.dump(settings, f, indent=2) + +print(" hooks configured in " + settings_file) +PYEOF +fi + echo "" -echo " Restart Claude Code or run /reload." -echo " Skills auto-trigger when you work — no commands needed." +echo "Done. Restart Claude Code or run /reload." +echo "Skills auto-trigger when you work."