{"id":45690812,"url":"https://github.com/affromero/gitpane","last_synced_at":"2026-03-02T15:00:37.846Z","repository":{"id":340361321,"uuid":"1165764217","full_name":"affromero/gitpane","owner":"affromero","description":"Multi-repo Git workspace dashboard for the terminal","archived":false,"fork":false,"pushed_at":"2026-02-28T13:03:57.000Z","size":10276,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-28T15:41:24.723Z","etag":null,"topics":["cli","dashboard","developer-tools","git","multi-repo","ratatui","rust","terminal","tui","worktree"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/affromero.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-24T14:18:46.000Z","updated_at":"2026-02-28T13:04:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/affromero/gitpane","commit_stats":null,"previous_names":["affromero/gitpane"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/affromero/gitpane","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/affromero%2Fgitpane","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/affromero%2Fgitpane/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/affromero%2Fgitpane/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/affromero%2Fgitpane/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/affromero","download_url":"https://codeload.github.com/affromero/gitpane/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/affromero%2Fgitpane/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29970543,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T13:32:00.443Z","status":"ssl_error","status_checked_at":"2026-03-01T13:32:00.084Z","response_time":124,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","dashboard","developer-tools","git","multi-repo","ratatui","rust","terminal","tui","worktree"],"created_at":"2026-02-24T17:03:10.863Z","updated_at":"2026-03-01T14:00:45.359Z","avatar_url":"https://github.com/affromero.png","language":"Rust","readme":"\u003cp align=\"center\"\u003e\n  \u003ch1 align=\"center\"\u003egitpane\u003c/h1\u003e\n  \u003cp align=\"center\"\u003e\n    \u003cstrong\u003eMulti-repo Git workspace dashboard for the terminal\u003c/strong\u003e\n  \u003c/p\u003e\n  \u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/affromero/gitpane/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/affromero/gitpane/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://crates.io/crates/gitpane\"\u003e\u003cimg src=\"https://img.shields.io/crates/v/gitpane.svg\" alt=\"crates.io\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/affromero/gitpane/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/affromero/gitpane?label=release\" alt=\"GitHub Release\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/affromero/gitpane/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License: MIT\"\u003e\u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/platform-linux%20%7C%20macos%20%7C%20windows-informational\" alt=\"Platform\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/languages/top/affromero/gitpane\" alt=\"Language\"\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n---\n\nMonitor **all your repos at a glance** — branch, dirty state, ahead/behind, active worktrees, changed files, and commit history — without leaving the terminal.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/demo.gif\" alt=\"gitpane demo\" width=\"800\"\u003e\n\u003c/p\u003e\n\n## Install\n\n```bash\ncargo install gitpane\n```\n\nThat's it. No cloning, no building from source. Runs on **Linux, macOS, and Windows**.\n\n\u003e **Don't have Rust?** Download a pre-built binary from [GitHub Releases](https://github.com/affromero/gitpane/releases/latest) — single static binary, zero dependencies.\n\u003e\n\u003e ```bash\n\u003e # macOS (Apple Silicon)\n\u003e curl -LO https://github.com/affromero/gitpane/releases/latest/download/gitpane-aarch64-apple-darwin.tar.gz\n\u003e tar xzf gitpane-aarch64-apple-darwin.tar.gz \u0026\u0026 sudo mv gitpane /usr/local/bin/\n\u003e\n\u003e # macOS (Intel)\n\u003e curl -LO https://github.com/affromero/gitpane/releases/latest/download/gitpane-x86_64-apple-darwin.tar.gz\n\u003e tar xzf gitpane-x86_64-apple-darwin.tar.gz \u0026\u0026 sudo mv gitpane /usr/local/bin/\n\u003e\n\u003e # Linux (x86_64, statically linked)\n\u003e curl -LO https://github.com/affromero/gitpane/releases/latest/download/gitpane-x86_64-unknown-linux-musl.tar.gz\n\u003e tar xzf gitpane-x86_64-unknown-linux-musl.tar.gz \u0026\u0026 sudo mv gitpane /usr/local/bin/\n\u003e\n\u003e # Linux (ARM64)\n\u003e curl -LO https://github.com/affromero/gitpane/releases/latest/download/gitpane-aarch64-unknown-linux-gnu.tar.gz\n\u003e tar xzf gitpane-aarch64-unknown-linux-gnu.tar.gz \u0026\u0026 sudo mv gitpane /usr/local/bin/\n\u003e ```\n\nThen run:\n\n```bash\ngitpane                     # Scans ~/Code by default\ngitpane --root ~/projects   # Scan a specific directory\n```\n\n## Update\n\n```bash\ncargo install gitpane       # Same command — overwrites the old binary\n```\n\nIf you installed from a [GitHub Release](https://github.com/affromero/gitpane/releases/latest), re-download the latest binary for your platform using the same commands from the install section above.\n\n## Why gitpane?\n\nIf you work across multiple repositories — microservices, monorepos with submodules, a mix of projects — you know the pain of `cd`-ing into each one to check status. Existing TUI tools focus on **one repo at a time**:\n\n| Tool | Multi-repo | Real-time watch | Worktrees | Mouse | Commit graph | Split diffs | Push/Pull |\n|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:|\n| **gitpane** | **Yes** | **Yes** | **Yes** | **Yes** | **Yes** | **Yes** | **Yes** |\n| [lazygit](https://github.com/jesseduffield/lazygit) | No | No | No | Yes | Yes | Yes | Yes |\n| [gitui](https://github.com/extrawurst/gitui) | No | No | No | Yes | Yes | Yes | Yes |\n| [tig](https://github.com/jonas/tig) | No | No | No | No | Yes | No | No |\n| [git-delta](https://github.com/dandavison/delta) | No | No | No | No | No | Yes (pager) | No |\n| [grv](https://github.com/rgburke/grv) | No | No | No | Yes | Yes | No | No |\n| [git-summary](https://github.com/MircoT/git-summary) | Yes (list only) | No | No | No | No | No | No |\n| [mgitstatus](https://github.com/fboender/multi-git-status) | Yes (list only) | No | No | No | No | No | No |\n| [gita](https://github.com/nosarthur/gita) | Yes (CLI only) | No | No | No | No | No | Yes |\n\n**lazygit** and **gitui** are excellent for deep single-repo work — staging hunks, interactive rebase, conflict resolution. gitpane is the **workspace-level dashboard** — see everything across all repos, drill into anything, never leave the terminal. They complement each other.\n\n## Screenshots\n\n### Three-panel overview\nRepos on the left show branch, dirty state (`*`), ahead/behind arrows (`↑↓`), worktree count (`⎇`), and file count. Changes in the middle. Commit graph on the right.\n\n\u003cimg src=\"assets/screenshot-main.png\" alt=\"Three-panel overview\" width=\"800\"\u003e\n\n### Split diff view\nClick a changed file (or press Enter) to see its diff side-by-side. File list stays navigable on the left.\n\n\u003cimg src=\"assets/screenshot-diff.png\" alt=\"Split diff view\" width=\"800\"\u003e\n\n### Commit detail drill-down\nClick a commit in the graph to see its files. Click a file to see the commit diff. Layered Esc dismissal: diff → files → graph.\n\n\u003cimg src=\"assets/screenshot-commit.png\" alt=\"Commit detail drill-down\" width=\"800\"\u003e\n\n## Features\n\n- **Multi-repo overview** — Scans `~/Code` (configurable) for git repos; shows branch, dirty indicator (`*`), ahead/behind arrows (`↑↓`), worktree count (`⎇`), and change count\n- **Worktree awareness** — Shows the number of linked git worktrees per repo (`⎇2`). In the agentic AI era, tools like Claude Code create worktrees for parallel development — gitpane lets you see at a glance which repos have active parallel work\n- **Real-time filesystem watching** — Status updates within ~500ms of any file change via `notify`\n- **Commit graph** — Lane-based graph with colored box-drawing characters, up to 200 commits\n- **Split diff views** — Click a file to see its diff side-by-side; click a commit to see its files and per-file diffs\n- **Full mouse support** — Click to select, right-click for context menu, scroll wheel everywhere\n- **Push / Pull / Rebase** — Right-click context menu with ahead/behind-aware git operations (explicit `origin \u003cbranch\u003e` for reliability)\n- **Add \u0026 remove repos** — Press `a` to add any repo with tab-completing path input; `d` to remove; `R` to rescan\n- **Sort repos** — Cycle between alphabetical and dirty-first with `s`\n- **Copy to clipboard** — Press `y` to copy selected item from any panel (OSC 52)\n- **Configurable** — TOML config for root dirs, scan depth, pinned repos, exclusions, frame rate\n- **Responsive layout** — Three horizontal panels on wide terminals, vertical stack on narrow ones\n- **Cross-platform** — Linux, macOS, Windows\n\n## Keybindings\n\n### Global\n\n| Key | Action |\n|-----|--------|\n| `Tab` / `Shift+Tab` | Cycle focus between panels |\n| `r` | Refresh all repo statuses |\n| `R` | Rescan directories for repos (clears exclusions) |\n| `g` | Reload git graph for selected repo |\n| `a` | Add a repo (opens path input with tab completion) |\n| `d` | Remove selected repo from the list |\n| `s` | Cycle sort order (Alphabetical / Dirty-first) |\n| `y` | Copy selected item to clipboard |\n| `q` | Quit (or close diff if one is open) |\n| `Esc` | Navigate back through panels, then quit |\n\n### Panel navigation\n\n| Key | Repos | Changes | Graph |\n|-----|-------|---------|-------|\n| `j` / `↓` | Next repo | Next file | Next commit / file |\n| `k` / `↑` | Prev repo | Prev file | Prev commit / file |\n| `Enter` | — | Open diff | Open commit files / file diff |\n| `Esc` / `h` / `←` | — | Close diff | Close diff → close files → back |\n\n### Mouse\n\n| Action | Effect |\n|--------|--------|\n| Left click | Select item, switch panel focus |\n| Click selected row | Open diff / commit detail |\n| Right click (repo list) | Context menu (push, pull, copy path) |\n| Scroll wheel | Navigate lists or scroll diffs |\n\n### Path input (`a`)\n\n| Key | Action |\n|-----|--------|\n| `Tab` | Autocomplete directory path (cycles matches) |\n| `Enter` | Add the repo |\n| `Esc` | Cancel |\n| `Ctrl+A` / `Home` | Cursor to start |\n| `Ctrl+E` / `End` | Cursor to end |\n| `Ctrl+U` | Clear line before cursor |\n\n## Configuration\n\nConfig file location: `~/.config/gitpane/config.toml`\n\n```toml\n# Directories to scan for git repositories\nroot_dirs = [\"~/Code\", \"~/work\"]\n\n# Maximum directory depth for repo discovery\nscan_depth = 2\n\n# Always show these repos at the top\npinned_repos = [\"~/Code/important-project\"]\n\n# Skip repos matching these directory names\nexcluded_repos = [\"node_modules\", \".cargo\", \"target\"]\n\n[watch]\ndebounce_ms = 500    # Filesystem change debounce (ms)\n\n[ui]\nframe_rate = 30      # Terminal refresh rate (fps)\n```\n\nSee [`examples/config.toml`](examples/config.toml) for a fully annotated example.\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                     tokio runtime                        │\n│  ┌──────────┐  ┌──────────┐  ┌──────────────────────┐   │\n│  │ Event    │→ │ Action   │→ │ Components            │   │\n│  │ Loop     │  │ Dispatch │  │  RepoList             │   │\n│  │ (tui.rs) │  │ (app.rs) │  │  FileList (split diff)│   │\n│  └──────────┘  └──────────┘  │  GitGraph (drill-down)│   │\n│       ↑                      │  ContextMenu          │   │\n│  ┌──────────┐                │  PathInput             │   │\n│  │ notify   │                │  StatusBar             │   │\n│  │ watcher  │                └──────────────────────┘   │\n│  └──────────┘                                           │\n│       ↑              ┌───────────────────────┐           │\n│  filesystem          │ git2 (spawn_blocking) │           │\n│  changes             │  status · graph       │           │\n│                      │  commit_files · fetch │           │\n│                      └───────────────────────┘           │\n└──────────────────────────────────────────────────────────┘\n```\n\n- **[ratatui](https://github.com/ratatui/ratatui)** + **[crossterm](https://github.com/crossterm-rs/crossterm)** — TUI rendering with full mouse support\n- **[git2](https://github.com/rust-lang/git2-rs)** (libgit2) — Branch, status, ahead/behind, graph, commit diffs\n- **[notify](https://github.com/notify-rs/notify)** — Filesystem watching with configurable debounce\n- **[tokio](https://github.com/tokio-rs/tokio)** — Async runtime; git queries run in `spawn_blocking` to keep the UI responsive\n\nMessage-passing architecture: terminal events → actions → component updates → render. Each component implements a `Component` trait with `draw`, `handle_key_event`, `handle_mouse_event`, and `update`.\n\n## Development\n\n```bash\njust run           # Build and run\njust test          # Run test suite (17 tests)\njust fmt           # Format code\njust lint          # Run clippy\njust ci            # fmt + lint + test (mirrors CI pipeline)\n```\n\n### Project structure\n\n```\nsrc/\n├── main.rs              # Entry point, CLI parsing\n├── app.rs               # Main loop, action dispatch, layout\n├── action.rs            # Action enum (message passing)\n├── event.rs             # Terminal event types\n├── tui.rs               # Terminal setup, event loop\n├── config.rs            # TOML config load/save\n├── watcher.rs           # Filesystem watcher → repo index mapping\n├── components/\n│   ├── mod.rs           # Component trait\n│   ├── repo_list.rs     # Left panel: repo list with status\n│   ├── file_list.rs     # Middle panel: changed files + split diff\n│   ├── git_graph.rs     # Right panel: commit graph + drill-down\n│   ├── context_menu.rs  # Right-click overlay\n│   ├── path_input.rs    # Add-repo input overlay\n│   └── status_bar.rs    # Bottom bar with keybinding hints\n└── git/\n    ├── mod.rs\n    ├── scanner.rs       # Repo discovery via walkdir\n    ├── status.rs        # Branch, files, ahead/behind, fetch\n    ├── graph.rs         # Lane-based commit graph builder\n    ├── graph_render.rs  # Box-drawing character rendering\n    └── commit_files.rs  # Commit file list and per-file diffs\n```\n\n## License\n\n[MIT](LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faffromero%2Fgitpane","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faffromero%2Fgitpane","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faffromero%2Fgitpane/lists"}