alterdb 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.
Files changed (84) hide show
  1. alterdb-0.1.0/.env.example +1 -0
  2. alterdb-0.1.0/.gitignore +38 -0
  3. alterdb-0.1.0/.python-version +1 -0
  4. alterdb-0.1.0/LICENSE +21 -0
  5. alterdb-0.1.0/PKG-INFO +502 -0
  6. alterdb-0.1.0/README.md +472 -0
  7. alterdb-0.1.0/docker-compose.yml +20 -0
  8. alterdb-0.1.0/docs/Canvas.png +0 -0
  9. alterdb-0.1.0/examples/saas-starter/alembic/alembic.ini +39 -0
  10. alterdb-0.1.0/examples/saas-starter/alembic/env.py +43 -0
  11. alterdb-0.1.0/examples/saas-starter/alembic/script.py.mako +26 -0
  12. alterdb-0.1.0/examples/saas-starter/app/__init__.py +0 -0
  13. alterdb-0.1.0/examples/saas-starter/app/database.py +15 -0
  14. alterdb-0.1.0/examples/saas-starter/app/enums.py +39 -0
  15. alterdb-0.1.0/examples/saas-starter/app/main.py +11 -0
  16. alterdb-0.1.0/examples/saas-starter/app/models/parents.py +28 -0
  17. alterdb-0.1.0/examples/saas-starter/app/models/starter.py +122 -0
  18. alterdb-0.1.0/examples/saas-starter/pyproject.toml +19 -0
  19. alterdb-0.1.0/examples/saas-starter/tests/__init__.py +0 -0
  20. alterdb-0.1.0/examples/saas-starter/tests/test_integration.py +1 -0
  21. alterdb-0.1.0/examples/saas-starter/tests/test_round_trip.py +1 -0
  22. alterdb-0.1.0/pyproject.toml +78 -0
  23. alterdb-0.1.0/src/alter/__init__.py +0 -0
  24. alterdb-0.1.0/src/alter/canvas/__init__.py +0 -0
  25. alterdb-0.1.0/src/alter/canvas/server.py +811 -0
  26. alterdb-0.1.0/src/alter/canvas/static/canvas.js +1561 -0
  27. alterdb-0.1.0/src/alter/canvas/static/index.html +329 -0
  28. alterdb-0.1.0/src/alter/canvas/static/style.css +1079 -0
  29. alterdb-0.1.0/src/alter/cli.py +805 -0
  30. alterdb-0.1.0/src/alter/diff.py +204 -0
  31. alterdb-0.1.0/src/alter/errors.py +43 -0
  32. alterdb-0.1.0/src/alter/exporters/__init__.py +0 -0
  33. alterdb-0.1.0/src/alter/exporters/alter_file.py +8 -0
  34. alterdb-0.1.0/src/alter/exporters/mermaid.py +69 -0
  35. alterdb-0.1.0/src/alter/exporters/sql.py +111 -0
  36. alterdb-0.1.0/src/alter/file_watcher.py +1 -0
  37. alterdb-0.1.0/src/alter/generators/__init__.py +8 -0
  38. alterdb-0.1.0/src/alter/generators/_surgical.py +372 -0
  39. alterdb-0.1.0/src/alter/generators/base.py +95 -0
  40. alterdb-0.1.0/src/alter/generators/sqlalchemy.py +498 -0
  41. alterdb-0.1.0/src/alter/generators/sqlmodel.py +481 -0
  42. alterdb-0.1.0/src/alter/importers/__init__.py +0 -0
  43. alterdb-0.1.0/src/alter/importers/alter_file.py +30 -0
  44. alterdb-0.1.0/src/alter/importers/database.py +300 -0
  45. alterdb-0.1.0/src/alter/importers/sql.py +354 -0
  46. alterdb-0.1.0/src/alter/mcp_server.py +1014 -0
  47. alterdb-0.1.0/src/alter/merge_driver.py +215 -0
  48. alterdb-0.1.0/src/alter/parsers/__init__.py +71 -0
  49. alterdb-0.1.0/src/alter/parsers/base.py +256 -0
  50. alterdb-0.1.0/src/alter/parsers/sqlalchemy.py +822 -0
  51. alterdb-0.1.0/src/alter/parsers/sqlmodel.py +840 -0
  52. alterdb-0.1.0/src/alter/schema.py +202 -0
  53. alterdb-0.1.0/src/alter/staging.py +161 -0
  54. alterdb-0.1.0/src/alter/types.py +284 -0
  55. alterdb-0.1.0/src/alter/validate.py +147 -0
  56. alterdb-0.1.0/templates/auth.alter +81 -0
  57. alterdb-0.1.0/templates/cms.alter +106 -0
  58. alterdb-0.1.0/templates/ecommerce.alter +102 -0
  59. alterdb-0.1.0/templates/saas-base.alter +75 -0
  60. alterdb-0.1.0/tests/__init__.py +0 -0
  61. alterdb-0.1.0/tests/conftest.py +1 -0
  62. alterdb-0.1.0/tests/fixtures/__init__.py +0 -0
  63. alterdb-0.1.0/tests/fixtures/sqlalchemy_models.py +111 -0
  64. alterdb-0.1.0/tests/test_alembic_wrapper.py +70 -0
  65. alterdb-0.1.0/tests/test_canvas_actions.py +400 -0
  66. alterdb-0.1.0/tests/test_cli.py +450 -0
  67. alterdb-0.1.0/tests/test_diff.py +217 -0
  68. alterdb-0.1.0/tests/test_e2e.py +564 -0
  69. alterdb-0.1.0/tests/test_exporters.py +283 -0
  70. alterdb-0.1.0/tests/test_generator_sqlalchemy.py +482 -0
  71. alterdb-0.1.0/tests/test_generator_sqlmodel.py +762 -0
  72. alterdb-0.1.0/tests/test_importers.py +276 -0
  73. alterdb-0.1.0/tests/test_mcp_server.py +551 -0
  74. alterdb-0.1.0/tests/test_merge_driver.py +280 -0
  75. alterdb-0.1.0/tests/test_parser_sqlalchemy.py +369 -0
  76. alterdb-0.1.0/tests/test_parser_sqlmodel.py +817 -0
  77. alterdb-0.1.0/tests/test_round_trip.py +283 -0
  78. alterdb-0.1.0/tests/test_schema.py +325 -0
  79. alterdb-0.1.0/tests/test_smoke.py +215 -0
  80. alterdb-0.1.0/tests/test_staging.py +283 -0
  81. alterdb-0.1.0/tests/test_surgical.py +325 -0
  82. alterdb-0.1.0/tests/test_types.py +343 -0
  83. alterdb-0.1.0/tests/test_validate.py +241 -0
  84. alterdb-0.1.0/uv.lock +1193 -0
@@ -0,0 +1 @@
1
+ DATABASE_URL=postgresql://alter:alter@localhost:5433/alter_test
@@ -0,0 +1,38 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .venv/
9
+
10
+ # Tools
11
+ .mypy_cache/
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ .coverage
15
+ htmlcov/
16
+
17
+ # Environment
18
+ .env
19
+
20
+ # IDE
21
+ .vscode/
22
+ .idea/
23
+ *.swp
24
+ *.swo
25
+ *~
26
+
27
+ # OS
28
+ .DS_Store
29
+ Thumbs.db
30
+
31
+ # Claude Code dev session files
32
+ .claude/
33
+
34
+ # Example project generated files (local only)
35
+ examples/saas-starter/schema.alter
36
+ examples/saas-starter/uv.lock
37
+
38
+ docs/RULES.md
@@ -0,0 +1 @@
1
+ 3.11
alterdb-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chimi Labs
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.
alterdb-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,502 @@
1
+ Metadata-Version: 2.4
2
+ Name: alterdb
3
+ Version: 0.1.0
4
+ Summary: Visual schema design for SQLModel and SQLAlchemy. Edit your database as a diagram, write it back as code.
5
+ Project-URL: Homepage, https://github.com/chimi-labs/alter
6
+ Project-URL: Repository, https://github.com/chimi-labs/alter
7
+ Project-URL: Issues, https://github.com/chimi-labs/alter/issues
8
+ Author: Chimi Labs
9
+ Author-email: Franco Mahl <francomahl@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: canvas,database,mcp,orm,schema,sqlalchemy,sqlmodel
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Database
19
+ Classifier: Topic :: Software Development :: Code Generators
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: click>=8.0
22
+ Requires-Dist: mcp>=1.0
23
+ Requires-Dist: pydantic>=2.0
24
+ Requires-Dist: sqlalchemy>=2.0
25
+ Requires-Dist: sqlparse>=0.5
26
+ Requires-Dist: watchfiles>=0.20
27
+ Provides-Extra: db
28
+ Requires-Dist: psycopg2-binary>=2.9; extra == 'db'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Alter
32
+
33
+ > Comprehension first, design second.
34
+
35
+ Visual schema design for SQLModel and SQLAlchemy. Edit your database as a diagram, write it back as code.
36
+
37
+ ![Canvas](docs/Canvas.png)
38
+
39
+ ## What is Alter?
40
+
41
+ Alter is a local-first schema tool that keeps your ORM models and a visual ERD canvas in sync — in both directions:
42
+
43
+ ```
44
+ ┌─────────────┐ ┌───────────────┐
45
+ │ Your Code │ ── alter sync ─────► │ Canvas │
46
+ │ (models.py) │ │ (visual ERD) │
47
+ │ │ ◄── alter apply ──── │ │
48
+ └─────────────┘ └───────────────┘
49
+ schema.alter
50
+ (keeps both in sync)
51
+ ```
52
+
53
+ You design tables on the canvas, and Alter writes clean Python classes back to your files.
54
+ You edit your models by hand, and Alter updates the canvas to match.
55
+
56
+ Everything runs locally. No cloud, no account, no data leaves your machine.
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ pip install alterdb
62
+ ```
63
+
64
+ Or with [uv](https://docs.astral.sh/uv/):
65
+
66
+ ```bash
67
+ uv add alterdb
68
+ ```
69
+
70
+ **Requirements:** Python 3.11+
71
+
72
+ > **Live database introspection** (MCP `introspect_db` tool): requires `psycopg2-binary`, install with `pip install alterdb[db]`.
73
+
74
+ ## Quick Start
75
+
76
+ ### From existing models
77
+
78
+ ```bash
79
+ alter init # scan your ORM models → create schema.alter
80
+ alter canvas # open the visual ERD in your browser
81
+ ```
82
+
83
+ Your browser opens with an interactive diagram of every table, column, and relation in your project.
84
+
85
+ ### From an existing database
86
+
87
+ Export your database schema as SQL, then import it:
88
+
89
+ ```bash
90
+ pg_dump --schema-only --no-owner mydb > schema.sql
91
+ alter import schema.sql # parse DDL and merge tables into schema.alter
92
+ alter canvas # open the visual editor
93
+ ```
94
+
95
+ Or start the canvas first and use **Paste SQL** in the toolbar to paste your DDL directly.
96
+
97
+ ### Starting from scratch
98
+
99
+ No models yet? Start with a blank canvas or one of the built-in templates:
100
+
101
+ ```bash
102
+ alter init # creates an empty schema.alter
103
+ alter canvas # open the canvas, click "Templates" to pick a starter
104
+ ```
105
+
106
+ Choose from **saas-base**, **auth**, **cms**, or **ecommerce** — tables are proposed on the canvas
107
+ so you can review and customize before committing anything.
108
+
109
+ ## What is `schema.alter`?
110
+
111
+ `schema.alter` is a JSON file that captures your table definitions, column types, relations, and
112
+ canvas layout positions. It sits between your Python code and the visual editor — a single source
113
+ of truth that's human-readable, git-diffable, and lives in your repo.
114
+
115
+ Think of it as a `.lock` file for your database schema, except you can open it in a browser and
116
+ edit it visually.
117
+
118
+ A minimal example:
119
+
120
+ ```json
121
+ {
122
+ "version": 1,
123
+ "orm": "sqlmodel",
124
+ "tables": [
125
+ {
126
+ "name": "users",
127
+ "file_path": "app/models.py",
128
+ "position": { "x": 0, "y": 0 },
129
+ "columns": [
130
+ { "name": "id", "type": "uuid", "primary_key": true, "default": "uuid4" },
131
+ { "name": "email", "type": "string", "nullable": false, "unique": true },
132
+ { "name": "name", "type": "string", "nullable": false }
133
+ ]
134
+ }
135
+ ]
136
+ }
137
+ ```
138
+
139
+ ## The Two-Way Workflow
140
+
141
+ Two commands keep `schema.alter` synchronized with your code:
142
+
143
+ ### Canvas → Code
144
+
145
+ You add a table or modify a column on the canvas, then click **Commit** (or use the in-canvas
146
+ **Apply to Code** button), or run from the terminal:
147
+
148
+ ```bash
149
+ alter apply --preview # see exactly what will change (unified diff)
150
+ alter apply # write the changes to your model files
151
+ ```
152
+
153
+ `alter apply` is surgical — it only modifies the classes that changed. Your docstrings,
154
+ `Relationship()` definitions, inline comments, and hand-written formatting are preserved.
155
+
156
+ For example, drawing a `Payment` table on the canvas and clicking **Commit** writes this to
157
+ `app/models.py`:
158
+
159
+ ```python
160
+ import uuid
161
+ from sqlmodel import Field, SQLModel
162
+
163
+
164
+ class Payment(SQLModel, table=True):
165
+ __tablename__ = "payments"
166
+
167
+ id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
168
+ amount: int
169
+ currency: str = Field(max_length=3)
170
+ user_id: uuid.UUID = Field(foreign_key="users.id")
171
+ ```
172
+
173
+ Enum changes are written to the correct file: if `Role` is defined in `app/enums.py`, edits on
174
+ the canvas update `app/enums.py` — not your model file.
175
+
176
+ ### Code → Canvas
177
+
178
+ You edit `models.py` by hand, then click the in-canvas **Sync from Code** button, or run:
179
+
180
+ ```bash
181
+ alter sync # re-parse your models, update schema.alter
182
+ ```
183
+
184
+ The canvas picks up the change automatically via live reload — no restart needed.
185
+
186
+ ### Preview changes before committing
187
+
188
+ ```bash
189
+ alter diff # see what changed (text)
190
+ alter diff --format markdown # PR-ready changelog
191
+ ```
192
+
193
+ ## Complete Workflow Example
194
+
195
+ Here's the full story, from a fresh project to running migrations:
196
+
197
+ ```bash
198
+ # 1. Initialise
199
+ alter init # scan models → schema.alter
200
+
201
+ # 2. Create the initial migration (one-time, with your migration manager)
202
+ # Example with Alembic — see Migrations section below
203
+ alembic init alembic
204
+ alembic revision --autogenerate -m "initial schema"
205
+ alembic upgrade head # create tables in the database
206
+
207
+ # 3. Open the canvas and make changes
208
+ alter canvas
209
+
210
+ # — design on the canvas —
211
+ # add a "payments" table, click Commit
212
+ # the "Migrations" tab shows the SQL that needs to run
213
+
214
+ # 4. Apply canvas changes to code
215
+ alter apply --preview # see the unified diff
216
+ alter apply # write class Payments to models.py
217
+
218
+ # 5. Run the migration with your own tooling
219
+ # Copy the SQL from the canvas Migrations tab, then:
220
+ alembic revision -m "add payments table" # create revision file
221
+ # paste the SQL into the upgrade() function
222
+ alembic upgrade head
223
+ ```
224
+
225
+ ## Migrations
226
+
227
+ Alter generates the SQL — you run it with whatever migration tool you already use.
228
+
229
+ The **Migrations tab** in the canvas shows the pending SQL at any time. The `preview_migration`
230
+ MCP tool returns the same SQL to AI assistants. Copy it into your migration manager of choice.
231
+
232
+ ### With Alembic (one-time setup)
233
+
234
+ ```bash
235
+ alembic init alembic # creates alembic.ini + alembic/env.py + alembic/versions/
236
+ ```
237
+
238
+ Edit `alembic/env.py` so Alembic knows about your models:
239
+
240
+ ```python
241
+ from sqlmodel import SQLModel
242
+ import app.models # ensure all models are imported and registered
243
+
244
+ target_metadata = SQLModel.metadata # required for autogenerate
245
+ ```
246
+
247
+ ### Initial migration
248
+
249
+ Create all tables from scratch:
250
+
251
+ ```bash
252
+ alembic revision --autogenerate -m "initial schema"
253
+ alembic upgrade head
254
+ ```
255
+
256
+ ### Incremental migrations (canvas or MCP driven)
257
+
258
+ After the initial migration, use the canvas Migrations tab to see the SQL for any canvas
259
+ or MCP change, then apply it with your tool:
260
+
261
+ ```bash
262
+ # 1. Make changes on the canvas or via MCP
263
+ # 2. See the SQL in the canvas Migrations tab (or call preview_migration via MCP)
264
+ # 3. Create and apply the migration:
265
+ alembic revision -m "add payments table" # create an empty revision
266
+ # paste the SQL into upgrade() in the new file
267
+ alembic upgrade head
268
+ ```
269
+
270
+ > **With other tools** (Django, Flyway, raw SQL, etc.) — the workflow is the same: copy the
271
+ > SQL from the canvas Migrations tab and apply it however your project requires.
272
+
273
+ ## Adding a File to an Existing Schema
274
+
275
+ Got a legacy module or a new plugin with its own models? Add it without touching your main schema:
276
+
277
+ ```bash
278
+ alter add app/legacy/models.py # parse and merge new tables into schema.alter
279
+ alter add lib/plugins/billing.py # tables already in the schema are skipped
280
+ ```
281
+
282
+ `alter add` parses the file, adds any new tables (and their enum types), and saves `schema.alter`.
283
+ Already-tracked tables are silently skipped — safe to run multiple times.
284
+
285
+ ## Cross-File Support
286
+
287
+ Alter understands multi-file projects out of the box:
288
+
289
+ - **Enums in separate files** — if `Role` is defined in `app/enums.py`, Alter tracks its
290
+ `file_path` so that `alter apply` never duplicates the enum class in your model file.
291
+ - **Base class inheritance** — columns inherited from mixin classes (e.g. `UUIDBase`,
292
+ `TimestampedBase`) are tracked as inherited and never re-injected as explicit field definitions
293
+ when applying to code.
294
+ - **Multi-file models** — tables can live in different files; `alter apply` writes each table to
295
+ the correct file independently.
296
+
297
+ ## Enums on the Canvas
298
+
299
+ Enums are displayed on the canvas as read-only reference cards showing each enum's name and
300
+ values. This lets you see which types are available when wiring up columns, but **enums cannot
301
+ be added, edited, or deleted from the canvas** — the source file is the single source of truth.
302
+
303
+ To add or change an enum, edit the source file directly (e.g. `app/enums.py`), then sync:
304
+
305
+ ```bash
306
+ alter sync # re-parse models → refresh schema.alter
307
+ ```
308
+
309
+ Or click **Sync from Code** in the canvas toolbar. The updated enum appears immediately.
310
+
311
+ ## Templates
312
+
313
+ Alter ships four starter templates, accessible from the **Templates** button in the canvas
314
+ toolbar or via the CLI:
315
+
316
+ | Template | Tables |
317
+ | ----------- | ------------------------------------------- |
318
+ | `saas-base` | users, organizations, memberships, sessions |
319
+ | `auth` | users, sessions, tokens, oauth_accounts |
320
+ | `cms` | posts, categories, tags, media |
321
+ | `ecommerce` | products, orders, order_items, customers |
322
+
323
+ Import a template into an existing project:
324
+
325
+ ```bash
326
+ alter import templates/ecommerce.alter
327
+ ```
328
+
329
+ Tables already in your schema are skipped — no duplicates.
330
+
331
+ ## Commands
332
+
333
+ ### Quick reference
334
+
335
+ | Command | What it does |
336
+ | -------------------- | ------------------------------------------------------------- |
337
+ | `alter init` | Create `schema.alter` from existing ORM model files |
338
+ | `alter canvas` | Open the interactive ERD in your browser |
339
+ | `alter apply` | Write schema changes to your ORM model files |
340
+ | `alter sync` | Update `schema.alter` from your ORM model files |
341
+ | `alter add` | Add tables from a model file to the schema |
342
+ | `alter diff` | Show pending changes between schema and code |
343
+ | `alter validate` | Check your schema for errors and warnings |
344
+ | `alter export` | Export as SQL DDL, Mermaid ERD, or `.alter` JSON |
345
+ | `alter import` | Import tables from a `.sql` or `.alter` file |
346
+ | `alter merge-driver` | Git merge driver for `.alter` files |
347
+ | `alter mcp` | Start the MCP server |
348
+
349
+ ### `alter diff`
350
+
351
+ Compare `schema.alter` with your ORM model files and show what has drifted:
352
+
353
+ ```bash
354
+ alter diff # text summary (+ added, ~ modified, - removed)
355
+ alter diff --format markdown # PR-ready markdown changelog
356
+ ```
357
+
358
+ Useful before committing code changes or before opening a PR to make sure the
359
+ canvas and the code are still in sync. Exits non-zero if there are differences.
360
+
361
+ ### `alter validate`
362
+
363
+ Check the schema for structural problems before applying or exporting:
364
+
365
+ ```bash
366
+ alter validate
367
+ ```
368
+
369
+ Reports errors (broken FK references, duplicate table names, unsupported type
370
+ combinations), warnings, and info-level hints. Exits with code 1 if any errors
371
+ are found — safe to use in CI.
372
+
373
+ ### `alter export`
374
+
375
+ Export the committed schema in different formats:
376
+
377
+ ```bash
378
+ alter export # SQL DDL to stdout (default)
379
+ alter export --format mermaid # Mermaid ERD diagram to stdout
380
+ alter export --format alter # raw schema.alter JSON to stdout
381
+ alter export --output schema.sql # write to a file instead of stdout
382
+ alter export --format mermaid --output erd.md # write Mermaid to a file
383
+ alter export --proposed # export staged (uncommitted) changes
384
+ ```
385
+
386
+ The Mermaid output can be pasted directly into GitHub Markdown, Notion, or any
387
+ tool that renders ```` ```mermaid ```` fences:
388
+
389
+ ````markdown
390
+ ```mermaid
391
+ erDiagram
392
+ users {
393
+ uuid id PK
394
+ string email
395
+ }
396
+ posts {
397
+ uuid id PK
398
+ uuid author_id FK
399
+ }
400
+ users ||--o{ posts : "author_id"
401
+ ```
402
+ ````
403
+
404
+ ### `alter import`
405
+
406
+ Merge tables from an external source into `schema.alter`. Tables already present
407
+ are skipped — safe to run multiple times:
408
+
409
+ ```bash
410
+ alter import schema.sql # import from a pg_dump or hand-written DDL
411
+ alter import other.alter # import from another schema.alter file
412
+ alter import templates/saas.alter # import a built-in template
413
+ ```
414
+
415
+ Format is auto-detected from the file extension (`.sql` or `.alter`). You can
416
+ also override it with `--format sql` or `--format alter`.
417
+
418
+ ### `alter merge-driver`
419
+
420
+ A custom Git merge driver that merges `schema.alter` files structurally (by
421
+ table name) instead of line-by-line, which eliminates most merge conflicts when
422
+ two branches add different tables.
423
+
424
+ **One-time setup** (run once per machine):
425
+
426
+ ```bash
427
+ git config --global merge.alter.name "Alter schema merge driver"
428
+ git config --global merge.alter.driver "alter merge-driver %O %A %B"
429
+ ```
430
+
431
+ Then add to your repo's `.gitattributes`:
432
+
433
+ ```
434
+ *.alter merge=alter
435
+ ```
436
+
437
+ After that, Git uses the driver automatically whenever a `.alter` file is
438
+ involved in a merge or rebase. No further action needed.
439
+
440
+ ## MCP Server
441
+
442
+ Alter exposes your schema to any MCP-compatible AI assistant (Claude, Cursor, Windsurf, etc.)
443
+ so it can read, modify, and commit schema changes programmatically.
444
+
445
+ ```bash
446
+ alter mcp # starts the MCP server over stdio
447
+ ```
448
+
449
+ ### What AI assistants can do through MCP
450
+
451
+ - **Read** your current schema (tables, columns, relations, enums)
452
+ - **Propose changes** — add/remove/rename tables and columns in a staging area
453
+ - **Add a file** — parse a model file and merge its tables into the schema (`add_file` tool)
454
+ - **Preview diffs** before committing anything
455
+ - **Preview migration SQL** — see the DDL that needs to run for pending changes
456
+ - **Undo/redo** any staged change
457
+ - **Commit** approved changes to `schema.alter`
458
+ - **Export** as SQL, Mermaid, or JSON
459
+ - **Validate** the schema for errors
460
+
461
+ ### Configure in your editor
462
+
463
+ **Claude Desktop** (`claude_desktop_config.json`):
464
+
465
+ ```json
466
+ {
467
+ "mcpServers": {
468
+ "alter": {
469
+ "command": "uv",
470
+ "args": ["run", "--directory", "/path/to/project", "alter", "mcp"]
471
+ }
472
+ }
473
+ }
474
+ ```
475
+
476
+ **Cursor** (`.cursor/mcp.json`):
477
+
478
+ ```json
479
+ {
480
+ "mcpServers": {
481
+ "alter": {
482
+ "command": "uv",
483
+ "args": ["run", "--directory", "/path/to/project", "alter", "mcp"]
484
+ }
485
+ }
486
+ }
487
+ ```
488
+
489
+ Replace `/path/to/project` with the absolute path to your project directory (where `schema.alter`
490
+ lives or will be created).
491
+
492
+ Then ask your AI assistant: _"Add a `payments` table with `id`, `amount`, `currency`, and a
493
+ foreign key to `users`"_ — it will stage the change, show you the diff, and commit on your approval.
494
+
495
+ ## Supported ORMs
496
+
497
+ - **SQLModel** — auto-detected from `from sqlmodel import ...`
498
+ - **SQLAlchemy 2.0** (declarative) — auto-detected from `from sqlalchemy import ...`
499
+
500
+ ## License
501
+
502
+ MIT