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

Commit cda9c6d

Browse files
committed
chore: add project documentation and config updates
- Add CLAUDE.md with project guidance - Add .env.example for environment variables - Update config.py with new helper functions - Update dependencies in uv.lock
1 parent ea782bc commit cda9c6d

6 files changed

Lines changed: 216 additions & 3 deletions

File tree

.env.example

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Git Notes Memory Plugin - Environment Configuration
2+
# Copy this file to .env and modify as needed
3+
# All variables are optional - defaults are shown
4+
5+
# =============================================================================
6+
# Storage Configuration
7+
# =============================================================================
8+
9+
# Override the XDG-compliant data directory
10+
# Default: ~/.local/share/memory-plugin/
11+
# MEMORY_PLUGIN_DATA_DIR=~/.local/share/memory-plugin
12+
13+
# =============================================================================
14+
# Git Notes Configuration
15+
# =============================================================================
16+
17+
# Override the git notes namespace (ref prefix)
18+
# Default: refs/notes/mem
19+
# MEMORY_PLUGIN_GIT_NAMESPACE=refs/notes/mem
20+
21+
# =============================================================================
22+
# Embedding Model Configuration
23+
# =============================================================================
24+
25+
# Override the sentence-transformers embedding model
26+
# Default: all-MiniLM-L6-v2
27+
# MEMORY_PLUGIN_EMBEDDING_MODEL=all-MiniLM-L6-v2
28+
29+
# =============================================================================
30+
# Feature Flags
31+
# =============================================================================
32+
33+
# Enable auto-capture of memories during Claude sessions
34+
# Accepts: 1, true, yes, on (case-insensitive)
35+
# Default: disabled
36+
# MEMORY_PLUGIN_AUTO_CAPTURE=false
37+
38+
# =============================================================================
39+
# XDG Base Directory (System)
40+
# =============================================================================
41+
42+
# Override XDG data home (affects default data directory)
43+
# Default: ~/.local/share
44+
# XDG_DATA_HOME=~/.local/share

CLAUDE.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
`git-notes-memory` is a Python library and Claude Code plugin that provides git-native, semantically-searchable memory storage. Memories are stored as git notes with YAML front matter and indexed in SQLite with sqlite-vec for vector similarity search.
8+
9+
## Development Commands
10+
11+
```bash
12+
# Install with dev dependencies
13+
uv sync
14+
15+
# Run all tests
16+
make test
17+
18+
# Run tests with coverage (80% minimum required)
19+
make coverage
20+
21+
# Run a specific test file
22+
uv run pytest tests/test_capture.py -v
23+
24+
# Run a single test
25+
uv run pytest tests/test_capture.py::TestCaptureService::test_capture_basic -v
26+
27+
# Skip slow tests
28+
uv run pytest -m "not slow"
29+
30+
# Run all quality checks (format, lint, typecheck, security, tests)
31+
make quality
32+
33+
# Individual quality checks
34+
make format # Auto-fix formatting
35+
make lint # Ruff linting
36+
make typecheck # mypy strict mode
37+
make security # bandit security scan
38+
```
39+
40+
## Architecture
41+
42+
### Service Layer Pattern
43+
44+
The codebase uses a singleton service factory pattern with lazy initialization:
45+
46+
```
47+
__init__.py # Lazy imports via __getattr__ to avoid loading embedding model at import
48+
└── get_capture_service() → CaptureService
49+
└── get_recall_service() → RecallService
50+
└── get_sync_service() → SyncService
51+
```
52+
53+
Services are exposed through factory functions (`get_*_service()`) that return singleton instances. Internal modules use `get_default_service()` naming.
54+
55+
### Core Data Flow
56+
57+
```
58+
Capture:
59+
CaptureService.capture()
60+
→ validate (namespace, summary ≤100 chars, content ≤100KB)
61+
→ serialize_note() (YAML front matter + body)
62+
→ GitOps.append_note() (atomic append to refs/notes/mem/{namespace})
63+
→ EmbeddingService.embed() (sentence-transformers, graceful degradation)
64+
→ IndexService.insert() (SQLite + sqlite-vec)
65+
66+
Recall:
67+
RecallService.search()
68+
→ EmbeddingService.embed(query)
69+
→ IndexService.search_vector() (KNN via sqlite-vec)
70+
→ Memory objects with distance scores
71+
```
72+
73+
### Git Notes Storage
74+
75+
Memories are stored under `refs/notes/mem/{namespace}` where namespace is one of:
76+
`inception`, `elicitation`, `research`, `decisions`, `progress`, `blockers`, `reviews`, `learnings`, `retrospective`, `patterns`
77+
78+
Each note has YAML front matter:
79+
```yaml
80+
---
81+
type: decisions
82+
timestamp: 2024-01-15T10:30:00Z
83+
summary: Use PostgreSQL for persistence
84+
spec: my-project
85+
tags: [database, architecture]
86+
---
87+
## Context
88+
...
89+
```
90+
91+
### Key Modules
92+
93+
| Module | Responsibility |
94+
|--------|---------------|
95+
| `capture.py` | Memory capture with file locking (`fcntl`) for concurrency |
96+
| `recall.py` | Search and retrieval with progressive hydration |
97+
| `index.py` | SQLite + sqlite-vec for metadata and vector search |
98+
| `embedding.py` | Sentence-transformer embeddings (all-MiniLM-L6-v2) |
99+
| `git_ops.py` | Git notes operations with security validation |
100+
| `note_parser.py` | YAML front matter parsing/serialization |
101+
| `models.py` | Frozen dataclasses for all domain objects |
102+
| `sync.py` | Index synchronization with git notes |
103+
104+
### Models
105+
106+
All models are immutable (`@dataclass(frozen=True)`):
107+
- `Memory` - Core entity with id format `{namespace}:{commit_sha}:{index}`
108+
- `MemoryResult` - Memory + distance score from vector search
109+
- `CaptureResult` - Operation result with success/warning status
110+
- `HydrationLevel` - SUMMARY → FULL → FILES progressive loading
111+
112+
### Claude Code Plugin Integration
113+
114+
The `.claude-plugin/` directory defines:
115+
- Commands: `/capture`, `/recall`, `/search`, `/sync`, `/status`
116+
- Hooks: `Stop` (sync index on session end)
117+
- Skills: `memory-recall` for semantic search
118+
119+
## Code Conventions
120+
121+
- Python 3.11+ with full type annotations (mypy strict)
122+
- Google-style docstrings
123+
- Frozen dataclasses for all models (immutability)
124+
- Tuple over list for immutable collections in models
125+
- Factory functions expose services; internal modules use `get_default_service()`
126+
- Graceful degradation: embedding failures don't block capture
127+
128+
## Testing
129+
130+
The test suite uses pytest with automatic singleton reset via `conftest.py`. Each test gets isolated service instances to prevent cross-test pollution.
131+
132+
```python
133+
# Tests automatically reset singletons via autouse fixture
134+
# For manual isolation, use tmp_path and monkeypatch:
135+
@pytest.fixture
136+
def capture_service(tmp_path, monkeypatch):
137+
monkeypatch.setenv("MEMORY_PLUGIN_DATA_DIR", str(tmp_path))
138+
return get_capture_service(repo_path=tmp_path)
139+
```
140+
141+
## Environment Variables
142+
143+
| Variable | Description | Default |
144+
|----------|-------------|---------|
145+
| `MEMORY_PLUGIN_DATA_DIR` | Data/index directory | `~/.local/share/memory-plugin/` |
146+
| `MEMORY_PLUGIN_GIT_NAMESPACE` | Git notes ref prefix | `refs/notes/mem` |
147+
| `MEMORY_PLUGIN_EMBEDDING_MODEL` | Embedding model | `all-MiniLM-L6-v2` |

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ test: ## Run tests
3232
uv run pytest
3333

3434
test-cov: ## Run tests with coverage
35-
uv run pytest --cov=git_notes_memory_manager --cov-report=html --cov-report=term-missing
35+
uv run pytest --cov=git_notes_memory --cov-report=html --cov-report=term-missing
3636

3737
lint: ## Run linter (ruff)
3838
uv run ruff check src/ tests/
@@ -52,7 +52,7 @@ format-check: ## Check formatting
5252
uv run ruff check src/ tests/
5353

5454
coverage: ## Run tests with coverage threshold
55-
uv run pytest --cov=git_notes_memory_manager --cov-report=term-missing --cov-fail-under=80
55+
uv run pytest --cov=git_notes_memory --cov-report=term-missing --cov-fail-under=80
5656

5757
quality: ## Run all quality checks
5858
@echo "Running quality checks..."
@@ -75,7 +75,7 @@ quality: ## Run all quality checks
7575
@echo "Security: PASS"
7676
@echo ""
7777
@echo "5. Tests with coverage..."
78-
@uv run pytest --cov=git_notes_memory_manager --cov-report=term-missing --cov-fail-under=80 -q
78+
@uv run pytest --cov=git_notes_memory --cov-report=term-missing --cov-fail-under=80 -q
7979
@echo ""
8080
@echo "ALL QUALITY CHECKS PASSED"
8181

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ classifiers = [
2424
requires-python = ">=3.11"
2525
dependencies = [
2626
"pyyaml>=6.0",
27+
"python-dotenv>=1.0.0",
2728
"sentence-transformers>=2.2.0",
2829
"sqlite-vec>=0.1.1",
2930
]

src/git_notes_memory/config.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,23 @@
1212
XDG Compliance:
1313
By default, data is stored in $XDG_DATA_HOME/memory-plugin/ which
1414
defaults to ~/.local/share/memory-plugin/ if XDG_DATA_HOME is not set.
15+
16+
.env File Support:
17+
Place a .env file in the project root or working directory to set
18+
environment variables. See .env.example for available options.
1519
"""
1620

1721
from __future__ import annotations
1822

1923
import os
2024
from pathlib import Path
2125

26+
from dotenv import load_dotenv
27+
28+
# Load .env file early, before any environment variable access
29+
# This looks for .env in the current directory and parent directories
30+
load_dotenv()
31+
2232
__all__ = [
2333
# Namespaces
2434
"NAMESPACES",

uv.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)