Rust TUI/CLI for Zellij-based development — manage projects, git worktrees, Zellij sessions, and workflow automations from one terminal dashboard.
Install · Basic start · Shortcuts · Configuration · Autopilot · Development
zigzag is for developers who keep many repositories, branches, and terminal sessions open at once. It gives you one workflow around Zellij and git worktrees:
- Project dashboard — browse configured projects, worktrees, running sessions, notifications, and git/PR/CI preview data.
- Worktree-first sessions —
zigzag openrestores the primary checkout or creates/restores a branch worktree throughwt. - Native Zellij integration — generated layouts load the Zigzag WASM plugin for in-session toasts and session switching, plus shortcuts for actions and logs.
- Action menu — run contextual tools such as review, lazygit, PR opening, CI fixes, or custom commands.
- Autopilot workflows — KDL-defined background workflows for CI fixes, review follow-up, merge/deploy flows, and custom automation.
┌─ Zigzag ──────────────────────────────────────┐
│ PROJECTS WORKTREES │
│ > myapp main ● │
│ api feat/login 🔔 │
│ │
│ PREVIEW │
│ myapp:feat/login · dirty · PR #42 · CI passing │
│ │
│ [o]pen [n]ew [r]un [K]ill [d]el [?]help [q]uit│
└────────────────────────────────────────────────┘
Note
Zigzag is still in early development. For deeper design context, see docs/PRD.md and docs/SPECS.md.
| Tool | Minimum | Used for |
|---|---|---|
| Rust | stable | Build toolchain |
| Zellij | 0.44.0 |
Terminal sessions |
wt |
0.34.0 |
Git worktrees |
| GitHub CLI | 2.0.0 |
PR, CI, issue data |
Zigzag checks these dependencies at startup and reports missing or outdated tools.
# Latest release
curl -fsSL https://raw.githubusercontent.com/arkan/zigzag/main/install.sh | bash
# Specific version
curl -fsSL https://raw.githubusercontent.com/arkan/zigzag/main/install.sh | ZIGZAG_VERSION=v0.7.0 bash
# Custom install directory, default is ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/arkan/zigzag/main/install.sh | ZIGZAG_INSTALL_DIR=/usr/local/bin bash# Install from the flake
nix profile install github:arkan/zigzag
# Or try it without installing
nix run github:arkan/zigzag -- listThe Nix package wraps zigzag with the common runtime tools it shells out to: zellij, wt, git, gh, ssh, and mosh.
Zigzag does not install a z symlink automatically. If you still want the short command, add this to your shell profile:
alias z=zigzagZigzag does not read old z paths. If you used the previous name, move local files manually:
mv "$HOME/.config/z" "$HOME/.config/zigzag"
mv "$HOME/.local/state/z" "$HOME/.local/state/zigzag"# Builds the CLI and the native Zellij WASM plugin.
# The plugin is a prerequisite for generated Zellij layouts: Alt+k loads it
# from Zigzag's user data directory.
make installBy default this installs:
- CLI:
~/.local/bin/zigzag - Zellij WASM plugin:
~/.local/share/zigzag/zigzag_plugin.wasm
If you build manually instead of using make install, install the plugin in the same canonical path:
rustup target add wasm32-wasip1
cargo build --manifest-path zigzag/Cargo.toml -p zigzag-plugin --release --target wasm32-wasip1
mkdir -p ~/.local/share/zigzag
cp zigzag/target/wasm32-wasip1/release/zigzag_plugin.wasm ~/.local/share/zigzag/zigzag_plugin.wasm
cargo install --path zigzag/crates/zigzag-clizigzag expects the native Zellij plugin for switcher and notifications at ~/.local/share/zigzag/zigzag_plugin.wasm. Override it with ZIGZAG_PLUGIN_WASM=/path/to/zigzag_plugin.wasm when testing a local build.
Create ~/.config/zigzag/projects.kdl:
project "myapp" {
path "~/Code/myapp"
}
project "api" {
path "~/Code/api"
}zigzagThen use:
| Key | Action |
|---|---|
↑ / ↓ |
Move in the current list |
← / → or Tab |
Switch between Projects and Worktrees |
Enter or o |
Open/restore the selected worktree session |
s or Alt+k |
Open the active-session switcher; inside Zellij this is the native WASM plugin |
n |
Create a new worktree + session from a branch, issue, or PR |
/ |
Fuzzy search |
? |
Show in-app help |
q |
Quit the dashboard |
Tip
Arrow keys always work. h/j/k/l navigation is available when keybindings "vim" is enabled in your config.
zigzag open myapp # Open/restore the primary checkout session
zigzag open myapp feat/login # Open/restore a branch worktree + session
zigzag switch # Pick another local Zigzag-managed sessionWhen a branch worktree does not exist yet, zigzag open <project> <branch> creates it with wt, generates a Zellij layout, starts the session, then attaches to it.
Inside a session, press Ctrl+O, then D to detach. The Zellij session keeps running in the background, and you can return with zigzag or zigzag open <project> [branch].
| Key | Action |
|---|---|
o / Enter |
Open/restore selected project or worktree |
s / Alt+k |
Open the active-session switcher; inside Zellij this is the native WASM plugin |
n |
New worktree + session |
r |
Run action menu |
a |
Autopilot workflows |
K |
Kill active session only |
d |
Delete selected worktree |
D |
Run doctor diagnostics |
A / E / X |
Add, edit, or delete a project |
e |
Edit per-repo .config/zigzag.kdl |
/ |
Search |
? |
Help |
Zigzag injects these shortcuts into generated Zellij layouts:
| Shortcut | Action |
|---|---|
Alt+k |
Open/focus the floating native Zigzag session switcher plugin |
Alt+z |
Open the floating action menu |
Alt+l |
Open the floating log viewer |
| Shortcut | Action |
|---|---|
Ctrl+O, then D |
Detach from the session |
Ctrl+Q |
Quit the session |
Ctrl+T, then N |
New tab |
Ctrl+T, then 1-9 |
Switch to tab by number |
| Command | Description |
|---|---|
zigzag |
Launch the dashboard |
zigzag list |
List configured projects and active sessions |
zigzag open <project> [branch] |
Open/restore a checkout or branch session |
zigzag close [session] |
Detach a session without deleting it |
zigzag switch |
Pick and jump to another local Zigzag session |
zigzag actions |
Open the action menu for the current session |
zigzag logs [-n <count>] |
Show Zigzag logs |
zigzag doctor [--fix] |
Diagnose or repair safe project/session issues |
zigzag session kill <project> <branch> |
Kill a Zellij session only |
zigzag worktree delete <project> <branch> [--confirm <branch>] |
Delete a worktree |
zigzag project delete <project> |
Remove a project from projects.kdl |
zigzag notify [session] <message> |
Add a session notification |
zigzag autopilot <subcommand> |
Manage workflow automation |
Zigzag uses KDL with three main files:
| File | Purpose |
|---|---|
~/.config/zigzag/projects.kdl |
Project registry |
~/.config/zigzag/config.kdl |
Global preferences, layout defaults, actions, notifications |
<repo>/.config/zigzag.kdl |
Per-repository layout, actions, and autopilot settings |
Minimal global config:
keybindings "vim" // or omit for arrow-key navigation
theme "dracula"
notifications {
tui true
zellij true
macos-native false
}notifications.zellij true sends zigzag notify events to the native plugin with zellij action pipe. The plugin is launched automatically as a floating notification pane when a toast arrives; this does not create a terminal pane and should not steal keyboard focus.
Minimal per-repo layout:
layout {
tab "code" {
pane "editor"
pane "shell" size=30
}
tab "agent" {
pane command="claude"
}
}The action menu (r in the dashboard, Alt+z in a generated Zellij session) resolves built-in, global, and per-repo actions against the current project/session context.
Notifications are stored in local worktree metadata and surfaced as dashboard/switcher badges. From inside a Zellij pane, $ZELLIJ_SESSION_NAME lets you notify the current session without naming it:
zigzag notify "CI finished" --level info
zigzag notify myapp:feat-login "Review comments arrived" --level warningWith zellij true, the same command also emits a native in-session toast via the plugin. Toasts render as a four-line card: status icon + notification type, session subtitle, spacer, then message body:
❌ Error
hub:main
Build failed
The pipe payload is JSON and targets the zigzag-notify pipe; for manual testing:
zellij -s myapp:feat-login action pipe \
--name zigzag-notify \
--plugin file:$HOME/.local/share/zigzag/zigzag_plugin.wasm \
--floating-plugin true \
--plugin-title Zigzag \
--skip-plugin-cache \
-- '{"message":"CI finished","level":"info","session":"myapp:feat-login"}'Autopilot workflows are KDL-defined state machines that can run commands, send notifications, ask for confirmations, and transition on success/failure.
zigzag autopilot list
zigzag autopilot status
zigzag autopilot run <project> <workflow>Built-in workflows cover common PR and deploy loops such as CI fixing, review follow-up, merge-when-ready, Dependabot auto-merge, and deploy monitoring.
This repository is a Rust workspace:
zigzag/crates/
├── zigzag-core # Domain types, config, actions, traits
├── zigzag-cli # CLI entry point and process/filesystem adapters
├── zigzag-tui # Ratatui dashboard, switcher, logs, action picker
├── zigzag-autopilot # Workflow DSL and runner
├── zigzag-plugin # Native Zellij WASM plugin: toasts + session switcher
└── zigzag-web # Future web bridge
Common checks:
npm run typecheck
npm test
cargo fmt --manifest-path zigzag/Cargo.toml --all --check
cargo test --manifest-path zigzag/Cargo.toml --workspace
cargo build --manifest-path zigzag/Cargo.toml -p zigzag-plugin --target wasm32-wasip1Further reading:
codemap.md— repository map and entry pointsdocs/PRD.md— product requirementsdocs/SPECS.md— technical specs