ops-recap

GitHub

管理多会话摘要守护进程,聚合Claude Code会话与Shell活动生成单行摘要,并通过tmux状态栏实时展示。支持状态检查、日志查看、配置及重启等子命令。

claude-ops/skills/ops-recap/SKILL.md Lifecycle-Innovations-Limited/claude-ops

Trigger Scenarios

需要查看跨会话操作汇总 运维监控终端活动 调试后台守护进程状态

Install

npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-recap -g -y
More Options

Non-standard path

npx skills add https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-recap -g -y

Use without installing

npx skills use Lifecycle-Innovations-Limited/claude-ops@ops-recap

指定 Agent (Claude Code)

npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-recap -a claude-code -g -y

安装 repo 全部 skill

npx skills add Lifecycle-Innovations-Limited/claude-ops --all -g -y

预览 repo 内 skill

npx skills add Lifecycle-Innovations-Limited/claude-ops --list

SKILL.md

Frontmatter
{
    "name": "ops-recap",
    "effort": "low",
    "maxTurns": 12,
    "description": "Manage the multi-session recap marquee daemon — a background process that synthesizes a one-line digest across all parallel Claude Code sessions and shell activity, displayed in tmux status-right. Subcommands status\/tail\/configure\/restart.",
    "allowed-tools": [
        "Bash",
        "Read",
        "Write",
        "Edit",
        "AskUserQuestion"
    ],
    "argument-hint": "[status|tail|configure|restart]"
}

OPS ► RECAP

The recap marquee is a launchd-managed daemon that aggregates per-session Claude transcripts (via the recap-capture Stop hook) and per-tool activity (via the recap-tool-activity PostToolUse hook) into a single rolling headline at /tmp/claude-recap-digest. Tmux reads that file every refresh interval via scripts/recap/marquee.sh and scrolls it across status-right.

Files:

Path Role
${CLAUDE_PLUGIN_ROOT}/scripts/recap/daemon.sh Background loop — polls inputs, calls digest.sh when stale
${CLAUDE_PLUGIN_ROOT}/scripts/recap/digest.sh Synthesizes one-line digest via claude -p --model claude-sonnet-4-6
${CLAUDE_PLUGIN_ROOT}/scripts/recap/marquee.sh Tmux-side scroller (called from status-right)
${CLAUDE_PLUGIN_ROOT}/hooks/recap-capture.sh Stop hook → writes /tmp/claude-recap-<sid>
${CLAUDE_PLUGIN_ROOT}/hooks/recap-tool-activity.sh PostToolUse hook → live activity per session
~/Library/LaunchAgents/com.claude-ops.recap-daemon.plist Launchd agent (macOS)
/tmp/claude-recap-digest Rolling one-liner (read by tmux + marquee.sh)
/tmp/claude-recap-daemon.log Daemon log (rotated at 500KB)
/tmp/claude-recap-digest.log Last 50 generated digests, chronological

Subcommand: status (default)

Print a compact health panel:

PLIST=~/Library/LaunchAgents/com.claude-ops.recap-daemon.plist
LABEL=com.claude-ops.recap-daemon
DIGEST=/tmp/claude-recap-digest
DAEMON_LOG=/tmp/claude-recap-daemon.log

# Plist installed?
if [ -f "$PLIST" ]; then echo "✓ plist installed: $PLIST"; else echo "✗ plist missing"; fi

# Launchd loaded?
launchctl print "gui/$(id -u)/${LABEL}" >/dev/null 2>&1 \
  && echo "✓ launchd loaded ($LABEL)" \
  || echo "✗ launchd not loaded — run /ops:recap restart"

# Daemon process alive?
if [ -f /tmp/claude-recap-daemon.pid ]; then
  pid=$(cat /tmp/claude-recap-daemon.pid)
  kill -0 "$pid" 2>/dev/null && echo "✓ daemon alive (pid $pid)" || echo "✗ stale pid file"
else
  echo "✗ no pid file"
fi

# Digest freshness
if [ -f "$DIGEST" ]; then
  age=$(($(date +%s) - $(stat -f %m "$DIGEST" 2>/dev/null || stat -c %Y "$DIGEST" 2>/dev/null || echo 0)))
  echo "✓ digest age: ${age}s"
  echo "  preview: $(head -c 120 "$DIGEST")..."
else
  echo "✗ digest file missing — daemon may not have produced one yet"
fi

# Log size
if [ -f "$DAEMON_LOG" ]; then
  bytes=$(stat -f %z "$DAEMON_LOG" 2>/dev/null || stat -c %s "$DAEMON_LOG" 2>/dev/null)
  echo "  log: $DAEMON_LOG (${bytes} bytes)"
fi

# tmux integration?
# Display surfaces — tmux status-right + Claude Code statusLine can coexist
tmux_wired=0
statusline_wired=0

if command -v tmux >/dev/null 2>&1; then
  if grep -q claude-recap "$HOME/.tmux.conf" 2>/dev/null; then
    echo "✓ tmux status-right wired"
    tmux_wired=1
  else
    echo "○ tmux installed but status-right not wired — run /ops:recap configure"
  fi
else
  echo "○ tmux not installed"
fi

SETTINGS="$HOME/.claude/settings.json"
statusline_check_skipped=0
if ! command -v jq >/dev/null 2>&1; then
  echo "○ Claude Code statusLine — cannot check (jq not installed; install via 'brew install jq' or your distro's package manager)"
  statusline_check_skipped=1
elif [ ! -f "$SETTINGS" ]; then
  echo "○ Claude Code statusLine — no ~/.claude/settings.json found (run Claude Code at least once, or run /ops:recap configure to create one)"
  statusline_check_skipped=1
else
  sl_cmd=$(jq -r '.statusLine.command // empty' "$SETTINGS" 2>/dev/null)
  if echo "$sl_cmd" | grep -q claude-recap-digest; then
    echo "✓ Claude Code statusLine wired"
    statusline_wired=1
  else
    echo "○ Claude Code statusLine not wired — run /ops:recap configure"
  fi
fi

# Only warn "no display surface active" when we actually verified both surfaces.
# If statusline check was skipped due to missing prerequisites, statusline_wired
# being 0 is uninformative — surface that explicitly instead of misleading text.
if [ "$tmux_wired" -eq 0 ] && [ "$statusline_wired" -eq 0 ]; then
  if [ "$statusline_check_skipped" -eq 1 ]; then
    echo "  → tmux not wired; statusLine status unknown (prerequisite missing — see above). Daemon still produces /tmp/claude-recap-digest (useful for /ops:recap tail)."
  else
    echo "  → no display surface active. Daemon still produces /tmp/claude-recap-digest (useful for /ops:recap tail)."
  fi
fi

Subcommand: tail

Stream the rolling digest log:

echo "─── Last 20 generated digests ───"
tail -n 20 /tmp/claude-recap-digest.log 2>/dev/null || echo "(no digest log yet)"
echo
echo "─── Daemon log (tail 30) ───"
tail -n 30 /tmp/claude-recap-daemon.log 2>/dev/null || echo "(no daemon log yet)"

Subcommand: configure

Walk the user through display-surface integration. Two surfaces are supported and they can coexist: tmux status-right and Claude Code statusLine (~/.claude/settings.json). Detect existing config first to avoid clobbering.

  1. Check tmux availability — if missing, jump to the statusLine fallback flow below:

    if ! command -v tmux >/dev/null 2>&1; then
      echo "tmux not installed — offering Claude Code statusLine fallback."
      # → see "statusLine fallback" section below
    fi
    
  2. Check current ~/.tmux.conf:

    TMUX_CONF="$HOME/.tmux.conf"
    tmux_already_wired=0
    if grep -q claude-recap "$TMUX_CONF" 2>/dev/null; then
      echo "✓ tmux status-right already configured."
      tmux_already_wired=1
    fi
    existing=$(grep -E '^\s*set\s+-g\s+status-right' "$TMUX_CONF" 2>/dev/null | head -1)
    

    Steps 3–5 only apply when tmux is not already wired (tmux_already_wired=0):

  3. If existing is non-empty, AskUserQuestion:

    • Question: "Existing tmux status-right detected: $existing. Append recap marquee?"
    • Options: [Append (keep existing)] [Replace with recap-only] [Skip]
  4. On append: insert the marquee snippet ahead of the existing setting so both render. On replace: comment out the old line and add the new one.

    Snippet to append — expand the plugin path when writing ~/.tmux.conf (tmux #() does not expand env vars):

    PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d "$HOME/.claude/plugins/cache/ops-marketplace/ops"/*/ 2>/dev/null | sort -V | tail -1)}"
    cat >> "$TMUX_CONF" <<TMUX
    

claude-ops recap marquee

set -g status-right '#('"${PLUGIN_ROOT}"'/scripts/recap/marquee.sh) #[fg=#a6e3a1]%H:%M ' set -g status-interval 2 TMUX

  1. Reload if tmux is running:
tmux info >/dev/null 2>&1 && tmux source-file "$TMUX_CONF" 2>/dev/null

configure — statusLine fallback (no tmux, or in addition to tmux)

When tmux is missing — or the user wants a second surface — wire the recap into Claude Code's own status bar via ~/.claude/settings.json.

  1. AskUserQuestion (Rule 1 — exactly 4 options):

    Wire recap into Claude Code statusLine (~/.claude/settings.json)?
      [Add to Claude Code statusLine]  [Show me the JSON, I'll add manually]  [Skip]  [Help]
    
  2. On Add to Claude Code statusLine, detect existing entry:

    SETTINGS="$HOME/.claude/settings.json"
    mkdir -p "$(dirname "$SETTINGS")"
    [ -f "$SETTINGS" ] || echo '{}' > "$SETTINGS"
    existing=$(jq -r '.statusLine // empty' "$SETTINGS")
    
  3. If existing is non-empty, ask (Rule 1 — 3 options):

    Existing statusLine detected. How to handle?
      [Replace with recap]  [Append after current (chain commands)]  [Skip]
    
  4. Merge with jq so other settings are preserved:

    TMP=$(mktemp)
    jq '.statusLine = {
      "type": "command",
      "command": "cat /tmp/claude-recap-digest 2>/dev/null | head -c 80",
      "refreshInterval": 30
    }' "$SETTINGS" > "$TMP" && mv "$TMP" "$SETTINGS"
    

    For the append branch, chain commands so both render side-by-side:

    prev_cmd=$(jq -r '.statusLine.command // ""' "$SETTINGS")
    if [ -n "$prev_cmd" ]; then
      new_cmd="${prev_cmd}; cat /tmp/claude-recap-digest 2>/dev/null | head -c 80"
    else
      new_cmd="cat /tmp/claude-recap-digest 2>/dev/null | head -c 80"
    fi
    TMP=$(mktemp)
    jq --arg cmd "$new_cmd" '.statusLine.command = $cmd' "$SETTINGS" > "$TMP" && mv "$TMP" "$SETTINGS"
    
  5. Print: ✓ Claude Code statusLine wired — restart Claude Code (or open a new session) to activate.

The JSON snippet (for the manual / Show me the JSON path):

{
  "statusLine": {
    "type": "command",
    "command": "cat /tmp/claude-recap-digest 2>/dev/null | head -c 80",
    "refreshInterval": 30
  }
}

Subcommand: restart

Reload the launchd agent without reconfiguring:

LABEL=com.claude-ops.recap-daemon
PLIST=~/Library/LaunchAgents/com.claude-ops.recap-daemon.plist
launchctl bootout "gui/$(id -u)/${LABEL}" 2>/dev/null || true
rm -rf /tmp/claude-recap-daemon.lock /tmp/claude-recap-daemon.pid
launchctl bootstrap "gui/$(id -u)" "$PLIST" && echo "✓ daemon restarted"

Linux / systemd alternative

The launchd plist is macOS-only. Linux users can wrap scripts/recap/daemon.sh in a systemd --user unit. Minimal example (~/.config/systemd/user/claude-recap-daemon.service):

[Unit]
Description=Claude Ops Recap Daemon
After=default.target

[Service]
Type=simple
ExecStart=/bin/sh %h/.claude/plugins/cache/ops-marketplace/ops/CURRENT/scripts/recap/daemon.sh
Restart=always
RestartSec=30

[Install]
WantedBy=default.target

Then systemctl --user daemon-reload && systemctl --user enable --now claude-recap-daemon. The CLI subcommands above (status / tail / restart) won't auto-detect systemd — use systemctl --user status claude-recap-daemon directly.

Invocation

/ops:recap (alias: shows status). Subcommand parsing:

sub="${1:-status}"
case "$sub" in
  status|tail|configure|restart) ;;
  *) echo "Unknown subcommand: $sub. Try: status | tail | configure | restart"; exit 1 ;;
esac

Version History

  • 64bad13 Current 2026-08-12 09:01

Same Skill Collection

claude-ops/skills/boss/SKILL.md
claude-ops/skills/flow/SKILL.md
claude-ops/skills/ledger/SKILL.md
claude-ops/skills/ops-accounts/SKILL.md
claude-ops/skills/ops-ar/SKILL.md
claude-ops/skills/ops-aws-audit/SKILL.md
claude-ops/skills/ops-comms/SKILL.md
claude-ops/skills/ops-competitors/SKILL.md
claude-ops/skills/ops-credentials/SKILL.md
claude-ops/skills/ops-daemon/SKILL.md
claude-ops/skills/ops-dash/SKILL.md
claude-ops/skills/ops-deploy-fix/SKILL.md
claude-ops/skills/ops-deploy/SKILL.md
claude-ops/skills/ops-desktop/SKILL.md
claude-ops/skills/ops-doctor/SKILL.md
claude-ops/skills/ops-ecom/SKILL.md
claude-ops/skills/ops-feature-dev/SKILL.md
claude-ops/skills/ops-fires/SKILL.md
claude-ops/skills/ops-fleet/SKILL.md
claude-ops/skills/ops-go/SKILL.md
claude-ops/skills/ops-gtm/SKILL.md
claude-ops/skills/ops-home/SKILL.md
claude-ops/skills/ops-inbox/SKILL.md
claude-ops/skills/ops-integrate/SKILL.md
claude-ops/skills/ops-leadgen/SKILL.md
claude-ops/skills/ops-linear/SKILL.md
claude-ops/skills/ops-mac/SKILL.md
claude-ops/skills/ops-marketing/SKILL.md
claude-ops/skills/ops-mcp/SKILL.md
claude-ops/skills/ops-merge/SKILL.md
claude-ops/skills/ops-monitor/SKILL.md
claude-ops/skills/ops-next/SKILL.md
claude-ops/skills/ops-orchestrate/SKILL.md
claude-ops/skills/ops-package/SKILL.md
claude-ops/skills/ops-pocket/SKILL.md
claude-ops/skills/ops-projects/SKILL.md
claude-ops/skills/ops-release/SKILL.md
claude-ops/skills/ops-resume/SKILL.md
claude-ops/skills/ops-revenue/SKILL.md
claude-ops/skills/ops-rotate-setup/SKILL.md
claude-ops/skills/ops-rotate/SKILL.md
claude-ops/skills/ops-secret-sync/SKILL.md
claude-ops/skills/ops-settings/SKILL.md
claude-ops/skills/ops-ship/SKILL.md
claude-ops/skills/ops-speedup/SKILL.md
claude-ops/skills/ops-status/SKILL.md
claude-ops/skills/ops-triage/SKILL.md
claude-ops/skills/ops-unifi/SKILL.md
claude-ops/skills/ops-update/SKILL.md

Metadata

Files
0
Version
64bad13
Hash
43a927d1
Indexed
2026-08-12 09:01

Главная - Вики-сайт
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-12 20:21
浙ICP备14020137号-1 $Гость$