ramets 0.3.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.
- ramets-0.3.0/LICENSE +21 -0
- ramets-0.3.0/PKG-INFO +216 -0
- ramets-0.3.0/README.md +178 -0
- ramets-0.3.0/pyproject.toml +82 -0
- ramets-0.3.0/setup.cfg +4 -0
- ramets-0.3.0/src/ramets/__init__.py +13 -0
- ramets-0.3.0/src/ramets/__main__.py +5 -0
- ramets-0.3.0/src/ramets/cli.py +501 -0
- ramets-0.3.0/src/ramets/core/__init__.py +1 -0
- ramets-0.3.0/src/ramets/core/base.py +45 -0
- ramets-0.3.0/src/ramets/core/branch.py +116 -0
- ramets-0.3.0/src/ramets/core/db.py +335 -0
- ramets-0.3.0/src/ramets/core/delta.py +155 -0
- ramets-0.3.0/src/ramets/core/materialize.py +296 -0
- ramets-0.3.0/src/ramets/decision/__init__.py +1 -0
- ramets-0.3.0/src/ramets/decision/schema.py +85 -0
- ramets-0.3.0/src/ramets/decision/tracker.py +170 -0
- ramets-0.3.0/src/ramets/extract/__init__.py +1 -0
- ramets-0.3.0/src/ramets/extract/ast_bridge.py +80 -0
- ramets-0.3.0/src/ramets/hooks/__init__.py +1 -0
- ramets-0.3.0/src/ramets/hooks/claude.py +227 -0
- ramets-0.3.0/src/ramets/hooks/git.py +266 -0
- ramets-0.3.0/src/ramets/mcp/__init__.py +1 -0
- ramets-0.3.0/src/ramets/mcp/server.py +259 -0
- ramets-0.3.0/src/ramets/obsidian/__init__.py +1 -0
- ramets-0.3.0/src/ramets/obsidian/config.py +6 -0
- ramets-0.3.0/src/ramets/obsidian/layers.py +9 -0
- ramets-0.3.0/src/ramets/obsidian/vault.py +543 -0
- ramets-0.3.0/src/ramets.egg-info/PKG-INFO +216 -0
- ramets-0.3.0/src/ramets.egg-info/SOURCES.txt +38 -0
- ramets-0.3.0/src/ramets.egg-info/dependency_links.txt +1 -0
- ramets-0.3.0/src/ramets.egg-info/entry_points.txt +2 -0
- ramets-0.3.0/src/ramets.egg-info/requires.txt +19 -0
- ramets-0.3.0/src/ramets.egg-info/top_level.txt +1 -0
- ramets-0.3.0/tests/test_db.py +202 -0
- ramets-0.3.0/tests/test_decisions.py +239 -0
- ramets-0.3.0/tests/test_delta.py +144 -0
- ramets-0.3.0/tests/test_hooks.py +110 -0
- ramets-0.3.0/tests/test_materialize.py +177 -0
- ramets-0.3.0/tests/test_obsidian.py +212 -0
ramets-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Harish Panneer Selvam
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ramets-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ramets
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Per-branch AI coding context — delta-encoded knowledge graphs, decision tracking, and Obsidian visualization. Your codebase is one organism. Each branch is a ramet.
|
|
5
|
+
Author: Harish Panneer Selvam
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/panne027/ramets
|
|
8
|
+
Project-URL: Repository, https://github.com/panne027/ramets
|
|
9
|
+
Project-URL: Issues, https://github.com/panne027/ramets/issues
|
|
10
|
+
Keywords: ai,coding,context,git,worktree,knowledge-graph,obsidian,claude,cursor,codex,branch,delta
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: networkx>=3.0
|
|
22
|
+
Requires-Dist: click>=8.0
|
|
23
|
+
Requires-Dist: pydantic>=2.0
|
|
24
|
+
Requires-Dist: graphifyy>=0.3.10
|
|
25
|
+
Requires-Dist: jinja2>=3.0
|
|
26
|
+
Provides-Extra: mcp
|
|
27
|
+
Requires-Dist: mcp>=1.0; extra == "mcp"
|
|
28
|
+
Requires-Dist: fastmcp>=0.1; extra == "mcp"
|
|
29
|
+
Provides-Extra: all
|
|
30
|
+
Requires-Dist: mcp>=1.0; extra == "all"
|
|
31
|
+
Requires-Dist: fastmcp>=0.1; extra == "all"
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# ramets
|
|
40
|
+
|
|
41
|
+
**Per-branch AI coding context** — delta-encoded knowledge graphs, decision tracking, and Obsidian visualization.
|
|
42
|
+
|
|
43
|
+
*Your codebase is one organism. Each branch is a ramet.*
|
|
44
|
+
|
|
45
|
+
[](https://github.com/panne027/ramets/actions/workflows/ci.yml)
|
|
46
|
+
[](https://pypi.org/project/ramets/)
|
|
47
|
+
[](https://pypi.org/project/ramets/)
|
|
48
|
+
|
|
49
|
+
Named after [Pando](https://en.wikipedia.org/wiki/Pando_(tree)) (*Populus tremuloides*), the world's largest organism — a single aspen clone where individual trunks (ramets) share one root system (genet).
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## The Problem
|
|
54
|
+
|
|
55
|
+
AI coding assistants (Claude Code, Cursor, Codex) waste enormous tokens re-reading your codebase every session:
|
|
56
|
+
|
|
57
|
+
| Without ramets | With ramets | Savings |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| Read knowledge graph: **212K tokens** | Session summary injection: ~400 tokens | **99.8%** |
|
|
60
|
+
| Re-read files on branch switch: ~50K | Delta summary: ~200 tokens | **99.6%** |
|
|
61
|
+
| "What did we decide?" — grep history: ~10K | `ramets decisions`: ~300 tokens | **97%** |
|
|
62
|
+
| New session, re-explore codebase: ~30K | SessionStart hook: ~500 tokens | **98%** |
|
|
63
|
+
|
|
64
|
+
LLM providers aren't incentivized to fix this — more tokens means more subscription revenue. So we fix it ourselves.
|
|
65
|
+
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install ramets
|
|
70
|
+
|
|
71
|
+
cd your-repo
|
|
72
|
+
ramets init # Build genet, install hooks (~5 seconds)
|
|
73
|
+
ramets query "how does authentication work?" # ~300 tokens
|
|
74
|
+
ramets status # Show genet freshness, branch deltas
|
|
75
|
+
ramets summary # Session context (~400 tokens)
|
|
76
|
+
ramets obsidian # Generate Obsidian vault for visualization
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## How It Works
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Genet (shared root) ──> base knowledge graph from common ancestor
|
|
83
|
+
├── Ramet: main ──> 0 deltas (is the base)
|
|
84
|
+
├── Ramet: feat/auth ──> 12 deltas (added auth module)
|
|
85
|
+
├── Ramet: fix/typo ──> 2 deltas (renamed function)
|
|
86
|
+
└── Ramet: feat/api ──> 28 deltas (new API layer)
|
|
87
|
+
|
|
88
|
+
Total storage: ~100KB for 400 nodes (ramets codebase itself)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
1. **`ramets init`** builds the genet from tree-sitter AST extraction (via [graphify](https://pypi.org/project/graphifyy/))
|
|
92
|
+
2. **Git hooks** fire on every commit/checkout — zero LLM tokens, all local computation
|
|
93
|
+
3. **Claude Code hooks** inject pre-computed summaries at session start (~400 tokens)
|
|
94
|
+
4. **`ramets query`** does keyword + BFS traversal with configurable token budgets
|
|
95
|
+
|
|
96
|
+
**Git hooks do ALL computation. The LLM only consumes pre-computed results.**
|
|
97
|
+
|
|
98
|
+
## Features
|
|
99
|
+
|
|
100
|
+
### Delta-Encoded Knowledge Graphs
|
|
101
|
+
- **Genet**: shared base graph (zlib-compressed, ~80KB)
|
|
102
|
+
- **Ramets**: per-branch deltas — only what changed (add/remove/modify nodes and edges)
|
|
103
|
+
- Concurrent worktree access via SQLite WAL mode
|
|
104
|
+
- Storage: **104KB** for 408 nodes, 837 edges (real measurement on ramets codebase)
|
|
105
|
+
|
|
106
|
+
### Git Hooks (Zero Token Cost)
|
|
107
|
+
|
|
108
|
+
| Hook | Trigger | What it does |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| post-commit | Every commit | Compute branch delta (AST diff vs genet) |
|
|
111
|
+
| post-checkout | Branch switch | Register branch, prep snapshot |
|
|
112
|
+
| post-merge | After pull/merge | Recompute deltas |
|
|
113
|
+
| post-rewrite | After rebase | Rebuild deltas for rewritten commits |
|
|
114
|
+
|
|
115
|
+
### Claude Code Hooks (Token Savings)
|
|
116
|
+
|
|
117
|
+
| Hook | Trigger | Tokens saved |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| SessionStart | Session begins | ~212K (injects 400-token summary instead) |
|
|
120
|
+
| UserPromptSubmit | User sends prompt | ~30-50K (redirects to graph query) |
|
|
121
|
+
| PreToolUse | File read attempted | ~10-50K (gates expensive reads) |
|
|
122
|
+
|
|
123
|
+
### Decision Tracking
|
|
124
|
+
|
|
125
|
+
Structured records of "AI suggested X, user chose Y" — not natural language summaries.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
ramets decide \
|
|
129
|
+
-q "Which auth strategy?" \
|
|
130
|
+
-o "JWT:Stateless tokens" \
|
|
131
|
+
-o "Session cookies:Server-side sessions" \
|
|
132
|
+
-c 0 \
|
|
133
|
+
-r "Stateless fits our microservices design" \
|
|
134
|
+
--category architecture \
|
|
135
|
+
--confidence 0.85
|
|
136
|
+
|
|
137
|
+
ramets decisions # List active decisions
|
|
138
|
+
ramets decisions -s "auth" # Full-text search
|
|
139
|
+
ramets decisions --id abc123 # View decision detail
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Obsidian Visualization
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
ramets obsidian # Generate vault
|
|
146
|
+
ramets obsidian --open # Generate and open in Obsidian
|
|
147
|
+
ramets obsidian --all-branches # Include all branch layers
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Generates a navigable vault with:
|
|
151
|
+
- **Base layer**: Community-colored nodes with `[[wikilinks]]`
|
|
152
|
+
- **Branch delta layers**: Added/modified/removed nodes per branch
|
|
153
|
+
- **Decision notes**: Structured choices with options and rationale
|
|
154
|
+
- **Graph settings**: Community coloring for the graph view
|
|
155
|
+
|
|
156
|
+
### MCP Server (15 tools)
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
pip install ramets[mcp]
|
|
160
|
+
ramets serve # stdio transport
|
|
161
|
+
# Or: claude mcp add ramets -- ramets serve
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Tools: `query_graph`, `get_node`, `diff_branches`, `session_summary`, `record_decision`, `list_decisions`, `search_decisions`, `generate_obsidian_vault`, and more.
|
|
165
|
+
|
|
166
|
+
## Architecture
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
.ramets/store.db (SQLite, WAL mode)
|
|
170
|
+
├── genet — shared root graph (compressed blob)
|
|
171
|
+
├── ramets — materialized per-branch snapshots
|
|
172
|
+
├── ramet_deltas — delta log per branch
|
|
173
|
+
├── decisions — structured decision records
|
|
174
|
+
├── decision_edges — decision relationship graph
|
|
175
|
+
├── sessions — AI session tracking
|
|
176
|
+
└── branches — branch registry
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## CLI Reference
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
ramets init Create .ramets/, build genet, install hooks
|
|
183
|
+
ramets build Full genet rebuild from HEAD
|
|
184
|
+
ramets update Compute branch delta vs genet (called by hooks)
|
|
185
|
+
ramets status Genet freshness, ramet count, storage
|
|
186
|
+
ramets query "..." BFS traversal on current branch graph
|
|
187
|
+
ramets diff feat/a main Graph diff between branches
|
|
188
|
+
ramets summary Compact summary for session injection (~400 tokens)
|
|
189
|
+
ramets decide Record a structured decision
|
|
190
|
+
ramets decisions List/search decisions for current branch
|
|
191
|
+
ramets obsidian Generate Obsidian vault with branch layers
|
|
192
|
+
ramets obsidian --open Generate and open in Obsidian
|
|
193
|
+
ramets serve Start MCP server (stdio)
|
|
194
|
+
ramets gc Prune dead ramets, compact DB
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Development
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
git clone https://github.com/panne027/ramets.git
|
|
201
|
+
cd ramets
|
|
202
|
+
pip install -e ".[dev]"
|
|
203
|
+
pytest tests/ -v # 70 tests
|
|
204
|
+
ruff check src/ tests/ # Lint
|
|
205
|
+
ruff format src/ tests/ # Format
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Requirements
|
|
209
|
+
|
|
210
|
+
- Python >= 3.10
|
|
211
|
+
- Git repository
|
|
212
|
+
- [graphify](https://pypi.org/project/graphifyy/) (installed as dependency)
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT
|
ramets-0.3.0/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# ramets
|
|
2
|
+
|
|
3
|
+
**Per-branch AI coding context** — delta-encoded knowledge graphs, decision tracking, and Obsidian visualization.
|
|
4
|
+
|
|
5
|
+
*Your codebase is one organism. Each branch is a ramet.*
|
|
6
|
+
|
|
7
|
+
[](https://github.com/panne027/ramets/actions/workflows/ci.yml)
|
|
8
|
+
[](https://pypi.org/project/ramets/)
|
|
9
|
+
[](https://pypi.org/project/ramets/)
|
|
10
|
+
|
|
11
|
+
Named after [Pando](https://en.wikipedia.org/wiki/Pando_(tree)) (*Populus tremuloides*), the world's largest organism — a single aspen clone where individual trunks (ramets) share one root system (genet).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The Problem
|
|
16
|
+
|
|
17
|
+
AI coding assistants (Claude Code, Cursor, Codex) waste enormous tokens re-reading your codebase every session:
|
|
18
|
+
|
|
19
|
+
| Without ramets | With ramets | Savings |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| Read knowledge graph: **212K tokens** | Session summary injection: ~400 tokens | **99.8%** |
|
|
22
|
+
| Re-read files on branch switch: ~50K | Delta summary: ~200 tokens | **99.6%** |
|
|
23
|
+
| "What did we decide?" — grep history: ~10K | `ramets decisions`: ~300 tokens | **97%** |
|
|
24
|
+
| New session, re-explore codebase: ~30K | SessionStart hook: ~500 tokens | **98%** |
|
|
25
|
+
|
|
26
|
+
LLM providers aren't incentivized to fix this — more tokens means more subscription revenue. So we fix it ourselves.
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install ramets
|
|
32
|
+
|
|
33
|
+
cd your-repo
|
|
34
|
+
ramets init # Build genet, install hooks (~5 seconds)
|
|
35
|
+
ramets query "how does authentication work?" # ~300 tokens
|
|
36
|
+
ramets status # Show genet freshness, branch deltas
|
|
37
|
+
ramets summary # Session context (~400 tokens)
|
|
38
|
+
ramets obsidian # Generate Obsidian vault for visualization
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## How It Works
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
Genet (shared root) ──> base knowledge graph from common ancestor
|
|
45
|
+
├── Ramet: main ──> 0 deltas (is the base)
|
|
46
|
+
├── Ramet: feat/auth ──> 12 deltas (added auth module)
|
|
47
|
+
├── Ramet: fix/typo ──> 2 deltas (renamed function)
|
|
48
|
+
└── Ramet: feat/api ──> 28 deltas (new API layer)
|
|
49
|
+
|
|
50
|
+
Total storage: ~100KB for 400 nodes (ramets codebase itself)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
1. **`ramets init`** builds the genet from tree-sitter AST extraction (via [graphify](https://pypi.org/project/graphifyy/))
|
|
54
|
+
2. **Git hooks** fire on every commit/checkout — zero LLM tokens, all local computation
|
|
55
|
+
3. **Claude Code hooks** inject pre-computed summaries at session start (~400 tokens)
|
|
56
|
+
4. **`ramets query`** does keyword + BFS traversal with configurable token budgets
|
|
57
|
+
|
|
58
|
+
**Git hooks do ALL computation. The LLM only consumes pre-computed results.**
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
### Delta-Encoded Knowledge Graphs
|
|
63
|
+
- **Genet**: shared base graph (zlib-compressed, ~80KB)
|
|
64
|
+
- **Ramets**: per-branch deltas — only what changed (add/remove/modify nodes and edges)
|
|
65
|
+
- Concurrent worktree access via SQLite WAL mode
|
|
66
|
+
- Storage: **104KB** for 408 nodes, 837 edges (real measurement on ramets codebase)
|
|
67
|
+
|
|
68
|
+
### Git Hooks (Zero Token Cost)
|
|
69
|
+
|
|
70
|
+
| Hook | Trigger | What it does |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| post-commit | Every commit | Compute branch delta (AST diff vs genet) |
|
|
73
|
+
| post-checkout | Branch switch | Register branch, prep snapshot |
|
|
74
|
+
| post-merge | After pull/merge | Recompute deltas |
|
|
75
|
+
| post-rewrite | After rebase | Rebuild deltas for rewritten commits |
|
|
76
|
+
|
|
77
|
+
### Claude Code Hooks (Token Savings)
|
|
78
|
+
|
|
79
|
+
| Hook | Trigger | Tokens saved |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| SessionStart | Session begins | ~212K (injects 400-token summary instead) |
|
|
82
|
+
| UserPromptSubmit | User sends prompt | ~30-50K (redirects to graph query) |
|
|
83
|
+
| PreToolUse | File read attempted | ~10-50K (gates expensive reads) |
|
|
84
|
+
|
|
85
|
+
### Decision Tracking
|
|
86
|
+
|
|
87
|
+
Structured records of "AI suggested X, user chose Y" — not natural language summaries.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
ramets decide \
|
|
91
|
+
-q "Which auth strategy?" \
|
|
92
|
+
-o "JWT:Stateless tokens" \
|
|
93
|
+
-o "Session cookies:Server-side sessions" \
|
|
94
|
+
-c 0 \
|
|
95
|
+
-r "Stateless fits our microservices design" \
|
|
96
|
+
--category architecture \
|
|
97
|
+
--confidence 0.85
|
|
98
|
+
|
|
99
|
+
ramets decisions # List active decisions
|
|
100
|
+
ramets decisions -s "auth" # Full-text search
|
|
101
|
+
ramets decisions --id abc123 # View decision detail
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Obsidian Visualization
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
ramets obsidian # Generate vault
|
|
108
|
+
ramets obsidian --open # Generate and open in Obsidian
|
|
109
|
+
ramets obsidian --all-branches # Include all branch layers
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Generates a navigable vault with:
|
|
113
|
+
- **Base layer**: Community-colored nodes with `[[wikilinks]]`
|
|
114
|
+
- **Branch delta layers**: Added/modified/removed nodes per branch
|
|
115
|
+
- **Decision notes**: Structured choices with options and rationale
|
|
116
|
+
- **Graph settings**: Community coloring for the graph view
|
|
117
|
+
|
|
118
|
+
### MCP Server (15 tools)
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pip install ramets[mcp]
|
|
122
|
+
ramets serve # stdio transport
|
|
123
|
+
# Or: claude mcp add ramets -- ramets serve
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Tools: `query_graph`, `get_node`, `diff_branches`, `session_summary`, `record_decision`, `list_decisions`, `search_decisions`, `generate_obsidian_vault`, and more.
|
|
127
|
+
|
|
128
|
+
## Architecture
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
.ramets/store.db (SQLite, WAL mode)
|
|
132
|
+
├── genet — shared root graph (compressed blob)
|
|
133
|
+
├── ramets — materialized per-branch snapshots
|
|
134
|
+
├── ramet_deltas — delta log per branch
|
|
135
|
+
├── decisions — structured decision records
|
|
136
|
+
├── decision_edges — decision relationship graph
|
|
137
|
+
├── sessions — AI session tracking
|
|
138
|
+
└── branches — branch registry
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## CLI Reference
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
ramets init Create .ramets/, build genet, install hooks
|
|
145
|
+
ramets build Full genet rebuild from HEAD
|
|
146
|
+
ramets update Compute branch delta vs genet (called by hooks)
|
|
147
|
+
ramets status Genet freshness, ramet count, storage
|
|
148
|
+
ramets query "..." BFS traversal on current branch graph
|
|
149
|
+
ramets diff feat/a main Graph diff between branches
|
|
150
|
+
ramets summary Compact summary for session injection (~400 tokens)
|
|
151
|
+
ramets decide Record a structured decision
|
|
152
|
+
ramets decisions List/search decisions for current branch
|
|
153
|
+
ramets obsidian Generate Obsidian vault with branch layers
|
|
154
|
+
ramets obsidian --open Generate and open in Obsidian
|
|
155
|
+
ramets serve Start MCP server (stdio)
|
|
156
|
+
ramets gc Prune dead ramets, compact DB
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Development
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
git clone https://github.com/panne027/ramets.git
|
|
163
|
+
cd ramets
|
|
164
|
+
pip install -e ".[dev]"
|
|
165
|
+
pytest tests/ -v # 70 tests
|
|
166
|
+
ruff check src/ tests/ # Lint
|
|
167
|
+
ruff format src/ tests/ # Format
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Requirements
|
|
171
|
+
|
|
172
|
+
- Python >= 3.10
|
|
173
|
+
- Git repository
|
|
174
|
+
- [graphify](https://pypi.org/project/graphifyy/) (installed as dependency)
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ramets"
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Per-branch AI coding context — delta-encoded knowledge graphs, decision tracking, and Obsidian visualization. Your codebase is one organism. Each branch is a ramet."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Harish Panneer Selvam"},
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"ai", "coding", "context", "git", "worktree", "knowledge-graph",
|
|
17
|
+
"obsidian", "claude", "cursor", "codex", "branch", "delta",
|
|
18
|
+
]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Topic :: Software Development :: Version Control :: Git",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
dependencies = [
|
|
30
|
+
"networkx>=3.0",
|
|
31
|
+
"click>=8.0",
|
|
32
|
+
"pydantic>=2.0",
|
|
33
|
+
"graphifyy>=0.3.10",
|
|
34
|
+
"jinja2>=3.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
mcp = ["mcp>=1.0", "fastmcp>=0.1"]
|
|
39
|
+
all = ["mcp>=1.0", "fastmcp>=0.1"]
|
|
40
|
+
dev = ["pytest>=7.0", "pytest-asyncio", "ruff", "mypy"]
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
ramets = "ramets.cli:main"
|
|
44
|
+
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://github.com/panne027/ramets"
|
|
47
|
+
Repository = "https://github.com/panne027/ramets"
|
|
48
|
+
Issues = "https://github.com/panne027/ramets/issues"
|
|
49
|
+
|
|
50
|
+
[tool.setuptools.packages.find]
|
|
51
|
+
where = ["src"]
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
target-version = "py310"
|
|
55
|
+
line-length = 100
|
|
56
|
+
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
testpaths = ["tests"]
|
|
59
|
+
|
|
60
|
+
# ── Semantic Release ──────────────────────────────────────────
|
|
61
|
+
# Reads conventional commits (feat:, fix:, etc.) to determine version bumps.
|
|
62
|
+
# feat: → minor bump, fix: → patch bump, BREAKING CHANGE → major bump.
|
|
63
|
+
# Only releases from main branch.
|
|
64
|
+
|
|
65
|
+
[tool.semantic_release]
|
|
66
|
+
version_toml = ["pyproject.toml:project.version"]
|
|
67
|
+
version_variables = ["src/ramets/__init__.py:__version__"]
|
|
68
|
+
branch = "main"
|
|
69
|
+
commit_message = "chore(release): {version}\n\nAutomatically generated by python-semantic-release"
|
|
70
|
+
upload_to_pypi = false # Handled by gh-action-pypi-publish via OIDC
|
|
71
|
+
|
|
72
|
+
[tool.semantic_release.branches.main]
|
|
73
|
+
match = "main"
|
|
74
|
+
prerelease = false
|
|
75
|
+
|
|
76
|
+
[tool.semantic_release.commit_parser_options]
|
|
77
|
+
allowed_tags = ["feat", "fix", "perf", "refactor", "docs", "test", "chore"]
|
|
78
|
+
minor_tags = ["feat"]
|
|
79
|
+
patch_tags = ["fix", "perf", "refactor"]
|
|
80
|
+
|
|
81
|
+
[tool.semantic_release.changelog]
|
|
82
|
+
changelog_file = "CHANGELOG.md"
|
ramets-0.3.0/setup.cfg
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""ramets — Per-branch AI coding context.
|
|
2
|
+
|
|
3
|
+
Your codebase is one organism. Each branch is a ramet.
|
|
4
|
+
|
|
5
|
+
Named after Pando (Populus tremuloides), the world's largest organism —
|
|
6
|
+
a single aspen clone where individual trunks (ramets) share one root system (genet).
|
|
7
|
+
|
|
8
|
+
- Genet: the shared base knowledge graph (common ancestor of all branches)
|
|
9
|
+
- Ramets: per-branch delta-encoded graphs (individual trunks from the shared root)
|
|
10
|
+
- Decisions: structured tracking of AI suggestions and user choices
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__version__ = "0.3.0"
|