Skip to content

The data model

Forest is the data-side parallel to git's version control. Git tracks code in .git/; forest tracks large data — local layout plus remote sync — in .forest/. The two domains never overlap and neither requires the other.

A fixed-depth chain

No arbitrary nesting:

workspace → checkout → stage → unit → files
flowchart LR
    W["workspace<br/><code>.forest/</code>"] --> C["checkout<br/><code>demo</code>"]
    C --> S1["stage<br/><code>raw</code>"]
    C --> S2["stage<br/><code>models</code>"]
    S1 --> U1["unit"] --> F1["files"]
    S2 --> U2["unit"] --> F2["files"]
Level What it is
Workspace The per-repo .forest/ control area (registry + active pointer).
Checkout A named data view registered in the workspace — like a git branch you stay rooted in. Switching is an O(1) pointer rewrite; data never moves.
Stage A named data category inside a checkout, with a remote layout.
Unit One addressable item within a stage — a subdirectory, directory, or file, per the stage's sync_by.

Metadata layout

Everything forest owns lives under .forest/; your data does not.

.forest/
  config.yaml                     # workspace registry: version, checkouts{}
  HEAD                            # active checkout name (gitignored)
  checkouts/
    demo/
      forest.yaml                 # shared: stages, remotes, manifest
      local.yaml                  # user-local: active_remote, stage_paths (gitignored)
      sync_state.json             # user-local push/pull state (gitignored)

Shared metadata (config.yaml, each forest.yaml) is committed, so a fresh clone bootstraps with bind + remote use + pull. User-local files (HEAD, local.yaml, sync_state.json) are gitignored — see the dogfood chapter for this split running live.

Design constraints (v1)

  • Single active machine. The user-local files are git-invisible but may be moved around by file-syncing tools; forest assumes one active machine and protects intra-machine write races with atomic writes plus a per-checkout flock that spans each unit's whole transfer, so concurrent runs on one checkout serialize instead of racing.
  • Real filenames. Forest stores data under real paths, not a content-addressed blob store.
  • Content-agnostic, integrity-aware. Forest never interprets file contents, but it does record per-file SHA-256 hashes to detect changes (even same-size ones) and verifies every transfer against the remote before recording it.

Design history

The repository's docs/adr/ directory records the architecture decisions behind the workspace/checkout model.