feat(server): t3 doctor reclaims database space
Existing databases keep their size after compaction (#19435) because they were created without incremental auto-vacuum, and switching that on requires a full offline VACUUM.
t3 doctor inspects the data directory and offers one repair: Reclaim database space. It verifies projections, compacts history, verifies again, switches the database to incremental auto-vacuum and runs VACUUM.
| Command | Behavior |
|---|---|
t3 doctor | Choose repairs in a terminal; recommended ones preselected |
t3 doctor --fix | Run the recommended repairs without prompting |
t3 doctor --dry-run | Show repairs, change nothing (wins over --fix) |
- It takes an exclusive SQLite lock, so it refuses while any server or desktop app has the database open.
- If this home's background service is installed, doctor stops it for the repair and starts it again afterwards, including when the repair or the stop fails. A crash-looping or throttled service is stopped too, and a disabled service isn't enabled. Services for other homes are left alone.
- User docs: a "Reclaim database space" section in the background service guide, and a row in the CLI table.
Measured on a copy of my real database
Copied read-only from the live install with the SQLite backup API, on Linux x86_64 with Node 24.21.
| Before | After | |
|---|---|---|
| Database file | 7.02 GiB | 3.83 GiB |
| Orchestration events | 962,244 | 426,382 |
auto_vacuum | 0 (none) | 2 (incremental) |
The repair took 183 s. A second run reports "Nothing to repair". The removed events include 535,828 superseded events. The 237 v1 thread.created rows that went belong to legacy threads whose transcripts were already imported into v2, which compaction removed before this change too.
$ t3 doctor --base-dir <copy> --fix
Database: 7.02 GiB, 0.0 MiB reclaimable.
Reclaim database space (recommended)
Returns unused space to disk and turns on automatic shrinking.
Pauses the background service, if installed, while it runs and may need temporary disk space.
Reclaiming database space. This can take several minutes...
Done: 7.02 GiB -> 3.83 GiB, 535828 superseded events removed.
Takes over #19249.
š¤ Generated with Claude Code