Skip to content
Development
Hook

Hooks

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

From plugin
litestar
1531 skills1 agent1 hook
Install
> /plugin marketplace add litestar-org/litestar-skills
> /plugin install litestar@litestar

Ships with litestar. 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.

  • Matchesstartup|clear|compactr="${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-}}"; if [ -n "$r" ] && [ ! -f "${r%/}/hooks/session-start.sh" ]; then r=""; fi; if [ -z "$r" ] && [ -d "$HOME/.claude/plugins/marketplaces" ]; then r="$(find -L "$HOME/.claude/plugins/marketplaces" -path "*/litestar/hooks/session-start.sh" -type f -print 2>/de
Read hooks/hooks.json

Where it lives

  • hooks/session-start.jsGitHub
    Read the script
    #!/usr/bin/env node
    // hooks/session-start.js
    // SessionStart hook for litestar-skills (Node ESM port).
    // Detects host via env vars and emits the host-correct JSON shape.
    //
    // Hosts:
    //   CLAUDE_PLUGIN_ROOT  -> Claude Code  -> hookSpecificOutput.additionalContext
    //   CODEX_PLUGIN_ROOT   -> Codex CLI    -> hookSpecificOutput.additionalContext
    //   CURSOR_PLUGIN_ROOT  -> Cursor       -> additional_context
    //   (none of the above) -> Unknown      -> additional_context (Cursor-shape fallback)
    
    import { detectEnv } from "./lib/detect-env.js";
    
    function pickHost(env) {
      if (env.CLAUDE_PLUGIN_ROOT) return "claude";
      if (env.CODEX_PLUGIN_ROOT) return "codex";
      if (env.CURSOR_PLUGIN_ROOT) return "cursor";
      return "unknown";
    }
    
    function shape(host, context) {
      if (host === "claude" || host === "codex") {
        return {
          hookSpecificOutput: { hookEventName: "SessionStart", additionalContext: context },
        };
      }
      // cursor + unknown
      return { additional_context: context };
    }
    
    async function main() {
      const detector = await detectEnv(process.env.PWD || process.cwd());
      if (!detector || Object.keys(detector).length === 0) {
        process.stdout.write("{}\n");
        return;
      }
      const host = pickHost(process.env);
      const out = shape(host, detector.context || "");
      process.stdout.write(JSON.stringify(out) + "\n");
    }
    
    main().catch((err) => {
      process.stderr.write(JSON.stringify({ error: String(err) }) + "\n");
      process.exit(1);
    });
    
  • hooks/session-start.ps1GitHub
    Read the script
    <#
    .SYNOPSIS
        SessionStart hook for litestar-skills (PowerShell parity of session-start.sh).
    
    .DESCRIPTION
        Detects the host via env vars and emits the host-correct JSON shape with
        project-aware skill reminders. Detection logic is delegated to detect-env.ps1
        (which in turn delegates to python3 / hooks/lib/_detector.py).
    #>
    
    [CmdletBinding()]
    param()
    
    $ErrorActionPreference = 'Stop'
    
    $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
    $detectEnv = Join-Path $scriptDir 'lib/detect-env.ps1'
    
    if (-not (Test-Path -LiteralPath $detectEnv)) {
        Write-Output '{}'
        return
    }
    
    $detectorOutput = & $detectEnv $PWD.Path
    if (-not $detectorOutput -or $detectorOutput.Trim() -eq '{}') {
        Write-Output '{}'
        return
    }
    
    $detector = $detectorOutput | ConvertFrom-Json
    $context = if ($detector.context) { $detector.context } else { '' }
    
    $host_ = 'unknown'
    if ($env:CLAUDE_PLUGIN_ROOT)   { $host_ = 'claude'  }
    elseif ($env:CODEX_PLUGIN_ROOT) { $host_ = 'codex'   }
    elseif ($env:CURSOR_PLUGIN_ROOT){ $host_ = 'cursor'  }
    
    switch ($host_) {
        { $_ -in 'claude','codex' } {
            $out = [ordered]@{
                hookSpecificOutput = [ordered]@{
                    hookEventName     = 'SessionStart'
                    additionalContext = $context
                }
            }
        }
        default {
            $out = [ordered]@{ additional_context = $context }
        }
    }
    
    $out | ConvertTo-Json -Compress -Depth 20
    
  • hooks/session-start.shRunsGitHub
    Read the script
    #!/usr/bin/env bash
    # hooks/session-start.sh
    # SessionStart hook for litestar-skills. Detects host via env vars and emits the
    # host-correct JSON shape with project-aware skill reminders.
    #
    # Hosts:
    #   CLAUDE_PLUGIN_ROOT  -> Claude Code  -> hookSpecificOutput.additionalContext
    #   CODEX_PLUGIN_ROOT   -> Codex CLI    -> hookSpecificOutput.additionalContext
    #   ANTIGRAVITY_PLUGIN_ROOT -> Antigravity CLI -> hookSpecificOutput.additionalContext
    #   CURSOR_PLUGIN_ROOT  -> Cursor       -> additional_context
    #   (none of the above) -> Unknown      -> additional_context (Cursor-shape fallback)
    
    set -euo pipefail
    
    SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
    # shellcheck source=hooks/lib/detect-env.sh
    source "${SCRIPT_DIR}/lib/detect-env.sh"
    
    # Determine project root: prefer cwd; the detector resolves further.
    project_root="${PWD}"
    
    # Run detection -> JSON ({"detected_skills": [...], "context": "...", "project_root": "..."}).
    detector_output="$(detect_env "$project_root")"
    
    # Short-circuit if disabled (detector returned "{}").
    if [[ "$detector_output" == "{}" ]]; then
        echo "{}"
        exit 0
    fi
    
    # Host-specific output shaping using a single Python pass for safe JSON handling.
    host="unknown"
    if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" ]]; then
        host="claude"
    elif [[ -n "${CODEX_PLUGIN_ROOT:-}" ]]; then
        host="codex"
    elif [[ -n "${ANTIGRAVITY_PLUGIN_ROOT:-}" || -n "${AGY_PLUGIN_ROOT:-}" ]]; then
        host="antigravity"
    elif [[ -n "${CURSOR_PLUGIN_ROOT:-}" ]]; then
        host="cursor"
    fi
    
    _session_python=""
    if _session_python=$(_resolve_python); then
        "$_session_python" - "$host" "$detector_output" <<'PY'
    import json, sys
    host = sys.argv[1]
    data = json.loads(sys.argv[2])
    context = data.get("context", "")
    
    if host in ("claude", "codex", "antigravity"):
        out = {"hookSpecificOutput": {"hookEventName": "SessionStart", "additionalContext": context}}
    else:
        # cursor + unknown share the same shape
        out = {"additional_context": context}
    
    print(json.dumps(out, ensure_ascii=False))
    PY
    else
        # Pure-bash fallback (Python should be present, but stay safe).
        case "$host" in
            claude|codex)
                printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":""}}\n' ;;
            *)
                printf '{"additional_context":""}\n' ;;
        esac
    fi
    

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 withlitestar

Opinionated, first-party agent skills, plugins, subagents, slash commands, and MCP servers for the Litestar framework and its ecosystem — publishable to every major AI agent and IDE from a single repo.

Get the whole plugin