https://github.com/epilande/repos
📦 Interactive CLI tool for managing multiple git repositories
https://github.com/epilande/repos
cli command-line devtools ink productivity tui
Last synced: 2 months ago
JSON representation
📦 Interactive CLI tool for managing multiple git repositories
- Host: GitHub
- URL: https://github.com/epilande/repos
- Owner: epilande
- License: mit
- Created: 2025-12-24T07:14:48.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-04-13T05:22:29.000Z (2 months ago)
- Last Synced: 2026-04-13T07:20:09.220Z (2 months ago)
- Topics: cli, command-line, devtools, ink, productivity, tui
- Language: TypeScript
- Homepage:
- Size: 204 KB
- Stars: 33
- Watchers: 0
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
Repos 📦
An interactive CLI tool for managing multiple git repositories.

## ❓ Why?
Managing hundreds of repositories across an organization is tedious. You constantly need to:
- Check which repos have uncommitted changes
- Pull the latest updates across all projects
- Clone new repos that have been created
- Clean up experimental branches and changes
**`repos`** solves this by providing a CLI to manage all your repositories with a terminal UI, parallel operations, and GitHub integration.
## ✨ Features
- 🎯 **Interactive Mode**: Run `repos` without arguments for a menu-driven TUI experience
- 🔀 **Git-like Commands**: Familiar commands (`fetch`, `pull`, `diff`, `checkout`) work across all repos
- 📊 **Terminal UI**: Progress bars, tables, spinners, and colored output
- ⚡ **Parallel Operations**: Fast updates with configurable concurrency
- 🐙 **GitHub Integration**: Clone repos from any GitHub org (Cloud or Enterprise)
- 🔧 **Smart Defaults**: Detects `gh` CLI config and respects `.gitignore` patterns
- 📁 **Config File Support**: Save your settings in `.reposrc.json`
- 🛠️ **Escape Hatch**: Run any command across repos with `repos exec`
## 📦 Installation
### Homebrew
```sh
brew install epilande/tap/repos
```
### Binary Download
Download the pre-built binary for your platform from [Releases](https://github.com/epilande/repos/releases/latest):
```sh
# 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/
```
### Build from Source
```sh
git clone https://github.com/epilande/repos.git
cd repos
bun install
bun run build
```
### Development Setup
```sh
git clone https://github.com/epilande/repos.git
cd repos
bun install
bun link # Link globally for development
```
## 🚀 Quick Start
1. Run the setup wizard to configure your GitHub org:
```sh
repos init
```
2. Check the status of all repos in your current directory:
```sh
repos status
```
3. Pull the latest changes across all repos:
```sh
repos pull
```
4. Clone all active repos from your organization:
```sh
repos clone --org my-org
```
## 🎮 Usage
### Interactive Mode
Run `repos` without any arguments to launch the interactive menu:
```sh
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 |
### Commands
| 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 ` | Switch branches across all repos |
| `repos clone` | Clone repos from GitHub org |
| `repos clean` | Revert changes in repositories |
| `repos exec ""` | Run arbitrary command across all repos |
| `repos config` | View or modify configuration |
### Status Command
```sh
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
```
### Fetch Command
```sh
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
```
### Pull Command
```sh
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]
> Repos with uncommitted changes are automatically skipped to protect your work.
### Clone Command
```sh
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 --dry-run # Preview what would be cloned
```
### Diff Command
```sh
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
```
### Checkout Command
```sh
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 `--force` is used.
### Clean Command
```sh
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-run` first!
### Exec Command
```sh
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 exec` as an escape hatch for any command not directly supported.
### Config Command
```sh
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
```
## ⚙️ Configuration
Create `.reposrc.json` in your project directory or home folder:
```json
{
"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
```json
{
"github": {
"host": "github.mycompany.com",
"apiUrl": "https://github.mycompany.com/api/v3"
},
"org": "my-team"
}
```
### Configuration Priority
1. **CLI flags** (highest) — `--org`, `--parallel`, etc.
2. **Project config** — `.reposrc.json` in current directory
3. **User config** — `~/.reposrc.json`
4. **gh CLI** — Detected from `~/.config/gh/hosts.yml`
5. **Defaults** (lowest)
## 🔐 Authentication
For `repos clone`, authentication is required. The tool checks these sources:
1. **gh CLI** — If you have `gh` installed and authenticated (`gh auth login`)
2. **Environment variables** — `GITHUB_TOKEN` or `GH_TOKEN`
3. **Interactive prompt** — Runs setup wizard if no auth found
## 🔧 Development
```sh
# 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
```