A lazygit-inspired TUI for managing multiple git repositories.
Built with Rust, ratatui, and libgit2.
┌────────────────────────────────────────────────────────────────┐
│ [1 Repos] 2 Files 3 Branches 4 Commits 5 Stash workspace │
├───────────────────────┬────────────────────────────────────────┤
│ ┌ 1 Repos ──────────┐ │ │
│ │ ▸ repo-alpha ● Δ2 │ │ Preview │
│ │ repo-beta ● │ │ (context-sensitive) │
│ │ repo-gamma ↑1 │ │ │
│ └────────────────────┘ │ Repos → repo summary │
│ ┌ 2 Files ──────────┐ │ Files → syntax-highlighted diff │
│ │ ● M src/main.rs │ │ Branches → recent commits │
│ │ ○ A README.md │ │ Commits → commit diff │
│ └────────────────────┘ │ Stash → stash diff │
│ ┌ 3 Branches ───────┐ │ │
│ │ ● main origin/main │ │ │
│ │ feat/login [↑2] │ │ │
│ └────────────────────┘ │ │
│ ┌ 4 Commits ────────┐ │ │
│ │ abc1234 Fix bug 2m │ │ │
│ └────────────────────┘ │ │
│ ┌ 5 Stash ──────────┐ │ │
│ │ stash@{0}: WIP │ │ │
│ └────────────────────┘ │ │
├───────────────────────┴────────────────────────────────────────┤
│ j/k nav Tab panel 1-5 jump a stage c commit q quit │
└────────────────────────────────────────────────────────────────┘
| Category |
Features |
| Workspace |
Multi-repo view, workspace switching (w), repo hiding, search/filter (/), bulk mark (Space/Ctrl+a) |
| Files |
Stage (a), unstage (u), discard (x), per-file diff (d/Enter), open in editor (e), blame (b) |
| Branches |
Checkout (Enter), create (n), delete (D), rename (R), merge (m), auto-detect default branch |
| Commits |
Browse history, cherry-pick (C), revert (X), create tag (t), copy hash (y), commit diff preview |
| Stash |
Stash with message (s), pop (Enter), drop (x), browse stash diffs |
| Git ops |
Pull (p), push (P), fetch (f), commit (c), amend (A) — all non-blocking via rayon |
| UI |
5 stacked panels + context preview, mouse support, syntax-highlighted diffs, <50ms startup |
| Undo |
Ctrl+z reverses checkout and stash operations |
git clone https://github.com/monal94/gitool.git
cd gitool
cargo install --path .
gitool ~/Projects/my-workspace # open a workspace
gitool # current directory (single repo or workspace)
| Key |
Action |
Key |
Action |
1-5 |
Jump to panel |
Tab/BackTab |
Cycle panels |
q/Esc |
Quit |
r |
Refresh |
/ |
Filter |
` |
Command log |
w |
Switch workspace |
Ctrl+z |
Undo |
| Key |
Action |
Key |
Action |
j/k |
Navigate |
Enter |
Jump to Files |
p/P |
Pull / Push |
f |
Fetch |
Space |
Mark repo |
Ctrl+a/Ctrl+d |
Mark / Unmark all |
| Key |
Action |
Key |
Action |
a |
Stage |
u |
Unstage |
x |
Discard |
d/Enter |
View diff |
c |
Commit |
A |
Amend commit |
e |
Open in editor |
b |
Blame view |
| Key |
Action |
Key |
Action |
Enter |
Checkout |
n |
New branch |
D |
Delete |
R |
Rename |
m |
Merge |
s |
Stash |
| Key |
Action |
Key |
Action |
d/u |
Scroll preview |
y |
Copy hash |
C |
Cherry-pick |
X |
Revert |
t |
Create tag |
|
|
| Key |
Action |
Key |
Action |
s/Enter |
Pop stash |
x |
Drop stash |
Auto-created at ~/.config/ws/config.yaml:
workspaces:
sentry:
path: ~/Projects/sentry
hidden_repos: [docs]
defaults:
workspace: sentry
src/
├── main.rs # Event loop, key/mouse handlers
├── app/
│ ├── mod.rs # App struct, enums, core state
│ ├── navigation.rs # Panel switching, selection
│ ├── dispatch.rs # Async background operations
│ ├── git_ops.rs # Git action methods
│ ├── branch_ops.rs # Branch CRUD, text input
│ ├── state.rs # Refresh, workspace, load data
│ ├── watcher.rs # File system watching
│ └── undo.rs # Undo stack
├── git/
│ ├── mod.rs # Re-exports, test helpers
│ ├── scan.rs # Repo scanning, branch loading
│ ├── status.rs # File status via libgit2
│ ├── diff.rs # Diff generation via libgit2
│ ├── ops.rs # Git mutations (libgit2 + CLI)
│ └── log.rs # Commit log, blame, show files
├── config.rs # YAML workspace config
├── types.rs # Data models
├── highlight.rs # Syntect diff highlighting
└── ui/
├── mod.rs # Layout orchestrator
├── repo_list.rs # Repos panel
├── files.rs # Files panel
├── branches.rs # Branches panel
├── commits.rs # Commits panel
├── stash_panel.rs # Stash panel
├── preview.rs # Context preview (right)
├── diff.rs # Full-screen diff overlay
├── blame.rs # Blame overlay
├── command_log.rs # Command history overlay
├── confirm.rs # Confirmation dialog
└── modal.rs # Workspace switcher
Git reads use libgit2 directly (no subprocess). Mutations use rayon thread pool for non-blocking execution. Diffs are syntax-highlighted with windowed rendering (only visible lines processed). File watching auto-refreshes on .git changes with generation-counter caching.
ratatui | git2 | syntect | rayon | arboard | notify | crossterm | clap
MIT