Skip to content

Hooks

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

From plugin
deadeye
69 skills3 commands8 hooks

Claude Code

> /plugin marketplace add deepaksinghcs14/deadeye-cc
> /plugin install deadeye@deadeye

What fires, and when

SessionStart

Fires once when a session begins, and again after a context compaction. It is where a plugin sets up its environment, or restores state the compaction dropped.

  • "${CLAUDE_PLUGIN_ROOT}/hooks/deadeye-hook.sh" SessionStart

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.

  • "${CLAUDE_PLUGIN_ROOT}/hooks/deadeye-hook.sh" UserPromptSubmit

PreToolUse

  • MatchesAgent"${CLAUDE_PLUGIN_ROOT}/hooks/deadeye-hook.sh" PreToolUse
  • MatchesBash|Edit|Write|Read|Grep|WebFetch|Workflow"${CLAUDE_PLUGIN_ROOT}/hooks/deadeye-hook.sh" PreToolUse

PostToolUse

  • MatchesBash|Edit|Write|Agent|Read|Grep|Glob|WebFetch|WebSearch|mcp__.*"${CLAUDE_PLUGIN_ROOT}/hooks/deadeye-hook.sh" PostToolUse

SubagentStart

  • "${CLAUDE_PLUGIN_ROOT}/hooks/deadeye-hook.sh" SubagentStart

SubagentStop

  • "${CLAUDE_PLUGIN_ROOT}/hooks/deadeye-hook.sh" SubagentStop

Stop

  • "${CLAUDE_PLUGIN_ROOT}/hooks/deadeye-hook.sh" Stop

SessionEnd

  • "${CLAUDE_PLUGIN_ROOT}/hooks/deadeye-hook.sh" SessionEnd
Read hooks/hooks.json

Where it lives

  • hooks/bootstrap.shGitHub
    Read the script
    #!/usr/bin/env bash
    # Best-effort background download of the deadeye release binary, sha256
    # checksum-verified against the release's checksums.txt. Silent on any
    # failure -- by the time this runs, the hook that spawned it has already
    # returned {} to Claude Code (INV-5).
    #
    # Also doubles as the update path: an install is only skipped if it's
    # already at the version plugin.json declares. Comparing against a local
    # file (rather than querying GitHub for "latest") avoids a network round
    # trip on every check -- deadeye-hook.sh calls this at most once per
    # session, but it's still cheap to keep cheap.
    set -u
    
    REPO="deepaksinghcs14/deadeye-cc"
    DEST_DIR="$HOME/.deadeye/bin"
    DEST="$DEST_DIR/deadeye"
    LOCK_DIR="$DEST_DIR/.bootstrap.lock"
    INSTALL_TMP=""
    
    mkdir -p "$DEST_DIR" 2>/dev/null || exit 0
    # `mkdir -p -m` only guarantees the mode on the deepest directory (BSD and
    # GNU mkdir both leave intermediate dirs at the process umask), and this is
    # the path that FIRST creates ~/.deadeye on a fresh machine -- chmod both
    # explicitly so the state dir matches the 0700 every Go writer in this repo
    # assumes, regardless of the caller's umask.
    chmod 700 "$HOME/.deadeye" "$DEST_DIR" 2>/dev/null
    
    # One install/update at a time. deadeye-hook.sh only fires this on
    # SessionStart, but two Claude Code windows can start within the same
    # second -- without this, both race to curl+mv onto the same destination.
    # `mkdir` as a lock is atomic even across processes/machines sharing $HOME.
    if ! mkdir "$LOCK_DIR" 2>/dev/null; then
      # Someone else is already installing. If that lock is old enough to be
      # from a run that was SIGKILLed mid-install rather than one still in
      # progress, clear it and take over; otherwise just exit -- the next
      # SessionStart retries.
      if [ -n "$(find "$LOCK_DIR" -maxdepth 0 -mmin +10 2>/dev/null)" ]; then
        rmdir "$LOCK_DIR" 2>/dev/null
        mkdir "$LOCK_DIR" 2>/dev/null || exit 0
      else
        exit 0
      fi
    fi
    trap 'rmdir "$LOCK_DIR" 2>/dev/null; rm -f "$INSTALL_TMP"' EXIT
    
    PLUGIN_VERSION=""
    if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && [ -f "$CLAUDE_PLUGIN_ROOT/.claude-plugin/plugin.json" ]; then
      PLUGIN_VERSION="$(grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' "$CLAUDE_PLUGIN_ROOT/.claude-plugin/plugin.json" | head -1 | sed -E 's/.*"([^"]+)"$/\1/')"
    fi
    
    if [ -x "$DEST" ]; then
      # Can't tell whether it's stale without a version to compare against --
      # leave a working binary alone rather than guess.
      [ -z "$PLUGIN_VERSION" ] && exit 0
      INSTALLED_VERSION="$("$DEST" version 2>/dev/null | awk '{print $2}')"
      [ "$INSTALLED_VERSION" = "$PLUGIN_VERSION" ] && exit 0
    fi
    command -v curl >/dev/null 2>&1 || exit 0
    
    OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
    ARCH="$(uname -m)"
    case "$ARCH" in
      x86_64) ARCH="amd64" ;;
      arm64|aarch64) ARCH="arm64" ;;
      *) exit 0 ;;
    esac
    
    LATEST_URL="https://github.com/${REPO}/releases/latest/download"
    ASSET="deadeye_${OS}_${ARCH}"
    TMP="$(mktemp -d)" || exit 0
    trap 'rmdir "$LOCK_DIR" 2>/dev/null; rm -f "$INSTALL_TMP"; rm -rf "$TMP"' EXIT
    
    # Pin to the checked-out plugin's own version rather than always pulling
    # "latest" -- otherwise the version comparison above (against
    # plugin.json) and what actually gets downloaded (always latest) can
    # permanently disagree, re-downloading the full binary every single
    # session without ever converging. Fall back to latest once if the
    # pinned tag 404s (checkout ahead of the release, or an older plugin
    # checkout with no matching release asset name).
    if [ -n "$PLUGIN_VERSION" ]; then
      BASE_URL="https://github.com/${REPO}/releases/download/v${PLUGIN_VERSION}"
    else
      BASE_URL="$LATEST_URL"
    fi
    
    # A plugin version whose release assets don't exist yet (the minutes between
    # a tag and its finished build -- or forever, if that build failed) falls
    # back to `latest`, which installs something still BEHIND plugin.json. The
    # hook then sees "managed < plugin" again next session and re-downloads, on
    # every session, indefinitely. Stamp the attempt and don't retry the same
    # version for 24h.
    STAMP="$HOME/.deadeye/.bootstrap-attempted-${PLUGIN_VERSION:-latest}"
    if [ -f "$STAMP" ]; then
      STAMP_AGE=$(( $(date +%s) - $(stat -f %m "$STAMP" 2>/dev/null || stat -c %Y "$STAMP" 2>/dev/null || echo 0) ))
      [ "$STAMP_AGE" -lt 86400 ] && exit 0
    fi
    
    if ! curl -fsSL -o "$TMP/deadeye" "$BASE_URL/$ASSET"; then
      [ "$BASE_URL" = "$LATEST_URL" ] && { mkdir -p "$HOME/.deadeye" && : > "$STAMP"; exit 0; }
      BASE_URL="$LATEST_URL"
      mkdir -p "$HOME/.deadeye" && : > "$STAMP"
      curl -fsSL -o "$TMP/deadeye" "$BASE_URL/$ASSET" || exit 0
    fi
    curl -fsSL -o "$TMP/checksums.txt" "$BASE_URL/checksums.txt" || exit 0
    
    WANT="$(grep " $ASSET\$" "$TMP/checksums.txt" | awk '{print $1}')"
    [ -n "$WANT" ] || exit 0
    
    if command -v sha256sum >/dev/null 2>&1; then
      GOT="$(sha256sum "$TMP/deadeye" | awk '{print $1}')"
    else
      GOT="$(shasum -a 256 "$TMP/deadeye" | awk '{print $1}')"
    fi
    [ "$WANT" = "$GOT" ] || exit 0
    
    # Install atomically. $TMP (mktemp -d, usually $TMPDIR) is frequently a
    # different filesystem from $HOME, so `mv` straight into $DEST would
    # silently degrade to copy-then-unlink -- not atomic, and on an update it
    # would truncate-and-rewrite $DEST in place while deadeye-hook.sh's
    # `[ -x "$DEST" ]` check could see a half-written binary mid-copy.
    # chmod BEFORE the same-filesystem rename, then rename within $DEST_DIR --
    # that final step is what's actually atomic.
    chmod +x "$TMP/deadeye"
    INSTALL_TMP="$DEST_DIR/.deadeye.tmp.$$"
    cp "$TMP/deadeye" "$INSTALL_TMP" && mv "$INSTALL_TMP" "$DEST"
    
  • hooks/deadeye-codex-hook.shGitHub
    Read the script
    #!/usr/bin/env bash
    # deadeye hook adapter for Codex CLI. Reached two ways: as a Codex plugin
    # (hooks/codex-hooks.json runs it from the plugin root), or installed by
    # `deadeye init codex` to ~/.deadeye/hooks/ and referenced from
    # ~/.codex/hooks.json.
    set -u
    EVENT="${1:-}"
    
    # Plugin install on a machine with no deadeye binary yet: fetch it in the
    # background, the way the Claude Code adapter does. bootstrap.sh reads the
    # version from CLAUDE_PLUGIN_ROOT, which Codex sets alongside PLUGIN_ROOT.
    # Only when the binary is missing -- after that, `deadeye update` updates it.
    if [ "$EVENT" = "SessionStart" ] && [ -n "${PLUGIN_ROOT:-}" ] && [ ! -x "$HOME/.deadeye/bin/deadeye" ] \
       && ! command -v deadeye >/dev/null 2>&1 && [ -x "$PLUGIN_ROOT/hooks/bootstrap.sh" ]; then
      ( CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" "$PLUGIN_ROOT/hooks/bootstrap.sh" >/dev/null 2>&1 & ) 2>/dev/null
    fi
    
    BIN="$(command -v deadeye 2>/dev/null || true)"
    if [ -z "$BIN" ] || [ ! -x "$BIN" ]; then
      BIN="$HOME/.deadeye/bin/deadeye"
    fi
    if [ ! -x "$BIN" ]; then
      cat > /dev/null 2>&1 || true
      printf '{}'
      exit 0
    fi
    
    # Capture rather than exec: if the binary dies without output, Codex
    # still gets valid JSON (fail open, INV-5).
    out="$("$BIN" hook "$EVENT" --host codex 2>/dev/null)" || true
    [ -n "$out" ] || out="{}"
    printf '%s' "$out"
    
  • hooks/deadeye-gemini-hook.shGitHub
    Read the script
    #!/usr/bin/env bash
    # deadeye hook adapter for Gemini CLI. Installed by `deadeye init gemini`
    # to ~/.deadeye/hooks/ and referenced from the deadeye Gemini extension's
    # hooks/hooks.json. Gemini passes the hook payload as JSON on stdin and
    # reads the response as JSON on stdout -- the binary handles both; the
    # --host gemini flag selects Gemini's output dialect (hookSpecificOutput.
    # tool_input, decision:deny, etc.). The event name is passed as $1 (the
    # canonical Claude event the daemon switches on), mapped from Gemini's own
    # event name in hooks.json.
    set -u
    EVENT="${1:-}"
    
    BIN="$(command -v deadeye 2>/dev/null || true)"
    if [ -z "$BIN" ] || [ ! -x "$BIN" ]; then
      BIN="$HOME/.deadeye/bin/deadeye"
    fi
    if [ ! -x "$BIN" ]; then
      cat > /dev/null 2>&1 || true
      printf '{}'
      exit 0
    fi
    
    # Capture rather than exec: if the binary dies without output, Gemini
    # still gets valid JSON (fail open, INV-5).
    out="$("$BIN" hook "$EVENT" --host gemini 2>/dev/null)" || true
    [ -n "$out" ] || out="{}"
    printf '%s' "$out"
    
  • hooks/deadeye-hook.ps1GitHub
    Read the script
    # Resolves the deadeye binary and forwards this hook invocation to it.
    # Fail-open per INV-5: any resolution or execution failure prints {} and
    # exits 0.
    #
    # Binary resolution mirrors deadeye-hook.sh: a `deadeye` on PATH is used only
    # when it is at least the plugin's version; a STALE PATH binary defers to the
    # managed %USERPROFILE%\.deadeye\bin\deadeye.exe so plugin updates aren't
    # shadowed. NOTE: Windows self-bootstrap (auto-downloading the managed binary,
    # as hooks/bootstrap.sh does on macOS/Linux) is still not implemented -- until
    # then, Windows users must put deadeye.exe on PATH or at that managed path
    # themselves. deadeye's own version-skew warning (see /deadeye-status) flags a
    # stale binary when it happens.
    param([string]$Event)
    $ErrorActionPreference = 'SilentlyContinue'
    
    # Recursion guard: deadeye's AI routing judge spawns a nested `claude -p`
    # session; it must run no deadeye hooks (no re-judging, no cost).
    if ($env:DEADEYE_JUDGE) { Write-Output '{}'; exit 0 }
    
    function Get-PluginVersion {
        $pj = "$env:CLAUDE_PLUGIN_ROOT\.claude-plugin\plugin.json"
        if ($env:CLAUDE_PLUGIN_ROOT -and (Test-Path $pj)) {
            try { return (Get-Content $pj -Raw | ConvertFrom-Json).version } catch { return $null }
        }
        return $null
    }
    
    function Get-BinVersion([string]$bin) {
        try { $o = & $bin version 2>$null; if ($o) { return ($o -split '\s+')[1] } } catch {}
        return $null
    }
    
    function ConvertTo-VerParts([string]$s) {
        $out = @(0, 0, 0)
        if ($s) {
            $s = ($s -replace '^v', '') -replace '[^0-9.].*$', ''
            $parts = $s -split '\.'
            for ($i = 0; $i -lt 3; $i++) {
                if ($i -lt $parts.Count -and $parts[$i] -match '^\d+$') { $out[$i] = [int]$parts[$i] }
            }
        }
        return , $out
    }
    
    function Test-VerGE([string]$a, [string]$b) {
        $pa = ConvertTo-VerParts $a
        $pb = ConvertTo-VerParts $b
        for ($i = 0; $i -lt 3; $i++) {
            if ($pa[$i] -gt $pb[$i]) { return $true }
            if ($pa[$i] -lt $pb[$i]) { return $false }
        }
        return $true
    }
    
    $pv = Get-PluginVersion
    $pathCmd = Get-Command deadeye -ErrorAction SilentlyContinue
    $pathBin = if ($pathCmd) { $pathCmd.Source } else { $null }
    $managed = "$env:USERPROFILE\.deadeye\bin\deadeye.exe"
    $hasManaged = Test-Path $managed
    
    $binPath = $null
    if ($pathBin) {
        if ((-not $pv) -or (Test-VerGE (Get-BinVersion $pathBin) $pv)) {
            $binPath = $pathBin          # no plugin context, or current/newer build -- stays in charge
        } elseif ($hasManaged) {
            $binPath = $managed          # stale PATH binary -> managed one takes over
        } else {
            $binPath = $pathBin          # stale, but nothing managed present
        }
    } elseif ($hasManaged) {
        $binPath = $managed
    }
    
    if (-not $binPath) {
        Write-Output '{}'
        exit 0
    }
    
    try {
        $out = & $binPath hook $Event 2>$null
    } catch {
        $out = $null
    }
    
    if ([string]::IsNullOrWhiteSpace($out)) {
        Write-Output '{}'
    } else {
        Write-Output $out
    }
    
  • hooks/deadeye-hook.shRunsGitHub
    Read the script
    #!/usr/bin/env bash
    # Resolves the deadeye binary and forwards this hook invocation to it.
    # Fail-open per INV-5: any resolution or execution failure prints {} and
    # exits 0 -- a broken policy layer must never block the user's work.
    #
    # Binary resolution keeps auto-update RELIABLE. A `deadeye` on PATH is used
    # only when it is at least the plugin's version. A STALE PATH binary (an old
    # `go install`ed one) is bypassed in favor of the managed, self-updating
    # ~/.deadeye/bin/deadeye -- otherwise it would shadow the managed binary
    # forever and never see a plugin update. A current-or-newer PATH build still
    # wins, so a dev's own build stays in charge. Version checks are only paid
    # when a PATH binary actually exists (the ambiguous case); the common
    # plugin-only install resolves straight to the managed binary.
    set -u
    
    # Recursion guard: deadeye's own AI routing judge (mode.routing_judge) spawns a
    # nested `claude -p` session to classify a task. That session must run no
    # deadeye hooks -- no re-judging, no cost from the judge session itself.
    [ -n "${DEADEYE_JUDGE:-}" ] && { echo '{}'; exit 0; }
    
    EVENT="${1:-}"
    # `set -u` above turns an unset HOME into "unbound variable", exit 1, with
    # no JSON at all -- noisy on every single tool call in an environment that
    # strips HOME. Fall back rather than fail: the hook contract is to always
    # answer, even if that answer is {}.
    HOME="${HOME:-$(cd ~ 2>/dev/null && pwd || echo /tmp)}"
    export HOME
    MANAGED="$HOME/.deadeye/bin/deadeye"
    
    plugin_version() {
      [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && [ -f "$CLAUDE_PLUGIN_ROOT/.claude-plugin/plugin.json" ] || return 0
      grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' "$CLAUDE_PLUGIN_ROOT/.claude-plugin/plugin.json" | head -1 | sed -E 's/.*"([^"]+)"$/\1/'
    }
    
    bin_version() { "$1" version 2>/dev/null | awk '{print $2}'; }
    
    # ver_ge A B: exit 0 if A >= B as x.y.z. Strips a leading v and any -dev /
    # prerelease suffix; a missing or unparseable version compares as 0.0.0, so an
    # unknowable PATH binary is treated as behind (safe: defer to the managed one).
    ver_ge() {
      awk -v a="$1" -v b="$2" 'BEGIN{
        sub(/^v/,"",a); sub(/^v/,"",b);
        gsub(/[^0-9.].*$/,"",a); gsub(/[^0-9.].*$/,"",b);
        na=split(a,x,"."); nb=split(b,y,".");
        for(i=1;i<=3;i++){ai=(i<=na?x[i]+0:0); bi=(i<=nb?y[i]+0:0); if(ai>bi)exit 0; if(ai<bi)exit 1}
        exit 0
      }'
    }
    
    PV="$(plugin_version)"
    PATH_BIN="$(command -v deadeye 2>/dev/null || true)"
    
    BIN=""
    if [ -n "$PATH_BIN" ]; then
      if [ -z "$PV" ] || ver_ge "$(bin_version "$PATH_BIN")" "$PV"; then
        BIN="$PATH_BIN"          # no plugin context, or a current/newer build -- stays in charge
      elif [ -x "$MANAGED" ]; then
        BIN="$MANAGED"           # PATH binary is STALE -> the self-updating managed binary takes over
      else
        BIN="$PATH_BIN"          # stale, but nothing managed yet; the bootstrap below fixes next session
      fi
    elif [ -x "$MANAGED" ]; then
      BIN="$MANAGED"
    fi
    
    # Keep the managed binary converging to the plugin version: on SessionStart,
    # bootstrap it if it's missing or behind. Never touches a PATH binary.
    if [ "$EVENT" = "SessionStart" ] && [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
      if [ ! -x "$MANAGED" ] || { [ -n "$PV" ] && ! ver_ge "$(bin_version "$MANAGED")" "$PV"; }; then
        ( "${CLAUDE_PLUGIN_ROOT}/hooks/bootstrap.sh" >/dev/null 2>&1 & ) 2>/dev/null
      fi
    fi
    
    if [ -z "$BIN" ]; then
      echo '{}'
      exit 0
    fi
    
    OUT="$("$BIN" hook "$EVENT" 2>/dev/null)"
    if [ -z "$OUT" ]; then
      echo '{}'
    else
      echo "$OUT"
    fi
    
  • hooks/deadeye-statusline.shGitHub
    Read the script
    #!/usr/bin/env bash
    # Statusline badge for deadeye's coder mode. Claude Code pipes session JSON
    # on stdin; the session_id in it selects this session's own mode file
    # (~/.deadeye/coder-mode.<id>), so concurrent sessions each show their own
    # badge. No session_id on stdin -> the global ~/.deadeye/coder-mode
    # fallback (last writer wins). Silent when the mode is off/absent -- an
    # empty statusline segment, not an error.
    set -u
    
    # A kill switch makes deadeye silent by design -- but silence is
    # indistinguishable from "forgot I turned it off". Surface it. Env check
    # only: no sockets, no files, nothing slow on the statusline render path.
    if [ "${DEADEYE:-}" = "off" ]; then
      printf '\033[38;5;245m[DEADEYE:OFF]\033[0m'; exit 0
    fi
    if [ "${DEADEYE_CODER:-}" = "off" ]; then
      printf '\033[38;5;245m[DEADEYE:CODER OFF]\033[0m'; exit 0
    fi
    
    MODE_FILE="$HOME/.deadeye/coder-mode"
    sid="$(cat 2>/dev/null | sed -n 's/.*"session_id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)"
    if [ -n "$sid" ]; then
      # Mirror the daemon's sanitization: anything outside [A-Za-z0-9-] -> _
      sid_safe="$(printf '%s' "$sid" | tr -c 'A-Za-z0-9-' '_')"
      [ -f "$HOME/.deadeye/coder-mode.$sid_safe" ] && MODE_FILE="$HOME/.deadeye/coder-mode.$sid_safe"
    fi
    [ -f "$MODE_FILE" ] || exit 0
    level="$(tr -d '[:space:]' < "$MODE_FILE")"
    [ -n "$level" ] || exit 0
    
    case "$level" in
      marksman) printf '\033[38;5;108m[DEADEYE]\033[0m' ;;          # green -- the default discipline
      spotter)  printf '\033[38;5;65m[DEADEYE:SPOTTER]\033[0m' ;;   # muted green -- light touch
      sniper)   printf '\033[38;5;173m[DEADEYE:SNIPER]\033[0m' ;;   # amber -- maximum minimalism
      review)   printf '\033[38;5;109m[DEADEYE:REVIEW]\033[0m' ;;   # steel blue -- review pass
      *) exit 0 ;;
    esac
    
  • hooks/register.test.tsGitHub
  • hooks/register.tsGitHub
  • hooks/themes.tsGitHub
  • hooks/toggle.test.tsGitHub

All 10 scripts are listed above. The source is inlined for 6 of them, starting with whatever hooks.json actually runs. See all of them in the repo.

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.

@deepaksinghcs14
Ships withdeadeye

Claude Code plugin that fits the model, effort, and context to each task — fewer tokens, same quality. Deterministic policy kernel in the hooks; every number it reports is measured, not estimated.

Stars on GitHub

Momentum

stars in total
6
Star history of deepaksinghcs14/deadeye-cc 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 deadeye.

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