Automatic Git worktree sync · TUI · MCP server

Keep every branch checked out. For you and your AI agents.

sync-worktrees turns every Git branch, in every repo, into a folder on disk — auto-synced with the remote. cd instead of stashing, grep -r across repos, and your AI agents see the whole workspace over MCP.

Git history is stored once and shared — each extra branch costs only its working files, not another clone.

1 Just a config
repositories: [
  {
    name: "frontend",
    repoUrl: "github.com/acme/frontend",
  },
  {
    name: "backend",
    repoUrl: "github.com/acme/backend",
  },
];

Declare your repos and branches once. Commit the file — every teammate and every new machine rebuilds the exact same workspace.

$ sync-worktrees
bootstrapping — in seconds
cloned frontend
frontend/main
frontend/feature-login
cloned backend
backend/main
backend/release-2.4
worktrees/
├─ frontend/
│  ├─ main
│  └─ feature-login
└─ backend/
   ├─ main
   └─ release-2.4
↳ MCP exposes this workspace to agents
workspace ready
Get started
$ npm install -g sync-worktrees Works with AI agents via MCP →
The problem

Stash. Switch. Re-explain. Repeat.

Every live branch across repos becomes another context switch — for you and your agent.

Without sync-worktrees
  • Stash half-finished work to glance at another branch
  • Hunt for where you cloned that sibling repo last month
  • Switch branches in five repos for one cross-cutting feature
  • Re-explain to Claude or Cursor which directory holds which branch
  • Onboard new hires through a brittle copy-paste setup doc
With sync-worktrees
  • Clean branches fast-forward themselves on a schedule — no manual git fetch
  • Switching branches becomes cd
  • Every repo at a predictable path, declared once in config
  • Multi-repo search is one grep -r across the workspace
  • AI agents call detect_context and see every repo at once
  • New machine: one config, one command, the whole workspace appears
The solution

Declare the workspace once. Get every selected branch at a stable path.

One config. It clones what's missing, makes a worktree per selected branch, and keeps each at a predictable path.

Git objects are stored once in .bare/; force-push survivors move to .diverged/ instead of being overwritten.

cfg

Create sync-worktrees.config.js

The config decides which repo branches get a folder.

// sync-worktrees.config.js

/** @satisfies {import("sync-worktrees").SyncWorktreesConfig} */
const config = {
  defaults: {
    branchInclude: ["main", "feature/*", "release-*"],
    branchExclude: ["wip-*", "tmp-*"],
  },
  repositories: [
    {
      name: "frontend",
      repoUrl: "[email protected]:company/frontend.git",
      worktreeDir: "./worktrees/frontend",
    },
    {
      name: "backend",
      repoUrl: "[email protected]:company/backend.git",
      worktreeDir: "./worktrees/backend",
      branchMaxAge: "6m",
    },
  ],
};

export default config;
Why this removes the tax

Selected branches only

Keep main, feature, and release branches while excluding wip branches or stale branches by age.

Stable paths for humans

Jump straight to ./worktrees/frontend/feature-login instead of checking out and stashing.

Same map for agents

AI tools can discover the configured workspace instead of asking where sibling repos live.

Worktree mode

Every remote branch gets its own directory, all sharing one .git database. Disk usage scales with working-tree size, not branch count.

Clone mode

When one checkout is enough, get a single branch checked out at a fixed path — no .bare/, no per-branch subfolders. First-class alternative for dependency siblings.

MCP server

Ships sync-worktrees-mcp as a second binary. AI agents call tools like detect_context, list_worktrees, create_worktree, sync, and update_worktree over stdio.

Interactive TUI

Ink-based terminal UI with wizards for opening worktrees in editor or terminal, creating branches, and inspecting multi-repo status.

Smart filtering

Glob include/exclude, age-based pruning, sparse checkout for monorepos, per-repo overrides. Keep huge repos manageable.

Safety by default

By default it won't touch your work: sync and removal refuse worktrees with uncommitted changes, unpushed commits, stashes, or in-progress operations, and force-pushed history is moved aside into .diverged/ rather than overwritten.

Quick start

Three commands to a synced workspace.

  1. 1

    Install

    Global npm install. Node 22+, macOS or Linux.

    terminal
    npm install -g sync-worktrees
  2. 2

    Run the init wizard

    Writes sync-worktrees.config.js where you run it. Add more repos later.

    terminal
    cd ~/projects/my-sync-dir
    sync-worktrees init
  3. 3

    Launch the TUI — or sync once

    Bare command = interactive UI + cron. --runOnce for CI.

    terminal
    sync-worktrees                # interactive TUI + cron
    sync-worktrees --runOnce      # one-shot
AI agents

Your workspace, exposed over MCP.

A second binary, sync-worktrees-mcp, speaks MCP over stdio. Wire it into any client; your agent lists, creates, inspects, and syncs worktrees directly.

Prerequisite: a loaded sync-worktrees config, or running from a managed worktree.

Use the Claude Code CLI. Append -e SYNC_WORKTREES_CONFIG=... to point at a config.

claude mcp add sync-worktrees -- npx -y -p sync-worktrees sync-worktrees-mcp
Example workflow

Fix backend/release-2.4 from frontend/main.

You're in worktrees/frontend/main. You tell the agent: "inspect backend/release-2.4, branch a fix, and sync it." It chains the tools itself:

  1. 1detect_context — finds the configured backend repo, no path hunting
  2. 2get_worktree_status — reads release-2.4
  3. 3create_worktree — branches the fix
  4. 4sync — fetches, creates, prunes

No "where's the other repo?" — detect_context returns every configured repo and worktree, each with a { available, reason } capability flag.

  • detect_context Resolve the workspace from any path. Can include every configured repo and worktree, plus per-capability { available, reason } flags so the agent knows what it can actually call.
  • list_worktrees Status-labelled list (clean / dirty / stale / current), divergence, safeToRemove, last sync. Cross-repo when no repoName is supplied.
  • get_worktree_status Per-worktree detail: dirty files, unpushed commits, stashes, operation in progress.
  • create_worktree Create a worktree for a branch. When creating a new branch, optionally branch from baseBranch and publish with --no-track + push -u.
  • sync Full sync cycle: fetch, create, prune, update. Streams progress notifications.
  • update_worktree Fast-forward one worktree to match upstream.
When not to use it

Skip it for simple Git setups.

sync-worktrees earns its keep across many branches and repos. Skip it if:

  • Solo on your own repos, no collaboration

    Branches don't change underneath you, so auto-sync buys little — and a small workspace rarely needs a bootstrapping config.

  • One repo, one branch you ever touch

    Plain git worktree, or a single clone, is enough.

  • Tiny repos where re-cloning is instant

    The disk and bookkeeping savings don't matter.

  • You don't want many persistent branch directories

    sync-worktrees keeps a folder per branch on disk by design.

FAQ

Common questions

What's the difference between git worktree and sync-worktrees?

git worktree is the underlying Git primitive: a single command that adds one extra working directory backed by a shared .git database (it works with any repo, bare or not). sync-worktrees is a workspace orchestrator built on top of it — in worktree mode it sets up a bare repo, creates a directory for every selected remote branch automatically, prunes them when branches are deleted upstream, and keeps the whole thing fresh on a cron schedule. It also ships an interactive TUI and an MCP server so AI agents can navigate and operate the workspace.

Worktrees share the object database for free, so the bare repo is not a redundant reference store — it is simply the layout that lets every branch (the default included) be a peer directory instead of one privileged checkout. What sync-worktrees adds is the bookkeeping around that primitive — mirroring the remote, pruning deleted branches, fast-forwarding clean trees on a schedule, across many repos from one config — not the worktrees themselves.

One caveat worth naming: this shared store covers the repository’s own objects only. Submodules keep Git’s normal per-worktree behavior, so each worktree maintains its own submodule checkout rather than sharing one across worktrees.

Why use this instead of cloning each branch separately?

Cloning duplicates the entire Git object database for every branch — wasteful on disk and slow to refresh. Worktrees share one .git directory among many checkouts, so disk usage scales with working-tree size, not with branch count. sync-worktrees automates the bookkeeping you’d otherwise have to do manually (creating worktrees for new remote branches, removing stale ones, handling force-pushes safely).

How does the MCP server help AI coding agents?

The bundled sync-worktrees-mcp binary exposes its tools over MCP (stdio). detect_context, list_worktrees, create_worktree, and sync let an agent discover every configured sibling repo and worktree in one detect_context call, so “go look in the other repo” works without manual re-orientation.

Does it work with monorepos?

Yes. Per-repo branch include/exclude globs and sparse-checkout support let you scope each worktree to the slice of the monorepo you actually care about. Combined with branchMaxAge to ignore stale branches, this keeps multi-million-line monorepos manageable on disk.

What happens when a branch is force-pushed or deleted upstream?

Force-pushes are detected and the divergent working copy is moved aside into a .diverged/ directory rather than overwritten — uncommitted work is never silently lost. Deleted branches have their worktrees removed only if they are clean, with no unpushed commits, no stashes, and no operation in progress; anything else is preserved and surfaced in the TUI’s status view.

Can I run it continuously or on a cron?

Yes. The default invocation launches the interactive TUI and syncs continuously based on the cronSchedule field in your config (per-repo overrides are supported). For one-shot or scripted use, pass --runOnce. For CI pipelines, point --config at your workspace config and the same one-shot path applies.

Is it safe with uncommitted work?

Yes. Sync operations never merge or rebase your working copies. They fetch, create missing worktrees, fast-forward eligible existing worktrees, and prune only when the safety checks pass. Worktree removal refuses on dirty trees, unpushed commits, stashes, or in-progress operations (merge/rebase/cherry-pick/revert/bisect). Newly created branches are pushed with explicit --no-track so they don’t inherit origin/main as upstream by accident.

Every branch, checked out and current. From one config.

Point it at your repos. Stop paying the branch-switching tax.

$ npm install -g sync-worktrees