Hooks, Rules & Automation

The mechanisms you can use to make memory routing deterministic.

Path-Scoped Rules: The Most Reliable Mechanism

Rules in .claude/rules/ with paths: frontmatter are mechanically enforced by the harness. They re-inject every time Claude accesses a matching file — unlike CLAUDE.md triggers which depend on Claude "remembering."

# .claude/rules/api-conventions.md
---
paths:
  - "src/api/**/*.ts"
  - "src/routes/api/**"
---
# API Rules
- All endpoints must validate input at the handler level
- Use typed error responses, never raw strings
- Read memory/api-patterns.md for the full conventions
# .claude/rules/deploy-safety.md
---
paths:
  - "**/deploy*"
  - "**/Dockerfile"
  - "**/.github/workflows/**"
  - "**/*.service"
---
# Deploy Rules
- Read memory/deploy-guide.md before any deploy changes
- Use systemctl for systemd services — never manual kill/start

Rules without paths: frontmatter load unconditionally at session start. Use sparingly — they consume context every session.

Hook Events (27 total)

The most useful hooks for memory management:

EventUse for MemoryCan Block?
SessionStartInject rules + context at every session start (including after compaction)No
PreToolUseInject context before specific tools runYes
PostToolUseInject context after tool resultsNo
FileChangedReact when watched files change on diskNo
InstructionsLoadedTrack which instruction files loaded and whyNo

SessionStart Hook: Inject Context Every Session

Configuration

// ~/.claude/settings.json
{
  "hooks": {
    "SessionStart": [{
      "matcher": "startup|resume|compact",
      "hooks": [{
        "type": "command",
        "command": "/path/to/session-context.sh",
        "timeout": 5
      }]
    }]
  }
}

The Script

#!/bin/bash
# session-context.sh — inject always-on rules + git state

RULES="## Session Context (auto-injected)

### Always-On Rules
1. One fix at a time — only the approved change, no extras
2. Verify claims — label uncertainty, offer to verify before acting
3. Evidence-first debugging — cite logs/timestamps, not speculation
4. No magic strings — use constants or enums for property checks"

GIT_INFO=""
if git rev-parse --git-dir >/dev/null 2&1; then
  BRANCH=$(git branch --show-current 2>/dev/null)
  RECENT=$(git log --oneline -3 2>/dev/null)
  GIT_INFO="

### Git State
Branch: $BRANCH
Recent:
$RECENT"
fi

jq -n --arg ctx "$RULES$GIT_INFO" '{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": $ctx
  }
}'

What SessionStart Can Return

FieldEffect
additionalContextInjected into Claude's context
initialUserMessageSets the first user message
watchPathsArray of absolute file paths to monitor for FileChanged events

Environment Variables Available

VariableAvailable InValue
CLAUDE_PROJECT_DIRAll hooksReal repo root (stable)
CLAUDE_ENV_FILESessionStart, CwdChanged, FileChangedPath to temp .sh file — write exports here to persist env vars across the session

Hook I/O

Hooks receive JSON on stdin:

{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.jsonl",
  "cwd": "/current/working/directory",
  "hook_event_name": "SessionStart",
  "source": "startup"  // or "resume", "compact"
}

Exit codes: 0 = success (stdout parsed as JSON), 2 = block action (stderr shown to Claude), other = non-blocking error.

The if Field (for Tool Hooks)

Pre-execution filter using permission rule syntax. Avoids spawning the hook process for non-matching commands:

{
  "type": "command",
  "command": "/path/to/check-git.sh",
  "if": "Bash(git *)"  // only fires for git commands
}

Only works for tool events (PreToolUse, PostToolUse, etc.), not SessionStart.

MCP Servers for Memory

Give Claude an explicit search_memories() tool:

ServerBackendPrivacy
@modelcontextprotocol/server-memoryJSONL filesLocal
memorious-mcpChromaDBLocal
mcp-server-qdrantQdrantLocal/cloud
mcp-memory-serviceKnowledge graphLocal
// ~/.claude/.mcp.json
{
  "mcpServers": {
    "memory-search": {
      "command": "uvx",
      "args": ["memorious-mcp"],
      "env": { "MEMORIOUS_DB_PATH": "~/.claude/semantic-memory" }
    }
  }
}