Skip to content

Physical Files And Volumes

The easiest mental model is:

app.db path repository path and worktree entry
Graft Volume mutable page store used by the Graft VFS
snapshot immutable point-in-time view of a Volume
physical .db file optional materialized copy for external SQLite tools

app.db is the name users work with, but the Graft VFS reads and writes pages through a Volume. A SQLite transaction advances that Volume to a new snapshot. The snapshot becomes part of repository history only after graft add and graft commit.

Not exactly.

When you run:

Terminal window
graft sql "INSERT INTO users(name) VALUES ('Alice');"

the current app.db worktree path points at a writable Graft Volume. That Volume now has a newer snapshot, but no repository commit has been created yet.

When you run:

Terminal window
graft add app.db
graft commit -m "add alice"

the repository commit records a sqlite-snapshot-v1 object for app.db. That object describes how to reconstruct the database snapshot from Graft page/log storage.

With the Graft VFS, the operating-system file does not have to exist. The path is still meaningful because SQLite opens:

file:/project/app.db?vfs=graft

Graft maps that path to the repo-local store under .graft/. In a fresh repository, you can have committed data for app.db even if ls app.db shows no ordinary file.

Use graft export when you want a normal SQLite database file for tools such as sqlite3, DB Browser for SQLite, Datasette, or application debuggers.

Export the current worktree Volume:

Terminal window
graft export --output app.inspect.db app.db
sqlite3 app.inspect.db

Export a committed revision:

Terminal window
graft export --source HEAD --output app.head.db app.db
graft export --source HEAD~1 --output app.previous.db app.db

The exported file is a regular SQLite database. It is not connected to the Graft Volume after export.

If you edit the exported file with an ordinary SQLite tool, Graft will not automatically see those edits.

To import an edited physical file back into the repository, stage it as a physical SQLite file:

Terminal window
sqlite3 app.inspect.db "INSERT INTO users(name) VALUES ('Bob');"
cp app.inspect.db app.db
graft --db .graft-control.db add app.db
graft commit -m "import sqlite tool edits"

The --db .graft-control.db part matters when app.db is a physical file you want to import. It lets the CLI enter the repository through a separate control database, so app.db is treated as a physical worktree file rather than as the current Graft VFS Volume.

  • Use graft sql or a vfs=graft SQLite connection for normal Graft-managed writes.
  • Use graft export for read-only inspection in standard SQLite tools.
  • Treat exported files inside the project directory as untracked files unless you intentionally import them.
  • Commit exported files only if they are fixtures or artifacts you really want in the repository.