Skip to content
Data
Hook

Hooks

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

From plugin
subrosa
52 skills5 hooks
Install
> /plugin marketplace add ij5a/subrosa
> /plugin install subrosa@subrosa

Ships with subrosa. Installing the plugin gets these hooks.

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/run.sh session-start

SessionEnd

  • "${CLAUDE_PLUGIN_ROOT}"/hooks/run.sh session-end

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/run.sh user-prompt-submit

PreCompact

  • "${CLAUDE_PLUGIN_ROOT}"/hooks/run.sh pre-compact

Stop

  • "${CLAUDE_PLUGIN_ROOT}"/hooks/run.sh stop
Read hooks/hooks.json

Where it lives

  • hooks/run.shRunsGitHub
    Read the script
    #!/bin/sh
    # Find the subrosa binary and run the given hook event. If no binary exists yet,
    # bootstrap the release pinned in hooks/binary-version for this platform —
    # sha256-verified against hooks/sha256sums.txt committed in this repo — into the
    # data dir. Everything is best-effort and quiet: a failed download must never
    # break a Claude Code session.
    EVENT="$1"
    [ -n "$EVENT" ] || exit 0
    
    DATA="${SUBROSA_DIR:-$HOME/.claude/subrosa}"
    # Parameter expansion, not $(dirname): the hot path must not fork. hooks.json
    # always invokes us by absolute path, so stripping the last component works.
    SELF="${0%/*}"
    [ "$SELF" != "$0" ] || SELF="."
    
    # Sets BIN directly (no $(...) capture subshell — this runs on every prompt).
    find_bin() {
      if command -v subrosa >/dev/null 2>&1; then
        BIN=subrosa
        return 0
      fi
      for c in "$HOME/.cargo/bin/subrosa" "$DATA/bin/subrosa" "$SELF/../bin/subrosa"; do
        if [ -x "$c" ]; then
          BIN="$c"
          return 0
        fi
      done
      BIN=""
    }
    
    bootstrap() {
      # Owner-only for everything the bootstrap creates (data dir, temp download).
      umask 077
      [ -s "$SELF/binary-version" ] && [ -s "$SELF/sha256sums.txt" ] || return 1
      VERSION="$(cat "$SELF/binary-version")"
      case "$(uname -s)-$(uname -m)" in
        Darwin-arm64)              TARGET=aarch64-apple-darwin ;;
        Darwin-x86_64)             TARGET=x86_64-apple-darwin ;;
        Linux-x86_64)              TARGET=x86_64-unknown-linux-musl ;;
        Linux-aarch64|Linux-arm64) TARGET=aarch64-unknown-linux-musl ;;
        *) return 1 ;;
      esac
      ARCHIVE="subrosa-$VERSION-$TARGET.tar.gz"
      WANT="$(awk -v f="$ARCHIVE" '$2 == f {print $1}' "$SELF/sha256sums.txt")"
      [ -n "$WANT" ] || return 1
    
      TMP="$(mktemp -d)" || return 1
      if ! curl -fsSL --proto '=https' --proto-redir '=https' --max-time 120 -o "$TMP/$ARCHIVE" \
        "https://github.com/ij5a/subrosa/releases/download/$VERSION/$ARCHIVE"; then
        rm -rf "$TMP"
        return 1
      fi
      if command -v sha256sum >/dev/null 2>&1; then
        GOT="$(sha256sum "$TMP/$ARCHIVE" | awk '{print $1}')"
      else
        GOT="$(shasum -a 256 "$TMP/$ARCHIVE" | awk '{print $1}')"
      fi
      if [ "$GOT" != "$WANT" ]; then
        rm -rf "$TMP"
        return 1
      fi
      mkdir -p "$DATA/bin" && chmod 700 "$DATA" "$DATA/bin" 2>/dev/null
      tar -xzf "$TMP/$ARCHIVE" -C "$DATA/bin" subrosa && chmod 755 "$DATA/bin/subrosa"
      STATUS=$?
      rm -rf "$TMP"
      return $STATUS
    }
    
    find_bin
    if [ -z "$BIN" ]; then
      mkdir -p "$DATA" 2>/dev/null
      if bootstrap >>"$DATA/hook.log" 2>&1; then
        echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) bootstrap: installed $(cat "$SELF/binary-version") to $DATA/bin" >>"$DATA/hook.log"
      fi
      find_bin
      [ -n "$BIN" ] || exit 0
    fi
    # No exec, and stderr dropped: an older PATH binary that doesn't know this
    # event yet must degrade to a silent no-op, never a failed hook.
    "$BIN" hook "$EVENT" 2>/dev/null
    exit 0
    

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.

Ships withsubrosa

Persistent, private memory for Claude Code — every session archived locally, searchable. Sub rosa.

Get the whole plugin
Stats
5
Stars
0
Forks
Active
Maintenance
Rust
Language
MIT
License
12d ago
Last commit
3mo ago
Created

Repo: ij5a/subrosa