multirepo

A hands-on guide to multirepo

multirepo manages a set of git repositories as one workspace, described by a single .code-workspace file. It clones and updates them, lets you jump between them by name, and keeps .claudeignore / .geminiignore in step so AI tools only see the repos you want.

This guide walks through the things you’ll actually do, in the order you’ll hit them. For install, see the README; for the full behavior and the file format, see plan.md.

You already have the repos cloned

Use this when a directory already holds several git checkouts and you want to manage them together.

cd ~/code/myproject        # holds api/, web/, infra/ — each a git clone
multirepo new              # writes ~/code/myproject/myproject.code-workspace

new scans the directory, reads each repo’s origin remote, and writes a workspace file listing them. It works out the source from the remote itself — a github.com repo becomes a github source when gh is set up, a gitlab.com repo a gitlab source, anything else a plain git source with the exact URL. Non-git folders are skipped with a note, and so are repos with no origin.

By default it opens a picker with everything checked, so you can drop a repo before writing. To take all of them without prompting:

multirepo new --all                 # or: multirepo new --yes
multirepo new ~/code/other out.code-workspace   # scan elsewhere, name the file

It only writes the file. Step into the directory (or run multirepo sync) to start using it.

Someone handed you a workspace file

Use this when you have a .code-workspace file and need the repos on disk.

multirepo sync ~/path/to/myproject.code-workspace

sync with a file sets up a fresh copy: it asks where to put it, clones every repo listed inside, and drops you into the new workspace. Pass -y to take the defaults without prompts.

Working in a workspace

Once you’re in a workspace directory, repos are reachable by name and a few commands cover the day-to-day:

@api                       # cd into the api repo
@web                       # cd into the web repo
multirepo status           # git state across every repo, at a glance
multirepo sync             # with no file: reconcile — fetch, fast-forward,
                           # rebase what diverged, leave dirty repos alone

status reads local git state only, so it’s fast and works offline. sync is the one that touches the network. Both are safe to run as often as you like.

Choose what AI tools see

Use this when you want to hide some repos from Claude, Gemini, or the editor’s file tree without deleting anything.

multirepo config           # pick the enabled repos in a checklist

Enabled state is the single source of truth. From it, multirepo regenerates .claudeignore, .geminiignore, and the editor’s files.exclude — a disabled repo disappears from all of them at once. For scripts, skip the picker:

multirepo config --disable infra
multirepo config --enable infra,web
multirepo config --set api,web        # set the enabled list exactly

Keep the repos current

multirepo sync             # fetch + fast-forward/rebase where it's safe
multirepo reset            # clean repos back to their main branch, then pull
multirepo prune            # delete local branches whose upstream is gone

None of these touch a dirty or ahead repo — they never throw away work.

Juggle several workspaces

multirepo remembers every workspace you’ve set up on this machine.

multirepo ls               # list them (the current one is marked)
multirepo select           # switch to another (type to filter, enter to jump)
multirepo rm               # unregister one — the files on disk stay put

The .code-workspace file

Everything lives in one file, so there’s no separate config to keep in sync. It’s a normal VSCode .code-workspace with one extra multirepo block:

{
  "folders": [
    { "name": "api", "path": "api" },
    { "name": "web", "path": "web" }
  ],
  "multirepo": {
    "version": 1,
    "repositories": {
      "api": { "source": "github", "repo": "your-org/api", "path": "api", "enabled": true },
      "web": { "source": "git",    "url": "git@github.com:your-org/web.git", "path": "web", "enabled": true }
    }
  }
}

multirepo new writes this for you from repos you already have; you can also hand-write it and run multirepo sync <file>. The full schema — sources, aliases, the derived files, and the shell eval contract — is in plan.md.