- Rust 99.1%
- Shell 0.6%
- PowerShell 0.3%
|
Some checks failed
CI / installers (push) Successful in 8s
CI / deny (push) Successful in 5m42s
CI / msrv (push) Successful in 5m43s
CI / check (rust) (push) Successful in 6m49s
CI / check (windows) (push) Has been cancelled
CI / installers-windows (push) Has been cancelled
Integrates feat/wt-shell-jumps (shell-init -> init rename with alias, worktree/repos directory jumps, PowerShell finally-block fix) landed on origin with the local gx branches rework. Auto-merges cleanly; overlap was only README.md and repos_dash.rs. |
||
|---|---|---|
| .forgejo/workflows | ||
| crates | ||
| scripts | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| deny.toml | ||
| install.ps1 | ||
| install.sh | ||
| LICENSE | ||
| README.md | ||
| RELEASING.md | ||
🌌 Galax
Navigate your git galaxy.
Eight git power tools in one fast, dependency-free binary — built for the terminal.
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--jsonwhere 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 init |
Prints the shell wrapper that powers every gx directory jump |
Bare noun → TUI. Noun + verb → script. Every TUI shares the same muscle memory:
/fuzzy search,Enterdrill in,q/Escclose,?help. All keys are rebindable.
Install
The crate is
galax; the installed command isgx.cargo install gxfinds nothing — installgalax.
| 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.gitbrew 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 every gx directory jump)
gx wt jumps into any worktree, gx wt add drops you in the one it just created,
and gx repos can cd straight to a repo — 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 init bash)" |
| zsh | ~/.zshrc |
eval "$(gx init zsh)" |
| fish | ~/.config/fish/config.fish |
gx init fish | source |
| PowerShell | $PROFILE |
Invoke-Expression (gx init powershell | Out-String) |
Without it those commands still work — they print the target path instead of cd-ing,
and say so once, so you can wire it up yourself (cd "$(gx wt)").
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 · f cycle filter · o cycle sort |
📦 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) · Enter drill menu (c = cd here) |
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>(defaultchrono) - Keys:
j/knavigate ·g/Gtop/bottom ·Entertoggle detail ·dopen commit diff ·rtoggle refs pane ·/search,n/Ncycle matches ·c/ycopy commit hash ·stoggle 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:
Tabswitch file list / hunk pane ·Shift-J/Shift-Knext/prev file ·]/[next/prev hunk ·stoggle inline / side-by-side
gx wt [COMMAND]
Worktree manager. Bare gx wt opens the interactive picker (needs gx init — see Quickstart). Verbs are scriptable:
list— list worktrees.--json.add <branch> [--from <ref>] [--no-cd]— create a worktree for<branch>, run any configured setup hooks, then jump into it.--no-cdstays put.rm <name> --yes [--force]— remove a worktree by name or path. Refuses without--yes;--forcealso removes a dirty one (and implies--yes).
gx branches [COMMAND]
Branch cleanup. Bare gx branches opens a TUI: columns for NAME, STATE, AGE, UNMERGED, DIV (↑↓ vs upstream), TIP and UPSTREAM, listed left to right; NAME, STATE and UNMERGED are always present (UNMERGED never drops — it's the column the view exists to show), while UPSTREAM, then DIV, then TIP, then AGE drop off as the terminal narrows. o cycles the sort column; f cycles the filter (none → merged → gone → active → stale → none). Space toggles a candidate — merged-into-base or upstream-gone branches only, never the current or base branch, and never one checked out in another linked worktree (marked w and excluded up front, since git refuses to delete those). Enter arms a y/n delete confirmation, which warns when the selection would make commits unreachable. Verbs:
list [--base <branch>]— list branches with state (Active/Merged/Gone).--json.clean [--dry-run] [--yes] [--base <branch>] [--force]— delete every branch that's merged into base, plus every upstream-gone branch whose whole diff is confirmed already in base (e.g. squash- or rebase-merged). A gone branch carrying commits that exist nowhere else is refused unless--forceis also passed. Refuses to run at all without--dry-runor--yes. Exit code: nonzero if any branch was refused for lacking--force, or if a deletion failed — so a script relying onclean --yesalone (no--force) now fails closed on unmerged work instead of silently destroying it.
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.fetch—git fetch --all --pruneacross every repo in parallel.--json.pull— fast-forward-only pull across every repo in parallel (see Fleet safety below).--json.- Dashboard keys:
Spacetoggle row ·Shift-Aselect/deselect all ·ffetch ·upull (both act on the selection, or every repo if none selected; each arms ay/nconfirm naming the count) ·/search by name or branch,n/Ncycle ·?help. Enteron a repo opens a drill menu:ograph ·ddiff ·bbranches ·wworktrees ·ccd here (quits the dashboard and moves your shell to that repo).
gx init <bash|zsh|fish|powershell>
Prints the shell wrapper function from Quickstart. Never touches your shell directly; you eval/source its output yourself. (Previously shell-init; that name still works as a hidden alias.)
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:
- 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. pullis fast-forward only. Never merges, never rebases. Dirty, detached, no-upstream, or diverged repos are skipped with a reason, untouched.- 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.
- Aborting aborts. Ctrl-C, or quitting the dashboard mid-run, stops the git processes too — no
git merge --ff-onlystill 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