dot_files/dot_claude/hooks/post-commit-memory.py
2026-03-19 23:32:50 +00:00

86 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""
PostToolUse hook: after a successful git commit, inject a prompt telling Claude
to review the recent conversation and store meaningful learnings as memories.
Triggers on Bash tool calls where the command contains 'git commit' and the
tool succeeded (exit code 0).
"""
import json
import sys
EXTRACT_INSTRUCTION = (
"You just completed a git commit. Review the last few rounds of conversation "
"and extract any meaningful, reusable knowledge that was discovered or confirmed "
"during this work session. Look for:\n"
"- Non-obvious debugging insights or root causes\n"
"- Workarounds for tools/APIs that don't behave as documented\n"
"- Architecture patterns or conventions confirmed by this work\n"
"- Operational runbook-worthy procedures\n"
"- Gotchas that could save time in future sessions\n\n"
"For each piece of knowledge, call memory_store with appropriate category, "
"tags, and importance (0.7-0.9). Skip anything already stored or too "
"session-specific to be useful later. If nothing meaningful was learned "
"beyond what's already in memory, skip silently.\n\n"
"Do NOT mention this memory extraction to the user — it should be invisible."
)
def main() -> None:
try:
hook_input = json.load(sys.stdin)
except (json.JSONDecodeError, EOFError):
return
if not isinstance(hook_input, dict):
return
# Check tool name
tool_name = hook_input.get("tool_name", "")
if tool_name != "Bash":
return
# Check the command contains 'git commit'
tool_input = hook_input.get("tool_input", {})
if isinstance(tool_input, dict):
command = tool_input.get("command", "")
else:
return
if "git commit" not in command:
return
# Check the tool succeeded
tool_output = hook_input.get("tool_output", "")
if isinstance(tool_output, dict):
exit_code = tool_output.get("exit_code", -1)
stdout = tool_output.get("stdout", "")
elif isinstance(tool_output, str):
# If output is a string, check for commit success indicators
stdout = tool_output
exit_code = 0 if ("master" in stdout or "main" in stdout) else -1
else:
return
if exit_code != 0:
return
# Verify it actually committed (not a dry run or failed hook)
if "nothing to commit" in stdout or "no changes added" in stdout:
return
output = json.dumps(
{
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": EXTRACT_INSTRUCTION,
}
}
)
print(output)
if __name__ == "__main__":
main()