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
Find a file
Ivan Exposito 40b7cdefe3
All checks were successful
CI / msrv (push) Successful in 6m26s
CI / check (rust) (push) Successful in 9m50s
CI / deny (push) Successful in 5m48s
CI / check (windows) (push) Successful in 13m53s
Release / build-linux (push) Successful in 5m3s
Release / build-windows (push) Successful in 6m31s
Release / publish (push) Successful in 3m31s
Merge branch 'deps-gix-upgrade': gix 0.85, closing RUSTSEC-2025-0140
2026-07-19 19:56:39 +02:00
.forgejo/workflows ci: actually enforce cargo-deny, with the surviving advisories reasoned about 2026-07-19 19:52:01 +02:00
crates deps: upgrade gix to 0.85 and drop the gix-date advisory exception 2026-07-19 19:56:39 +02:00
.gitignore chore: untrack local planning docs 2026-07-12 00:00:46 +02:00
Cargo.lock deps: upgrade gix to 0.85 and drop the gix-date advisory exception 2026-07-19 19:56:39 +02:00
Cargo.toml deps: upgrade gix to 0.85 and drop the gix-date advisory exception 2026-07-19 19:56:39 +02:00
CHANGELOG.md docs: date 0.1.0 to the actual release day and tidy the entry 2026-07-19 16:21:15 +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
LICENSE refactor: rename binary crate to galax, add package metadata, LICENSE and README 2026-07-12 13:44:17 +02:00
README.md docs: cover the post-rc features in the 0.1.0 notes and document the MSRV 2026-07-19 16:15:17 +02:00
RELEASING.md docs: correct the runner labels in the release runbook 2026-07-19 16:23:07 +02:00

Galax

Navigate your git galaxy.

Galax (gx) is a suite of git power tools that live in one fast, dependency-free binary. Browse your commit graph as a constellation, jump through diffs, juggle worktrees, craft conventional commits, clean up stale branches, and browse your stashes — all without leaving the terminal.

Pure Rust, no C dependencies, works the same on Linux, macOS, and Windows (yes, even in tmux).

Install

Method Command
crates.io (any platform with Rust) cargo install galax
Homebrew (macOS / Linux) brew tap byjokese/tap https://code.byjokese.net/byjokese/homebrew-tap.git then brew install byjokese/tap/galax
Prebuilt binary (Linux / Windows) Download from the latest release and put gx on your PATH

All install methods give you the gx binary. Building from source:

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

Building from source (including cargo install) needs Rust 1.90 or newer. The prebuilt binaries have no toolchain requirement.

Shell setup (do this next)

gx wt (no verb) opens an interactive picker so you can jump into any worktree. But a picker running as a normal subprocess cannot change the directory of the shell that launched it — that's a hard OS limitation, not a gx bug. To get the "pick a worktree, land in its directory" experience, add one line to your shell's startup file. It defines a gx shell function that wraps the real binary: it runs gx, and if the picker chose a worktree, the wrapper cds your actual shell there.

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 this, gx wt still works — it just prints the chosen path instead of cd-ing there, same as any other CLI output.

Usage

Bare gx (no subcommand) prints repo status. Most other tools open an interactive TUI when called bare, and take a verb for scriptable CLI use:

gx                    # repo status
gx status --json      # machine-readable status
gx graph              # interactive commit graph browser
gx graph -n 50         # limit to 50 commits
gx wt                 # interactive worktree picker (cd's your shell — see Setup above)
gx wt list --json     # scriptable: list worktrees as JSON

Inside any TUI: / fuzzy search, Enter drill in, q / Esc quit or close, ? help overlay listing every binding (all rebindable via config).

Commands

  • 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. -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 copy commit hash · s toggle the diff view between inline and side-by-side.

  • gx diff [REV] — a one-shot diff viewer. With no arguments, shows the working tree; --staged shows the index vs HEAD; REV shows a commit against its first parent, or A..B for 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 layout.

  • gx wt [COMMAND] — worktree manager. Bare gx wt opens the interactive picker (needs shell-init — see Setup above); verbs are scriptable:

    • list — list worktrees. --json.
    • add <branch> [--from <ref>] — create a worktree for <branch>, running any configured setup hooks afterward.
    • rm <name> [--force] — remove a worktree by name or path; --force for a dirty worktree.
  • gx branches [COMMAND] — branch cleanup. Bare gx branches opens an interactive 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 their 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 they do on the command line). -a, --all stages all tracked modifications first (git commit -a). The body is a single-line field in this wizard — 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 an interactive TUI with a diff preview per stash: a apply, p pop, x drop, each armed 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 browses and 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 in the status line) while rescanning the configured watch folders in the background; verbs are scriptable:

    • 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 rules below). --json.

    Dashboard keys: space toggle the current row's selection · Shift-A select/deselect every row · f fetch · u pull (both act on the selection, or every repo if nothing is selected; each arms a y/n confirm naming the count) · / search by name or branch, n/N cycle matches · ? help.

    See Fleet below for the [repos] config block and the safety rules the dashboard is built around.

  • gx shell-init <bash|zsh|fish|powershell> — prints the shell wrapper function described in Setup above. Never touches your shell directly; you eval/source its output yourself.

Configuration

gx reads config.toml from your OS config directory (e.g. ~/.config/gx/config.toml on Linux, ~/Library/Application Support/gx/ on macOS), or from $GX_CONFIG_FILE if set.

Theme

Pick a built-in base theme with ui.theme ("default" or "light"), then override individual colors under [theme]:

[ui]
theme = "light"   # built-in: "default" (dark terminals), "light" (bright terminals)

All TUI colors are overridable via a [theme] section. Any subset of keys; values are color names ("cyan", "lightred"), #RRGGBB hex, or 0-255 indexed colors:

[theme]
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. The built-in default is six truecolor (RGB hex) entries; the example above overrides it with a six-color palette of named colors instead, but a list of any length works -- a shorter one cycles sooner, a longer one keeps more lanes visually distinct before repeating.

Graph

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

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

Diff

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

split lays diffs out side-by-side (old left, new right) when the pane is at least 100 columns wide, falling back to inline on narrower terminals. s toggles the layout live in the gx diff and graph diff views.

Fleet

gx repos operates on every git repository found under the paths in [repos].watch_folders, walked to scan_depth directories deep. Configure it in your config.toml (bare gx repos status prints the exact expected path if no watch folders are set; $GX_CONFIG_FILE overrides it):

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

Fleet safety rules

These are load-bearing, not configurable — they are why fleet operations are built the way they are:

  1. Fetch/pull never ask a human for anything. Nothing in a fleet operation can put a prompt or a dialog in front of you: git's terminal prompt (GIT_TERMINAL_PROMPT=0), askpass helpers (GIT_ASKPASS, core.askPass, SSH_ASKPASS), ssh passphrase and host-key confirmations (BatchMode=yes), and interactive credential helpers (credential.interactive=false, GCM_INTERACTIVE=never — Git for Windows enables Git Credential Manager by default) are all disabled. A repo that genuinely needs auth fails fast, for that repo alone, instead of hanging its thread — and, once the whole pool is stuck the same way, the entire batch — or popping one GUI dialog per repo.

    Your credential helper is not disabled, only its ability to interact: it can still answer silently from the keychain, so unattended fetches of private repos keep working. Use an ssh-agent or a helper with stored credentials for any remote that needs auth.

  2. pull is fast-forward only. It never merges and never rebases. A repo that is dirty, detached, has no upstream, or has diverged from its upstream is skipped with a stated reason and left completely untouched.

  3. Every operation is bounded in time. Rule 1 is enforced with settings a determined credential helper is free to ignore — and pull fast-forwards with git merge --ff-only, which still runs your repo's hooks, and a hook can do anything, including wait on input. So each git subprocess also gets a watchdog: if it outlives the timeout it is killed — along with everything it spawned, since git does the work that hangs (ssh, a hook, a credential helper) in a child that would otherwise outlive it — and the repo is reported as a failed row, rather than silently consuming a worker for the rest of the run. This is what actually guarantees that gx repos fetch over a large fleet terminates.

    The bound is per git invocation. A pull is two of them (a fetch, then a fast-forward), so a repo wedged on both legs takes up to twice the timeout before it gives up.

  4. Aborting aborts. Ctrl-C, or quitting the dashboard while an operation is running, stops the git processes too. Without this they would keep going in the background — git merge --ff-only still fast-forwarding your repos seconds after gx had left the screen.

Roadmap

  • status — repo status, human or --json
  • graph — commit graph browser
  • diff — diff navigator
  • wt — worktree manager + shell-init cd integration
  • commit — semantic (conventional) commit wizard
  • branches — branch cleanup (merged/gone classification)
  • stash — stash browser
  • fleet — multi-repo dashboard
  • polish & release — themes, docs pass, packaged release (Forgejo releases + crates.io)

Design principles

  • One binary. Everything ships in gx; no plugins, no runtime deps.
  • 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.
  • Terminal-first. Unicode box-drawing, no image protocols — works over SSH, in tmux, and on Windows.

Development

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

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

License

MIT