Files
hooks/skills/hooks-install/SKILL.md
T

6.3 KiB

name, description
name description
hooks-install Wire jsc hooks (STE100 guard, session timer, skill usage logger, SDLC model gate, plugin version guard) into every installed AI CLI, purging all pre-existing hooks first — third-party ones included, backed up before removal. Drive it per CLI through tools/wire-cli.sh purge, tools/wire-cli.sh, tools/wire-cli.sh smoke and tools/scan-hook-errors.sh. Hand any hook error, wiring or runtime, to jsc-hooks:repair, which must finish with a PR against develop; aborting the rest of the install to start that repair is allowed. Use after installing or updating the jsc plugin set; not for writing new hooks.

hooks-install — wire jsc hooks into every installed CLI

Goal: make the five hooks (ste100-guard.sh, session-timer.sh, skill-usage.sh, sdlc-gate.sh, version-guard.sh) effective in every CLI, with nothing else wired alongside them.

Install on a clean slate. Every CLI is purged of all hooks first, third-party ones included, so a later failure has exactly one owner. tools/wire-cli.sh purge backs up every file it touches before it removes anything, so the removal stays reversible.

Only claude has both PreToolUse and UserPromptSubmit, so only claude reports wired. On codex, copilot, antigravity and kiro the version guard cannot be wired at all and the SDLC gate degrades to the skill-step check, so all four report degraded — report that gap as the script words it instead of implying every CLI is covered. The lock file still works on those four because the SDLC skills call sdlc-gate.sh lock {stage} directly — that call is where the capability-tag comparison happens, so the gate keeps its force even where the prompt hook cannot be wired. The gate needs $JSC_HOME/model-tags.tsv; when it is missing, report that jsc-cli:models (or jsc-cli/tools/model-tags.sh sync) must run once, because sdlc-gate.sh lock refuses to lock without it.

Treat any hook error as repair work, whether it appeared while wiring or while running. Stopping the remaining installs to start that repair is the right call; leaving a broken hook wired is not.

The detailed flow MUST run as a sub agent; the main agent only reports the summary.

Steps

  1. Run jsc-cli/tools/detect-clis.sh. Done when you hold the list of installed CLIs; when the list is empty, report that and stop.
  2. For each installed CLI, run tools/wire-cli.sh purge {cli}. The script backs up every file it touches, removes all hooks, re-reads each file to confirm the removal, and restores the backup by itself when a check fails. Done when every CLI has printed exactly one status=purged|skipped|failed reason=... line and you have noted the backup directory path from its [jsc] output.
  3. For each installed CLI, run tools/wire-cli.sh {cli}. The script owns both the wiring and its verification: it writes the config, alias or hook file inside a <!-- jsc-hooks --> (or # jsc-hooks) marker block, re-reads every file it wrote, and confirms the block is present and correctly placed before it prints a success status. Trust its first line, status=wired|degraded|skipped|failed reason=.... Exit 2 means a bad CLI name, not a wiring outcome — fix the name and rerun. Done when every installed CLI has printed exactly one status= line and none exited 2.
  4. For each installed CLI, run tools/wire-cli.sh smoke {cli}. This runs all five hooks once each and catches what the wiring check cannot see: a hook that is wired correctly and still fails when it executes. Done when every CLI has printed one status=ok|failed reason=... line plus one result line per hook.
  5. For each installed CLI, run tools/scan-hook-errors.sh --cli {cli}. Only claude keeps hook results in its native records and can answer clean or errors; codex, copilot, antigravity and kiro answer unavailable, and their runtime evidence comes from step 4 alone. Done when every CLI has printed one status=clean|errors|unavailable reason=... line and the four unavailable CLIs are reported as exactly that, not as clean.
  6. For each error — purge failed, wiring failed, smoke failed, or a scanned error with jsc=true — run tools/report-error.sh --hook {script name} --exit {code} --summary "{reason}" --cli {cli} with the script's [jsc] output on stdin, then hand the failure to jsc-hooks:repair, which MUST run as a sub agent and must finish by opening a PR against develop. Aborting the remaining installs here is allowed as long as the repair starts. A scanned error with jsc=false belongs to a third-party hook: report it and leave it alone. Done when each error has either an ERROR_{HASH} page name on stdout, or an empty exit 0 meaning JSC_WIKI_REPO_ERROR and JSC_WIKI_REPO are both unset — in that second case carry the reason into step 7 instead. Skip this step when every CLI passed all four checks.
  7. Report four results per CLI — purge, wiring, smoke, scan — each with the reason its script printed, plus any ERROR_{HASH} page name and repair PR URL. Done when every detected CLI has exactly one status per check and every repair has a PR against develop.

Notes

  • Every hook script accepts both stdin JSON and environment variables (JSC_CLI, JSC_SESSION_ID, JSC_SKILL, JSC_TOOL_NAME, JSC_MODEL); jsc-wrap.sh sets the first two itself.
  • session-timer.sh takes start (keep an existing start time), restart (always overwrite it, for a CLI with no session id — kiro), mark and report. wire-cli.sh picks the right one per CLI; do not hand-edit the generated hook files.
  • purge reaches the user-level config only. Hooks that another plugin ships in its own hooks.json stay active, and uninstalling that plugin is the only way to clear them — say so when reporting, and treat their errors as third-party.
  • Backups land in $JSC_HOME/backup/hooks/{cli}/{yyyyMMdd_HHmmss}/, one directory per purge run, under the original file names. Hand that path to the user whenever a purge removed something.
  • smoke treats sdlc-gate.sh check exit 2 as healthy: that exit is the stage lock blocking a turn on purpose, not a runtime error.
  • tools/report-error.sh is operator- or skill-invoked only. Never wire it to fire from a failing hook: hooks stay silent and exit 0, and a failing hook that reports itself can loop.
  • Data lands in $JSC_HOME (default ~/.jsc), consumed by jsc-log:worklog and jsc-log:stats.