Files
mem0/mem0-plugin/scripts/on_bash_output.sh
T
kartik-mem0 97a3a2cf8d feat(mem0-plugin): complete all Tier 1-8 spec items, add scheduled dream and bash error detection
- Add /mem0:dream --schedule support via Claude Code /schedule command
  with local launchd/cron fallback for non-cloud users
- Add /mem0:digest --schedule and file output to ~/.mem0/weekly-digest.md
  with digest-history.log for trend tracking
- Add on_post_commit.sh PostToolUse hook: interactive prompt after git
  commit asking user to save change as memory with category suggestion
- Add on_bash_output.sh PostToolUse hook: detects stack traces and error
  patterns in bash command output, injects mem0 search rubric for prior
  occurrences (complements existing user prompt error detection)
- Fix session-end report: now shows per-category breakdown
  "wrote 3 memories (decision 2, anti_pattern 1)" matching spec
- Wire new hooks into all 3 platforms (Claude Code, Cursor, Codex)
- Add post_commit and bash_error telemetry events
- Add CTO demo testing guide with tier-by-tier manual test steps
2026-05-21 23:55:06 +05:30

105 lines
3.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# Hook: PostToolUse (matcher: Bash)
#
# Scans bash command output for stack traces and error patterns.
# When found, injects a search rubric telling the agent to check mem0
# for prior occurrences of the same error.
#
# This complements on_user_prompt.sh (which catches errors in the user's
# typed message). This hook catches errors in COMMAND OUTPUT — e.g.,
# when `npm test` or `python script.py` fails with a traceback.
#
# Input: JSON on stdin with tool_name, tool_input, tool_result
# Output: Context injected into Claude's next response (exit 0)
set -uo pipefail
INPUT=$(cat)
TOOL_RESULT=$(echo "$INPUT" | jq -r '.tool_result // ""' 2>/dev/null || echo "")
# Skip short output (< 50 chars unlikely to contain a real stack trace)
if [ ${#TOOL_RESULT} -lt 50 ]; then
exit 0
fi
# Skip if this is a git commit (handled by on_post_commit.sh)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null || echo "")
case "$COMMAND" in
*"git commit"*|*"git merge"*|*"git rebase"*)
exit 0
;;
esac
# Detect stack traces and error patterns in command output
HAS_ERROR=""
if echo "$TOOL_RESULT" | grep -qiE '(Traceback \(most recent|Error:|Exception:|panic:|FAILED|fatal:|FAIL:| at .+\.[a-z]+:[0-9]+|error\[E[0-9]+\])'; then
HAS_ERROR="true"
fi
if [ -z "$HAS_ERROR" ]; then
exit 0
fi
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
. "$SCRIPT_DIR/_identity.sh" 2>/dev/null || true
if [ -z "${MEM0_API_KEY:-}" ]; then
exit 0
fi
# Extract error class/message (first matching line)
ERROR_LINE=$(echo "$TOOL_RESULT" | grep -iE '(Error:|Exception:|panic:|FAIL:|fatal:)' | head -1 | sed 's/^[[:space:]]*//' | cut -c1-120)
# Extract file paths from stack trace frames
TRACE_FILES=$(echo "$TOOL_RESULT" | grep -oE '([a-zA-Z0-9_./-]+\.(py|ts|tsx|js|jsx|rs|go|rb|java|sh))(:[0-9]+)?' | head -5 | sort -u)
# Build file list for display
FILE_DISPLAY=""
if [ -n "$TRACE_FILES" ]; then
FILE_DISPLAY=$(echo "$TRACE_FILES" | sed 's/^/ - /')
fi
USER_ID="$MEM0_RESOLVED_USER_ID"
cat <<EOF
## Error detected in command output
\`$COMMAND\` produced an error:
> $ERROR_LINE
EOF
if [ -n "$FILE_DISPLAY" ]; then
cat <<EOF
**Files in stack trace:**
$FILE_DISPLAY
EOF
fi
cat <<EOF
Search mem0 for prior occurrences — this error may have been seen before:
- \`search_memories(query="$(echo "$ERROR_LINE" | cut -c1-60)", filters={"AND": [{"user_id": "$USER_ID"}, {"app_id": "$MEM0_PROJECT_ID"}, {"metadata": {"type": "anti_pattern"}}]})\`
- \`search_memories(query="$(echo "$ERROR_LINE" | cut -c1-60)", filters={"AND": [{"user_id": "$USER_ID"}, {"app_id": "$MEM0_PROJECT_ID"}, {"metadata": {"type": "bug_fix"}}]})\`
EOF
if [ -n "$TRACE_FILES" ]; then
FIRST_FILE=$(echo "$TRACE_FILES" | head -1 | sed 's/:[0-9]*//')
cat <<EOF
- \`search_memories(query="$FIRST_FILE", filters={"AND": [{"user_id": "$USER_ID"}, {"app_id": "$MEM0_PROJECT_ID"}]})\`
EOF
fi
cat <<EOF
If mem0 returns relevant context, use it to debug faster.
If you solve this, store the fix as an \`anti_pattern\` or \`bug_fix\` memory for next time.
EOF
# Telemetry
python3 "$SCRIPT_DIR/telemetry.py" bash_error --error_detected 2>/dev/null &
exit 0