claudememory 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claudememory-0.1.0/CLAUDE.md +97 -0
- claudememory-0.1.0/MANIFEST.in +6 -0
- claudememory-0.1.0/PKG-INFO +97 -0
- claudememory-0.1.0/README.md +75 -0
- claudememory-0.1.0/claudememory.egg-info/PKG-INFO +97 -0
- claudememory-0.1.0/claudememory.egg-info/SOURCES.txt +20 -0
- claudememory-0.1.0/claudememory.egg-info/dependency_links.txt +1 -0
- claudememory-0.1.0/claudememory.egg-info/entry_points.txt +5 -0
- claudememory-0.1.0/claudememory.egg-info/requires.txt +16 -0
- claudememory-0.1.0/claudememory.egg-info/top_level.txt +1 -0
- claudememory-0.1.0/config/mcp_config_example.json +15 -0
- claudememory-0.1.0/git_memory/__init__.py +27 -0
- claudememory-0.1.0/git_memory/chroma_index.py +190 -0
- claudememory-0.1.0/git_memory/cli.py +190 -0
- claudememory-0.1.0/git_memory/filters.py +80 -0
- claudememory-0.1.0/git_memory/indexer.py +151 -0
- claudememory-0.1.0/pyproject.toml +53 -0
- claudememory-0.1.0/setup.cfg +4 -0
- claudememory-0.1.0/skills/git-memory-debug/SKILL.md +104 -0
- claudememory-0.1.0/skills/git-memory-index/SKILL.md +96 -0
- claudememory-0.1.0/skills/git-memory-search/SKILL.md +94 -0
- claudememory-0.1.0/skills/git-memory-status/SKILL.md +81 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<!-- git-memory:start -->
|
|
2
|
+
|
|
3
|
+
# Git Memory System
|
|
4
|
+
|
|
5
|
+
This project provides **git-memory** — a dual-layer semantic index over Git commit history for Claude Code.
|
|
6
|
+
|
|
7
|
+
Two storage layers work together:
|
|
8
|
+
- **ChromaDB** — 1 document per commit, cosine similarity, metadata filters (fast, authoritative facts)
|
|
9
|
+
- **Mem0** — LLM-extracted context, cross-session learned interpretation (why things were built a certain way)
|
|
10
|
+
|
|
11
|
+
## Always Start Here
|
|
12
|
+
|
|
13
|
+
When beginning any task in a repository that has git-memory configured:
|
|
14
|
+
|
|
15
|
+
1. Call `latest_commits(5)` to understand what changed recently
|
|
16
|
+
2. Call `search_git_history(<relevant topic>)` before touching any module with history
|
|
17
|
+
3. After fixing a bug, call `bug_fix_history(<component>)` to check for prior regressions
|
|
18
|
+
|
|
19
|
+
## Available Skills
|
|
20
|
+
|
|
21
|
+
| Task | Skill |
|
|
22
|
+
|------|-------|
|
|
23
|
+
| Search commit history for a topic | `/git-memory-search` |
|
|
24
|
+
| Index a new repository | `/git-memory-index` |
|
|
25
|
+
| Debug why a component behaves a certain way | `/git-memory-debug` |
|
|
26
|
+
| Check what's currently indexed | `/git-memory-status` |
|
|
27
|
+
|
|
28
|
+
## MCP Tools Reference
|
|
29
|
+
|
|
30
|
+
These tools are available when the `git-memory` MCP server is running.
|
|
31
|
+
|
|
32
|
+
| Tool | What it gives you | When to use |
|
|
33
|
+
|------|-------------------|-------------|
|
|
34
|
+
| `search_git_history(query, limit, category)` | Commits semantically related to a topic | Before editing any significant module |
|
|
35
|
+
| `latest_commits(limit)` | N most-recent indexed commits | Session start, before investigating regressions |
|
|
36
|
+
| `commits_touching_file(filename, limit)` | All commits that modified a file | Before editing a file — understand its history |
|
|
37
|
+
| `bug_fix_history(component, include_security)` | Bug/security fixes for a component | Before adding new code near known bug areas |
|
|
38
|
+
| `architecture_decisions(topic, limit)` | Refactors, migrations, design decisions | Understanding why code is structured a certain way |
|
|
39
|
+
|
|
40
|
+
## Proactive Usage Rules
|
|
41
|
+
|
|
42
|
+
**Always call before editing:**
|
|
43
|
+
```
|
|
44
|
+
commits_touching_file("PaymentService.php") # know what's broken here before
|
|
45
|
+
bug_fix_history("auth") # avoid re-introducing fixed bugs
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Always call at session start:**
|
|
49
|
+
```
|
|
50
|
+
latest_commits(10) # what changed while you were away?
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Always call when confused about design:**
|
|
54
|
+
```
|
|
55
|
+
architecture_decisions("state machine") # why was this abstraction introduced?
|
|
56
|
+
search_git_history("why was X removed")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Category Filter Values
|
|
60
|
+
|
|
61
|
+
Use `category=` in `search_git_history()` to narrow results:
|
|
62
|
+
|
|
63
|
+
| Category | Matches |
|
|
64
|
+
|----------|---------|
|
|
65
|
+
| `fix` | Bug fixes, hotfixes, patches |
|
|
66
|
+
| `feat` | New features |
|
|
67
|
+
| `security` | Security-related changes |
|
|
68
|
+
| `refactor` | Code refactors |
|
|
69
|
+
| `migration` | Database/schema migrations |
|
|
70
|
+
| `arch` | Architecture decisions |
|
|
71
|
+
| `perf` | Performance improvements |
|
|
72
|
+
|
|
73
|
+
## Integration with GitNexus
|
|
74
|
+
|
|
75
|
+
If GitNexus is also configured, use both systems together:
|
|
76
|
+
|
|
77
|
+
| Question | Use |
|
|
78
|
+
|----------|-----|
|
|
79
|
+
| What does this function call? | GitNexus `context(symbol)` |
|
|
80
|
+
| Why was this function written this way? | git-memory `search_git_history(symbol)` |
|
|
81
|
+
| What will break if I change this? | GitNexus `impact(symbol)` |
|
|
82
|
+
| Has this area had bugs before? | git-memory `bug_fix_history(component)` |
|
|
83
|
+
| What changed recently? | git-memory `latest_commits(10)` |
|
|
84
|
+
|
|
85
|
+
## Setup for a New Repository
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# 1. Index the repo
|
|
89
|
+
git-memory index --repo-path /path/to/repo --user-id my-repo
|
|
90
|
+
|
|
91
|
+
# 2. Install Claude Code plugin (skills + MCP config)
|
|
92
|
+
git-memory install --repo-path /path/to/repo --user-id my-repo
|
|
93
|
+
|
|
94
|
+
# 3. Restart Claude Code
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
<!-- git-memory:end -->
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: claudememory
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Dual-layer ChromaDB + Mem0 Git commit index for Claude Code
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: claude-code,mcp,git,memory,chromadb,mem0,ai,claudememory
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: gitpython>=3.1.40
|
|
10
|
+
Requires-Dist: mem0ai>=0.1.0
|
|
11
|
+
Requires-Dist: fastmcp>=0.4.0
|
|
12
|
+
Requires-Dist: chromadb>=1.0.0
|
|
13
|
+
Requires-Dist: ollama>=0.3.0
|
|
14
|
+
Provides-Extra: openai
|
|
15
|
+
Requires-Dist: openai>=1.0.0; extra == "openai"
|
|
16
|
+
Provides-Extra: sentence-transformers
|
|
17
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == "sentence-transformers"
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest; extra == "dev"
|
|
20
|
+
Requires-Dist: ruff; extra == "dev"
|
|
21
|
+
Requires-Dist: mypy; extra == "dev"
|
|
22
|
+
|
|
23
|
+
# git-memory
|
|
24
|
+
|
|
25
|
+
Dual-layer semantic index over Git commit history for Claude Code.
|
|
26
|
+
|
|
27
|
+
| Layer | Purpose |
|
|
28
|
+
|-------|---------|
|
|
29
|
+
| **ChromaDB** | 1 document/commit, cosine similarity, metadata filters — fast, authoritative facts |
|
|
30
|
+
| **Mem0** | LLM-extracted context, cross-session learned interpretation — the *why* layer |
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install git-memory
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
No external services required — works out of the box with three embedding options:
|
|
39
|
+
|
|
40
|
+
| Mode | Setup | Cost |
|
|
41
|
+
|------|-------|------|
|
|
42
|
+
| **Ollama** (default) | `ollama pull nomic-embed-text` | Free, fully local |
|
|
43
|
+
| **sentence-transformers** | `pip install "git-memory[sentence-transformers]"` | Free, fully local, no Ollama |
|
|
44
|
+
| **OpenAI** | `pip install "git-memory[openai]"` + `OPENAI_API_KEY` | ~$0.0001/commit |
|
|
45
|
+
|
|
46
|
+
## Quick start
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# 1. Index your repository
|
|
50
|
+
git-memory index --repo-path /path/to/repo --user-id my-repo
|
|
51
|
+
|
|
52
|
+
# 2. Install Claude Code skills + MCP config
|
|
53
|
+
git-memory install --repo-path /path/to/repo --user-id my-repo
|
|
54
|
+
|
|
55
|
+
# 3. Restart Claude Code — then use /git-memory-search, /git-memory-debug etc.
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## MCP tools
|
|
59
|
+
|
|
60
|
+
| Tool | Description |
|
|
61
|
+
|------|-------------|
|
|
62
|
+
| `search_git_history(query)` | Semantic search over commit history |
|
|
63
|
+
| `latest_commits(limit)` | N most-recent indexed commits |
|
|
64
|
+
| `commits_touching_file(filename)` | All commits that modified a file |
|
|
65
|
+
| `bug_fix_history(component)` | Bug/security fixes for a component |
|
|
66
|
+
| `architecture_decisions(topic)` | Refactors, migrations, design decisions |
|
|
67
|
+
|
|
68
|
+
## CLI
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git-memory index --repo-path . --user-id myapp # bulk index
|
|
72
|
+
git-memory serve # start MCP server (stdio)
|
|
73
|
+
git-memory status --repo-path . # show coverage
|
|
74
|
+
git-memory install --repo-path . --user-id myapp # install plugin
|
|
75
|
+
git-memory store HEAD # store single commit (hook)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Configuration
|
|
79
|
+
|
|
80
|
+
All settings via environment variables:
|
|
81
|
+
|
|
82
|
+
| Variable | Default | Description |
|
|
83
|
+
|----------|---------|-------------|
|
|
84
|
+
| `GIT_MEMORY_REPO_PATH` | `.` | Repository to index |
|
|
85
|
+
| `GIT_MEMORY_USER_ID` | `git_memory_system` | Mem0 namespace (use per-repo names) |
|
|
86
|
+
| `GIT_MEMORY_CHROMA_DIR` | `~/.cache/git_memory/chroma_commits` | ChromaDB storage path |
|
|
87
|
+
| `GIT_MEMORY_EMBED_PROVIDER` | `ollama` | Embedding backend: `ollama`, `openai`, `sentence-transformers` |
|
|
88
|
+
| `GIT_MEMORY_EMBED_MODEL` | *(provider default)* | Override embedding model name |
|
|
89
|
+
| `GIT_MEMORY_LLM_MODEL` | *(provider default)* | Override LLM model name (Mem0 layer) |
|
|
90
|
+
| `OPENAI_API_KEY` | *(empty)* | Enables OpenAI embeddings + LLM automatically |
|
|
91
|
+
| `MEM0_API_KEY` | *(empty)* | Use Mem0 cloud instead of local inference |
|
|
92
|
+
| `OLLAMA_URL` | `http://localhost:11434` | Ollama endpoint |
|
|
93
|
+
|
|
94
|
+
## Works great alongside [GitNexus](https://github.com/your-org/gitnexus)
|
|
95
|
+
|
|
96
|
+
- GitNexus answers **what calls what** (structural, live code)
|
|
97
|
+
- git-memory answers **why it was written that way** (historical, commit-level)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# git-memory
|
|
2
|
+
|
|
3
|
+
Dual-layer semantic index over Git commit history for Claude Code.
|
|
4
|
+
|
|
5
|
+
| Layer | Purpose |
|
|
6
|
+
|-------|---------|
|
|
7
|
+
| **ChromaDB** | 1 document/commit, cosine similarity, metadata filters — fast, authoritative facts |
|
|
8
|
+
| **Mem0** | LLM-extracted context, cross-session learned interpretation — the *why* layer |
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install git-memory
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
No external services required — works out of the box with three embedding options:
|
|
17
|
+
|
|
18
|
+
| Mode | Setup | Cost |
|
|
19
|
+
|------|-------|------|
|
|
20
|
+
| **Ollama** (default) | `ollama pull nomic-embed-text` | Free, fully local |
|
|
21
|
+
| **sentence-transformers** | `pip install "git-memory[sentence-transformers]"` | Free, fully local, no Ollama |
|
|
22
|
+
| **OpenAI** | `pip install "git-memory[openai]"` + `OPENAI_API_KEY` | ~$0.0001/commit |
|
|
23
|
+
|
|
24
|
+
## Quick start
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 1. Index your repository
|
|
28
|
+
git-memory index --repo-path /path/to/repo --user-id my-repo
|
|
29
|
+
|
|
30
|
+
# 2. Install Claude Code skills + MCP config
|
|
31
|
+
git-memory install --repo-path /path/to/repo --user-id my-repo
|
|
32
|
+
|
|
33
|
+
# 3. Restart Claude Code — then use /git-memory-search, /git-memory-debug etc.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## MCP tools
|
|
37
|
+
|
|
38
|
+
| Tool | Description |
|
|
39
|
+
|------|-------------|
|
|
40
|
+
| `search_git_history(query)` | Semantic search over commit history |
|
|
41
|
+
| `latest_commits(limit)` | N most-recent indexed commits |
|
|
42
|
+
| `commits_touching_file(filename)` | All commits that modified a file |
|
|
43
|
+
| `bug_fix_history(component)` | Bug/security fixes for a component |
|
|
44
|
+
| `architecture_decisions(topic)` | Refactors, migrations, design decisions |
|
|
45
|
+
|
|
46
|
+
## CLI
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
git-memory index --repo-path . --user-id myapp # bulk index
|
|
50
|
+
git-memory serve # start MCP server (stdio)
|
|
51
|
+
git-memory status --repo-path . # show coverage
|
|
52
|
+
git-memory install --repo-path . --user-id myapp # install plugin
|
|
53
|
+
git-memory store HEAD # store single commit (hook)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Configuration
|
|
57
|
+
|
|
58
|
+
All settings via environment variables:
|
|
59
|
+
|
|
60
|
+
| Variable | Default | Description |
|
|
61
|
+
|----------|---------|-------------|
|
|
62
|
+
| `GIT_MEMORY_REPO_PATH` | `.` | Repository to index |
|
|
63
|
+
| `GIT_MEMORY_USER_ID` | `git_memory_system` | Mem0 namespace (use per-repo names) |
|
|
64
|
+
| `GIT_MEMORY_CHROMA_DIR` | `~/.cache/git_memory/chroma_commits` | ChromaDB storage path |
|
|
65
|
+
| `GIT_MEMORY_EMBED_PROVIDER` | `ollama` | Embedding backend: `ollama`, `openai`, `sentence-transformers` |
|
|
66
|
+
| `GIT_MEMORY_EMBED_MODEL` | *(provider default)* | Override embedding model name |
|
|
67
|
+
| `GIT_MEMORY_LLM_MODEL` | *(provider default)* | Override LLM model name (Mem0 layer) |
|
|
68
|
+
| `OPENAI_API_KEY` | *(empty)* | Enables OpenAI embeddings + LLM automatically |
|
|
69
|
+
| `MEM0_API_KEY` | *(empty)* | Use Mem0 cloud instead of local inference |
|
|
70
|
+
| `OLLAMA_URL` | `http://localhost:11434` | Ollama endpoint |
|
|
71
|
+
|
|
72
|
+
## Works great alongside [GitNexus](https://github.com/your-org/gitnexus)
|
|
73
|
+
|
|
74
|
+
- GitNexus answers **what calls what** (structural, live code)
|
|
75
|
+
- git-memory answers **why it was written that way** (historical, commit-level)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: claudememory
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Dual-layer ChromaDB + Mem0 Git commit index for Claude Code
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: claude-code,mcp,git,memory,chromadb,mem0,ai,claudememory
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: gitpython>=3.1.40
|
|
10
|
+
Requires-Dist: mem0ai>=0.1.0
|
|
11
|
+
Requires-Dist: fastmcp>=0.4.0
|
|
12
|
+
Requires-Dist: chromadb>=1.0.0
|
|
13
|
+
Requires-Dist: ollama>=0.3.0
|
|
14
|
+
Provides-Extra: openai
|
|
15
|
+
Requires-Dist: openai>=1.0.0; extra == "openai"
|
|
16
|
+
Provides-Extra: sentence-transformers
|
|
17
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == "sentence-transformers"
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest; extra == "dev"
|
|
20
|
+
Requires-Dist: ruff; extra == "dev"
|
|
21
|
+
Requires-Dist: mypy; extra == "dev"
|
|
22
|
+
|
|
23
|
+
# git-memory
|
|
24
|
+
|
|
25
|
+
Dual-layer semantic index over Git commit history for Claude Code.
|
|
26
|
+
|
|
27
|
+
| Layer | Purpose |
|
|
28
|
+
|-------|---------|
|
|
29
|
+
| **ChromaDB** | 1 document/commit, cosine similarity, metadata filters — fast, authoritative facts |
|
|
30
|
+
| **Mem0** | LLM-extracted context, cross-session learned interpretation — the *why* layer |
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install git-memory
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
No external services required — works out of the box with three embedding options:
|
|
39
|
+
|
|
40
|
+
| Mode | Setup | Cost |
|
|
41
|
+
|------|-------|------|
|
|
42
|
+
| **Ollama** (default) | `ollama pull nomic-embed-text` | Free, fully local |
|
|
43
|
+
| **sentence-transformers** | `pip install "git-memory[sentence-transformers]"` | Free, fully local, no Ollama |
|
|
44
|
+
| **OpenAI** | `pip install "git-memory[openai]"` + `OPENAI_API_KEY` | ~$0.0001/commit |
|
|
45
|
+
|
|
46
|
+
## Quick start
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# 1. Index your repository
|
|
50
|
+
git-memory index --repo-path /path/to/repo --user-id my-repo
|
|
51
|
+
|
|
52
|
+
# 2. Install Claude Code skills + MCP config
|
|
53
|
+
git-memory install --repo-path /path/to/repo --user-id my-repo
|
|
54
|
+
|
|
55
|
+
# 3. Restart Claude Code — then use /git-memory-search, /git-memory-debug etc.
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## MCP tools
|
|
59
|
+
|
|
60
|
+
| Tool | Description |
|
|
61
|
+
|------|-------------|
|
|
62
|
+
| `search_git_history(query)` | Semantic search over commit history |
|
|
63
|
+
| `latest_commits(limit)` | N most-recent indexed commits |
|
|
64
|
+
| `commits_touching_file(filename)` | All commits that modified a file |
|
|
65
|
+
| `bug_fix_history(component)` | Bug/security fixes for a component |
|
|
66
|
+
| `architecture_decisions(topic)` | Refactors, migrations, design decisions |
|
|
67
|
+
|
|
68
|
+
## CLI
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git-memory index --repo-path . --user-id myapp # bulk index
|
|
72
|
+
git-memory serve # start MCP server (stdio)
|
|
73
|
+
git-memory status --repo-path . # show coverage
|
|
74
|
+
git-memory install --repo-path . --user-id myapp # install plugin
|
|
75
|
+
git-memory store HEAD # store single commit (hook)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Configuration
|
|
79
|
+
|
|
80
|
+
All settings via environment variables:
|
|
81
|
+
|
|
82
|
+
| Variable | Default | Description |
|
|
83
|
+
|----------|---------|-------------|
|
|
84
|
+
| `GIT_MEMORY_REPO_PATH` | `.` | Repository to index |
|
|
85
|
+
| `GIT_MEMORY_USER_ID` | `git_memory_system` | Mem0 namespace (use per-repo names) |
|
|
86
|
+
| `GIT_MEMORY_CHROMA_DIR` | `~/.cache/git_memory/chroma_commits` | ChromaDB storage path |
|
|
87
|
+
| `GIT_MEMORY_EMBED_PROVIDER` | `ollama` | Embedding backend: `ollama`, `openai`, `sentence-transformers` |
|
|
88
|
+
| `GIT_MEMORY_EMBED_MODEL` | *(provider default)* | Override embedding model name |
|
|
89
|
+
| `GIT_MEMORY_LLM_MODEL` | *(provider default)* | Override LLM model name (Mem0 layer) |
|
|
90
|
+
| `OPENAI_API_KEY` | *(empty)* | Enables OpenAI embeddings + LLM automatically |
|
|
91
|
+
| `MEM0_API_KEY` | *(empty)* | Use Mem0 cloud instead of local inference |
|
|
92
|
+
| `OLLAMA_URL` | `http://localhost:11434` | Ollama endpoint |
|
|
93
|
+
|
|
94
|
+
## Works great alongside [GitNexus](https://github.com/your-org/gitnexus)
|
|
95
|
+
|
|
96
|
+
- GitNexus answers **what calls what** (structural, live code)
|
|
97
|
+
- git-memory answers **why it was written that way** (historical, commit-level)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
CLAUDE.md
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
claudememory.egg-info/PKG-INFO
|
|
6
|
+
claudememory.egg-info/SOURCES.txt
|
|
7
|
+
claudememory.egg-info/dependency_links.txt
|
|
8
|
+
claudememory.egg-info/entry_points.txt
|
|
9
|
+
claudememory.egg-info/requires.txt
|
|
10
|
+
claudememory.egg-info/top_level.txt
|
|
11
|
+
config/mcp_config_example.json
|
|
12
|
+
git_memory/__init__.py
|
|
13
|
+
git_memory/chroma_index.py
|
|
14
|
+
git_memory/cli.py
|
|
15
|
+
git_memory/filters.py
|
|
16
|
+
git_memory/indexer.py
|
|
17
|
+
skills/git-memory-debug/SKILL.md
|
|
18
|
+
skills/git-memory-index/SKILL.md
|
|
19
|
+
skills/git-memory-search/SKILL.md
|
|
20
|
+
skills/git-memory-status/SKILL.md
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
git_memory
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Add the 'mcpServers' block to your existing ~/.claude/claude_desktop_config.json",
|
|
3
|
+
"mcpServers": {
|
|
4
|
+
"git-memory": {
|
|
5
|
+
"command": "python",
|
|
6
|
+
"args": ["/ABSOLUTE/PATH/TO/YOUR/REPO/ai/git_memory_mcp_server.py"],
|
|
7
|
+
"env": {
|
|
8
|
+
"GIT_MEMORY_REPO_PATH": "/ABSOLUTE/PATH/TO/YOUR/REPO",
|
|
9
|
+
"GIT_MEMORY_USER_ID": "git_memory_system",
|
|
10
|
+
"MEM0_API_KEY": "YOUR_MEM0_API_KEY_OR_LEAVE_EMPTY_FOR_LOCAL_CHROMA",
|
|
11
|
+
"GIT_MEMORY_CHROMA_DIR": "/Users/YOU/.cache/git_memory/chroma"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""
|
|
2
|
+
git-memory — Dual-layer ChromaDB + Mem0 commit index for Claude Code.
|
|
3
|
+
|
|
4
|
+
Layers:
|
|
5
|
+
ChromaDB — 1 document per commit, cosine similarity, metadata filters
|
|
6
|
+
Mem0 — LLM-extracted context, cross-session learned interpretation
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
git-memory index --repo-path /path/to/repo
|
|
10
|
+
git-memory serve
|
|
11
|
+
git-memory install # installs Claude Code plugin
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
__version__ = "0.1.0"
|
|
15
|
+
__author__ = "Güneş Bizim"
|
|
16
|
+
|
|
17
|
+
from git_memory.chroma_index import ChromaCommitIndex
|
|
18
|
+
from git_memory.indexer import GitMemoryIndexer
|
|
19
|
+
from git_memory.filters import is_relevant, summarize_commit, build_metadata
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"ChromaCommitIndex",
|
|
23
|
+
"GitMemoryIndexer",
|
|
24
|
+
"is_relevant",
|
|
25
|
+
"summarize_commit",
|
|
26
|
+
"build_metadata",
|
|
27
|
+
]
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ChromaDB layer for git commits.
|
|
3
|
+
1 document = 1 commit — no fragmentation, no LLM extraction overhead.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
import chromadb
|
|
12
|
+
|
|
13
|
+
log = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
CHROMA_DIR = os.getenv("GIT_MEMORY_CHROMA_DIR",
|
|
16
|
+
str(Path.home() / ".cache" / "git_memory" / "chroma_commits"))
|
|
17
|
+
OLLAMA_URL = os.getenv("OLLAMA_URL", "http://localhost:11434")
|
|
18
|
+
EMBED_MODEL = os.getenv("GIT_MEMORY_EMBED_MODEL", "nomic-embed-text")
|
|
19
|
+
EMBED_PROVIDER = os.getenv("GIT_MEMORY_EMBED_PROVIDER", "ollama") # ollama | openai | sentence-transformers
|
|
20
|
+
COLLECTION = "git_commits"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _build_embedding_function():
|
|
24
|
+
"""Return a ChromaDB embedding function based on GIT_MEMORY_EMBED_PROVIDER."""
|
|
25
|
+
if EMBED_PROVIDER == "openai":
|
|
26
|
+
from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction
|
|
27
|
+
model = os.getenv("GIT_MEMORY_EMBED_MODEL", "text-embedding-3-small")
|
|
28
|
+
return OpenAIEmbeddingFunction(
|
|
29
|
+
api_key=os.environ["OPENAI_API_KEY"],
|
|
30
|
+
model_name=model,
|
|
31
|
+
)
|
|
32
|
+
if EMBED_PROVIDER == "sentence-transformers":
|
|
33
|
+
from chromadb.utils.embedding_functions import SentenceTransformerEmbeddingFunction
|
|
34
|
+
model = os.getenv("GIT_MEMORY_EMBED_MODEL", "all-MiniLM-L6-v2")
|
|
35
|
+
return SentenceTransformerEmbeddingFunction(model_name=model)
|
|
36
|
+
# default: ollama
|
|
37
|
+
from chromadb.utils.embedding_functions import OllamaEmbeddingFunction
|
|
38
|
+
return OllamaEmbeddingFunction(
|
|
39
|
+
url=f"{OLLAMA_URL}/api/embeddings",
|
|
40
|
+
model_name=EMBED_MODEL,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _build_document(commit_hash, author, date, message, stats, files):
|
|
45
|
+
files_str = ", ".join(files) if files else "none"
|
|
46
|
+
return (
|
|
47
|
+
f"{message.strip()}\n"
|
|
48
|
+
f"Author: {author}\n"
|
|
49
|
+
f"Date: {date}\n"
|
|
50
|
+
f"Stats: {stats}\n"
|
|
51
|
+
f"Files: {files_str}"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ChromaCommitIndex:
|
|
56
|
+
"""1 ChromaDB document per Git commit — fast, accurate, no LLM overhead."""
|
|
57
|
+
|
|
58
|
+
def __init__(self, chroma_dir=CHROMA_DIR):
|
|
59
|
+
Path(chroma_dir).mkdir(parents=True, exist_ok=True)
|
|
60
|
+
self._client = chromadb.PersistentClient(path=chroma_dir)
|
|
61
|
+
self._ef = _build_embedding_function()
|
|
62
|
+
self._col = self._client.get_or_create_collection(
|
|
63
|
+
name=COLLECTION,
|
|
64
|
+
embedding_function=self._ef,
|
|
65
|
+
metadata={"hnsw:space": "cosine"},
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def upsert_commit(self, commit_hash, author_name, author_email, committed_date,
|
|
69
|
+
message, category, files, stats_str, repo) -> bool:
|
|
70
|
+
if self._col.get(ids=[commit_hash])["ids"]:
|
|
71
|
+
return False
|
|
72
|
+
self._col.add(
|
|
73
|
+
ids=[commit_hash],
|
|
74
|
+
documents=[_build_document(
|
|
75
|
+
commit_hash, f"{author_name} <{author_email}>",
|
|
76
|
+
committed_date[:10], message, stats_str, files,
|
|
77
|
+
)],
|
|
78
|
+
metadatas=[{
|
|
79
|
+
"short_hash": commit_hash[:8],
|
|
80
|
+
"author_name": author_name,
|
|
81
|
+
"author_email": author_email,
|
|
82
|
+
"committed_date": committed_date,
|
|
83
|
+
"category": category,
|
|
84
|
+
"repo": repo,
|
|
85
|
+
"files_str": "|".join(files),
|
|
86
|
+
"date_str": committed_date[:10],
|
|
87
|
+
}],
|
|
88
|
+
)
|
|
89
|
+
return True
|
|
90
|
+
|
|
91
|
+
def search(self, query, n_results=10, category=None, repo=None) -> list[dict]:
|
|
92
|
+
where = self._build_where(category=category, repo=repo)
|
|
93
|
+
kwargs = dict(
|
|
94
|
+
query_texts=[query],
|
|
95
|
+
n_results=min(n_results, max(1, self._col.count())),
|
|
96
|
+
include=["documents", "metadatas", "distances"],
|
|
97
|
+
)
|
|
98
|
+
if where:
|
|
99
|
+
kwargs["where"] = where
|
|
100
|
+
try:
|
|
101
|
+
return self._format_results(self._col.query(**kwargs))
|
|
102
|
+
except Exception as exc:
|
|
103
|
+
log.error("Chroma search error: %s", exc)
|
|
104
|
+
return []
|
|
105
|
+
|
|
106
|
+
def get_latest(self, n=10, repo=None) -> list[dict]:
|
|
107
|
+
where = self._build_where(repo=repo)
|
|
108
|
+
count = self._col.count()
|
|
109
|
+
if count == 0:
|
|
110
|
+
return []
|
|
111
|
+
kwargs = dict(limit=min(count, max(n * 3, 50)), include=["documents", "metadatas"])
|
|
112
|
+
if where:
|
|
113
|
+
kwargs["where"] = where
|
|
114
|
+
try:
|
|
115
|
+
raw = self._col.get(**kwargs)
|
|
116
|
+
except Exception as exc:
|
|
117
|
+
log.error("Chroma get_latest error: %s", exc)
|
|
118
|
+
return []
|
|
119
|
+
records = [
|
|
120
|
+
{
|
|
121
|
+
"commit_hash": raw["ids"][i],
|
|
122
|
+
"short_hash": raw["metadatas"][i].get("short_hash", ""),
|
|
123
|
+
"author": raw["metadatas"][i].get("author_name", ""),
|
|
124
|
+
"date": raw["metadatas"][i].get("committed_date", ""),
|
|
125
|
+
"category": raw["metadatas"][i].get("category", "general"),
|
|
126
|
+
"files_changed": [f for f in raw["metadatas"][i].get("files_str","").split("|") if f],
|
|
127
|
+
"summary": (raw.get("documents") or [""])[i],
|
|
128
|
+
"source": "chroma",
|
|
129
|
+
}
|
|
130
|
+
for i in range(len(raw["ids"]))
|
|
131
|
+
]
|
|
132
|
+
records.sort(key=lambda r: r.get("date", ""), reverse=True)
|
|
133
|
+
return records[:n]
|
|
134
|
+
|
|
135
|
+
def search_by_file(self, filename, n_results=20) -> list[dict]:
|
|
136
|
+
try:
|
|
137
|
+
all_docs = self._col.get(include=["metadatas", "documents"])
|
|
138
|
+
matched = [
|
|
139
|
+
{
|
|
140
|
+
"commit_hash": all_docs["ids"][i],
|
|
141
|
+
"short_hash": m.get("short_hash", ""),
|
|
142
|
+
"author": m.get("author_name", ""),
|
|
143
|
+
"date": m.get("committed_date", ""),
|
|
144
|
+
"category": m.get("category", "general"),
|
|
145
|
+
"files_changed": [f for f in m.get("files_str","").split("|") if f],
|
|
146
|
+
"summary": (all_docs.get("documents") or [""])[i],
|
|
147
|
+
"source": "chroma",
|
|
148
|
+
}
|
|
149
|
+
for i, m in enumerate(all_docs["metadatas"])
|
|
150
|
+
if filename.lower() in m.get("files_str", "").lower()
|
|
151
|
+
]
|
|
152
|
+
if matched:
|
|
153
|
+
matched.sort(key=lambda r: r.get("date",""), reverse=True)
|
|
154
|
+
return matched[:n_results]
|
|
155
|
+
except Exception:
|
|
156
|
+
pass
|
|
157
|
+
return self.search(f"changes to {filename}", n_results=n_results)
|
|
158
|
+
|
|
159
|
+
def count(self) -> int:
|
|
160
|
+
return self._col.count()
|
|
161
|
+
|
|
162
|
+
@staticmethod
|
|
163
|
+
def _build_where(category=None, repo=None) -> Optional[dict]:
|
|
164
|
+
conds = []
|
|
165
|
+
if category: conds.append({"category": {"$eq": category}})
|
|
166
|
+
if repo: conds.append({"repo": {"$eq": repo}})
|
|
167
|
+
if not conds: return None
|
|
168
|
+
if len(conds) == 1: return conds[0]
|
|
169
|
+
return {"$and": conds}
|
|
170
|
+
|
|
171
|
+
@staticmethod
|
|
172
|
+
def _format_results(raw) -> list[dict]:
|
|
173
|
+
ids, docs, metas, dists = (
|
|
174
|
+
raw.get("ids",[[]])[0], raw.get("documents",[[]])[0],
|
|
175
|
+
raw.get("metadatas",[[]])[0], raw.get("distances",[[]])[0],
|
|
176
|
+
)
|
|
177
|
+
return [
|
|
178
|
+
{
|
|
179
|
+
"commit_hash": h,
|
|
180
|
+
"short_hash": metas[i].get("short_hash", h[:8]),
|
|
181
|
+
"author": metas[i].get("author_name", "unknown"),
|
|
182
|
+
"date": metas[i].get("committed_date", ""),
|
|
183
|
+
"category": metas[i].get("category", "general"),
|
|
184
|
+
"files_changed": [f for f in metas[i].get("files_str","").split("|") if f],
|
|
185
|
+
"summary": docs[i] if docs else "",
|
|
186
|
+
"relevance_score": round(1.0 - float(dists[i] if dists else 1.0), 4),
|
|
187
|
+
"source": "chroma",
|
|
188
|
+
}
|
|
189
|
+
for i, h in enumerate(ids)
|
|
190
|
+
]
|