Skip to content
This repository was archived by the owner on Jan 2, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{
"name": "memory-capture",
"description": "Git-backed memory system for Claude Code. Captures decisions, learnings, and context as git notes with semantic search and automatic recall.",
"version": "0.8.0",
"version": "0.9.0",
"author": {
"name": "Robert Allen",
"email": "zircote@gmail.com"
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "memory-capture",
"version": "0.8.0",
"version": "0.9.0",
"description": "Git-backed memory system for Claude Code. Captures decisions, learnings, and context as git notes with semantic search and automatic recall.",
"author": {
"name": "Robert Allen",
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,4 @@ dmypy.json

# Memory plugin local index
.memory/
.claude/settings.local.json
38 changes: 38 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,41 @@ def capture_service(tmp_path, monkeypatch):
| `HOOK_DEBUG` | Enable debug logging to stderr | `false` |
| `HOOK_SESSION_START_INCLUDE_GUIDANCE` | Include response guidance templates | `true` |
| `HOOK_SESSION_START_GUIDANCE_DETAIL` | Guidance level: minimal/standard/detailed | `standard` |

## Code Intelligence (LSP)

LSP hooks are configured in `.claude/hooks.json` for immediate feedback on Python edits.

### Installed Hooks

| Hook | Trigger | Action |
|------|---------|--------|
| `format-on-edit` | PostToolUse (Write/Edit) | Runs `ruff format` on changed files |
| `lint-check-on-edit` | PostToolUse (Write/Edit) | Runs `ruff check` on changed files |
| `typecheck-on-edit` | PostToolUse (Write/Edit) | Runs `mypy` on changed files |
| `pre-commit-quality-gate` | PreToolUse (git commit) | Runs full `make quality` before commit |

### Navigation & Understanding

- Use LSP `goToDefinition` before modifying unfamiliar functions, classes, or modules
- Use LSP `findReferences` before refactoring any symbol to understand full impact
- Use LSP `documentSymbol` to get file structure overview before major edits
- Prefer LSP navigation over grep—it resolves through imports and re-exports

### Verification Workflow

1. After each edit, check hook output for lint/type errors
2. Fix errors immediately before proceeding
3. Run `make quality` before committing

### Pre-Edit Checklist

- [ ] Navigate to definition to understand implementation
- [ ] Find all references to assess change impact
- [ ] Review type annotations via hover before modifying function signatures

### Error Handling

- If hooks report errors, fix them before proceeding to the next task
- Type errors are blocking in this project (mypy strict mode)
- Use hook output to guide fixes, not guesswork
88 changes: 83 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,63 @@ recall = get_recall_service()
memories = recall.search("database choice", namespace="decisions", limit=5)
```

## API Reference

### Core Services

The library exposes three primary service interfaces via factory functions:

| Service | Factory Function | Description |
|---------|-----------------|-------------|
| `CaptureService` | `get_capture_service()` | Capture memories with validation, git notes storage, and indexing |
| `RecallService` | `get_recall_service()` | Search memories using semantic (vector) or text-based queries |
| `SyncService` | `get_sync_service()` | Synchronize the SQLite index with git notes, verify consistency |

### Key Models

All models are immutable dataclasses (`frozen=True`) for thread-safety:

| Model | Description |
|-------|-------------|
| `Memory` | Core entity representing a captured memory (id, namespace, summary, content, timestamp, tags) |
| `MemoryResult` | Memory with similarity distance score from vector search |
| `CaptureResult` | Result of capture operation (success, memory, indexed, warning) |
| `IndexStats` | Statistics about the memory index (total, by_namespace, by_spec, last_sync) |
| `HydrationLevel` | Enum for progressive loading: `SUMMARY`, `FULL`, `FILES` |

### Common Operations

```python
from git_notes_memory import get_capture_service, get_recall_service, get_sync_service

# Capture with tags
capture = get_capture_service()
result = capture.capture(
namespace="learnings",
summary="pytest fixtures can be module-scoped",
content="Use @pytest.fixture(scope='module') for expensive setup",
tags=["pytest", "testing"],
)

# Semantic search with filters
recall = get_recall_service()
results = recall.search(
query="database configuration",
k=10, # max results
namespace="decisions", # filter by namespace
min_similarity=0.5, # minimum relevance threshold
)

# Sync and verify index
sync = get_sync_service()
sync.reindex(full=True) # full reindex from git notes
verification = sync.verify_consistency()
if not verification.is_consistent:
sync.repair(verification)
```

For complete API documentation, see the [Developer Guide](docs/DEVELOPER_GUIDE.md).

## Claude Code Plugin

When used as a Claude Code plugin, the following slash commands are available:
Expand Down Expand Up @@ -102,27 +159,48 @@ make quality

## Configuration

Environment variables (see `.env.example` for all options):
### Core Settings

| Variable | Description | Default |
|----------|-------------|---------|
| `MEMORY_PLUGIN_DATA_DIR` | Data directory path | `~/.local/share/memory-plugin/` |
| `MEMORY_PLUGIN_GIT_NAMESPACE` | Git notes namespace | `refs/notes/mem` |
| `MEMORY_PLUGIN_EMBEDDING_MODEL` | Embedding model name | `all-MiniLM-L6-v2` |
| `MEMORY_PLUGIN_DATA_DIR` | Data directory for index and models | `~/.local/share/memory-plugin/` |
| `MEMORY_PLUGIN_GIT_NAMESPACE` | Git notes ref prefix | `refs/notes/mem` |
| `MEMORY_PLUGIN_EMBEDDING_MODEL` | Sentence-transformer model | `all-MiniLM-L6-v2` |
| `MEMORY_PLUGIN_AUTO_CAPTURE` | Enable auto-capture hook | `false` |

### Hook Configuration

| Variable | Description | Default |
|----------|-------------|---------|
| `HOOK_ENABLED` | Master switch for hooks | `true` |
| `HOOK_ENABLED` | Master switch for all hooks | `true` |
| `HOOK_SESSION_START_ENABLED` | Enable SessionStart context injection | `true` |
| `HOOK_SESSION_START_INCLUDE_GUIDANCE` | Include response guidance templates | `true` |
| `HOOK_SESSION_START_GUIDANCE_DETAIL` | Guidance level: minimal/standard/detailed | `standard` |
| `HOOK_USER_PROMPT_ENABLED` | Enable signal detection in prompts | `false` |
| `HOOK_POST_TOOL_USE_ENABLED` | Enable file-contextual memory injection | `true` |
| `HOOK_POST_TOOL_USE_MIN_SIMILARITY` | Minimum similarity threshold | `0.6` |
| `HOOK_POST_TOOL_USE_MAX_RESULTS` | Maximum memories to inject | `3` |
| `HOOK_POST_TOOL_USE_AUTO_CAPTURE` | Auto-capture from written content | `true` |
| `HOOK_PRE_COMPACT_ENABLED` | Enable auto-capture before compaction | `true` |
| `HOOK_PRE_COMPACT_AUTO_CAPTURE` | Auto-capture without prompt | `true` |
| `HOOK_PRE_COMPACT_PROMPT_FIRST` | Suggestion mode (show, don't capture) | `false` |
| `HOOK_PRE_COMPACT_MIN_CONFIDENCE` | Minimum confidence for capture | `0.85` |
| `HOOK_PRE_COMPACT_MAX_CAPTURES` | Maximum captures per compaction | `3` |
| `HOOK_STOP_ENABLED` | Enable Stop hook processing | `true` |
| `HOOK_STOP_SYNC_INDEX` | Sync index on session end | `true` |
| `HOOK_STOP_PROMPT_UNCAPTURED` | Prompt for uncaptured content | `true` |
| `HOOK_DEBUG` | Enable debug logging to stderr | `false` |

### Performance Tuning

| Variable | Description | Default |
|----------|-------------|---------|
| `HOOK_SESSION_START_TOKEN_BUDGET` | Max tokens for context injection | `2000` |
| `HOOK_POST_TOOL_USE_TIMEOUT` | Hook timeout in seconds | `5` |
| `HOOK_PRE_COMPACT_TIMEOUT` | Hook timeout in seconds | `15` |

See `.env.example` for the complete list of configuration options.

## Requirements

- Python 3.11+
Expand Down
73 changes: 67 additions & 6 deletions commands/capture.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,46 @@ argument-hint: "[namespace] <summary> -- <content>"
allowed-tools: ["Bash", "Write", "Read", "AskUserQuestion"]
---

<help_check>
## Help Check

If `$ARGUMENTS` contains `--help` or `-h`:

**Output this help and HALT (do not proceed further):**

<help_output>
```
CAPTURE(1) User Commands CAPTURE(1)

NAME
capture - Capture a memory (decision, learning, blocker, progress...

SYNOPSIS
/memory:capture [namespace] <summary> -- <content>

DESCRIPTION
Capture a memory (decision, learning, blocker, progress, etc.) to the git-backed memory system

OPTIONS
--help, -h Show this help message

EXAMPLES
/memory:capture
/memory:capture <namespace>
/memory:capture --help

SEE ALSO
/memory:* for related commands

CAPTURE(1)
```
</help_output>

**After outputting help, HALT immediately. Do not proceed with command execution.**
</help_check>

---

# /memory:capture - Capture a Memory

Capture information to the git-backed memory system for later retrieval.
Expand All @@ -12,7 +52,7 @@ Capture information to the git-backed memory system for later retrieval.

You will help the user capture a memory. The memory will be stored as a git note and indexed for semantic search.

### Step 1: Parse the Arguments
<step number="1" name="Parse the Arguments">

**Arguments format**: `$ARGUMENTS`

Expand All @@ -31,14 +71,18 @@ If no namespace specified, auto-detect based on content patterns:
- Contains "pattern", "recurring", "often" → `patterns`
- Default → `learnings`

### Step 2: Validate Content
</step>

<step number="2" name="Validate Content">

If `$ARGUMENTS` is empty or very short (< 10 characters):
- Use AskUserQuestion to prompt for the memory content
- Question: "What would you like to capture?"
- Provide examples for each memory type

### Step 3: Capture the Memory
</step>

<step number="3" name="Capture the Memory">

Use Bash to invoke the Python library:

Expand Down Expand Up @@ -69,7 +113,9 @@ Replace:
- `$SUMMARY` with a one-line summary (max 100 chars, escape quotes)
- `$CONTENT` with the full content (escape quotes)

### Step 4: Confirm to User
</step>

<step number="4" name="Confirm to User">

Show the result:
```
Expand All @@ -83,6 +129,8 @@ This memory will be available for recall in future sessions.
Use `/memory:recall` to retrieve it.
```

</step>

## Namespace Reference

| Namespace | Use For | Example |
Expand All @@ -108,13 +156,15 @@ For structured captures, the library also provides:
- `capture_pattern(summary, pattern_type, evidence, confidence)` - Patterns
- `capture_review(spec, summary, findings, verdict)` - Code reviews

## Error Handling
<error_handling>

If the capture fails:
1. Check if we're in a git repository: `git rev-parse --git-dir`
2. Check if the library is installed: `uv run python3 -c "import git_notes_memory"`
3. Show helpful error message with recovery action

</error_handling>

## Examples

**User**: `/memory:capture decisions Use Redis for session storage -- Due to built-in expiration and cluster support`
Expand All @@ -131,9 +181,20 @@ If the capture fails:
After successfully capturing a memory, remind the user:

```
💡 **Pro tip**: You can capture memories inline using markers:
**Pro tip**: You can capture memories inline using markers:
- `[remember] <insight>` - Captures a learning
- `[capture] <decision>` - Captures any type of memory
- `@memory <content>` - Same as [capture]

These markers work anywhere in your message and are automatically processed.
```

## Related Commands

| Command | Description |
|---------|-------------|
| `/memory:recall` | Search and retrieve captured memories semantically |
| `/memory:search` | Advanced search with filtering options |
| `/memory:status` | View memory system statistics and health |
| `/memory:sync` | Synchronize the index with git notes |
| `/memory:validate` | Validate the memory system is working correctly |
Loading
Loading