From 95c77c694f69e2d5ea1253b0009bf150e956f50c Mon Sep 17 00:00:00 2001 From: asepharyana Date: Sun, 26 Jul 2026 14:24:52 +0700 Subject: [PATCH] fix(hooks): restore Superpowers-style SessionStart command hook Properly follow Superpowers 6.1.1 pattern: - SessionStart command hook (type: command) runs run-hook.cmd session-start - run-hook.cmd is a cross-platform polyglot wrapper (Unix/Windows) - session-start script reads engineering-principles/SKILL.md and injects it as additionalContext wrapped in EXTREMELY_IMPORTANT tags - The 29 engineering principles are active in context from turn 1 plugin.json: remove sessionStart.skill, keep skills: ./skills/ The command hook is the primary mechanism (just like Superpowers' using-superpowers). --- .claude-plugin/plugin.json | 5 +---- README.md | 26 ++++++++++++------------ hooks/hooks.json | 15 +++++++++++++- hooks/run-hook.cmd | 41 ++++++++++++++++++++++++++++++++++++++ hooks/session-start | 35 ++++++++++++++++++++++++++++++++ install.ps1 | 2 +- install.sh | 4 ++-- 7 files changed, 107 insertions(+), 21 deletions(-) create mode 100755 hooks/run-hook.cmd create mode 100755 hooks/session-start diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 8d48f9d..6ff1a4e 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -7,8 +7,5 @@ "email": "asepharyana@users.noreply.github.com" }, "keywords": ["best-practice", "clean-code", "engineering-guide", "programming-standards", "architecture"], - "skills": "./skills/", - "sessionStart": { - "skill": "engineering-principles" - } + "skills": "./skills/" } diff --git a/README.md b/README.md index eca17aa..6957b0a 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ A Claude Code plugin serving as a complete engineering guide for **all programmi | **Infrastructure** | docker, ci-cd, monitoring | | **Monorepo** | monorepo (patterns + submodules + workspace tooling) | -Skills activate automatically when Claude detects relevant context (language, framework, topic). +Skills activate automatically when Claude detects relevant context. -### Auto-Loaded Skill +### SessionStart Hook -`engineering-principles` (29 principles) auto-loads at every session start — correctness, YAGNI, KISS, DRY, never assume, never suppress lints, show evidence, and more. This ensures foundational rules are always active. +A SessionStart command hook (identical to Superpowers' pattern) injects the full `engineering-principles` skill content into context at every session start — all 29 principles covering correctness, YAGNI, KISS, DRY, never assume (show evidence), never suppress lints, root-cause fixes, and more. These rules are active from turn 1. ## Installation @@ -50,18 +50,18 @@ code-guide/ ├── .claude-plugin/ │ └── plugin.json # Plugin manifest ├── hooks/ -│ └── hooks.json # Reserved for future use +│ ├── hooks.json # SessionStart command hook config +│ ├── run-hook.cmd # Cross-platform polyglot wrapper +│ └── session-start # Injects engineering-principles into context ├── skills/ -│ ├── clean-code/ # 24 skill directories -│ └── ... +│ ├── engineering-principles/ # Auto-injected at session start +│ ├── clean-code/ +│ ├── ... └── README.md ``` -## Development +## How It Works -Skills are in `skills//SKILL.md` format (modern Claude Code plugin convention). Each skill includes: - -- **Frontmatter** — `name` and `description` with trigger context -- **Lean body** — key rules, examples, and anti-patterns - -The `engineering-principles` skill auto-loads via plugin.json's `sessionStart.skill` field (same pattern as Superpowers' `using-superpowers`). +- **SessionStart hook** runs `hooks/run-hook.cmd session-start` which reads `skills/engineering-principles/SKILL.md` and injects it into the conversation context wrapped in `` tags (same pattern as Superpowers' `using-superpowers`). +- All 24 skills are auto-discovered from the `skills/` directory. +- Skills activate when Claude detects relevant context — no manual commands needed. diff --git a/hooks/hooks.json b/hooks/hooks.json index deffac9..79d8cee 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -1,3 +1,16 @@ { - "hooks": {} + "hooks": { + "SessionStart": [ + { + "matcher": "startup|clear|compact", + "hooks": [ + { + "type": "command", + "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" session-start", + "async": false + } + ] + } + ] + } } diff --git a/hooks/run-hook.cmd b/hooks/run-hook.cmd new file mode 100755 index 0000000..bd1356d --- /dev/null +++ b/hooks/run-hook.cmd @@ -0,0 +1,41 @@ +: << '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 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 new file mode 100755 index 0000000..5e60336 --- /dev/null +++ b/hooks/session-start @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# SessionStart hook for code-guide plugin. +# Reads engineering-principles SKILL.md and injects it as context +# so the 29 foundational principles are always active from turn 1. +# +# Pattern: identical to Superpowers' session-start hook +# which injects skills/using-superpowers/SKILL.md content. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" + +skill_content=$(cat "${PLUGIN_ROOT}/skills/engineering-principles/SKILL.md" 2>&1 || echo "Error reading engineering-principles skill") + +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" +} + +escaped=$(escape_for_json "$skill_content") +context="\nYou have the code-guide plugin loaded. Below is the full content of the 'code-guide:engineering-principles' skill — the 29 foundational rules that apply to every coding decision:\n\n${escaped}\n" + +if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then + printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"%s"}}\n' "$context" +else + printf '{"additionalContext":"%s"}\n' "$context" +fi + +exit 0 diff --git a/install.ps1 b/install.ps1 index e12c7e6..84827f7 100644 --- a/install.ps1 +++ b/install.ps1 @@ -30,4 +30,4 @@ if ($Link) { Write-Host "" Write-Host "Done. Restart Claude Code or run /reload." -Write-Host "Skills auto-trigger. engineering-principles skill auto-loads at session start." +Write-Host "Skills auto-trigger. SessionStart hook injects engineering-principles into context." diff --git a/install.sh b/install.sh index 075096d..994c4b0 100755 --- a/install.sh +++ b/install.sh @@ -1,7 +1,7 @@ #!/bin/bash # install.sh — code-guide installer for Claude Code # Installs the entire code-guide directory as one unit into ~/.claude/skills/. -# Skills auto-discover, engineering-principles auto-loads at session start. +# Skills auto-discover. SessionStart hook injects engineering-principles into context. # Usage: # ./install.sh # Copy code-guide to ~/.claude/skills/ # ./install.sh --link # Symlink (edits live) @@ -41,4 +41,4 @@ if [ "$LINK_MODE" = true ]; then fi echo "" echo "Done. Restart Claude Code or run /reload." -echo "Skills auto-trigger. engineering-principles skill auto-loads at session start." +echo "Skills auto-trigger. SessionStart hook injects engineering-principles into context."