From bc9a88328d2a6765dad6e722d414a527622bf8d6 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Sun, 26 Jul 2026 14:21:54 +0700 Subject: [PATCH] refactor(hooks): use sessionStart.skill instead of command hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace SessionStart command hook with plugin.json's native sessionStart.skill field (like Superpowers' using-superpowers pattern) - engineering-principles skill auto-loads at every session start - Remove hooks/session-start, hooks/run-hook.cmd scripts - Remove obsolete setup-hooks.sh (references deleted scripts) - Empty hooks.json — hooks not needed, skill auto-load handles it --- .claude-plugin/plugin.json | 4 +- hooks/hooks.json | 15 +------- hooks/run-hook.cmd | 44 ---------------------- hooks/session-start | 77 -------------------------------------- setup-hooks.sh | 58 ---------------------------- 5 files changed, 4 insertions(+), 194 deletions(-) delete mode 100755 hooks/run-hook.cmd delete mode 100755 hooks/session-start delete mode 100755 setup-hooks.sh diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 6886039..8d48f9d 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -8,5 +8,7 @@ }, "keywords": ["best-practice", "clean-code", "engineering-guide", "programming-standards", "architecture"], "skills": "./skills/", - "hooks": "./hooks/hooks.json" + "sessionStart": { + "skill": "engineering-principles" + } } diff --git a/hooks/hooks.json b/hooks/hooks.json index 79d8cee..deffac9 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -1,16 +1,3 @@ { - "hooks": { - "SessionStart": [ - { - "matcher": "startup|clear|compact", - "hooks": [ - { - "type": "command", - "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" session-start", - "async": false - } - ] - } - ] - } + "hooks": {} } diff --git a/hooks/run-hook.cmd b/hooks/run-hook.cmd deleted file mode 100755 index f80101b..0000000 --- a/hooks/run-hook.cmd +++ /dev/null @@ -1,44 +0,0 @@ -: << 'CMDBLOCK' -@echo off -REM Cross-platform polyglot wrapper for hook scripts. -REM On Windows: cmd.exe runs the batch portion, which finds and calls bash. -REM On Unix: the shell interprets this as a script (: is a no-op in bash). -REM -REM Hook scripts use extensionless filenames so Claude Code's Windows -REM auto-detection doesn't interfere. -REM -REM Usage: run-hook.cmd [args...] - -if "%~1"=="" ( - echo run-hook.cmd: missing script name >&2 - exit /b 1 -) - -set "HOOK_DIR=%~dp0" - -REM Try Git for Windows bash in standard locations -if exist "C:\Program Files\Git\bin\bash.exe" ( - "C:\Program Files\Git\bin\bash.exe" "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9 - exit /b %ERRORLEVEL% -) -if exist "C:\Program Files (x86)\Git\bin\bash.exe" ( - "C:\Program Files (x86)\Git\bin\bash.exe" "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9 - exit /b %ERRORLEVEL% -) - -REM Try bash on PATH -where bash >nul 2>nul -if %ERRORLEVEL% equ 0 ( - bash "%HOOK_DIR%%~1" %2 %3 %4 %5 %6 %7 %8 %9 - exit /b %ERRORLEVEL% -) - -REM No bash found — exit silently -exit /b 0 -CMDBLOCK - -# Unix: run the named script directly -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -SCRIPT_NAME="$1" -shift -exec bash "${SCRIPT_DIR}/${SCRIPT_NAME}" "$@" diff --git a/hooks/session-start b/hooks/session-start deleted file mode 100755 index 2291fb9..0000000 --- a/hooks/session-start +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash -# SessionStart hook for code-guide plugin -# Injects mandatory skill context at session start (like Superpowers pattern) - -set -euo pipefail - -# Determine plugin root directory -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" - -SKILLS_DIR="${PLUGIN_ROOT}/skills" - -# Build the context string by extracting descriptions from mandatory skill SKILL.md files -build_context() { - local ctx="" - - ctx="${ctx}\n" - ctx="${ctx}You have the code-guide plugin loaded. The following MANDATORY skills apply to EVERY coding task — load them via the Skill tool whenever relevant:\n\n" - - # Read each mandatory skill's frontmatter - local mandatory="engineering-principles clean-code clean-architecture testing error-handling security git-workflow api-design" - - for skill in $mandatory; do - local file="${SKILLS_DIR}/${skill}/SKILL.md" - if [ -f "$file" ]; then - # Extract description line — strip "description:" prefix and optional quotes - local desc - desc=$(grep "^description:" "$file" | head -1 | cut -d: -f2- | tr -d '\n') - desc="${desc#\"}" # strip leading quote if present - desc="${desc%\"}" # strip trailing quote if present - desc="$(echo "$desc" | awk '{$1=$1};1')" # trim whitespace - ctx="${ctx}• code-guide:${skill} — ${desc}\n" - fi - done - - ctx="${ctx}\n" - - # Add non-mandatory skills list (so Claude knows they exist) - ctx="${ctx}Other available skills (non-mandatory — trigger when relevant):\n" - ctx="${ctx}typescript, python, rust, go, react-frontend, nextjs, hono-backend, elysiajs, drizzle-database, docker, ci-cd, monitoring, logging-observability, performance, documentation, design-patterns, monorepo\n" - - ctx="${ctx}\n" - ctx="${ctx}Rules you MUST follow at all times:\n" - ctx="${ctx}1. NEVER suppress lints/type errors — fix the code instead.\n" - ctx="${ctx}2. NEVER assume — show evidence from codebase/docs for everything.\n" - ctx="${ctx}3. ASK when ambiguous — don't silently pick one interpretation.\n" - ctx="${ctx}4. Use the Workflow tool for complex multi-step tasks that need parallel execution or adversarial verification.\n" - ctx="${ctx}5. Fix root causes, not symptoms — patch the shared function, not every caller.\n" - ctx="${ctx}6. Tests come first — code without tests is legacy code.\n" - ctx="${ctx}7. The simplest solution that works is the correct one (YAGNI/KISS).\n" - ctx="${ctx}8. Leave every module cleaner than you found it (Boy Scout Rule).\n" - - ctx="${ctx}\n" - ctx="${ctx}When you need the full content of any skill, use the Skill tool to load it.\n" - ctx="${ctx}" - - printf '%s' "$ctx" -} - -# Escape string for JSON embedding -escape_for_json() { - local s="$1" - s="${s//\\/\\\\}" - s="${s//\"/\\\"}" - s="${s//$'\n'/\\n}" - s="${s//$'\r'/\\r}" - s="${s//$'\t'/\\t}" - printf '%s' "$s" -} - -context=$(build_context) -escaped_context=$(escape_for_json "$context") - -# Output JSON for Claude Code (hookSpecificOutput.additionalContext format) -printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"%s"}}\n' "$escaped_context" - -exit 0 diff --git a/setup-hooks.sh b/setup-hooks.sh deleted file mode 100755 index c1c1cb5..0000000 --- a/setup-hooks.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -# setup-hooks.sh — Configure code-guide hooks in Claude Code -# -# Adds code-guide hooks to ~/.claude/settings.local.json -# This allows Claude to auto-detect your project and suggest relevant skills. -# -# Usage: ./setup-hooks.sh - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SETTINGS_FILE="${HOME}/.claude/settings.local.json" - -echo "code-guide hooks setup" - -python3 << PYEOF -import json, os - -script_dir = os.path.dirname(os.path.abspath(__file__)) -settings_file = os.path.expanduser("~/.claude/settings.local.json") - -# Read existing or create empty -if os.path.exists(settings_file): - with open(settings_file) as f: - cfg = json.load(f) -else: - cfg = {} - -# Build hooks config -cfg["hooks"] = { - "SessionStart": [{ - "hooks": [{ - "type": "command", - "command": f"bash \"{script_dir}/hooks/scripts/detect-project.sh\"", - "timeout": 10 - }] - }], - "PreToolUse": [{ - "matcher": "Write|Edit", - "hooks": [{ - "type": "command", - "command": f"bash \"{script_dir}/hooks/scripts/detect-file-type.sh\" \"\$TOOL_INPUT\"", - "timeout": 10 - }] - }] -} - -# Ensure parent dir exists -os.makedirs(os.path.dirname(settings_file), exist_ok=True) - -with open(settings_file, 'w') as f: - json.dump(cfg, f, indent=2) - -print(f"Hooks configured in {settings_file}") -PYEOF - -echo "" -echo "Restart Claude Code or run /reload to activate hooks."