selvedge 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.
- selvedge-0.1.0/.gitignore +33 -0
- selvedge-0.1.0/CLAUDE.md +272 -0
- selvedge-0.1.0/PKG-INFO +201 -0
- selvedge-0.1.0/README.md +175 -0
- selvedge-0.1.0/docs/getting-started.md +117 -0
- selvedge-0.1.0/pyproject.toml +66 -0
- selvedge-0.1.0/selvedge/__init__.py +2 -0
- selvedge-0.1.0/selvedge/cli.py +374 -0
- selvedge-0.1.0/selvedge/config.py +52 -0
- selvedge-0.1.0/selvedge/models.py +84 -0
- selvedge-0.1.0/selvedge/server.py +236 -0
- selvedge-0.1.0/selvedge/storage.py +173 -0
- selvedge-0.1.0/tests/__init__.py +0 -0
- selvedge-0.1.0/tests/test_cli.py +179 -0
- selvedge-0.1.0/tests/test_server.py +159 -0
- selvedge-0.1.0/tests/test_storage.py +206 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Selvedge database (commit this if you want shared team history, ignore for local-only)
|
|
2
|
+
# .selvedge/
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.egg-info/
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
.eggs/
|
|
11
|
+
*.egg
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
|
|
16
|
+
# Testing
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
|
|
21
|
+
# Editor
|
|
22
|
+
.vscode/
|
|
23
|
+
.idea/
|
|
24
|
+
*.swp
|
|
25
|
+
*.swo
|
|
26
|
+
|
|
27
|
+
# OS
|
|
28
|
+
.DS_Store
|
|
29
|
+
Thumbs.db
|
|
30
|
+
|
|
31
|
+
# Env
|
|
32
|
+
.env
|
|
33
|
+
.env.local
|
selvedge-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# Selvedge — CLAUDE.md
|
|
2
|
+
|
|
3
|
+
> Change tracking for AI-era codebases.
|
|
4
|
+
> The pandas of codebase history — essential infrastructure, not a feature.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## What this is
|
|
9
|
+
|
|
10
|
+
Selvedge is an open-source MCP server that AI coding agents call as they work to log structured change events. It answers questions like:
|
|
11
|
+
|
|
12
|
+
- "When was `users.stripe_customer_id` added and why?"
|
|
13
|
+
- "What changed in the auth module in the last 30 days?"
|
|
14
|
+
- "Which agent added the payments table and what was the reasoning?"
|
|
15
|
+
|
|
16
|
+
The core insight: with human-written code, intent leaked into commit messages and PR descriptions. With AI-written code, intent lives in a prompt that evaporates when the session ends. Selvedge captures it before it's gone.
|
|
17
|
+
|
|
18
|
+
**Positioning:** "What pandas is to data manipulation, Selvedge is to codebase change tracking." Open source core, hosted platform as the business model.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
selvedge/
|
|
26
|
+
├── selvedge/
|
|
27
|
+
│ ├── __init__.py version string
|
|
28
|
+
│ ├── models.py ChangeEvent dataclass, ChangeType + EntityType enums
|
|
29
|
+
│ ├── config.py DB path resolution (env → walk-up → ~/.selvedge)
|
|
30
|
+
│ ├── storage.py SelvedgeStorage — SQLite CRUD layer
|
|
31
|
+
│ ├── server.py FastMCP server — 5 tools exposed to AI agents
|
|
32
|
+
│ └── cli.py Click + Rich CLI — init, status, diff, blame, history, search, log
|
|
33
|
+
├── tests/
|
|
34
|
+
│ ├── test_storage.py
|
|
35
|
+
│ ├── test_server.py
|
|
36
|
+
│ └── test_cli.py
|
|
37
|
+
├── docs/
|
|
38
|
+
│ └── getting-started.md
|
|
39
|
+
├── pyproject.toml
|
|
40
|
+
├── README.md
|
|
41
|
+
└── CLAUDE.md
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Tech stack
|
|
45
|
+
- **Python 3.10+** — matches pandas positioning (Python-first)
|
|
46
|
+
- **mcp** — official Anthropic MCP Python SDK (FastMCP)
|
|
47
|
+
- **SQLite** — zero-config local storage; WAL mode for concurrency
|
|
48
|
+
- **Click** — CLI framework
|
|
49
|
+
- **Rich** — terminal output formatting
|
|
50
|
+
- **Hatchling** — build backend
|
|
51
|
+
- **pytest** — test runner
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Data model
|
|
56
|
+
|
|
57
|
+
### ChangeEvent
|
|
58
|
+
|
|
59
|
+
The central entity. Every recorded change is one row in the `events` table.
|
|
60
|
+
|
|
61
|
+
| Field | Type | Description |
|
|
62
|
+
|-------|------|-------------|
|
|
63
|
+
| `id` | TEXT PK | UUID4 |
|
|
64
|
+
| `timestamp` | TEXT | UTC ISO 8601 |
|
|
65
|
+
| `entity_type` | TEXT | column, table, file, function, class, endpoint, dependency, env_var, index, schema, config, other |
|
|
66
|
+
| `entity_path` | TEXT | Dot/slash notation path (see conventions below) |
|
|
67
|
+
| `change_type` | TEXT | add, remove, modify, rename, retype, create, delete, index_add, index_remove, migrate |
|
|
68
|
+
| `diff` | TEXT | The actual change — SQL migration, code diff, or description |
|
|
69
|
+
| `reasoning` | TEXT | Why the change was made — the captured intent |
|
|
70
|
+
| `agent` | TEXT | Which AI agent (claude-code, cursor, copilot, human, etc.) |
|
|
71
|
+
| `session_id` | TEXT | Agent session/conversation ID |
|
|
72
|
+
| `git_commit` | TEXT | Git commit hash this change lands in |
|
|
73
|
+
| `project` | TEXT | Repository/project name |
|
|
74
|
+
| `metadata` | TEXT | JSON blob for extensibility |
|
|
75
|
+
|
|
76
|
+
### entity_path conventions
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
users.email → DB column (table.column)
|
|
80
|
+
users → DB table
|
|
81
|
+
src/auth.py::login → function in file (path::symbol)
|
|
82
|
+
src/auth.py → file
|
|
83
|
+
api/v1/users → API route
|
|
84
|
+
deps/stripe → dependency
|
|
85
|
+
env/STRIPE_SECRET_KEY → environment variable
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Prefix queries work everywhere: `users` matches `users`, `users.email`, `users.created_at`.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## MCP Server tools
|
|
93
|
+
|
|
94
|
+
The MCP server (`selvedge/server.py`) exposes these tools to AI agents:
|
|
95
|
+
|
|
96
|
+
### `log_change`
|
|
97
|
+
Record a change. Call this immediately after making any meaningful change.
|
|
98
|
+
|
|
99
|
+
**Required:** `entity_path`, `change_type`
|
|
100
|
+
**Optional:** `diff`, `entity_type`, `reasoning`, `agent`, `session_id`, `git_commit`, `project`
|
|
101
|
+
|
|
102
|
+
### `diff`
|
|
103
|
+
Get change history for an entity or entity prefix. Returns list of events, newest first.
|
|
104
|
+
|
|
105
|
+
### `blame`
|
|
106
|
+
Get the most recent change to an exact entity path — what, when, who, why.
|
|
107
|
+
|
|
108
|
+
### `history`
|
|
109
|
+
Filtered history across all entities. Supports `since` (ISO or relative like `7d`, `30d`, `1y`), `entity_path`, `project`, `limit`.
|
|
110
|
+
|
|
111
|
+
### `search`
|
|
112
|
+
Full-text substring search across `entity_path`, `diff`, `reasoning`, `agent`.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## CLI commands
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
selvedge init # init .selvedge/ in current dir
|
|
120
|
+
selvedge status # summary + recent events
|
|
121
|
+
selvedge diff users.email # history for an entity
|
|
122
|
+
selvedge diff users --limit 50 # all users.* columns, 50 entries
|
|
123
|
+
selvedge blame payments.amount # most recent change + context
|
|
124
|
+
selvedge history # all history
|
|
125
|
+
selvedge history --since 7d # last 7 days
|
|
126
|
+
selvedge history --entity users --since 30d
|
|
127
|
+
selvedge history --project my-api
|
|
128
|
+
selvedge search "billing" # full-text search
|
|
129
|
+
selvedge log users.phone add --reasoning "2FA" --agent me # manual entry
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
All commands support `--json` for machine-readable output.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## DB path resolution
|
|
137
|
+
|
|
138
|
+
Order of precedence:
|
|
139
|
+
1. `SELVEDGE_DB` environment variable
|
|
140
|
+
2. Walk up from CWD looking for an existing `.selvedge/` directory
|
|
141
|
+
3. `~/.selvedge/selvedge.db` (global fallback)
|
|
142
|
+
|
|
143
|
+
This means `selvedge init` in a project root locks that project to its own DB.
|
|
144
|
+
The global fallback ensures agents always have somewhere to write even before `init` is run.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Running the MCP server
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# After pip install
|
|
152
|
+
selvedge-server
|
|
153
|
+
|
|
154
|
+
# Or directly
|
|
155
|
+
python -m selvedge.server
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Claude Code config (~/.claude/config.json)
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"mcpServers": {
|
|
162
|
+
"selvedge": {
|
|
163
|
+
"command": "selvedge-server"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### With a project-specific DB
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"mcpServers": {
|
|
173
|
+
"selvedge": {
|
|
174
|
+
"command": "selvedge-server",
|
|
175
|
+
"env": {
|
|
176
|
+
"SELVEDGE_DB": "/path/to/your/project/.selvedge/selvedge.db"
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## System prompt / agent instructions
|
|
186
|
+
|
|
187
|
+
Add this to your agent's system prompt or CLAUDE.md to activate logging:
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
You have access to Selvedge (MCP server: selvedge) for change tracking.
|
|
191
|
+
|
|
192
|
+
Rules:
|
|
193
|
+
- Call selvedge.log_change immediately after adding, modifying, or removing
|
|
194
|
+
any DB column, table, function, API endpoint, dependency, or env variable.
|
|
195
|
+
- Set `reasoning` to the user's original request or the problem being solved.
|
|
196
|
+
- Set `agent` to "claude-code" (or whichever agent you are).
|
|
197
|
+
- Set `session_id` if you have access to the current session/conversation ID.
|
|
198
|
+
- Set `git_commit` to the commit hash once you know it.
|
|
199
|
+
- Before modifying an entity, call selvedge.diff or selvedge.blame to understand
|
|
200
|
+
its history and avoid conflicting with past decisions.
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Phase plan
|
|
206
|
+
|
|
207
|
+
### Phase 1 — Core (DONE ✓)
|
|
208
|
+
- [x] MCP server with 5 tools
|
|
209
|
+
- [x] SQLite storage with WAL mode
|
|
210
|
+
- [x] CLI (init, status, diff, blame, history, search, log)
|
|
211
|
+
- [x] PyPI package with entry points
|
|
212
|
+
- [x] Test suite (storage, server, CLI)
|
|
213
|
+
|
|
214
|
+
### Phase 2 — Integrations
|
|
215
|
+
- [ ] Git hook: auto-link selvedge events to commit hashes at commit time
|
|
216
|
+
- Post-commit hook reads `git rev-parse HEAD`, backfills `git_commit` on events with empty commit field and matching timestamp window
|
|
217
|
+
- [ ] Migration file parser: ingest Alembic / Liquibase / raw SQL migrations to backfill schema history
|
|
218
|
+
- Parse migration files, extract column/table ops, write ChangeEvents with `change_type` inferred from SQL
|
|
219
|
+
- [ ] `selvedge import` CLI command for the above parsers
|
|
220
|
+
- [ ] `selvedge export` — dump history as JSON/CSV
|
|
221
|
+
|
|
222
|
+
### Phase 3 — Team features
|
|
223
|
+
- [ ] PostgreSQL backend option (configurable via `SELVEDGE_BACKEND=postgresql://...`)
|
|
224
|
+
- Abstract `SelvedgeStorage` behind a protocol/interface so backends are swappable
|
|
225
|
+
- `storage_sqlite.py` and `storage_pg.py` both implement `StorageBackend`
|
|
226
|
+
- [ ] HTTP REST API layer (FastAPI) — exposes the same 5 operations over HTTP
|
|
227
|
+
- [ ] Auth (API keys) for the HTTP layer
|
|
228
|
+
|
|
229
|
+
### Phase 4 — Platform (hosted business)
|
|
230
|
+
- [ ] Web dashboard (React + the REST API)
|
|
231
|
+
- [ ] Cross-repo queries
|
|
232
|
+
- [ ] Retention policies
|
|
233
|
+
- [ ] Team/org management
|
|
234
|
+
- [ ] Webhook events (Slack, PagerDuty, etc. on schema changes)
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Development setup
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
git clone https://github.com/masondelan/selvedge
|
|
242
|
+
cd selvedge
|
|
243
|
+
pip install -e ".[dev]"
|
|
244
|
+
pytest
|
|
245
|
+
selvedge --version
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Code conventions
|
|
251
|
+
|
|
252
|
+
- **No external dependencies beyond the declared ones.** Keep the install footprint small.
|
|
253
|
+
- **SQLite first, always.** Don't reach for Postgres until Phase 3. SQLite with WAL handles concurrent reads fine.
|
|
254
|
+
- **ChangeEvent is a dataclass, not Pydantic.** Keep the core dependency-free. MCP serialization uses `to_dict()`.
|
|
255
|
+
- **Every public function has a docstring.** The MCP tool docstrings are user-facing — they appear in agent tool listings.
|
|
256
|
+
- **Tests use `tmp_path` fixtures and `SELVEDGE_DB` env var.** Never write to the real DB in tests.
|
|
257
|
+
- **Rich for all terminal output.** No bare `print()` in cli.py.
|
|
258
|
+
- **`--json` flag on every read command.** Machine-readable output is a first-class concern.
|
|
259
|
+
- **Type hints everywhere.** Python 3.10+ syntax (`X | Y`, `list[dict]`, etc.).
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Non-goals (Phase 1)
|
|
264
|
+
|
|
265
|
+
- No web UI
|
|
266
|
+
- No PostgreSQL
|
|
267
|
+
- No authentication
|
|
268
|
+
- No real-time streaming
|
|
269
|
+
- No git integration (Phase 2)
|
|
270
|
+
- No migration file parsing (Phase 2)
|
|
271
|
+
- No multi-user/team features (Phase 3)
|
|
272
|
+
- No LLM calls inside Selvedge itself — reasoning is captured FROM agents, not generated by Selvedge
|
selvedge-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: selvedge
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Change tracking for AI-era codebases
|
|
5
|
+
Project-URL: Homepage, https://github.com/masondelan/selvedge
|
|
6
|
+
Project-URL: Repository, https://github.com/masondelan/selvedge
|
|
7
|
+
Project-URL: Issues, https://github.com/masondelan/selvedge/issues
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: ai,changelog,codebase,devtools,mcp,tracking
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development :: Version Control
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: click>=8.0.0
|
|
19
|
+
Requires-Dist: mcp>=1.0.0
|
|
20
|
+
Requires-Dist: rich>=13.0.0
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: hatchling; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# Selvedge
|
|
28
|
+
|
|
29
|
+
**Change tracking for AI-era codebases.**
|
|
30
|
+
|
|
31
|
+
AI agents write your code now. But when they're done, the *why* disappears — the conversation that prompted the change, the reasoning behind the schema decision, the context that made the diff make sense. Selvedge captures all of it.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
$ selvedge blame payments.amount
|
|
35
|
+
|
|
36
|
+
payments.amount
|
|
37
|
+
Changed 2025-11-03 14:22:01
|
|
38
|
+
Type add
|
|
39
|
+
Agent claude-code
|
|
40
|
+
Commit a3f9c12
|
|
41
|
+
Diff + amount DECIMAL(10,2) NOT NULL DEFAULT 0
|
|
42
|
+
Reasoning User requested Stripe billing integration. Added amount column
|
|
43
|
+
to store transaction totals in cents per Stripe convention.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install selvedge
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Quickstart
|
|
55
|
+
|
|
56
|
+
**1. Initialize in your project**
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
cd your-project
|
|
60
|
+
selvedge init
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
This creates `.selvedge/selvedge.db` in your project root. Commit it to share history with your team, or add `.selvedge/` to `.gitignore` to keep it local.
|
|
64
|
+
|
|
65
|
+
**2. Add to your Claude Code config**
|
|
66
|
+
|
|
67
|
+
`~/.claude/config.json`:
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"mcpServers": {
|
|
71
|
+
"selvedge": {
|
|
72
|
+
"command": "selvedge-server"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**3. Tell your agent to use it**
|
|
79
|
+
|
|
80
|
+
Add to your project's `CLAUDE.md`:
|
|
81
|
+
```
|
|
82
|
+
You have access to Selvedge for change tracking.
|
|
83
|
+
Call selvedge.log_change immediately after adding, modifying, or removing
|
|
84
|
+
any DB column, table, function, API endpoint, dependency, or env variable.
|
|
85
|
+
Set `reasoning` to the user's original request or the problem being solved.
|
|
86
|
+
Set `agent` to "claude-code".
|
|
87
|
+
Before modifying an entity, call selvedge.blame to understand its history.
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**4. Start querying**
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
selvedge status # recent activity
|
|
94
|
+
selvedge diff users # all changes to the users table
|
|
95
|
+
selvedge diff users.email # changes to a specific column
|
|
96
|
+
selvedge blame payments.amount # what changed last and why
|
|
97
|
+
selvedge history --since 30d # last 30 days of changes
|
|
98
|
+
selvedge search "stripe" # full-text search
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## How it works
|
|
104
|
+
|
|
105
|
+
Selvedge runs as an MCP server. AI agents in tools like Claude Code call Selvedge's tools as they work — logging structured change events to a local SQLite database.
|
|
106
|
+
|
|
107
|
+
Each event records:
|
|
108
|
+
- **What** changed (entity path, change type, diff)
|
|
109
|
+
- **When** (timestamp)
|
|
110
|
+
- **Who** (agent, session ID)
|
|
111
|
+
- **Why** (reasoning — captured from the agent's context in the moment)
|
|
112
|
+
- **Where** (git commit, project)
|
|
113
|
+
|
|
114
|
+
The diff is git's job. The *why* is Selvedge's.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Entity path conventions
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
users.email DB column (table.column)
|
|
122
|
+
users DB table
|
|
123
|
+
src/auth.py::login Function in a file (path::symbol)
|
|
124
|
+
src/auth.py File
|
|
125
|
+
api/v1/users API route
|
|
126
|
+
deps/stripe Dependency
|
|
127
|
+
env/STRIPE_SECRET_KEY Environment variable
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## MCP tools
|
|
133
|
+
|
|
134
|
+
When connected as an MCP server, Selvedge exposes:
|
|
135
|
+
|
|
136
|
+
| Tool | Description |
|
|
137
|
+
|------|-------------|
|
|
138
|
+
| `log_change` | Record a change event |
|
|
139
|
+
| `diff` | History for an entity or entity prefix |
|
|
140
|
+
| `blame` | Most recent change + context for an entity |
|
|
141
|
+
| `history` | Filtered history across all entities |
|
|
142
|
+
| `search` | Full-text search across all events |
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## CLI reference
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
selvedge init [--path PATH] Initialize in project
|
|
150
|
+
selvedge status Recent activity summary
|
|
151
|
+
selvedge diff ENTITY [--limit N] Change history for entity
|
|
152
|
+
selvedge blame ENTITY Most recent change + context
|
|
153
|
+
selvedge history [--since SINCE] Browse all history
|
|
154
|
+
[--entity ENTITY]
|
|
155
|
+
[--project PROJECT]
|
|
156
|
+
[--limit N]
|
|
157
|
+
selvedge search QUERY [--limit N] Full-text search
|
|
158
|
+
selvedge log ENTITY CHANGE_TYPE Manually log a change
|
|
159
|
+
[--diff TEXT]
|
|
160
|
+
[--reasoning TEXT]
|
|
161
|
+
[--agent NAME]
|
|
162
|
+
[--commit HASH]
|
|
163
|
+
[--project NAME]
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
All read commands support `--json` for machine-readable output.
|
|
167
|
+
|
|
168
|
+
**Relative time in `--since`:**
|
|
169
|
+
- `7d` → last 7 days
|
|
170
|
+
- `24h` → last 24 hours
|
|
171
|
+
- `3m` → last 3 months
|
|
172
|
+
- `1y` → last year
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Configuration
|
|
177
|
+
|
|
178
|
+
| Method | Format | Example |
|
|
179
|
+
|--------|--------|---------|
|
|
180
|
+
| Env var | `SELVEDGE_DB=/path/to/db` | Per-session override |
|
|
181
|
+
| Project init | `selvedge init` | Creates `.selvedge/selvedge.db` in CWD |
|
|
182
|
+
| Global fallback | `~/.selvedge/selvedge.db` | Used if no project DB found |
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Contributing
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
git clone https://github.com/masondelan/selvedge
|
|
190
|
+
cd selvedge
|
|
191
|
+
pip install -e ".[dev]"
|
|
192
|
+
pytest
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
See `CLAUDE.md` for architecture details and the phase roadmap.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
MIT
|
selvedge-0.1.0/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Selvedge
|
|
2
|
+
|
|
3
|
+
**Change tracking for AI-era codebases.**
|
|
4
|
+
|
|
5
|
+
AI agents write your code now. But when they're done, the *why* disappears — the conversation that prompted the change, the reasoning behind the schema decision, the context that made the diff make sense. Selvedge captures all of it.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
$ selvedge blame payments.amount
|
|
9
|
+
|
|
10
|
+
payments.amount
|
|
11
|
+
Changed 2025-11-03 14:22:01
|
|
12
|
+
Type add
|
|
13
|
+
Agent claude-code
|
|
14
|
+
Commit a3f9c12
|
|
15
|
+
Diff + amount DECIMAL(10,2) NOT NULL DEFAULT 0
|
|
16
|
+
Reasoning User requested Stripe billing integration. Added amount column
|
|
17
|
+
to store transaction totals in cents per Stripe convention.
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install selvedge
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quickstart
|
|
29
|
+
|
|
30
|
+
**1. Initialize in your project**
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd your-project
|
|
34
|
+
selvedge init
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This creates `.selvedge/selvedge.db` in your project root. Commit it to share history with your team, or add `.selvedge/` to `.gitignore` to keep it local.
|
|
38
|
+
|
|
39
|
+
**2. Add to your Claude Code config**
|
|
40
|
+
|
|
41
|
+
`~/.claude/config.json`:
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mcpServers": {
|
|
45
|
+
"selvedge": {
|
|
46
|
+
"command": "selvedge-server"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**3. Tell your agent to use it**
|
|
53
|
+
|
|
54
|
+
Add to your project's `CLAUDE.md`:
|
|
55
|
+
```
|
|
56
|
+
You have access to Selvedge for change tracking.
|
|
57
|
+
Call selvedge.log_change immediately after adding, modifying, or removing
|
|
58
|
+
any DB column, table, function, API endpoint, dependency, or env variable.
|
|
59
|
+
Set `reasoning` to the user's original request or the problem being solved.
|
|
60
|
+
Set `agent` to "claude-code".
|
|
61
|
+
Before modifying an entity, call selvedge.blame to understand its history.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**4. Start querying**
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
selvedge status # recent activity
|
|
68
|
+
selvedge diff users # all changes to the users table
|
|
69
|
+
selvedge diff users.email # changes to a specific column
|
|
70
|
+
selvedge blame payments.amount # what changed last and why
|
|
71
|
+
selvedge history --since 30d # last 30 days of changes
|
|
72
|
+
selvedge search "stripe" # full-text search
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## How it works
|
|
78
|
+
|
|
79
|
+
Selvedge runs as an MCP server. AI agents in tools like Claude Code call Selvedge's tools as they work — logging structured change events to a local SQLite database.
|
|
80
|
+
|
|
81
|
+
Each event records:
|
|
82
|
+
- **What** changed (entity path, change type, diff)
|
|
83
|
+
- **When** (timestamp)
|
|
84
|
+
- **Who** (agent, session ID)
|
|
85
|
+
- **Why** (reasoning — captured from the agent's context in the moment)
|
|
86
|
+
- **Where** (git commit, project)
|
|
87
|
+
|
|
88
|
+
The diff is git's job. The *why* is Selvedge's.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Entity path conventions
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
users.email DB column (table.column)
|
|
96
|
+
users DB table
|
|
97
|
+
src/auth.py::login Function in a file (path::symbol)
|
|
98
|
+
src/auth.py File
|
|
99
|
+
api/v1/users API route
|
|
100
|
+
deps/stripe Dependency
|
|
101
|
+
env/STRIPE_SECRET_KEY Environment variable
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## MCP tools
|
|
107
|
+
|
|
108
|
+
When connected as an MCP server, Selvedge exposes:
|
|
109
|
+
|
|
110
|
+
| Tool | Description |
|
|
111
|
+
|------|-------------|
|
|
112
|
+
| `log_change` | Record a change event |
|
|
113
|
+
| `diff` | History for an entity or entity prefix |
|
|
114
|
+
| `blame` | Most recent change + context for an entity |
|
|
115
|
+
| `history` | Filtered history across all entities |
|
|
116
|
+
| `search` | Full-text search across all events |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## CLI reference
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
selvedge init [--path PATH] Initialize in project
|
|
124
|
+
selvedge status Recent activity summary
|
|
125
|
+
selvedge diff ENTITY [--limit N] Change history for entity
|
|
126
|
+
selvedge blame ENTITY Most recent change + context
|
|
127
|
+
selvedge history [--since SINCE] Browse all history
|
|
128
|
+
[--entity ENTITY]
|
|
129
|
+
[--project PROJECT]
|
|
130
|
+
[--limit N]
|
|
131
|
+
selvedge search QUERY [--limit N] Full-text search
|
|
132
|
+
selvedge log ENTITY CHANGE_TYPE Manually log a change
|
|
133
|
+
[--diff TEXT]
|
|
134
|
+
[--reasoning TEXT]
|
|
135
|
+
[--agent NAME]
|
|
136
|
+
[--commit HASH]
|
|
137
|
+
[--project NAME]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
All read commands support `--json` for machine-readable output.
|
|
141
|
+
|
|
142
|
+
**Relative time in `--since`:**
|
|
143
|
+
- `7d` → last 7 days
|
|
144
|
+
- `24h` → last 24 hours
|
|
145
|
+
- `3m` → last 3 months
|
|
146
|
+
- `1y` → last year
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Configuration
|
|
151
|
+
|
|
152
|
+
| Method | Format | Example |
|
|
153
|
+
|--------|--------|---------|
|
|
154
|
+
| Env var | `SELVEDGE_DB=/path/to/db` | Per-session override |
|
|
155
|
+
| Project init | `selvedge init` | Creates `.selvedge/selvedge.db` in CWD |
|
|
156
|
+
| Global fallback | `~/.selvedge/selvedge.db` | Used if no project DB found |
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Contributing
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
git clone https://github.com/masondelan/selvedge
|
|
164
|
+
cd selvedge
|
|
165
|
+
pip install -e ".[dev]"
|
|
166
|
+
pytest
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
See `CLAUDE.md` for architecture details and the phase roadmap.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
MIT
|