Skip to content
Development
Hook

Hooks

What ai-sdlc-harness runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.

From plugin
ai-sdlc-harness
208 skills3 agents4 hooks

Claude Code

> /plugin marketplace add MostAshraf/ai-sdlc-harness
> /plugin install ai-sdlc-harness@ai-sdlc-harness

What fires, and when

PreToolUse

  • MatchesBash|run_shell_commandexec "${CLAUDE_PLUGIN_ROOT}/hooks/run-guard" bash || ${CLAUDE_PLUGIN_ROOT}/hooks/run-guard bash
  • MatchesWrite|WriteFile|write_file|Edit|MultiEdit|NotebookEdit|notebook_exec "${CLAUDE_PLUGIN_ROOT}/hooks/run-guard" write || ${CLAUDE_PLUGIN_ROOT}/hooks/run-guard write
  • MatchesAgent|Taskexec "${CLAUDE_PLUGIN_ROOT}/hooks/run-guard" spawn || ${CLAUDE_PLUGIN_ROOT}/hooks/run-guard spawn
  • MatchesSkillexec "${CLAUDE_PLUGIN_ROOT}/hooks/run-guard" skill || ${CLAUDE_PLUGIN_ROOT}/hooks/run-guard skill
  • MatchesRead|ReadFile|read_file|Grep|grep_searchexec "${CLAUDE_PLUGIN_ROOT}/hooks/run-guard" read || ${CLAUDE_PLUGIN_ROOT}/hooks/run-guard read

UserPromptSubmit

Fires before Claude sees each prompt you send. A plugin can use it to inject context, so the same instruction reaches the model every turn instead of only at session start.

  • exec "${CLAUDE_PLUGIN_ROOT}/hooks/run-guard" user-prompt || ${CLAUDE_PLUGIN_ROOT}/hooks/run-guard user-prompt

PostToolUse

  • MatchesAgent|Taskexec "${CLAUDE_PLUGIN_ROOT}/hooks/run-guard" post-spawn || ${CLAUDE_PLUGIN_ROOT}/hooks/run-guard post-spawn

SubagentStop

  • exec "${CLAUDE_PLUGIN_ROOT}/hooks/run-guard" subagent-stop || ${CLAUDE_PLUGIN_ROOT}/hooks/run-guard subagent-stop
Read hooks/hooks.json

Where it lives

  • hooks/guards.pyGitHub
    Read the script
    #!/usr/bin/env python3
    """Plugin guard layer (design.md piece 3 + RC1/RC4 + invocation control).
    
    One dispatcher, selected by argv[1] — registered in hooks/hooks.json.
    Exit 0 = allow · exit 2 = block (stderr is the redirect-to-`harness` message).
    
    Per-guard policy (declared, a "keeping" from the original):
      bash            fail-open on unparseable payload — the HMAC chain (RC4) is
                      the guarantee for authority files; this guard is fast-fail.
                      Its raw-commit/merge/rebase/.../push block (GIT_VERB_RE) is
                      a STANDING, workspace-scoped invocation rule, not a
                      run-state guard: it applies for the life of a harness
                      workspace — from the moment `/init-workspace` completes,
                      regardless of whether any `ai/<run>/` currently exists —
                      unlike `spawn` below, there is no "no run yet" carve-out
                      for it (adversarial-review finding: previously
                      undocumented, easy to mistake for a run-scoped check like
                      the others in this list). It is NOT session- or repo-wide
                      beyond that: `_is_harness_workspace` gates it on the
                      `/init-workspace` bootstrap marker, so a session touching
                      an unrelated, never-initialized repo sees raw git
                      untouched — see `_is_harness_workspace` for the one
                      documented residual this leaves open.
      write           fail-open on unparseable payload; fail-closed on authority
                      paths (they are never legal via tools).
      spawn           FAIL-CLOSED: no run -> no harness-shape spawns beyond the
                      declared out_of_run exceptions; integrity failure blocks
                      spawn-legality from JUST the corrupt run, not the rest of
                      the workspace (harness reseal is the recovery verb).
      skill           fail-closed for user-entry skills from subagent context.
      user-prompt     never blocks (capture only).
      subagent-stop   never blocks (capture + stall detection feed events ledger).
    
    If PyYAML is missing, the yaml-needing guards DEGRADE OPEN with one visible
    remediation line on stderr (exit 0 — see main()'s YamlMissing handler; the
    yaml-free bash/write guards keep blocking); init-workspace verifies the
    dependency up front, and the HMAC chain (RC4) still detects authority-file
    tampering even with guards down — defense in depth, guard = fast-fail,
    chain = guarantee. The same posture covers a missing INTERPRETER: if the
    hook launcher pair (hooks/run-guard + run-guard.cmd, registered in
    hooks.json) finds no runnable python at all — including
    the Windows Store alias that answers to `python`/`python3` but only prints
    an install nag — the hook errors non-2 and the platform treats it as
    non-blocking. Accepted: pre-venv, nothing harness-y can execute anyway.
    """
    from __future__ import annotations
    
    import hashlib
    import json
    import os
    import re
    import sys
    import tempfile
    from pathlib import Path
    
    PLUGIN_ROOT = Path(__file__).resolve().parent.parent
    sys.path.insert(0, str(PLUGIN_ROOT))
    
    # stdlib-only modules at import time. `transitions` qualifies: it imports
    # nothing but json/sys/pathlib plus these two, and reaches for PyYAML only
    # lazily, inside the declared-data readers this file calls from paths that
    # have already loaded surfaces.yaml (i.e. already required it). `gates`
    # qualifies outright — hashlib + re, no I/O, no env — and is imported for
    # `session_digest` alone, so the capture hook and the CLI that writes the
    # stamp cannot drift into two different hashes of the same session id.
    from harness import chain, gates, ndjson, transitions  # noqa: E402
    
    
    class YamlMissing(Exception):
        pass
    
    
    def load_yaml(path: Path):
        """Lazy YAML — only the spawn/skill guards need it. The bash/write/capture
        guards are pure regex+payload and must keep working (and blocking!) on a
        Python without PyYAML, e.g. macOS system python3 before setup."""
        try:
            import yaml
        except ImportError:
            raise YamlMissing(
                "ai-sdlc-harness: PyYAML missing for this hook's interpreter — "
                "/init-workspace bootstraps the plugin venv; until then this "
                "guard degrades open.") from None
        with path.open(encoding="utf-8") as fh:
            return yaml.safe_load(fh)
    
    
    _TERMINAL_CACHE: tuple = ()
    
    
    def _terminal_statuses() -> tuple:
        """The task FSM's declared terminal statuses — the SAME `terminal:` list
        `harness.transitions.terminal_statuses` reads, not a second copy. A guard
        that disagreed with the engine about what "finished" means would refuse a
        spawn the engine considers legal, or wave one through that it doesn't."""
        global _TERMINAL_CACHE
        if not _TERMINAL_CACHE:
            fsm = load_yaml(PLUGIN_ROOT / "pipeline" / "task-fsm.yaml") or {}
            _TERMINAL_CACHE = tuple(fsm.get("terminal") or ())
        return _TERMINAL_CACHE
    
    # A single "word" a flag's value can take — a whole quoted string (its
    # space(s) included) counts as ONE token, not just up to the first
    # whitespace (adversarial-review round 3 finding: plain `\S+` matched only
    # `-C "my` out of `-C "my repo" commit`, leaving `repo" commit` unable to
    # reach the verb — silently reopening the bypass for any quoted,
    # space-containing flag value). Round 4 finding: a token can also be a MIX
    # of bare and quoted segments the way the shell itself tokenizes —
    # `-c user.name="My Name"` is ONE shell word, but the round-3 alternation
    # (whole-quoted OR \S+) consumed only `user.name="My` and the parse died
    # before the verb, reopening the same bypass one level down. One-or-more
    # runs of (quoted segment | bare segment) matches shell word semantics.
    _GIT_TOKEN = r"""(?:"[^"]*"|'[^']*'|[^\s"'|;&])+"""
    # `git` not immediately preceded by a quote char (adversarial-review round
    # 3 finding): without this, `grep -rn 'git reset --hard' .` — a pure read,
    # searching for the LITERAL PHRASE — blocked, because "git reset --har

Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.

@mostashraf
Ships withai-sdlc-harness

A governed multi-agent SDLC pipeline for Claude Code and Qwen Code — a ground-up rewrite of ai-sdlc-harness.

208 skills3 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
20
Star history of MostAshraf/ai-sdlc-harness on GitHub, a chart by star-history.com

More plugins that ship hooks.

superpowers

superpowers

A development methodology for coding agents that makes the agent brainstorm before building, follow plans, run parallel work and finish branches in a disciplined way. You get fewer skipped steps and more consistent results from your coding assistant.

15 skills1 hook311k
@obra@obra
Install Plugin
ponytail

ponytail

A Claude Code plugin with skills for auditing a whole repo, reviewing a change, listing deferred shortcut comments, and showing measured savings and a quick command reference.

6 skills10 hooks188k
@dietrichgebert@dietrichgebert
Install Plugin
agent-skills

agent-skills

Walks a software change from a written spec through design, testing, code review, CI/CD, and release, applying the matching engineering skill at each stage. Useful for developers using Claude Code on full development workflows.

25 skills+3112k
@addyosmani@addyosmani
Install Plugin
planning-with-files

planning-with-files

Persistent file-based planning for AI coding agents on long-running, multi-step tasks. It keeps task_plan.md, findings.md and progress.md on disk, so work can resume after /clear or context compaction.

6 skills+228k
@othmanadi@othmanadi
Install Plugin
gsd-core

gsd-core

A spec-driven development workflow for Claude Code that guides a project through planning, phases, milestone audits and fixes. Includes skills to generate tests from UAT criteria and to audit completed work.

72 skills+311k
@open-gsd@open-gsd
Install Plugin
superpowers-zh

superpowers-zh

Chinese-language skill pack for Claude Code that adds workflow guidance for brainstorming, TDD, debugging, and code review, plus Chinese conventions for commits, documentation, and domestic Git platforms like Gitee and Coding.net.

21 skills1 hook8.5k
@jnmetacode@jnmetacode
Install Plugin
socraticode

socraticode

Gives Claude Code semantic search, dependency graph and architecture context over a codebase, so an AI assistant can explore and understand a project's code. Includes skills for indexing a project and managing its file watching.

2 skills+33.4k
@giancarloerra@giancarloerra
Install Plugin
cocoindex-code

cocoindex-code

A lightweight code search engine that uses AST-based semantic search with local embeddings and incremental indexing. It helps Claude Code users find code faster and more efficiently.

1 skill1 MCP+13k
@cocoindex-io@cocoindex-io
Install Plugin

Questions about the hooks in ai-sdlc-harness.

Which coding agents can use the hooks in ai-sdlc-harness?
The hooks in ai-sdlc-harness install in Claude Code and Cursor: each runs Claude Code hooks from .claude/settings.json, so copy the hooks there.