Skip to main content

Architecture

Graft is a Go CLI that orchestrates three subsystems: the Docker lifecycle manager, the content-addressable storage (CAS) layer, and the state manager.

System Diagram

Subsystems

Docker Lifecycle

The internal/docker package wraps the Docker Engine SDK. It handles:
  • Container inspection (capturing image, env, ports, networks)
  • Graceful stop and start
  • Container removal and recreation with host bind mounts
  • Smart lifecycle (only restart if container was originally running)
Graft uses the Docker SDK directly (not shell commands) for type-safe, structured container management.

CAS Layer (DAG)

The internal/dag package contains three components:

State Manager

The internal/state package manages config.json — the lightweight state file at ~/.graft/<project>/. It tracks:
  • Schema version (for migration safety)
  • Target container ID
  • Active branch
  • Project root path
  • Operation mode (snapshot vs bind)
  • Container configuration (image, env, ports, network)
  • Branch metadata (name, path, size, timestamps)

Data Flow

Init Flow

Commit Flow

Checkout Flow

Two Operation Modes

Snapshot Mode (default)

The container stays on its original Docker volume. At commit time, Graft bridges data from the Docker volume to the host using an ephemeral Alpine runner. The container is never recreated. Best for: Quick evaluation, when you don’t want Graft managing your container.

Bind Mount Mode (—bind)

Graft recreates the container with a host bind mount pointing at the branch directory. The container’s data lives directly on the host. No Alpine runner is needed for subsequent operations. Best for: Full lifecycle management, frequent branching, production use.