urur 0.2.21

Multi-repo workspace manager - manage distributed Git repositories with a single config
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
# urur

A multi-repo workspace manager for developers who work across many distributed Git repositories.

[![Crates.io](https://img.shields.io/crates/v/urur.svg)](https://crates.io/crates/urur)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

## Why urur?

If you work with multiple Git repositories spread across GitHub, GitLab, and other hosts, you know the pain of:

- Cloning repos one by one
- Checking status of 10+ repos manually
- Running the same command in each repo
- Remembering which repos need to be pulled

**urur** solves this with a single configuration file that manages all your repositories.

```bash
# 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"
```

## Installation

### From crates.io

```bash
cargo install urur
```

### From source

```bash
git clone https://github.com/rusenbb/urur.git
cd urur
cargo install --path .
```

### Pre-built binaries

Download from the [releases page](https://github.com/rusenbb/urur/releases).

## Quick Start

```bash
# 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
```

## Configuration

urur uses a `.urur.toml` file for configuration:

```toml
[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"]
```

### Repository Options

| 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` |

## Commands

### Workspace Management

```bash
urur init [--name NAME]     # Initialize a new workspace
urur list [--json]          # List all repositories
urur doctor                 # Health check for your workspace
```

### Repository Operations

```bash
# 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
```

### Status and Sync

```bash
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
```

### Git Operations

```bash
urur pull [--group GROUP] [--tag TAG]      # Pull all repos
urur fetch [--group GROUP]                  # Fetch all 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 and Branch

```bash
# 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
```

### Execute Commands

```bash
urur exec <command>                         # Run in all repos
urur exec "npm install" --tag nodejs        # Run in tagged repos
urur exec "cargo test" --group rust-projects
```

### Group Management

```bash
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
```

## Select Mode

Focus on a single repository and use urur as a git alias:

```bash
# 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)"
```

### Shell Integration

For seamless `cd` on select/unselect, add to your `.bashrc` or `.zshrc`:

```bash
# 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)"
}
```

## Shell Completions

Generate shell completions:

```bash
# 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
```

## Examples

### Organize by Project Type

```toml
[[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"]
```

### Work vs Personal

```toml
[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
```

### Microservices

```toml
[[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
```

## Comparison with Other Tools

| 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 |

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## New Features

### Interactive TUI

Launch an interactive dashboard to view and manage all repositories:

```bash
urur tui
```

**TUI Features:**
- Tree or list view of all repos (`t` to toggle)
- Real-time status (branch, dirty, ahead/behind)
- Bulk operations on selected repos
- Add repos directly (`a` key)
- Import from GitHub/GitLab (`i` key)
- Move and rename repos (`m`, `R` keys)
- Search/filter repos (`/` key)
- Comprehensive help (`?` key)

### Cloud Sync

Sync your workspace config to a git repository (like your dotfiles):

```bash
# 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
```

### Worktree Management

Manage git worktrees across your repositories:

```bash
# 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
```

### Import from GitHub/GitLab

Bulk import repositories from your GitHub or GitLab account:

```bash
# 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
```

### Configurable Editor

Set your preferred editor in the config:

```toml
[defaults]
editor = "nvim"  # or "code", "zed", "vim", etc.
```

Priority: CLI arg > config > `$EDITOR` > `$VISUAL` > `"code"`

### Repository Templates

Define templates to quickly add repos with pre-configured settings:

```toml
[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:

```bash
# 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 checkout
- `shallow`: Whether to shallow clone
- `tags`: Tags to apply automatically
- `path_prefix`: Prefix for the local path (e.g., "libs/" → "libs/repo-name")
- `post_clone`: Command to run after cloning
- `groups`: Groups to automatically add the repo to

### Hooks

Run custom commands before/after operations:

```toml
[hooks]
strict = true  # Abort on pre-hook failure
pre_clone = "echo 'Starting clone...'"
post_clone = "npm install"
pre_pull = "git stash"
post_pull = "git stash pop"
```

### Search Across Repos

Search for patterns across all repositories:

```bash
urur search "TODO"
urur search "function.*Error" --glob "*.ts"
```

## Roadmap

- [x] Core workspace management
- [x] Group and tag filtering
- [x] Select mode for single-repo focus
- [x] Shell completions
- [x] Progress bars during operations
- [x] Interactive TUI mode
- [x] GitHub/GitLab import
- [x] Hooks system
- [x] Search across repos
- [x] Parallel operations
- [x] Cloud config sync
- [x] Worktree management
- [x] Configurable editor
- [x] TUI add/import modals
- [x] Repository templates
- [ ] Workspace snapshots
- [ ] Plugin system

See the [backlog](.project_docs/backlog.md) for future plans.