Claude Code Memory Compiler
This commit is contained in:
commit
f83d38d787
15 changed files with 2819 additions and 0 deletions
92
hooks/session-start.py
Normal file
92
hooks/session-start.py
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
"""
|
||||
SessionStart hook - injects knowledge base context into every conversation.
|
||||
|
||||
This is the "context injection" layer. When Claude Code starts a session,
|
||||
this hook reads the knowledge base index and recent daily log, then injects
|
||||
them as additional context so Claude always "remembers" what it has learned.
|
||||
|
||||
Configure in .claude/settings.json:
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [{
|
||||
"matcher": "",
|
||||
"command": "uv run python hooks/session-start.py"
|
||||
}]
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
|
||||
# Paths relative to project root
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
KNOWLEDGE_DIR = ROOT / "knowledge"
|
||||
DAILY_DIR = ROOT / "daily"
|
||||
INDEX_FILE = KNOWLEDGE_DIR / "index.md"
|
||||
|
||||
MAX_CONTEXT_CHARS = 20_000
|
||||
MAX_LOG_LINES = 30
|
||||
|
||||
|
||||
def get_recent_log() -> str:
|
||||
"""Read the most recent daily log (today or yesterday)."""
|
||||
today = datetime.now(timezone.utc).astimezone()
|
||||
|
||||
for offset in range(2):
|
||||
date = today - timedelta(days=offset)
|
||||
log_path = DAILY_DIR / f"{date.strftime('%Y-%m-%d')}.md"
|
||||
if log_path.exists():
|
||||
lines = log_path.read_text(encoding="utf-8").splitlines()
|
||||
# Return last N lines to keep context small
|
||||
recent = lines[-MAX_LOG_LINES:] if len(lines) > MAX_LOG_LINES else lines
|
||||
return "\n".join(recent)
|
||||
|
||||
return "(no recent daily log)"
|
||||
|
||||
|
||||
def build_context() -> str:
|
||||
"""Assemble the context to inject into the conversation."""
|
||||
parts = []
|
||||
|
||||
# Today's date
|
||||
today = datetime.now(timezone.utc).astimezone()
|
||||
parts.append(f"## Today\n{today.strftime('%A, %B %d, %Y')}")
|
||||
|
||||
# Knowledge base index (the core retrieval mechanism)
|
||||
if INDEX_FILE.exists():
|
||||
index_content = INDEX_FILE.read_text(encoding="utf-8")
|
||||
parts.append(f"## Knowledge Base Index\n\n{index_content}")
|
||||
else:
|
||||
parts.append("## Knowledge Base Index\n\n(empty - no articles compiled yet)")
|
||||
|
||||
# Recent daily log
|
||||
recent_log = get_recent_log()
|
||||
parts.append(f"## Recent Daily Log\n\n{recent_log}")
|
||||
|
||||
context = "\n\n---\n\n".join(parts)
|
||||
|
||||
# Truncate if too long
|
||||
if len(context) > MAX_CONTEXT_CHARS:
|
||||
context = context[:MAX_CONTEXT_CHARS] + "\n\n...(truncated)"
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def main():
|
||||
context = build_context()
|
||||
|
||||
output = {
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "SessionStart",
|
||||
"additionalContext": context,
|
||||
}
|
||||
}
|
||||
|
||||
print(json.dumps(output))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue