Skip to content
Agent Memory
Hook

Hooks

What arra-oracle-skills-cli runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.

From plugin
arra-oracle-skills-cli
12532 skills3 hooks
Install
> /plugin marketplace add soul-brews-studio/arra-oracle-skills-cli
> /plugin install oracle-skills@oracle-skills

Ships with arra-oracle-skills-cli. Installing the plugin gets these hooks.

Where it lives

  • hooks/safety-check.shGitHub
    Read the script
    #!/bin/bash
    # Safety check hook - blocks dangerous commands
    # Input: JSON via stdin with tool_input.command
    
    CMD=$(jq -r '.tool_input.command // ""' 2>/dev/null)
    
    # Block dangerous patterns - be specific to avoid false positives
    # Only block commands at START of line/command (not in text body, heredoc, echo, etc.)
    # Patterns: start of string, after ;, after &&, after ||, after newline
    
    # Block rm -rf only when it's an actual command (not in text)
    if echo "$CMD" | grep -qE '(^|;|&&|\|\|)\s*rm\s+-rf\s'; then
      echo "BLOCKED: rm -rf not allowed. Use safe alternatives." >&2
      exit 2
    fi
    
    # Block git/npm force flags only when actual command
    if echo "$CMD" | grep -qE '(^|;|&&|\|\|)\s*(git|npm|yarn|pnpm)\s+[a-z]+\s+.*(\s-f(\s|$)|--force(\s|$)|--force-with-lease(\s|$))'; then
      echo "BLOCKED: Force flags not allowed (including --force-with-lease). Use git pull --no-rebase + merge." >&2
      exit 2
    fi
    
    # Block reset --hard
    if echo "$CMD" | grep -qE '(^|;|&&|\|\|)\s*git\s+reset\s+--hard'; then
      echo "BLOCKED: git reset --hard not allowed." >&2
      exit 2
    fi
    
    # Block direct push to main
    if echo "$CMD" | grep -qE 'git\s+push\s+(origin\s+)?main(\s|$)'; then
      echo "BLOCKED: Never push directly to main. Use alpha branch + PR." >&2
      exit 2
    fi
    
    # Block git commit --amend (breaks multi-agent sync - causes hash divergence)
    if echo "$CMD" | grep -qE 'git\s+commit\s+.*--amend'; then
      echo "BLOCKED: Never use --amend in multi-agent setup. Creates hash divergence." >&2
      echo "Use a NEW commit instead: git commit -m 'fix: ...' " >&2
      exit 2
    fi
    
    # Block gh pr merge (DISABLED - local project hook handles this for worktree agents)
    # Main agent CAN merge after explicit user approval
    # if echo "$CMD" | grep -qE 'gh\s+pr\s+merge'; then
    #   echo "BLOCKED: Never merge PRs. Wait for user approval." >&2
    #   exit 2
    # fi
    
    exit 0
    
  • hooks/session-start.shGitHub
    Read the script
    #!/bin/bash
    # Session Start — show context on new session
    # Output appears as system-reminder (SessionStart stdout is visible to AI)
    
    INPUT=$(cat)
    CWD=$(echo "$INPUT" | /usr/bin/jq -r '.cwd // ""' 2>/dev/null)
    
    # Branch
    BRANCH=$(timeout 2 git -C "$CWD" symbolic-ref --short HEAD 2>/dev/null)
    WT=""; [ -f "$CWD/.git" ] && WT=" (worktree)"
    
    # Open issues count
    ISSUES=$(gh issue list --state open --limit 100 --json number 2>/dev/null | /usr/bin/jq 'length' 2>/dev/null || echo "?")
    
    # Latest handoff
    PSI=$(readlink -f "$CWD/ψ" 2>/dev/null || echo "$CWD/ψ")
    HANDOFF=$(ls -t "$PSI/inbox/handoff/"*.md 2>/dev/null | head -1)
    HANDOFF_NAME=$(basename "$HANDOFF" 2>/dev/null || echo "none")
    
    # Session ID
    SID=$(echo "$INPUT" | /usr/bin/jq -r '.session_id // ""' 2>/dev/null | cut -c1-8)
    
    # Previous session — find last .jsonl in project dir
    ENCODED_CWD=$(echo "$CWD" | sed 's|^/|-|; s|[/.]|-|g')
    PROJECT_DIR="$HOME/.claude/projects/${ENCODED_CWD}"
    PREV_JSONL=$(ls -t "$PROJECT_DIR"/*.jsonl 2>/dev/null | head -2 | tail -1)
    if [ -n "$PREV_JSONL" ]; then
      PREV_SID=$(basename "$PREV_JSONL" .jsonl | cut -c1-8)
      PREV_SIZE=$(du -h "$PREV_JSONL" 2>/dev/null | cut -f1)
      PREV_DATE=$(stat -c %y "$PREV_JSONL" 2>/dev/null | cut -d. -f1)
      PREV_INFO="Previous: ${PREV_SID} (${PREV_SIZE}, ${PREV_DATE})"
    else
      PREV_INFO="Previous: first session"
    fi
    
    echo "📡 Session ${SID} | Branch: ${BRANCH:-?}${WT} | Issues: ${ISSUES} open"
    echo "📋 ${PREV_INFO} | Handoff: ${HANDOFF_NAME}"
    echo "💡 /recap to orient, /whats-next for suggestions, /where-we-are for status"
    
  • hooks/statusline-command.shGitHub
    Read the script
    #!/bin/bash
    # Claude Code statusline — 2 lines
    # Line 1: 🌐 host 📁 cwd on branch*
    # Line 2: 🎨 time ⏱ dur • 📊 pct% (Nk/Mk) • ❌/✅ • 🤖 model
    
    input=$(cat)
    echo "$input" > "${TMPDIR:-${TMP:-${TEMP:-/tmp}}}"/statusline-raw.json 2>/dev/null
    
    cwd=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // "~"' 2>/dev/null) || cwd="~"
    model=$(echo "$input" | jq -r '.model.display_name // .model.id // "?"' 2>/dev/null) || model="?"
    pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0' 2>/dev/null | cut -d. -f1) || pct=0
    used_k=$(echo "$input" | jq -r '((.context_window.current_usage | ((.input_tokens//0)+(.cache_creation_input_tokens//0)+(.cache_read_input_tokens//0)+(.output_tokens//0))) / 1000) | floor' 2>/dev/null) || used_k=0
    max_k=$(echo "$input" | jq -r '((.context_window.context_window_size // 0) / 1000) | floor' 2>/dev/null) || max_k=0
    dur_ms=$(echo "$input" | jq -r '.cost.total_duration_ms // 0' 2>/dev/null | cut -d. -f1) || dur_ms=0
    
    # Duration
    s=$(( dur_ms / 1000 )) 2>/dev/null || s=0
    h=$(( s / 3600 )); m=$(( (s % 3600) / 60 ))
    [ "$h" -gt 0 ] 2>/dev/null && dur="${h}h${m}m" || dur="${m}m"
    
    # Auto-compact
    ac="❌"
    jq -e '.autoCompactEnabled != false' ~/.claude.json >/dev/null 2>&1 && ac="✅"
    
    # Git branch (timeout to avoid hangs)
    branch=$(timeout 2 git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null)
    git=""
    if [ -n "$branch" ]; then
      d=""; timeout 1 git -C "$cwd" diff-index --quiet HEAD -- 2>/dev/null || d="*"
      wt=""; [ -f "$cwd/.git" ] && wt=" 🌳"
      git=" on  ${branch}${d}${wt}"
    fi
    
    # Shorten path to org/repo (strip ~/Code/github.com/ prefix)
    dir="${cwd/#$HOME\/Code\/github.com\//}"
    # Fallback: if no match, shorten $HOME to ~
    [ "$dir" = "$cwd" ] && dir="${cwd/#$HOME/\~}"
    
    # Session ID (short)
    sid=$(echo "$input" | jq -r '.session_id // ""' 2>/dev/null | cut -c1-8)
    
    # Previous session ID
    ENCODED_CWD=$(echo "$cwd" | sed 's|/|-|g; s|\.|-|g')
    PROJ_DIR="$HOME/.claude/projects/${ENCODED_CWD}"
    prev_sid=$(ls -t "$PROJ_DIR"/*.jsonl 2>/dev/null | head -2 | tail -1 | xargs -I{} basename {} .jsonl 2>/dev/null | cut -c1-8)
    prev_info=""
    [ -n "$prev_sid" ] && [ "$prev_sid" != "$sid" ] && prev_info="${prev_sid} → "
    
    echo "📁 ${dir}${git}"
    echo "📡 ${sid}${prev_info} • $(date +%H:%M) • ${pct}% ${used_k}k/${max_k}k • ${model}"
    

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 witharra-oracle-skills-cli

25 skills for AI coding agents — persistent memory, session awareness, and collaborative tools.

Get the whole plugin
Stats
125
Stars
58
Forks
Active
Maintenance
TypeScript
Language
MIT
License
22d ago
Last commit
9mo ago
Created
3h ago
Added

Repo: soul-brews-studio/arra-oracle-skills-cli