| Crates.io | urur |
| lib.rs | urur |
| version | 0.2.44 |
| created_at | 2026-01-04 22:02:44.155671+00 |
| updated_at | 2026-01-22 13:25:31.272501+00 |
| description | Multi-repo workspace manager - manage distributed Git repositories with a single config |
| homepage | https://github.com/rusenbb/urur |
| repository | https://github.com/rusenbb/urur |
| max_upload_size | |
| id | 2022595 |
| size | 1,266,599 |
A multi-repo workspace manager for developers who work across many distributed Git repositories.
If you work with multiple Git repositories spread across GitHub, GitLab, and other hosts, you know the pain of:
urur solves this with a single configuration file that manages all your repositories.
# Clone all your repos
urur clone
# Check status everywhere
urur status
# Pull everything
urur pull
# Run any command across repos
urur exec "git log -1 --oneline"
cargo install urur
git clone https://github.com/rusenbb/urur.git
cd urur
cargo install --path .
Download from the releases page.
# 1. Initialize a workspace
mkdir my-repos && cd my-repos
urur init --name "my-workspace"
# 2. Add repositories
urur add https://github.com/user/repo1.git --tag work
urur add git@github.com:user/repo2.git --tag personal
# 3. Clone everything
urur clone
# 4. Check status
urur status
urur uses a .urur.toml file for configuration:
[workspace]
name = "my-workspace"
description = "All my projects"
[defaults]
branch = "main"
shallow = false
parallel = 4
editor = "code" # Editor for 'open' command (code, nvim, zed, etc.)
[[repos]]
name = "project-a"
url = "git@github.com:user/project-a.git"
path = "work/project-a" # Custom directory structure
branch = "develop" # Override default branch
tags = ["work", "rust"]
[[repos]]
name = "project-b"
url = "git@github.com:user/project-b.git"
path = "personal/project-b"
tags = ["personal", "python"]
[groups]
work = ["project-a"]
all-rust = ["project-a"]
| Field | Description | Default |
|---|---|---|
name |
Unique identifier | Derived from URL |
url |
Git clone URL (HTTPS or SSH) | Required |
path |
Local directory path | Same as name |
branch |
Default branch | From defaults.branch |
tags |
Tags for filtering | [] |
shallow |
Shallow clone | false |
disabled |
Skip this repo | false |
urur init [--name NAME] # Initialize a new workspace
urur list [--json] # List all repositories
urur doctor # Health check for your workspace
# Add/remove repos
urur add <url> [--name NAME] [--path PATH] [--branch BRANCH] [--tag TAG...] [--clone]
urur remove <name> [--delete] # --delete removes local files too
# Clone
urur clone # Clone all repos
urur clone repo1 repo2 # Clone specific repos
urur clone --group work # Clone repos in a group
urur clone --tag rust # Clone repos with a tag
urur status # Show all repo statuses
urur status --dirty # Show only dirty repos
urur dirty # List repos with uncommitted changes
urur behind # List repos behind remote
urur diff # Show diff summary across repos
urur pull [--group GROUP] [--tag TAG] # Pull all repos
urur fetch [--group GROUP] # Fetch all repos
urur fetch-upstream [--group GROUP] # Fetch from upstream for forked repos
urur push [--group GROUP] [--tag TAG] # Push all repos
urur checkout <branch> # Checkout branch across repos
urur sync # Smart sync: stash, fetch, rebase, unstash
urur gc # Run git gc in all repos
# Stash operations
urur stash # Stash in all repos
urur stash push # Same as above
urur stash pop # Pop stash in all repos
urur stash list # List stashes in all repos
# Branch operations
urur branch list # Show current branch in all repos
urur branch create <name> # Create branch in all repos
urur branch delete <name> # Delete branch in all repos
urur exec <command> # Run in all repos
urur exec "npm install" --tag nodejs # Run in tagged repos
urur exec "cargo test" --group rust-projects
urur group list # List all groups
urur group create <name> [repos...] # Create a group
urur group add <name> <repo> # Add repo to group
urur group remove <name> <repo> # Remove repo from group
urur group delete <name> # Delete a group
urur remote list [repo] # List remotes for repo(s)
urur remote add <repo> <name> <url> # Add a remote (e.g., upstream)
urur remote remove <repo> <name> # Remove a remote
# Move a repository to a new path
urur move <name> <new-path> [--force]
# Import existing git repos from a directory
urur import [path] [--recursive] [--tag TAG] [--dry-run]
Focus on a single repository and use urur as a git alias:
# Select a repo (and optionally cd into it)
urur select project-a
# Or with automatic cd:
eval "$(urur select project-a --cd)"
# Now urur commands run on that repo
urur status # git status in project-a
urur log # git log in project-a
urur commit -m "..." # git commit in project-a
# Open in editor or browser
urur open # Opens in $EDITOR or 'code'
urur web # Opens remote URL in browser
# See what's selected
urur which
# Back to multi-repo mode (and optionally cd to workspace)
urur unselect
# Or with automatic cd:
eval "$(urur unselect --cd)"
For seamless cd on select/unselect, add to your .bashrc or .zshrc:
# Shell wrapper for urur select/unselect with automatic cd
urur() {
case "$1" in
select)
shift
eval "$(command urur select "$@" --cd)"
;;
unselect)
eval "$(command urur unselect --cd)"
;;
*)
command urur "$@"
;;
esac
}
# Alternative: simple cd helper
ucd() {
cd "$(urur cd)"
}
Generate shell completions:
# Bash
urur completions bash > ~/.local/share/bash-completion/completions/urur
# Zsh
urur completions zsh > ~/.zfunc/_urur
# Fish
urur completions fish > ~/.config/fish/completions/urur.fish
# PowerShell
urur completions powershell > ~\Documents\PowerShell\Modules\urur\urur.ps1
[[repos]]
name = "frontend"
url = "git@github.com:company/frontend.git"
path = "web/frontend"
tags = ["web", "typescript"]
[[repos]]
name = "backend"
url = "git@github.com:company/backend.git"
path = "api/backend"
tags = ["api", "rust"]
[[repos]]
name = "mobile"
url = "git@github.com:company/mobile.git"
path = "mobile/app"
tags = ["mobile", "react-native"]
[groups]
work = ["frontend", "backend", "mobile"]
personal = ["dotfiles", "blog", "side-project"]
# Pull only work repos
# urur pull --group work
# Status of personal projects
# urur status --group personal
[[repos]]
name = "auth-service"
url = "git@github.com:company/auth-service.git"
tags = ["service", "critical"]
[[repos]]
name = "user-service"
url = "git@github.com:company/user-service.git"
tags = ["service"]
[[repos]]
name = "payment-service"
url = "git@github.com:company/payment-service.git"
tags = ["service", "critical"]
# Run tests on all services
# urur exec "make test" --tag service
# Check critical services
# urur status --tag critical
| Feature | urur | git-repo | gita | myrepos |
|---|---|---|---|---|
| Config format | TOML | XML | YAML | Config file |
| Tags/Groups | Yes | Yes (projects) | Yes | No |
| Custom paths | Yes | Limited | No | Yes |
| Select mode | Yes | No | No | No |
| Interactive TUI | Yes | No | No | No |
| Cloud sync | Yes | No | No | No |
| Worktrees | Yes | No | No | No |
| Shell completions | Yes | Yes | Yes | No |
| Written in | Rust | Python | Python | Perl |
Contributions are welcome! Please feel free to submit a Pull Request.
git checkout -b feature/amazing-feature)git commit -m 'Add some amazing feature')git push origin feature/amazing-feature)This project is licensed under the MIT License - see the LICENSE file for details.
Launch an interactive dashboard to view and manage all repositories:
urur tui
TUI Features:
t to toggle)a key)i key)m, R keys)/ key)? key)Sync your workspace config to a git repository (like your dotfiles):
# Initialize cloud sync
urur cloud init git@github.com:user/dotfiles.git
# Push config changes to cloud
urur cloud push
# Pull config from cloud
urur cloud pull
# Check sync status
urur cloud status
# Unlink cloud sync
urur cloud unlink
Manage git worktrees across your repositories:
# Add a worktree for a feature branch
urur worktree add my-repo feature-branch
# List worktrees
urur worktree list my-repo
# Remove a worktree
urur worktree remove my-repo feature-branch
Bulk import repositories from your GitHub or GitLab account:
# Import all your GitHub repos
urur import-github myusername
# Import private repos too (requires GITHUB_TOKEN)
urur import-github myusername --private
# Filter by language
urur import-github myusername --language rust
# Import from GitLab
urur import-gitlab myusername
Set your preferred editor in the config:
[defaults]
editor = "nvim" # or "code", "zed", "vim", etc.
Priority: CLI arg > config > $EDITOR > $VISUAL > "code"
Define templates to quickly add repos with pre-configured settings:
[templates.rust]
shallow = true
tags = ["rust", "backend"]
path_prefix = "libs/"
post_clone = "cargo build"
groups = ["backend"]
[templates.node]
tags = ["javascript", "frontend"]
path_prefix = "web/"
post_clone = "npm install"
Use templates when adding repos:
# Add with template
urur add https://github.com/user/my-lib.git --template rust
# List available templates
urur template list
# Show template details
urur template show rust
Template settings (explicit CLI args override template values):
branch: Default branch to checkoutshallow: Whether to shallow clonetags: Tags to apply automaticallypath_prefix: Prefix for the local path (e.g., "libs/" → "libs/repo-name")post_clone: Command to run after cloninggroups: Groups to automatically add the repo toRun custom commands before/after operations:
[hooks]
strict = true # Abort on pre-hook failure
# Clone hooks
pre_clone = "echo 'Starting clone...'"
post_clone = "npm install"
# Pull hooks
pre_pull = "git stash"
post_pull = "git stash pop"
# Fetch hooks
pre_fetch = "echo 'Fetching...'"
post_fetch = "echo 'Fetch complete'"
# Sync hooks (for `urur sync` command)
pre_sync = "echo 'Starting sync...'"
post_sync = "echo 'Sync complete'"
Environment variables available in hooks:
URUR_REPO_NAME - Repository nameURUR_REPO_PATH - Repository local pathURUR_REPO_URL - Repository remote URLURUR_WORKSPACE_ROOT - Workspace root directorySearch for patterns across all repositories:
urur search "TODO"
urur search "function.*Error" --glob "*.ts"
urur reconcile commandSee the backlog for future plans.