A native desktop GUI for ezstack, built with Tauri. See your stacks as a visual graph, run every operation through dialogs, and even drive an ezs install on a remote machine over SSH — all without touching the terminal.
The desktop app uses a three-panel layout: stacks sidebar on the left, the visual stack graph in the middle, and a detail view on the right for the selected branch.
The middle panel renders your stacks as a tree of branches, color-coded by health and with the current branch highlighted. Click any node to see PR state, CI checks, review status, and mergeable state in the detail panel.
# What you see in the desktop window:
┌──────────┬──────────────────────┬───────────────────┐
│ Stacks │ main (base) │ feat/auth
│ │ └─ feat/auth │ PR: #42 [OPEN] ↗
│ ● myapp │ └─ feat/login │ CI: 3/3 passed ✓
│ 2 br │ │ Review: Approved
│ │ │ [Sync] [Push] │
└──────────┴──────────────────────┴───────────────────┘
The app polls ezs status in the background and refreshes after every operation. Polling pauses when the window loses focus and uses exponential backoff on failures so it never gets in your way.
# Title bar shows live connection health:
● Connected # green: latency ≤ 800 ms
● Slow # yellow: latency > 800 ms
● Error # red: last ping failed (hover for details)
# Backoff schedule on failure:
30s → 60s → 120s → 240s → 300s
Every repo tracked in ~/.ezstack/config.json shows up in the left sidebar. Type in the Filter box to narrow the list by name or full path — useful when a single config tracks dozens of repos. The currently selected repo stays visible even if it doesn't match the filter, so the main panel can never show a repo you can't click back to. Toggle dark, light, or system theme from the title bar.
# Keyboard shortcuts:
Cmd+R # refresh
Cmd+N # new branch
Esc # clear selection / clear sidebar filter
↑ / ↓ # move between branches in the selected stack
← / → # move between stacks (also [ and ])
The branch detail panel shows a History timeline with the most recent reflog entries for the selected branch — short hash, action (checkout, rebase, commit…), and the full message — so you can spot a bad rebase or an unexpected reset without dropping to a terminal. Over in the stack graph, branch nodes are drag-and-drop reparentable: drag a node onto another branch and the app runs ezs reparent with the configured sync strategy. Drops that would form a cycle (onto a descendant), drops onto the branch itself, and drops onto the current parent are blocked with an inline toast so you can't accidentally corrupt the stack graph.
# Branch detail → History:
abc1234 HEAD@{0} checkout: moving from main to feat/b
def5678 HEAD@{1} rebase (start): checkout origin/main
9ab0011 HEAD@{2} commit: wire up the cycle check
# Drag-to-reparent (valid vs. blocked):
feat/b → feat/x # ok: same stack, new parent
feat/a → feat/c # blocked: would create a cycle
feat/b → feat/b # blocked: dropped on self
The Rust backend is a thin wrapper around the ezs CLI. The frontend exposes every operation through typed forms with confirmation dialogs — and shows the raw CLI output in a terminal-like panel below.
Create, sync, push, delete, and reparent branches without ever touching a terminal.
New branch # pick parent from a dropdown
Sync # current branch, stack, or all stacks
Push # current branch or full stack
Delete # with force toggle
Reparent # pick a new parent branch
Create, update, merge, and toggle draft for PRs. Refresh the stack navigation table in every PR description in one click.
PR Create # title, description, draft toggle
PR Update # push and refresh
PR Merge # squash, merge, or rebase
Toggle Draft # draft ↔ ready
Update Stack # refresh PR descriptions in the stack
Launch the ezstack agent on the current branch or stack, build a feature from a description, and edit prompts across all three layers (shipped, custom, repo) directly from the GUI.
Agent # branch- or stack-scoped
Agent Feature # describe the feature, get stacked PRs
Agent Prompts # view / edit / reset across all 3 layers
Every mutation surfaces a toast in the bottom-right corner with a labelled title (Push feat/auth succeeded, Reparent feat/b onto main failed) and the first line of CLI output. Success toasts auto-dismiss after five seconds; error toasts stay until you dismiss them so you can copy the failure message. Toasts expose the right ARIA live-region roles so screen readers announce them, and the list is capped so a burst of operations can't flood the screen.
✓ Sync stack succeeded
Rebased 3 branches onto main.
✗ Reparent feat/b onto feat/c failed
error: would create a cycle
The desktop app can become a thin client for an ezs install on a remote host. Every ezs, git, and gh invocation runs on the remote — useful for repos that live on a dev VM, build server, or beefy workstation.
Click the Connect pill in the title bar, fill in host / user / port / key, and optionally a jump host (passed through as ssh -J). Profiles are saved to ~/.ezstack/desktop/connections.json — no secrets stored, auth runs through your SSH agent or key file.
Host: dev-box.internal
User: kk
Port: 22
Key: ~/.ssh/id_ed25519
Jump host: bastion.internal # optional
Label: "dev box" # optional
The connect dialog has a Diagnose button that runs a six-step probe and reports pass / warn / fail with a per-step duration so you can see exactly where things break.
✓ SSH connectivity + latency 42ms
✓ Login shell PATH 12ms
✓ ezs binary present and runnable 88ms
✓ git present 15ms
✓ gh authenticated 160ms
✓ ~/.ezstack/config.json readable 11ms
Once connected, the app pings the remote every 30 seconds. The title-bar pill turns green (healthy), yellow (slow), or red (failed). Hover for the latency or the last error.
# Known limitations:
- Agent prompt EDIT is local-only over SSH (view/reset still work)
- First connect uses StrictHostKeyChecking=accept-new
- Every op is at least one SSH round-trip — expect a beat of latency
Requires Node.js 18+, the Rust toolchain (for building), and the ezs CLI on $PATH. gh (GitHub CLI) is required for PR features.
Grab the prebuilt installer for your platform from the GitHub releases page and run it. The app auto-discovers your repos.
# Download from:
github.com/KulkarniKaustubh/ezstack/releases
# macOS (universal)
$ open ezstack_4.4.2_universal.dmg
# Windows (.msi or .exe installer)
$ msiexec /i ezstack_4.4.2_x64_en-US.msi
# Linux (.AppImage / .deb / .rpm)
$ chmod +x ezstack_4.4.2_amd64.AppImage
Clone the repo, install dependencies, and run the dev build (Vite hot reload + Tauri window) or produce a release bundle.
$ cd tauri-ui
$ npm install
# Dev (hot reload)
$ npm run tauri dev
# Production bundle
$ npm run tauri build
→ src-tauri/target/release/bundle/
Built on a small set of well-known tools.
| Layer | Technology |
|---|---|
| Framework | Tauri v2 |
| Frontend | React 19 + TypeScript 5.7 |
| Styling | Tailwind CSS v4 |
| State | Zustand 5 |
| Icons | Lucide React |
| Build | Vite 6 |
| Backend | Rust — thin wrapper around ezs via std::process::Command |