multirepo
Manage many git repositories from one .code-workspace file —
clone them, keep them in sync, and jump between them by name.
One small Rust binary does the work. A thin shell shim (zsh, bash, fish)
wires it into your shell, so cd-ing into a workspace just works.
Install
Download a prebuilt binary and the shell shims:
curl -fsSL https://github.com/releasetools/multirepo/raw/main/install.sh | sh
Or build from a checkout with ./install.sh --local. The installer
offers to wire the shim into your shell rc; if you decline, add the line
yourself:
# zsh — add to ~/.zshrc
[ -f "$HOME/.local/share/multirepo/multirepo.plugin.zsh" ] && . "$HOME/.local/share/multirepo/multirepo.plugin.zsh"
# bash — add to ~/.bashrc
[ -f "$HOME/.local/share/multirepo/multirepo.plugin.bash" ] && . "$HOME/.local/share/multirepo/multirepo.plugin.bash"
# fish — add to ~/.config/fish/config.fish
test -f "$HOME/.local/share/multirepo/conf.d/multirepo.fish"; and source "$HOME/.local/share/multirepo/conf.d/multirepo.fish" Quickstart
A workspace is any directory with a *.code-workspace file. Add a
multirepo block that lists your repos — each one says where it
comes from (git, github, or gitlab),
where it lives on disk, and whether it's enabled:
{
"folders": [
{ "path": "api" },
{ "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 }
}
}
}
Already have the repos checked out? multirepo workspace create
writes that file for you — it scans a directory, reads each repo's
origin remote, and lists them with the right source.
Then let multirepo set it up and move you in:
# in the directory holding your-project.code-workspace
multirepo sync # clone the repos and drop you in
@api # jump into the api repo by name
multirepo status # git state across every repo
multirepo focus # pick which repos AI tools and the editor see
Run multirepo sync ./other.code-workspace with a file to set up a
fresh copy somewhere new; run multirepo sync with no file to
reconcile the workspace you're already in. multirepo sync --all
reconciles every registered workspace's repos in place — no activation or
cd, you stay where you are.
Cloned a repo into the workspace by hand? multirepo focus spots
it and offers to adopt it, or run multirepo focus --add <dir>
to add it straight away — the source is read from its origin.
Done with a repo? multirepo focus --rm <dir> drops it from
the workspace and leaves the clone on disk.
What it does
Everything lives in the .code-workspace file, so there's no
separate config to keep in sync.
-
A workspace is just its
.code-workspacefile; a machine-local registry only remembers where each one lives. -
Enabled state drives
.claudeignore,.geminiignore, and the workspace'sfolderslist, so a disabled repo drops out of both the editor's Explorer and what AI tools see. -
cdinto a workspace and it activates;@<repo>jumps into any repo by name. - A feature is a named subset of repos, each checked out as a git worktree, so you can work across several repos in isolation. The everyday commands act on whichever you're in — the main checkouts in a workspace, the worktrees inside a feature — and teardown never drops uncommitted or unmerged work.
- Every command is idempotent. Reconcile fast-forwards or rebases only where the tree is clean, and never touches dirty or unpushed work.
-
A shared
.code-workspaceis read as untrusted input, so a stray entry can't inject a git option or escape the workspace directory. - Clones, fetches, and status run in parallel with a live progress row each, and a cooperative lock keeps two runs from colliding on the same repo.
-
Repos clone from a
gitURL, GitHub viagh, or GitLab.
The commands:
| Command | What it does |
|---|---|
workspace create [dir] | Scaffold a .code-workspace from the git repos already in a directory, inferring each one's source from its origin remote. Alias ws. |
sync [file] | Set up a workspace, or reconcile the current one: clone missing repos, fast-forward what's behind, rebase what diverged, leave dirty repos alone. --all reconciles every registered workspace in place. |
status | Show git state across every repo. -o table for a columnar view, -a for every workspace. Reads local state, so it's fast and offline. |
focus | Pick which repos are enabled, and adopt (--add <dir>, or the picker) or drop (--rm <dir>) repos. Enabled state drives .claudeignore, .geminiignore, and the workspace's folders list (a disabled repo is hidden from the editor and AI tools). |
@<repo> | Change into a repo's directory by name. |
feature create <name> [repos…] | Spin up a feature: a named subset of repos, each checked out as a git worktree on a shared feature/<name> branch under .multirepo/feature/<name>/, with its own .code-workspace to open. Inside it, status/sync/focus/… act on the feature's worktrees. Alias feat. |
feature rm <name> | Tear a feature down: removes its worktrees after flagging any dirty, unpushed, or unmerged work (refuses without --force), and keeps the branches. |
select [name] | Switch workspace. With a name, jump straight there. With no args, one screen over every workspace: ←/→ switch workspace, ↑/↓ + space toggle its repos; enter saves every workspace you changed and moves you into the highlighted one. (To enter a feature, cd into its dir.) |
workspace ls | List every workspace on the machine. -a nests each one's repos and features; --prune drops entries whose files are gone. Alias ws. |
prune / reset | Drop branches whose upstream is gone; bring clean repos back to their main branch. |
lock | Show the cooperative per-repo locks across the workspace: what's free, what's held, and whether each hold is alive or stale. |
workspace rm [names…] | Unregister a workspace from the registry (files on disk stay put). Alias ws. |
New here? The guide walks through the common tasks. See the changelog for what's new, or the repository for the full spec.