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.
@@ -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
@@ -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
@@ -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
@@ -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