Worktrees

Braide uses git worktrees to give each session an isolated copy of the project's repository (if your project contains a git repository). This page explains what worktrees are, how they interact with the project, and how to manage changes made by agents.

Worktrees are the default mode for a session. Braide also supports two other modes — project-root (runs in the repo root, no worktree) and scratch (runs in an empty ephemeral directory). See Session Modes for an overview of all three.

Worktree Mode

Note: If you don't have a git repository in your project directory, Braide will work in root mode by default.

Caution: concurrent sessions working in the same directory stand to overwrite each others work, so always favour worktrees if that's what you want to do.

What is a Worktree?

A git worktree is a linked working copy of a repository that shares the same .git data but has its own checked-out branch and file state. Git natively supports multiple worktrees from a single repository.

When you create a session, Braide runs:

git worktree add <worktree-path> -b acp-session/<session-id>

This creates a new branch from the project's current HEAD and checks it out in a directory specific to the session:

~/.braide/projects/<project-id>/sessions/<session-id>/worktree/
Working with Worktrees

How Worktrees Provide Isolation

  • Each session operates in its own worktree directory with its own branch.
  • Agents read and write files only within the session's worktree — they shouldn't affect other sessions or your main working directory (but agents tend to have full system access so can work outside the worktree/project root if the want too)
  • The embedded terminal for each session also starts in the session's worktree, so any commands you run there operate on the same isolated copy.
  • Multiple sessions can run in parallel without conflicting, even if they modify the same files.

Worktree Setup

A fresh worktree starts with the project's source files but no installed dependenciesnode_modules, .venv, target/, and similar build outputs aren't carried over from the project root. For projects where the agent (or your terminal) needs those dependencies, configure a per-project worktree setup command that Braide will run once after the worktree is created.

Configure it in Settings > Project > Worktrees > Worktree setup command (the cog icon, then the project's settings page). Typical values:

npm install
pnpm install
uv sync
cargo build

The command is shell-evaluated, so you can chain steps with &&:

npm install && npm run build:wasm

How it runs:

  • The command runs in parallel with the agent handshake. The session UI lights up immediately with a "running setup" badge; you can start typing a prompt while the install proceeds.
  • Working directory is the session's worktree — relative paths in the command resolve against the worktree, not the project root.
  • Output is captured to the session's log file (~/.braide/projects/<project-id>/sessions/<session-id>/logs/session.log).
  • The setup command only runs for worktree sessions. Sessions created in the project root reuse your already-set-up tree, and scratch sessions are empty ephemeral directories with nothing to install against — both skip it. Within worktree sessions it still runs every time (sessions are created opportunistically and many are short-lived experiments where dependencies are never needed), so keep it idempotent and reasonably fast.

Failure handling: if the setup exits non-zero, the badge is replaced by a dismissible failure banner showing the exit code. The session itself remains usable — the agent and terminal still work, but commands that depend on the install will fail until you fix the issue and recreate the session (or run the install manually inside the worktree).

Cancellation: deleting a session while its setup is still running terminates the setup process. The worktree gets cleaned up regardless of how far the install got.

User-managed git hooks

Some projects ship a post-checkout hook (via core.hooksPath or .git/hooks/) that installs dependencies on every git worktree add. When Braide creates a worktree, that hook would run inside the git worktree add call, blocking the worktree creation phase before the agent even starts. The setup command above is the parallel alternative — but the hook may still be useful for direct (non-Braide) git worktree add use, e.g. when a developer creates a worktree from the terminal.

To support both flows, write the hook to bail out when Braide is driving:

#!/usr/bin/env bash
# Skip when Braide is creating the worktree — its setup command runs in parallel.
[ "$BRAIDE_WORKTREE_CREATE" = "1" ] && exit 0

# …rest of the hook only runs for direct git worktree add usage.
npm install

See BRAIDE_WORKTREE_CREATE in the configuration reference for the full contract.

Working with Session Branches

Branch selector & base branch

Branch Naming Convention

Session branches follow the pattern acp-session/<session-id>-<session-title>, where the session title is sanitized for git compatibility (lowercased, non-alphanumeric characters replaced with hyphens, truncated to 60 characters). When a session is first created it has no title, so the branch starts as acp-session/<session-id>. The branch is automatically renamed whenever the session title is set or changed — whether from the first prompt, an attached GitHub issue, or a manual rename.

Viewing Changes

From the session's terminal (or any terminal pointed at the worktree path), you can inspect what the agent has changed:

# See which files changed
git status

# View the full diff
git diff HEAD

Braide also displays a diff summary in the session UI.

Committing Changes

If you're happy with the agent's changes, commit them from the session's terminal:

git add -A
git commit -m "feat: implement feature X"

The commit is made on the session's branch (acp-session/<session-id>-<session-title>).

Rebasing from the Base Branch

If the project's main branch has moved forward since the session was created, you may want to rebase the session branch to incorporate those changes:

# Fetch latest changes (if working with a remote)
git fetch origin

# Rebase onto the main branch
git rebase main

If there are conflicts, resolve them as you normally would with git, then continue:

git rebase --continue

Merging Back to the Main Branch

Once the session's work is complete and committed, you can merge it back into the main branch. From your project root (not the worktree):

# Switch to main
git checkout main

# Merge the session branch
git merge acp-session/<session-id>-<session-title>

Alternatively, push the session branch and open a pull request if your workflow uses code review.

Tip: Creating a project-root session gives you an agent that already runs in the project root, so you can drive merges and rebases through it without leaving Braide.

Pushing the Session Branch

You can push the session branch to a remote for review or backup:

git push -u origin acp-session/<session-id>-<session-title>

Session Archive and Restore

Archiving a worktree session removes its worktree directory from disk immediately but preserves enough git state to restore the session later. This is how Braide reclaims the dominant per-session storage cost (node_modules, build output, the checked-out source) the moment you stop actively using a session.

When a session is archived, Braide:

  1. Captures uncommitted changes — anything git status would show (staged, unstaged, and untracked) is stashed and moved into a session-scoped ref at refs/braide/wip/<session-id>. Ignored files (.env, node_modules, anything in .gitignore) are not captured.
  2. Removes the worktree — the worktree directory is deleted and unlinked from the repository.
  3. Renames the branch to acp-session-archived/<session-id>-<session-title> — committed history stays reachable on the anchor branch.

Unarchive reverses each step: rename the branch back, recreate the worktree with git worktree add, apply and drop the wip ref, and re-run the setup command so ignored files are repopulated.

For the full archive lifecycle, including the affordance UX, retention protection, and how to recover from a stash-apply conflict, see the Archive & Retention guide.

Session Deletion and Cleanup

When a session is deleted, Braide:

  1. Removes the worktree — The worktree directory is deleted and unlinked from the repository.
  2. Renames the branch — The session branch is renamed from acp-session/<session-id>-<session-title> to acp-session-deleted/<session-id>-<session-title>, preserving the commit history rather than deleting it.

If you need to recover work from a deleted session, the commits are still available on the renamed branch:

git log acp-session-deleted/<session-id>-<session-title>

Deleting an archived session also purges the acp-session-archived/<session-id> branch and the refs/braide/wip/<session-id> ref, so the session leaves no git artifacts behind. The same cleanup happens when the background pruner finalises an archived session — see Archive & Retention.

Relationship to the Project Root

The project root is the original directory you selected when creating the project. It is the main repository. Worktrees are separate working directories that share the same git history and object store, but each has its own branch and file state. Changes in a worktree do not appear in the project root (or any other worktree) until they are committed and merged.

Projects Without a Git Repository

Worktrees require a git repository at the project root. When you add a project whose root is a plain directory, worktree mode is not available.

What happens when you click "New Session" on a non-git project:

  1. The session is auto-promoted to project-root mode — the agent runs directly in the project root and the session is badged with the orange ROOT pill.
  2. The agent's working directory is the project root itself, so any files it writes land there.

The auto-promotion happens transparently — you do not need to choose a mode from the split button's menu.

What UI is suppressed on a non-git project:

  • The branch selector in the prompt toolbar is hidden (there are no branches to pick).
  • The merge, commit, and pull-request sidebar actions are disabled because there is no session branch with commits ahead of a base branch.
  • The diff panel remains empty because there is no git index to diff against.

Migrating from non-git to git: If you later initialise a git repository in the project root and create a new session, that new session will use worktree mode normally. Existing sessions created before the initialisation retain their project-root mode — the mode is chosen at creation time.