An interactive CLI tool for managing multiple git repositories.
Managing hundreds of repositories across an organization is tedious. You constantly need to:
repos solves this by providing a CLI to manage all your repositories with a terminal UI, parallel operations, and GitHub integration.
repos without arguments for a menu-driven TUI experiencefetch, pull, diff, checkout) work across all reposgh CLI config and respects .gitignore patterns.reposrc.jsonrepos execbrew install epilande/tap/repos
Download the pre-built binary for your platform from Releases:
# macOS Apple Silicon
curl -L https://github.com/epilande/repos/releases/latest/download/repos-macos-arm64 -o repos
chmod +x repos
sudo mv repos /usr/local/bin/
git clone https://github.com/epilande/repos.git
cd repos
bun install
bun run build
git clone https://github.com/epilande/repos.git
cd repos
bun install
bun link # Link globally for development
sh
repos init
sh
repos status
sh
repos pull
sh
repos clone --org my-org
Run repos without any arguments to launch the interactive menu:
repos
Keyboard shortcuts:
| Key | Action |
|-----|--------|
| ↑↓ / jk | Navigate menu |
| Enter | Select command |
| s,f,p,d,c | Jump to git commands (Status, Fetch, Pull, Diff, Checkout) |
| o,x,e | Jump to repo commands (Clone, Clean, Exec) |
| g,i | Jump to settings (Config, Init) |
| q | Quit |
| Command | Description |
|---|---|
repos |
Launch interactive menu |
repos init |
Setup wizard for configuration |
repos status |
Check status of all repositories |
repos fetch |
Fetch latest changes from remotes |
repos pull |
Pull latest changes for all repos |
repos diff |
Show diffs across all repositories |
repos checkout <branch> |
Switch branches across all repos |
repos clone |
Clone repos from GitHub org |
repos clean |
Revert changes in repositories |
repos exec "<command>" |
Run arbitrary command across all repos |
repos config |
View or modify configuration |
repos status # Full table output
repos status --fetch # Fetch from remotes first
repos status --summary # Just show counts
repos status --quiet # Only show repos with changes
repos status --filter 'api-*' # Filter by pattern
Example output:
Repository Branch Modified Staged Untracked Sync
──────────────────────────────────────────────────────────────────────
✓ webapp main 0 0 0 ✓
● api-server main 2 0 1 ↓32
✓ auth-service feature/oauth 0 0 0 ↑3
repos fetch # Fetch all repos
repos fetch --prune # Remove stale remote-tracking refs
repos fetch --all # Fetch from all remotes
repos fetch --dry-run # Preview what would be fetched
repos fetch --filter 'api-*' # Fetch only matching repos
repos pull # Pull all repos
repos pull --dry-run # Preview what would be updated
repos pull --quiet # Minimal output
repos pull --parallel 5 # Limit concurrent operations
repos pull --filter 'api-*' # Pull only matching repos
[!NOTE] Pull uses
git pull --ff-only, so dirty repos are pulled too as long as the incoming changes do not overlap your modified files. Diverged branches (local commits + remote commits) are reported as errors instead of being silently merged. Repos without an upstream are skipped.
repos clone --org my-org # Clone from organization
repos clone --org my-username # Clone from user account
repos clone --host github.abc.com # Clone from GitHub Enterprise
repos clone --days 30 # Only repos active in last 30 days
repos clone --parallel 5 # Limit concurrent clone operations
repos clone --shallow # Shallow clone (faster)
repos clone --skip-existing # Only clone new repos; don't pull existing ones
repos clone --dry-run # Preview what would be cloned
[!NOTE] By default, clone pulls repos that already exist locally (and clones the rest). Pass
--skip-existingto clone only new repos and leave existing ones untouched.
repos diff # Show diffs (default: 500 lines per repo)
repos diff --max-lines 100 # Limit output to 100 lines per repo
repos diff --max-lines 0 # Show full diff (no limit)
repos diff --stat # Show diffstat summary
repos diff --quiet # Only list repos with changes
repos diff --parallel 5 # Limit concurrent operations
repos diff --filter 'api-*' # Diff only matching repos
repos checkout main # Switch to 'main' branch
repos checkout -b feature/new # Create and switch to new branch
repos checkout main --force # Skip repos with uncommitted changes
repos checkout main --parallel 5 # Limit concurrent operations
repos checkout main --filter '*' # Checkout only matching repos
[!NOTE] Repos with uncommitted changes are skipped unless
--forceis used.
repos clean --dry-run # Preview what would be cleaned
repos clean # Revert tracked file changes
repos clean --all # Also remove untracked files
repos clean --force # Skip confirmation prompt
repos clean --filter 'api-*' # Clean only matching repos
[!WARNING] The clean command will revert changes. Always use
--dry-runfirst!
repos exec "git log -1 --oneline" # Show last commit in each repo
repos exec "npm install" # Run npm install in all repos
repos exec "pwd" --quiet # Only show repos with output
repos exec "make test" --parallel 5 # Run with limited concurrency
repos exec "git branch" --filter 'api-*' # Run only in matching repos
[!TIP] Use
repos execas an escape hatch for any command not directly supported.
repos config # List all config values
repos config --list # List all config values
repos config --get org # Get a specific config value
repos config --set org --value my-org # Set a config value
repos config --location home # Use home directory config file
Create .reposrc.json in your project directory or home folder:
{
"github": {
"host": "github.com",
"apiUrl": "https://api.github.com"
},
"org": "my-org",
"daysThreshold": 90,
"parallel": 10,
"timeout": 30000,
"diffMaxLines": 500
}
| Option | Default | Description |
|---|---|---|
github.host |
github.com |
GitHub host (for Enterprise) |
github.apiUrl |
https://api.github.com |
GitHub API URL |
org |
- | Default organization to clone from |
daysThreshold |
90 |
Only clone repos active within N days |
parallel |
10 |
Number of concurrent operations |
timeout |
30000 |
Network timeout in milliseconds |
diffMaxLines |
500 |
Max lines per diff (0 for unlimited) |
GitHub Enterprise Configuration
{
"github": {
"host": "github.mycompany.com",
"apiUrl": "https://github.mycompany.com/api/v3"
},
"org": "my-team"
}
--org, --parallel, etc..reposrc.json in current directory~/.reposrc.json~/.config/gh/hosts.ymlFor repos clone, authentication is required. The tool checks these sources:
gh installed and authenticated (gh auth login)GITHUB_TOKEN or GH_TOKEN# Install dependencies
bun install
# Run in development
bun run src/index.ts status
# Type check
bun run typecheck
# Build binary
bun run build
# Cross-compile for all platforms
bun run build:all
Project Structure
repos/
├── src/
│ ├── index.ts # CLI entry point
│ ├── types.ts # TypeScript interfaces
│ ├── commands/ # Command implementations
│ ├── components/ # Reusable Ink components
│ └── lib/ # Core logic
├── bin/repos # Dev wrapper script
└── package.json
$ claude mcp add repos \
-- python -m otcore.mcp_server <graph>