Galax (gx) — a single-binary TUI suite of git power tools: commit graph browser, diff navigator, worktree manager, semantic commits, stash browser, and a multi-repo fleet dashboard. Pure Rust, cross-platform. https://byjokese.com
  • Rust 99.1%
  • Shell 0.6%
  • PowerShell 0.3%
Find a file
Ivan Exposito f5687820b9
All checks were successful
CI / installers (push) Successful in 9s
CI / deny (push) Successful in 10m5s
CI / msrv (push) Successful in 10m22s
CI / check (rust) (push) Successful in 12m13s
CI / check (windows) (push) Successful in 14m54s
CI / installers-windows (push) Successful in 11s
Merge branch 'feat/repos-fleet-scale'
gx repos: fleet dashboard rebuilt for 200-500 repos.

M1 triage core: hybrid coloured row, summary header, search that filters,
composable status filters, cyclable sort.
M2 view modes: flat/folder/status grouping with collapsible headers.
M3 cheap enrichment: stash, last-commit, remote host/owner, local-only;
host grouping; cold/local-only colouring.
M4 drill-in and safe push: enter opens a repo's graph/diff/branches/wt or
a shell in-process; bulk push is ahead-only and never --force.
M5 hygiene view: background disk/branch enrichment with progressive fill
and its own cache; cleanup filter.
M6 housekeeping: bulk prune (merged-only) and gc, in the TUI and as CLI
verbs.

Plus the post-M6 UI pass: aligned responsive columns with a header row,
one sort order per column marked with a moving indicator, and the
drill-in menu rendered as an overlay.
2026-08-02 11:19:04 +02:00
.forgejo/workflows fix: check $LASTEXITCODE in smoke-windows and correct bump-formula path in RELEASING 2026-08-01 13:03:49 +02:00
crates refactor(repos): every sort order is a column, including the default 2026-08-02 11:07:39 +02:00
scripts feat: add bump-formula.sh to render the Homebrew formula 2026-08-01 12:39:34 +02:00
.gitignore chore: untrack local planning docs 2026-07-12 00:00:46 +02:00
Cargo.lock chore: release v0.1.1 2026-08-01 12:54:26 +02:00
Cargo.toml chore: release v0.1.1 2026-08-01 12:54:26 +02:00
CHANGELOG.md chore: release v0.1.1 2026-08-01 12:54:26 +02:00
deny.toml deps: upgrade gix to 0.85 and drop the gix-date advisory exception 2026-07-19 19:56:39 +02:00
install.ps1 feat: add install.ps1 with checksum verification and unit tests 2026-08-01 12:10:12 +02:00
install.sh fix: silence shellcheck SC2016 false positive in shellinit_line 2026-08-01 12:05:22 +02:00
LICENSE refactor: rename binary crate to galax, add package metadata, LICENSE and README 2026-07-12 13:44:17 +02:00
README.md docs(readme): document global flags, aliases, -C, y, and fleet path handling 2026-08-01 16:20:06 +02:00
RELEASING.md fix: check $LASTEXITCODE in smoke-windows and correct bump-formula path in RELEASING 2026-08-01 13:03:49 +02:00

🌌 Galax

Navigate your git galaxy.

Eight git power tools in one fast, dependency-free binary — built for the terminal.

crates.io downloads MSRV license platforms


What is Galax?

gx is a single binary that bundles the git chores you keep leaving the terminal for: a commit-graph browser, a diff navigator, a worktree manager, a conventional-commit wizard, branch cleanup, a stash browser, and a multi-repo fleet dashboard — plus plain repo status.

  • One binary, no runtime deps. Pure Rust, no C libraries. Same behavior on Linux, macOS, and Windows — yes, even in tmux and over SSH.
  • Reads are fast, writes are safe. Reads go through gix in-process; anything that mutates a repo shells out to your git, so hooks, signing, and config behave exactly as they do on your command line.
  • Two faces per tool. A bare noun opens an interactive TUI (gx graph); a noun + verb is scriptable, with --json where it matters (gx graph, gx repos status --json).

Features at a glance

Command What it does
📊 gx · gx status Repo status: branch, ahead/behind, staged/modified/untracked, worktrees
🌌 gx graph Commit-graph browser — Unicode lanes (or pixel-perfect graphics), detail & refs panes, per-commit diff
🔍 gx diff One-shot diff viewer — working tree, --staged, a commit, or A..B, with hunk navigation
🌳 gx wt Worktree manager — interactive picker that cds your shell, plus list/add/rm
✍️ gx commit Conventional-commit wizard — Kind → Scope → Subject → Body → Breaking → Confirm
🌿 gx branches Branch cleanup — flags merged & upstream-gone branches, deletes on confirm
📦 gx stash Stash browser — per-stash diff preview; apply / pop / drop
🛰️ gx repos Multi-repo fleet dashboard — cached instant paint, parallel status/fetch/pull
🐚 gx shell-init Prints the shell wrapper that powers gx wt's directory jump

Bare noun → TUI. Noun + verb → script. Every TUI shares the same muscle memory: / fuzzy search, Enter drill in, q/Esc close, ? help. All keys are rebindable.

Install

The crate is galax; the installed command is gx. cargo install gx finds nothing — install galax.

Platform One-liner
🐧 Linux (script) curl -fsSL https://code.byjokese.net/byjokese/galax/raw/branch/main/install.sh | sh
🪟 Windows (script) iwr -useb https://code.byjokese.net/byjokese/galax/raw/branch/main/install.ps1 | iex
🍎 macOS / Linux (Homebrew) brew tap byjokese/tap https://code.byjokese.net/byjokese/homebrew-tap.git
brew install byjokese/tap/galax
📦 Prebuilt (cargo-binstall) cargo binstall galax
🦀 From source (crates.io) cargo install galax

The install.sh / install.ps1 scripts download the prebuilt binary, verify its SHA-256, and drop it in ~/.local/bin (Linux) or %LOCALAPPDATA%\Programs\gx (Windows) — add that directory to your PATH if the script says so.

Prebuilt binaries exist for x86_64 Linux and Windows only. On macOS or ARM, use Homebrew or cargo install — both build from source and need Rust 1.90+.

Build from a checkout
git clone https://code.byjokese.net/byjokese/galax.git
cd galax
cargo install --path crates/galax

Quickstart

gx                    # repo status (bare = quick overview)
gx graph              # browse the commit graph
gx diff --staged      # review what you're about to commit
gx commit -a          # stage tracked changes + conventional-commit wizard
gx repos status       # status across your whole fleet of repos

One-time shell setup (enables gx wt's directory jump)

gx wt opens a picker to jump into any worktree — but a subprocess can't change its parent shell's directory (an OS limit, not a bug). One line in your shell startup defines a gx wrapper that does the cd for you:

Shell Add to Line
bash ~/.bashrc eval "$(gx shell-init bash)"
zsh ~/.zshrc eval "$(gx shell-init zsh)"
fish ~/.config/fish/config.fish gx shell-init fish | source
PowerShell $PROFILE Invoke-Expression (gx shell-init powershell | Out-String)

Without it, gx wt still works — it just prints the chosen path instead of cd-ing.

Cheat sheet

Everywhere: / search · n / N next / prev match · Enter drill in · q / Esc close · ? help

View Keys
🌌 gx graph j/k move · g/G top/bottom · Enter detail · d commit diff · r refs pane · c/y copy SHA · s inline ↔ split
🔍 gx diff Tab file list ↔ hunks · Shift-J/Shift-K next/prev file · ]/[ next/prev hunk · s inline ↔ split
🌿 gx branches Space toggle candidate · Enter arm y/n delete
📦 gx stash a apply · p pop · x drop (each behind a y/n confirm)
🛰️ gx repos Space select row · Shift-A select all · f fetch · u pull (each confirms with a count)
Full command reference (flags, verbs & every binding)

Global flags (accepted by every command): --json machine-readable stdout · -q, --quiet silence progress/info (errors still show) · --no-color disable color (also honors NO_COLOR and TERM=dumb) · -C, --cwd <DIR> run as if started in <DIR>, like git -C. Long human output is paged through $PAGER (default less -FIRX) on a terminal.

Aliases — most subcommands take a git-style short name: st (status) · log/lg (graph) · di (diff) · worktree (wt) · branch/br (branches) · ci/cm (commit). gx help <command> prints per-command help.

gx / gx status

Repo status: branch, ahead/behind, staged/modified/untracked counts, worktree list. --json for machine-readable output.

gx graph

Interactive commit-graph browser: lane-based layout in Unicode box-drawing, commit detail pane, refs pane, live fuzzy search, and a full-screen diff view per commit. Rows carry git-style colored decorations (HEAD -> main, branches, tags, remotes), the short SHA, and an S marker on commits that carry a GPG/SSH signature (presence only — gx never verifies signatures).

On image-capable terminals the graph column renders as smooth pixel graphics (thick lines, curved corners, ringed HEAD node) — automatically on kitty, Ghostty, iTerm2, WezTerm, Windows Terminal, foot, and tmux on a kitty-class host; everywhere else it falls back to the classic text renderer.

  • Flags: -n, --max-count <N> limit commits loaded · --order <chrono|topo> (default chrono)
  • Keys: j/k navigate · g/G top/bottom · Enter toggle detail · d open commit diff · r toggle refs pane · / search, n/N cycle matches · c/y copy commit hash · s toggle inline / side-by-side diff

gx diff [REV]

One-shot diff viewer. No arguments → working tree; --staged → index vs HEAD; REV → a commit against its first parent; A..B → a range. (--staged conflicts with REV.)

  • Keys: Tab switch file list / hunk pane · Shift-J/Shift-K next/prev file · ]/[ next/prev hunk · s toggle inline / side-by-side

gx wt [COMMAND]

Worktree manager. Bare gx wt opens the interactive picker (needs shell-init — see Quickstart). Verbs are scriptable:

  • list — list worktrees. --json.
  • add <branch> [--from <ref>] — create a worktree for <branch>, running any configured setup hooks afterward.
  • rm <name> --yes [--force] — remove a worktree by name or path. Refuses without --yes; --force also removes a dirty one (and implies --yes).

gx branches [COMMAND]

Branch cleanup. Bare gx branches opens a TUI: Space toggles a candidate (merged-into-base or upstream-gone branches only — never the current or base branch), Enter arms a y/n delete confirmation. Verbs:

  • list [--base <branch>] — list branches with state (Active/Merged/Gone). --json.
  • clean [--dry-run] [--yes] [--base <branch>] — delete every merged/gone branch. Refuses to run without --dry-run or --yes.

gx commit [-a|--all]

Interactive Conventional Commits wizard: Kind → Scope → Subject → Body → Breaking → Confirm, then runs git commit -m <rendered message> (so hooks, signing, etc. behave exactly as on the command line). -a, --all stages all tracked modifications first. The body is a single-line field here — for a multi-line body, run plain git commit (no -m) to open your real editor.

gx stash [COMMAND]

Stash browser. Bare gx stash opens a TUI with a diff preview per stash: a apply, p pop, x drop, each behind a y/n confirm. Verbs:

  • list — list stashes.
  • apply <index> / pop <index> — apply (optionally removing) a stash.
  • drop <index> --yes — remove a stash without applying it. Refuses without --yes.

(gx stash manages existing stashes; creating one is a one-liner in git itself — git stash push.)

gx repos [COMMAND]

Multi-repo fleet dashboard. Bare gx repos opens instantly from a cached snapshot (noting its age) while rescanning watch folders in the background. Verbs:

  • status — scan and print each repo's branch, ahead/behind, and staged/modified/untracked counts. --json.
  • fetchgit fetch --all --prune across every repo in parallel. --json.
  • pull — fast-forward-only pull across every repo in parallel (see Fleet safety below). --json.
  • Dashboard keys: Space toggle row · Shift-A select/deselect all · f fetch · u pull (both act on the selection, or every repo if none selected; each arms a y/n confirm naming the count) · / search by name or branch, n/N cycle · ? help.

gx shell-init <bash|zsh|fish|powershell>

Prints the shell wrapper function from Quickstart. Never touches your shell directly; you eval/source its output yourself.

Configuration

gx reads config.toml from your OS config dir (~/.config/gx/config.toml on Linux, ~/Library/Application Support/gx/ on macOS), or from $GX_CONFIG_FILE.

Theme — pick a base, override any color
[ui]
theme = "light"   # built-in: "default" (dark terminals), "light" (bright terminals)

[theme]            # override any subset; names, #RRGGBB, or 0-255 indexed
sha = "yellow"            # short commit id column
branch = "green"         # local-branch badges
remote = "red"           # remote badges
tag = "yellow"           # tag badges
head = "cyan"            # HEAD -> badge text (the ◉ node keeps its lane color)
signature = "green"      # signed-commit marker
search_match = "#5c5200"    # search match background
diff_added_bg = "#1c3a24"   # added diff line background
diff_removed_bg = "#3d1f23" # removed diff line background
graph_palette = ["cyan", "magenta", "yellow", "green", "blue", "red"]

graph_palette cycles by lane, so it can be any length — a shorter list repeats sooner, a longer one keeps more lanes visually distinct.

Graph rendering
[graph]
renderer = "auto"    # auto | image | text
protocol = "auto"    # auto | kitty | kitty-unicode | iterm2 | sixel
style    = "rounded" # rounded | angular

auto enables images only on positively identified terminals and always falls back to text inside multiplexers without graphics passthrough (Zellij, screen). tmux works via kitty's unicode placeholders on a kitty-class host. Force a protocol if you know your setup passes graphics through.

Diff layout
[diff]
view = "inline"   # inline | split

split lays diffs side-by-side (old left, new right) when the pane is ≥100 columns, falling back to inline on narrower terminals. s toggles it live.

Fleet — watch folders for gx repos
[repos]
watch_folders = ["~/code", "~/work"]
scan_depth = 2       # how deep under each watch folder to look for a `.git`
parallelism = 0      # threads for fetch/pull; 0 = auto (rayon's default)

gx repos operates on every git repo found under watch_folders, walked scan_depth directories deep. A leading ~ is expanded to your home directory, and any watch folder that doesn't exist is reported and skipped (rather than silently ignored). Bare gx repos status prints the exact expected config path if no watch folders are set.

Fleet safety

gx repos runs git unattended across many repos with no terminal behind it, so four rules are load-bearing — not configurable:

  1. Fetch/pull never ask a human for anything. Terminal prompts (GIT_TERMINAL_PROMPT=0), askpass helpers, ssh passphrase/host-key confirmations (BatchMode=yes), and interactive credential helpers (credential.interactive=false, GCM_INTERACTIVE=never) are all disabled. A repo that truly needs auth fails fast, alone, instead of hanging the pool or popping a dialog per repo. Your credential helper still answers silently from the keychain — so unattended fetches of private repos keep working.
  2. pull is fast-forward only. Never merges, never rebases. Dirty, detached, no-upstream, or diverged repos are skipped with a reason, untouched.
  3. Every git invocation is time-bounded. A watchdog kills any subprocess that outlives the timeout — and everything it spawned (ssh, a hook, a credential helper), since git does the hanging work in a child that would otherwise outlive it. This is what guarantees a fleet run terminates.
  4. Aborting aborts. Ctrl-C, or quitting the dashboard mid-run, stops the git processes too — no git merge --ff-only still fast-forwarding your repos after gx has left the screen.

Building & contributing

cargo build
cargo test
cargo fmt --all && cargo clippy --workspace --all-targets -- -D warnings
cargo run -- graph            # run against the current repo

Workspace: gx-core (headless domain logic), gx-tui (shared TUI kit), galax (the gx binary), gx-testkit (test fixtures).

License

MIT © Ivan Exposito