Skip to content
This repository was archived by the owner on Jan 2, 2026. It is now read-only.

Commit d7b76b3

Browse files
zircoteclaude
andcommitted
refactor(hooks): extract shared utilities and add security validation
QUAL-1: Extract ~200 lines of duplicated utilities from 5 handlers into hook_utils.py module with setup_logging(), setup_timeout(), cancel_timeout(), and read_json_input() functions. SEC-1: Add validate_file_path() function with path traversal protection to prevent arbitrary file access via malicious hook input. DOC-1: Document PostToolUse and PreCompact hooks in README.md and USER_GUIDE.md with configuration options and usage examples. Changes: - Create src/git_notes_memory/hooks/hook_utils.py with shared utilities - Update 5 handlers to use centralized utilities - Add path validation to session_analyzer.py - Add 8 security tests for path validation - Document all 5 hooks and their configuration options - Add guidance config docs (HOOK_SESSION_START_INCLUDE_GUIDANCE) Test coverage: 1327 tests passing, 86.34% coverage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent eea02ba commit d7b76b3

13 files changed

Lines changed: 553 additions & 382 deletions

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,13 @@ When used as a Claude Code plugin, the following slash commands are available:
7373

7474
The plugin includes hooks that integrate with Claude Code's hook system for automatic memory context:
7575

76-
- **SessionStart**: Injects relevant project memories at session start
77-
- **UserPromptSubmit**: Detects capture-worthy content in user prompts (opt-in)
78-
- **Stop**: Prompts for uncaptured content and syncs the search index
76+
| Hook | Description |
77+
|------|-------------|
78+
| **SessionStart** | Injects relevant project memories and response guidance at session start |
79+
| **UserPromptSubmit** | Detects capture markers like `[remember]` and `@memory` in prompts |
80+
| **PostToolUse** | Surfaces related memories after file operations (Read/Write/Edit) |
81+
| **PreCompact** | Auto-captures high-confidence content before context compaction |
82+
| **Stop** | Prompts for uncaptured content and syncs the search index |
7983

8084
See [User Guide](docs/USER_GUIDE.md#hooks-integration) for configuration options.
8185

@@ -114,6 +118,8 @@ Environment variables (see `.env.example` for all options):
114118
| `HOOK_ENABLED` | Master switch for hooks | `true` |
115119
| `HOOK_SESSION_START_ENABLED` | Enable SessionStart context injection | `true` |
116120
| `HOOK_USER_PROMPT_ENABLED` | Enable signal detection in prompts | `false` |
121+
| `HOOK_POST_TOOL_USE_ENABLED` | Enable file-contextual memory injection | `true` |
122+
| `HOOK_PRE_COMPACT_ENABLED` | Enable auto-capture before compaction | `true` |
117123
| `HOOK_STOP_ENABLED` | Enable Stop hook processing | `true` |
118124
| `HOOK_DEBUG` | Enable debug logging to stderr | `false` |
119125

docs/USER_GUIDE.md

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ All environment variables are optional. Defaults are shown below.
397397
| `HOOK_ENABLED` | Master switch for hooks | `true` |
398398
| `HOOK_SESSION_START_ENABLED` | Enable SessionStart hook | `true` |
399399
| `HOOK_USER_PROMPT_ENABLED` | Enable UserPromptSubmit hook | `false` |
400+
| `HOOK_POST_TOOL_USE_ENABLED` | Enable PostToolUse hook | `true` |
401+
| `HOOK_PRE_COMPACT_ENABLED` | Enable PreCompact hook | `true` |
400402
| `HOOK_STOP_ENABLED` | Enable Stop hook | `true` |
401403
| `HOOK_DEBUG` | Enable debug logging | `false` |
402404
| `HOOK_TIMEOUT` | Hook timeout in seconds | `30` |
@@ -408,6 +410,8 @@ All environment variables are optional. Defaults are shown below.
408410
| `HOOK_SESSION_START_BUDGET_MODE` | Budget mode: adaptive, fixed, full, minimal | `adaptive` |
409411
| `HOOK_SESSION_START_FIXED_BUDGET` | Fixed budget (when mode=fixed) | `1000` |
410412
| `HOOK_SESSION_START_MAX_BUDGET` | Maximum budget cap | `3000` |
413+
| `HOOK_SESSION_START_INCLUDE_GUIDANCE` | Include response guidance in context | `true` |
414+
| `HOOK_SESSION_START_GUIDANCE_DETAIL` | Guidance detail: minimal, standard, detailed | `standard` |
411415

412416
#### Capture Detection Configuration
413417

@@ -449,12 +453,14 @@ The memory plugin includes hooks that integrate with Claude Code's hook system f
449453

450454
### Overview
451455

452-
Three hooks are available:
456+
Five hooks are available:
453457

454458
| Hook | Event | Purpose | Default |
455459
|------|-------|---------|---------|
456-
| SessionStart | Session begins | Inject project memories | Enabled |
457-
| UserPromptSubmit | User sends prompt | Detect capture signals | Disabled |
460+
| SessionStart | Session begins | Inject project memories and response guidance | Enabled |
461+
| UserPromptSubmit | User sends prompt | Detect capture signals and inline markers | Disabled |
462+
| PostToolUse | After Read/Write/Edit | Surface related memories for files | Enabled |
463+
| PreCompact | Before context compaction | Auto-capture high-confidence content | Enabled |
458464
| Stop | Session ends | Prompt for uncaptured content, sync index | Enabled |
459465

460466
### SessionStart Hook
@@ -519,6 +525,85 @@ export HOOK_CAPTURE_DETECTION_AUTO_THRESHOLD=0.95
519525
export HOOK_CAPTURE_DETECTION_NOVELTY_THRESHOLD=0.3
520526
```
521527

528+
### PostToolUse Hook
529+
530+
Surfaces related memories after file operations to provide contextual information.
531+
532+
**What it does:**
533+
1. Triggers after Read, Write, Edit, or MultiEdit operations
534+
2. Extracts domain terms from the file path (e.g., `src/auth/jwt.py` → auth, jwt)
535+
3. Searches for memories related to those domains
536+
4. Injects relevant memories as additional context
537+
538+
**Example output:**
539+
When you read or edit `src/auth/oauth_handler.py`, the hook may inject:
540+
```xml
541+
<related_memories>
542+
<memory namespace="decisions" confidence="0.82">
543+
Chose OAuth 2.0 with PKCE for authentication flow
544+
</memory>
545+
<memory namespace="learnings" confidence="0.75">
546+
Token refresh must happen before expiry to avoid race conditions
547+
</memory>
548+
</related_memories>
549+
```
550+
551+
**Configuration:**
552+
553+
```bash
554+
# Disable PostToolUse hook
555+
export HOOK_POST_TOOL_USE_ENABLED=false
556+
557+
# Minimum similarity threshold (0.0-1.0)
558+
export HOOK_POST_TOOL_USE_MIN_SIMILARITY=0.6
559+
560+
# Maximum memories to inject
561+
export HOOK_POST_TOOL_USE_MAX_RESULTS=3
562+
563+
# Timeout in seconds
564+
export HOOK_POST_TOOL_USE_TIMEOUT=5
565+
```
566+
567+
### PreCompact Hook
568+
569+
Auto-captures high-confidence content before Claude Code compacts the context.
570+
571+
**What it does:**
572+
1. Triggers before context compaction (automatic or manual)
573+
2. Analyzes the conversation transcript for uncaptured signals
574+
3. Filters to high-confidence items (≥85% by default)
575+
4. Auto-captures up to 3 memories to prevent information loss
576+
5. Reports captures via stderr (visible in terminal)
577+
578+
**Example stderr output:**
579+
```
580+
Auto-captured 2 memories before compaction:
581+
- [decisions] Chose PostgreSQL for JSONB support
582+
- [learnings] pytest fixtures need session scope for DB connections
583+
```
584+
585+
**Configuration:**
586+
587+
```bash
588+
# Disable PreCompact hook
589+
export HOOK_PRE_COMPACT_ENABLED=false
590+
591+
# Enable auto-capture (captures without prompting)
592+
export HOOK_PRE_COMPACT_AUTO_CAPTURE=true
593+
594+
# Enable suggestion mode (prompts before capturing)
595+
export HOOK_PRE_COMPACT_PROMPT_FIRST=false
596+
597+
# Minimum confidence for auto-capture (0.0-1.0)
598+
export HOOK_PRE_COMPACT_MIN_CONFIDENCE=0.85
599+
600+
# Maximum memories to auto-capture
601+
export HOOK_PRE_COMPACT_MAX_CAPTURES=3
602+
603+
# Timeout in seconds
604+
export HOOK_PRE_COMPACT_TIMEOUT=15
605+
```
606+
522607
### Stop Hook
523608

524609
Performs session-end cleanup and memory assistance.
@@ -560,6 +645,8 @@ The hooks are installed automatically when you configure the plugin in Claude Co
560645

561646
- `hooks/sessionstart.py` - SessionStart event handler
562647
- `hooks/userpromptsubmit.py` - UserPromptSubmit event handler
648+
- `hooks/posttooluse.py` - PostToolUse event handler
649+
- `hooks/precompact.py` - PreCompact event handler
563650
- `hooks/stop.py` - Stop event handler
564651
- `hooks/hooks.json` - Hook registration configuration
565652

0 commit comments

Comments
 (0)