Skip to content

Architecture

Graft is split into three layers:

CLI
human and script interface
SQLite extension
VFS + PRAGMA bridge
Core
storage runtime + repository semantics

This split is deliberate. The product API is the SQLite extension and its repository pragmas. The CLI exists to make those commands easy to run locally.

Core owns the durable semantics:

  • repository discovery and initialization
  • object encoding and object ids
  • refs, symbolic HEAD, tags, and remote-tracking refs
  • index state, including conflict stages
  • revision parsing
  • tree comparison
  • branch, checkout, reset, merge, fetch, pull, and push plans
  • runtime integration for snapshot materialization and hydration

Core does not need to know that a user typed graft diff. It receives repository operations and returns structured results.

The SQLite extension owns the bridge from database activity to repository state:

  • registers the Graft VFS
  • maps a physical database path to a repo-relative path
  • discovers .graft/
  • switches repository databases to .graft/store/
  • turns current SQLite database state into staged snapshot objects
  • materializes committed snapshots into SQLite databases on checkout/switch/reset/pull
  • exposes repository operations as PRAGMA graft_*

The extension is where SQLite page writes become Graft storage commits.

The CLI should remain thin:

parse args -> open app.db through embedded Graft VFS -> execute PRAGMA -> print

Examples:

graft status
-> PRAGMA graft_status
graft add app.db
-> PRAGMA graft_add = 'app.db'
graft diff HEAD~1 HEAD app.db
-> PRAGMA graft_diff = 'HEAD~1 HEAD -- app.db'

graft sql is special only because it executes arbitrary SQL through the same embedded VFS. It does not introduce another storage path.

SQLite transaction
writes pages through Graft VFS
storage runtime appends page/log commits
repo marks path dirty
graft add
reads current database snapshot
writes or reuses sqlite-snapshot-v1 object
records index entry
graft commit
writes tree object
writes commit object
updates HEAD or current branch ref

The SQLite transaction is still the database atomicity boundary. The Graft commit is the project history boundary.

resolve revision
-> find commit
-> read tree
-> find sqlite snapshot object
-> verify/hydrate needed storage commits
-> switch or materialize database state
-> update index/worktree bookkeeping

When the target path is the currently open VFS database, the extension can switch the active volume. When the target path is another physical SQLite file, repository mode materializes the file into the worktree.