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

Claude Code

> /plugin marketplace add ij5a/subrosa
> /plugin install subrosa@subrosa

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,
    # or at session start the data-dir binary does not match hooks/binary-version,
    # download that release 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
      # Write beside the target, then rename, so a running old binary is never rewritten in place.
      NEW="$DATA/bin/subrosa.$$"
      tar -xzf "$TMP/$ARCHIVE" -O subrosa >"$NEW" && chmod 755 "$NEW" && mv -f "$NEW" "$DATA/bin/subrosa"
      STATUS=$?
      rm -rf "$TMP" "$NEW"
      return $STATUS
    }
    
    find_bin
    
    # Session start only: a failed download then retries once per session, not on every prompt.
    # distill.rs puts this copy first on its child's PATH, so refresh it even when PATH wins.
    if [ "$EVENT" = session-start ] && [ -x "$DATA/bin/subrosa" ]; then
      PIN="$(cat "$SELF/binary-version" 2>/dev/null)"
      if [ "$("$DATA/bin/subrosa" -V 2>/dev/null)" != "subrosa ${PIN#v}" ] && bootstrap >>"$DATA/hook.log" 2>&1; then
        echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) bootstrap: installed $PIN to $DATA/bin" >>"$DATA/hook.log"
      fi
    fi
    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.

@ij5a
Ships withsubrosa

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

Stars on GitHub

Momentum

stars in total
5
Star history of ij5a/subrosa on GitHub, a chart by star-history.com

More plugins that ship hooks.

last30days-cn

last30days-cn

A Claude Code skill that researches what Chinese internet users said recently across Weibo, Xiaohongshu, Bilibili, Zhihu, Douyin, WeChat, Baidu and Toutiao. It ranks posts by engagement and recency and writes a sourced research report.

1 skill1 hook2.1k
@jesseovo@jesseovo
Install Plugin
episodic-memory

episodic-memory

Semantic search over past Claude Code conversations, so a session can recall earlier discussions, decisions, and patterns. It adds a remembering-conversations skill that checks prior sessions before the assistant says it doesn't know.

1 skill+3500
@obra-2@obra-2
Install Plugin
memx

memx

Gives Claude Code a long-term memory layer with semantic search, recall injection, and graph entities, letting agents recall, save, inspect, and audit memories through bundled MCP tools.

1 skill+2401
@neoli00@neoli00
Install Plugin
databricks-agent-skills

databricks-agent-skill…

Skills and agent plugins that let AI coding agents such as Claude Code work with Databricks, covering AI Functions, Agent Bricks, AI/BI dashboards, GPU training workloads and Databricks Apps design.

36 skills+2394
@databricks@databricks
Install Plugin
nutmeg

nutmeg

A Claude Code plugin for football data work: acquiring data from sources such as StatsBomb, Opta and FBref, analysing it, computing metrics like xG and PPDA, and fixing broken scrapers. Built for analysts, developers, journalists and researchers.

11 skills+373
@withqwerty@withqwerty
Install Plugin
pinecone

pinecone

A lightweight plugin that integrates Pinecone vector database capabilities directly into Claude Code, enabling semantic search, index management, and RAG (Retrieval Augmented Generation) workflows.

9 skills+368
@pinecone-io@pinecone-io
Install Plugin
magi

magi

A research workflow plugin for Claude Code that turns folders of papers, notes and drafts into a linked, Obsidian-compatible knowledge base. It adds skills to adopt existing material, compile sources into concept cards, answer questions with citations, and write up unattended runs.

11 skills1 hook7
@misaka16384@misaka16384
Install Plugin
ainl-cortex

ainl-cortex

Adds graph-based memory to Claude Code that records past interactions and learns recurring patterns across sessions. Runs as hooks and an MCP server.

7 hooks1 MCP4
@sbhooley@sbhooley
Install Plugin

Questions about the hooks in subrosa.

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