git-strata
origin remote branch

git-strata push sends refs/strata/publish/<branch> to this remote branch. A plain git push inside a session workspace is refused. The workspace pre-push hook tells you to publish with git-strata publish.

publish refs/strata/publish/<branch>

publish commits checkpointed paths onto refs/strata/publish/<branch>. When publish.push is on, that same command pushes. When it is off, the commits stay on the publish ref until git-strata push.

checkpoint recorded edits

checkpoint records edits, with -m or from a tool-call hook. publish takes a fresh BeforePublish checkpoint of each batch, then commits. restore CHECKPOINT rolls paths back.

session the clone you edit

CLI · v0.2.0 · 4 Nov 2026

Every session gets its own APFS clone. The base stays shared.

brew tap dickwu/tap
brew install dickwu/tap/git-strata

Formula: Apple silicon, macOS Ventura or later. Repos and the data root share one APFS volume. MIT or Apache-2.0.

The desktop app is a separate cask. This page is the CLI.

git-strata is a macOS CLI, and git-stratad is its per-user daemon. A session, human or agent, gets an APFS clone of each tracked repo over a shared base snapshot, and a shared dependency set. Checkpoints record the edits. publish commits them. The remote changes only when you run git-strata push, or when that repo is set to push on publish.

base shared snapshot

new fetches origin's default branch and builds each workspace as an APFS clone of that shared base. Dependency sets are shared generations under the data root, next to bases and sessions. That root and the repos have to be on one APFS volume.

Two programs, one socket

git-strata

The CLI. git strata runs the same binary. It creates sessions, records checkpoints, publishes, and pushes.

git-stratad

The per-user daemon. Write commands go through its unix socket. It runs as the LaunchAgent com.gwd.git-stratad. The CLI does not install that plist.

Do not use brew services for this formula. That loads a second LaunchAgent, homebrew.mxcl.git-strata, beside com.gwd.git-stratad. The two daemons would contend for the same socket and lock.

The socket is ~/Library/Application Support/git-strata/daemon.sock. With the daemon stopped, status, grep, files, diff, deps list, and daemon status still read the store. Repeating a checkpoint --tool-call whose checkpoint already exists also works. Every other command returns Busy with reason daemon_down.

The session loop

  1. Create the session

    git-strata new with --repo for each repo you want tracked. Those repos are fetched and get a workspace. The session id and the workspace paths come back on the JSON line, under data.manifest. The older --repos form, with no --repo, gives every repo in config.toml a workspace and tracks the names you list. Do not edit an untracked sibling. That edit is never checkpointed.

  2. Edit the workspace

    Work in data.manifest.repos.<repo>.path. Commands without --session take the session from the current directory. --session accepts an id or a ticket.

  3. Record a checkpoint

    git-strata checkpoint -m records the edits. A hook can send checkpoint --tool-call. status, diff, grep, and files inspect the session, including other sessions with --all or --session. There is no search command: grep searches content, files lists paths. restore rolls a checkpoint back.

  4. Publish the paths you name

    git-strata publish --from SESSION:PATH commits those checkpointed paths onto refs/strata/publish/<branch>. The manual's sequence leaves the workspace before publish. In zsh, write "${S}:path". "$S:path" is a history modifier and silently changes the string.

  5. Push only when that is the ask

    git-strata push REPO updates the remote. If the repo's publish.push is on, publish itself pushes. A gated repo waits for a person at a terminal.

  6. Remove the session after it is published

    git-strata rm --session removes the session once its work is published. Unpublished work makes rm return Dirty, and nothing is removed. rm --discard is a human command.

Each session leases four TCP ports, web, connector, connector_mcp, and aux, so concurrent dev servers do not collide. session exec runs a command in the workspace with PORT and the STRATA_* port variables set. The main checkout keeps the project's own ports.

Every call prints one compact JSON line with ok, data, and error. Branch on error.code. Do not parse the message. Help, --help, and --version print plain text.

Headless sequence from the manual. tool, billing-api, and front are its sample repo names.

git-strata daemon status
git-strata new PROJ-123 --repo tool --repo billing-api
# S = data.manifest.id
# W = data.manifest.repos.tool.path
git-strata add --session "$S" --repo front
cd "$W"
git-strata checkpoint -m "parse config before connect"
git-strata diff
cd ~
git-strata publish --from "${S}:src/a.ts" --from "${S}:src/lib"
git-strata rm --session "$S"

Install the formula, then write the agent

The Homebrew formula installs prebuilt binaries and a sample config.toml. It is Apple silicon only, macOS Ventura or later. The project itself also runs on Intel when you build it from source. Homebrew does not quarantine these formula binaries, so they need no xattr step.

  1. Install with Homebrew

    Tap first, then install the formula named in the tap README and in the project manual.

    brew tap dickwu/tap
    brew install dickwu/tap/git-strata
  2. Write the LaunchAgent and the config

    Point the plist at the stable Homebrew opt path so an upgrade does not need a plist edit. Copy the sample config, then set [paths] root to a directory on the same APFS volume as your repos. The default ~/.strata works only when those repos are on the startup volume. Edit the file before you start the daemon.

    mkdir -p ~/Library/LaunchAgents
    t=$(mktemp ~/Library/LaunchAgents/.git-stratad.XXXXXX) \
      && git-stratad --print-plist "$(brew --prefix)/opt/git-strata/bin/git-stratad" > "$t" \
      && mv "$t" ~/Library/LaunchAgents/com.gwd.git-stratad.plist
    mkdir -p ~/Library/Application\ Support/git-strata
    cp "$(brew --prefix)/share/git-strata/config.toml" \
      ~/Library/Application\ Support/git-strata/config.toml
    # edit config.toml ([paths] root on the same APFS volume as your repos), then:
    git-strata daemon start
  3. Restart after an upgrade. Stop before you uninstall.

    After brew upgrade git-strata, stop the daemon and start it again. Upgrading an existing data root to 0.2.0 migrates the store forward. Read the v0.2.0 release notes before you upgrade. Before brew uninstall git-strata, stop the daemon and remove the plist, or launchd keeps restarting a missing binary.

    git-strata daemon stop && git-strata daemon start
    git-strata daemon stop
    rm ~/Library/LaunchAgents/com.gwd.git-stratad.plist
    brew uninstall git-strata

Intel Macs build from source

scripts/dev-install.sh builds both binaries in release mode, copies them to ~/.cargo/bin, and restarts the daemon. The steps, including the optional codesign identity, are in the manual's dev install section.

Teach an agent the loop

The repository ships a skill for the session loop, the JSON line, and which commands belong to a person. The skills CLI needs Node 22.20 or later.

npx skills add dickwu/git-strata --skill git-strata -g -a claude-code -a codex -a cursor -y

A push can wait for Touch ID

A repo asks for confirmation when publish.confirm is true. The CLI keeps the gate on if either config.toml or pins.json says so. A missing or unreadable pins file, or a repo missing from it, counts as confirmation on. Deleting pins.json never opens the gate. A person loosens a pin with git-strata config relax REPO on a terminal, which asks for Touch ID or the login password.

These commands need a terminal. push when the repo is gated. publish when it would push a gated repo that still has something to commit. rm --discard, deps approve, config relax, resolve, and chain. Most of them then show a LocalAuthentication prompt. No flag, environment variable, or config value skips it. Faking a TTY is a bypass.

Without a terminal the CLI returns NotTty and sends nothing to the daemon. Hand the exact command to a person.

This page is the CLI

GIT STRATA Desktop is a separate Homebrew cask, brew install --cask dickwu/tap/git-strata-desktop. It drives the daemon from this formula. Its site is git-strata-desktop.lifefarmer.ca. Both sit in the lifefarmer catalog.

Questions

What is git-strata?

git-strata is a macOS command-line tool and a per-user daemon. Each coding session gets its own APFS clone of the repos it tracks, taken from a shared base snapshot, plus that repo's dependency set. Checkpoints record edits, publish commits them, and the remote is updated only by git-strata push or by a publish whose repo is configured to push.

How do I install the CLI?

Run brew tap dickwu/tap, then brew install dickwu/tap/git-strata. The formula installs the prebuilt git-strata and git-stratad binaries and a sample config.toml. It requires Apple silicon and macOS Ventura or later.

Does the Homebrew formula run on Intel Macs?

No. The formula depends on arm64. The software itself runs on macOS 13 or later, Apple silicon or Intel, when the repos and the data root are on one APFS volume. An Intel Mac builds from source. This formula does not install there.

How do I start the daemon?

Write the LaunchAgent plist once with git-stratad --print-plist, pointing at the Homebrew opt path. Copy the sample config.toml into ~/Library/Application Support/git-strata/, set paths.root to a directory on the same APFS volume as your repos, then run git-strata daemon start.

Why should I not use brew services?

brew services would load a second LaunchAgent, homebrew.mxcl.git-strata, beside com.gwd.git-stratad. Two daemons would contend for the same socket and lock. The formula leaves out a service block for that reason.

How is this different from GIT STRATA Desktop?

This site is the CLI and the daemon. GIT STRATA Desktop is a separate Homebrew cask, dickwu/tap/git-strata-desktop, and it uses the daemon from this formula. The desktop app has its own site at https://git-strata-desktop.lifefarmer.ca.

What is the session loop?

new creates a session and its workspaces. You edit files in the workspace path, checkpoint records the edits, publish commits them onto each repo's publish branch, push sends a repo when you ask it to, and rm removes the session once that work is published.

Which commands work if the daemon is stopped?

status, grep, files, diff, deps list, and daemon status read the store directly. Repeating a checkpoint --tool-call whose checkpoint already exists also works. Every other command returns Busy with reason daemon_down.

What license is git-strata under?

MIT or Apache-2.0, at your option. The source repository, which is also the homepage in the Homebrew formula, is https://github.com/dickwu/git-strata.