97a3a2cf8d
- 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
94 lines
2.8 KiB
Bash
Executable File
94 lines
2.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Hook: PostToolUse (matcher: Bash)
|
|
#
|
|
# Fires AFTER a Bash tool call completes. When a git commit/merge/rebase
|
|
# just succeeded, surfaces 1-3 relevant memories from the changed files
|
|
# and prompts Claude to ask the user if this change should be stored as
|
|
# a learning.
|
|
#
|
|
# Input: JSON on stdin with tool_name, tool_input, tool_result
|
|
# Output: Context injected into Claude's next response (exit 0)
|
|
#
|
|
# This implements Spec #28 — interactive pre-commit memory check.
|
|
|
|
set -uo pipefail
|
|
|
|
INPUT=$(cat)
|
|
|
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null || echo "")
|
|
|
|
if [ -z "$COMMAND" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Only trigger on git commit/merge/rebase commands
|
|
case "$COMMAND" in
|
|
*"git commit"*|*"git merge"*|*"git rebase"*)
|
|
;;
|
|
*)
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
# Check if the command actually succeeded (look for commit hash in output)
|
|
TOOL_RESULT=$(echo "$INPUT" | jq -r '.tool_result // ""' 2>/dev/null || echo "")
|
|
if echo "$TOOL_RESULT" | grep -qiE '(error|fatal|abort|nothing to commit|no changes)'; then
|
|
exit 0
|
|
fi
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
. "$SCRIPT_DIR/_identity.sh" 2>/dev/null || true
|
|
|
|
# No API key — skip interactive prompt
|
|
if [ -z "${MEM0_API_KEY:-}" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Extract changed files from commit
|
|
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | head -10 || echo "")
|
|
if [ -z "$CHANGED_FILES" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Get the commit message
|
|
COMMIT_MSG=$(git log -1 --format='%s' HEAD 2>/dev/null || echo "")
|
|
|
|
# Build file list for display
|
|
FILE_LIST=$(echo "$CHANGED_FILES" | sed 's/^/ - /' | head -5)
|
|
FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l | tr -d ' ')
|
|
|
|
cat <<EOF
|
|
|
|
## Commit captured — save as memory?
|
|
|
|
**Commit:** $COMMIT_MSG
|
|
**Files changed ($FILE_COUNT):**
|
|
$FILE_LIST
|
|
|
|
This commit may contain learnings worth preserving. Ask the user:
|
|
|
|
> **Save this change as a memory?** I can store it as one of:
|
|
> - \`decision\` — if an architectural or design choice was made
|
|
> - \`task_learning\` — if a strategy or approach worked well
|
|
> - \`anti_pattern\` — if this fixes a bug or avoids a known pitfall
|
|
> - \`convention\` — if this establishes a new pattern
|
|
>
|
|
> Type the category, or **skip** to move on.
|
|
|
|
If the user provides a category (or says yes/sure/go ahead):
|
|
1. Summarize the commit: what changed and why (from the diff + commit message)
|
|
2. Call \`add_memory\` with:
|
|
- \`messages=[{"role": "user", "content": "<your summary>"}]\`
|
|
- \`user_id="$MEM0_RESOLVED_USER_ID"\`
|
|
- \`app_id="$MEM0_PROJECT_ID"\`
|
|
- \`metadata={"type": "<chosen_category>", "branch": "$MEM0_BRANCH", "confidence": 0.8, "files": [<changed files>], "source": "post-commit"}\`
|
|
- \`infer=False\`
|
|
|
|
If the user says skip/no/nothing: proceed normally. Do NOT ask again for the same commit.
|
|
EOF
|
|
|
|
# Telemetry
|
|
python3 "$SCRIPT_DIR/telemetry.py" post_commit --files_count="$FILE_COUNT" 2>/dev/null &
|
|
|
|
exit 0
|