:GG~ .?Y. .... .. .. ..... . ^BG: .. ..... .7555YY7JP^ ~PJ ~PJ ?YY5PP~ 7YY5BGYYYYJ. J555YY557. .5B?. :JBB~ !#5 !#5 ...PB~ ...^BG:.... ~:. .7#5 :^^ 7#5 .GB~ !B5 !B5 PB~ :BG. .~7??J?JBG: .~JPPPY ?#Y PB~ !B5 !B5 PB~ :BG. 7GP7~^^^!BG: ~5GY!:. ^GB~ 7BB~ ^BG. .YB5 5#7 :BB: P#! JBG: ^GG7 ^5G5JJYJPB~ JBP???YYB5 ^5GYJJ?. 7GPJ???. ~PGJ77?5J5B! JG5 .^~^..GB: :~!!~. ^^ :~~~~ .^~~~~ .^!!!~. .^: JG5 .?!^^^!5G7 YB5 .!?JJJ?!: 75?
terminal based cross-platform git client made with ♡
guita╭, distributed as guitar, is a Rust terminal UI for working with Git history from a topology-first point of view. It is built with ratatui, crossterm, and libgit2, and is designed for exploring, filtering, and operating on large repositories without leaving the terminal.
guita╭ lets you instantly travel to prehistoric times in BIG repositores (500k+ commits)
shows all the changes
while looking really good
- Status And Warning
- Demo
- Requirements
- Install
- Run
- Mental Model
- Interface Sections
- Navigation
- Inputs And Keymaps
- Git Operations
- Authentication
- Settings
- Persistence
- Configuration Files
- Development
- Known Limitations
- Roadmap
- Screenshots
This is a hobby project with sharp Git tools. It can stage, unstage, commit, force checkout, force push, delete branches, reset, stash, pop, drop, rebase, merge, cherry-pick, prune worktrees, and discard file changes.
Use it carefully on important repositories. Keep backups, understand what the selected row and focused pane mean before using action mode, and report issues when behavior is surprising.
Older recording of the v0.1.12 feature set:
https://www.youtube.com/watch?v=oERA8MYlHjQ
The recording is still useful as a tour. This README and the in-app settings/help view are the current source of truth for shortcuts and behavior.
- Rust and Cargo when building from source.
- A non-bare Git repository. Bare repositories are not supported by the UI.
user.nameanduser.emailconfigured in Git before opening a repository.guitarreads these on repository load and uses them when creating commits.- Terminal mouse support for pane dragging and wheel scrolling.
- SSH or HTTPS credentials for private remotes when using network operations.
Set identity globally:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"Or set identity per repository:
git config user.name "Your Name"
git config user.email "you@example.com"Prebuilt binaries are published on the releases page:
https://github.com/asinglebit/guitar/releases
Build from source:
git clone https://github.com/asinglebit/guitar.git
cd guitar
cargo build --releaseThe release binary is written to:
target/release/guitarRun from inside a repository, a repository subdirectory, or with an explicit path:
guitar
guitar ../path/to/repositoryThe first non-flag argument is treated as the repository path. If no path is provided, . is used. The path is canonicalized and then resolved to the Git repository root when possible.
Meta flags:
guitar --version
guitar -v
guitar --reset--version and -v print the version and exit. --reset deletes the saved guitar config directory, then starts the app with regenerated defaults.
If the path cannot be opened as a Git repository, guitar falls back to the splash screen and shows saved recent repositories.
guitar is built around a few core ideas:
- The graph is the primary view. Commits, refs, stashes, worktrees, and optional HEAD reflog entries are projected onto one topology-oriented list.
- Row
0is a synthetic uncommitted-work row aboveHEAD. It represents staged files, unstaged files, and conflicts in the working tree. - Commit history loads incrementally on a background worker. The app becomes usable while more history is still being walked.
- Focus controls what keys operate on. The same key can scroll the graph, a side pane, a status pane, settings, a modal, or the file viewer depending on focus.
- Scope navigation is horizontal:
hwidens outward,lnarrows inward. - Dangerous commands are gated behind action mode. By default, press
Ctrl+a, then the action key.
The splash screen appears when no repository is open or when you back out of the graph. It lists recent repositories from recent.json.
Enterorlopens the selected recent repository.dremoves the selected recent repository fromrecent.json.Shift+KandShift+Jmove the selected recent repository up or down.Escreturns to the graph when a repository is already loaded.qexits.
The graph is the central history view. It can render:
- The synthetic uncommitted-work row.
- Commits in topology order.
- Local and remote branch labels.
- Lightweight and annotated tags resolved to commits.
- Stash commits placed near their base commits.
- Worktree badges for commits checked out in main or linked worktrees.
- Optional HEAD reflog labels and roots.
- Optional abbreviated SHA column.
Graph row details are loaded by window, so large repositories can stay responsive.
The branch pane lists local branches first and remote branches after them, sorted by name inside each group.
- Filled circle: visible local branch.
- Hollow circle: hidden local branch.
- Filled diamond: visible remote branch.
- Hollow diamond: hidden remote branch.
Branch visibility affects graph roots and filtering. An empty visibility set means all branches are visible.
The tag pane lists local tags sorted by name. Tags are shown in the graph at the commit they resolve to. The app can create and delete local lightweight tags.
The stash pane lists stash commits. Stashes are real commits and are rendered in the graph near their first parent.
The reflog pane lists recent HEAD reflog entries. Reflog rows can jump to commits that are visible in the graph. If the reflog commit is hidden, enable graph reflogs with 9 so the walker includes HEAD reflog roots.
The worktree pane lists the main worktree and linked worktrees.
Rows include:
- Worktree name.
- Branch name, detached HEAD short SHA, or no-head state.
- Current-worktree marker.
- Dirty marker.
- Locked marker.
- Invalid marker.
Valid worktrees can be opened from the pane. Linked worktrees can be locked, unlocked, removed, or pruned through the worktree actions.
The status area is on the right.
On the uncommitted row:
- The top status pane shows conflicts and staged changes.
- The bottom status pane shows conflicts and unstaged changes.
- Conflicts appear in both panes and are highlighted.
On a commit row:
- The top status pane shows files changed by the selected commit compared with its first parent.
- The bottom status pane is not used.
Status symbols:
!conflict.~modified.+added.-deleted.→renamed.
The inspector shows selected commit metadata:
- Commit SHA.
- Parent SHAs.
- Featured branch labels.
- Author.
- Committer.
- Summary.
- Body.
When the selected row is uncommitted, the inspector appears if there are conflicts.
The viewer opens from a selected status row. It can show:
- Working tree file contents and diff for the uncommitted row.
- Commit file contents and diff for selected commits.
- Conflict files with conflict-marker highlighting.
- Unified diff style.
- Hunk-only mode.
- Side-by-side split diff mode.
- Line numbers.
- Wrapped long lines.
For merge commits, file lists and file diffs compare against the first parent.
The settings/help view is opened with ?. It shows version, commit heatmap, config paths, recent repositories, Git identity, auth notes, theme choices, layout visibility, and active keymaps. Recent repository rows, theme rows, layout rows, and keybinding rows are selectable.
h and l are the most important navigation keys.
- In the graph,
lnarrows into details. On a commit row it focuses the inspector; on the uncommitted row it focuses staged or unstaged status. - In the inspector,
lmoves to status. - In status,
lopens the selected file in the viewer. - In the viewer,
hreturns to status. - In status,
hmoves outward to inspector or graph. - In the graph,
hopens/focuses the branch pane. - In branch, tag, stash, reflog, and worktree panes,
ljumps into the selected item. - In settings,
hreturns to the graph. - In the splash screen,
lopens the selected recent repository.
Tab and Ctrl+n move to the next focusable pane. Shift+Tab and Ctrl+p move to the previous focusable pane.
Ctrl+h, Ctrl+j, Ctrl+k, and Ctrl+l move focus to the nearest pane in that direction when one is visible.
Focusable panes are ordered:
graph/viewer, inspector, staged/commit status, unstaged status, worktrees, reflogs, stashes, tags, branches
Hidden panes are skipped. The unstaged status pane is focusable only on the uncommitted row.
Enter means "open/select" for the current focus:
- Splash: open selected recent repository.
- Settings theme: activate and save theme.
- Settings keybinding: open key capture.
- Settings layout row: toggle that layout option or reset layout.
- Graph: open a worktree badge if the selected commit has valid worktree candidates.
- Branch/tag/stash/reflog panes: jump to the corresponding graph row and center it when possible.
- Worktree pane: open the selected valid worktree.
- Status panes: open the selected file in the viewer.
- Choice modals: confirm the selected row.
Esc cancels modals or widens back to the graph.
- From graph: opens the splash screen when the history worker is idle.
- From splash: returns to graph when a repository is loaded.
- From viewer/settings/side panes/status/inspector: returns to graph.
- From text-entry modals: clears input and returns to the relevant view.
- From auth prompt: cancels the pending network operation.
All scroll commands act on the focused pane or viewport:
j/Down: one row down.k/Up: one row up.Ctrl+d: half page down.Ctrl+u: half page up.PageDown: page down.PageUp: page up.Ctrl+Alt+d: jump halfway toward the end of the focused graph/side pane list.Ctrl+Alt+u: jump halfway toward the beginning of the focused graph/side pane list.g/Home: beginning.Shift+G/End: end.
In full viewer mode, Ctrl+d and Ctrl+u jump between diff hunk edges. In hunk and split viewer modes, they scroll by half pages.
Ctrl+Alt+h, Ctrl+Alt+j, Ctrl+Alt+k, and Ctrl+Alt+l resize the focused pane one cell or row at a time.
- Left panes:
Ctrl+Alt+lwidens the left column;Ctrl+Alt+hnarrows it. - Right panes:
Ctrl+Alt+hwidens the right column;Ctrl+Alt+lnarrows it. - Graph/viewer focus:
Ctrl+Alt+hgrows the center left by shrinking the left pane;Ctrl+Alt+lgrows the center right by shrinking the right pane. - Split diff viewer: horizontal resizing still resizes the outer viewer area; the split divider stays centered.
- Stacked panes:
Ctrl+Alt+kgrows upward when possible;Ctrl+Alt+jgrows downward when possible.
Keyboard resize changes are saved to layout.json. Keyboard resize is disabled in splash, settings, modals, and zen mode.
{: jump to the previous visible branch-bearing commit.}: jump to the next visible branch-bearing commit.[: jump to the first loaded child of the selected commit.]: jump to the first parent of the selected commit./: open SHA-prefix lookup for loaded history.
SHA lookup accepts non-empty prefixes up to 40 characters. It searches commits already known to the worker.
Mouse capture is enabled while the app runs.
- Mouse wheel scrolls the pane under the cursor and focuses it.
- A single click selects the row under the cursor and focuses that pane.
- Double-click branch, tag, stash, reflog, worktree, status, theme, or keybinding rows to perform the same action as
Enter. - Single-click settings layout rows to toggle them immediately.
- Graph, viewer, and splash rows are selected by mouse clicks but not activated by double-click.
- Drag the left and right vertical dividers to resize side panes.
- Drag stacked pane dividers to resize branch/tag/stash/reflog/worktree, inspector/status, and staged/unstaged splits.
- Layout changes from dragging are saved when the mouse button is released.
There are two keymap modes:
- Normal mode: navigation, layout, safe operations, and non-destructive creation prompts.
- Action mode: single-shot mode for dangerous or destructive operations.
By default, Ctrl+a enters action mode. The next handled key runs through the action keymap and then the mode returns to normal.
Action mode inherits normal-mode navigation and safe operations, but overrides or adds the dangerous bindings listed below. Notably, action-mode r is rebase and action-mode m is merge.
Text prompts are single-line inputs.
Supported editing keys:
- Printable character keys insert text.
Backspaceremoves before the cursor.Deleteremoves at the cursor.LeftandRightmove the cursor.HomeandEndjump to the start or end.Entersubmits when the prompt accepts the current value.Esccancels.
Text prompts are used for commit messages, cherry-pick messages, branch names, tag names, worktree names, worktree paths, worktree lock reasons, SHA lookup, and auth fields.
The auth modal uses:
Tab,Shift+Tab,Up, orDownto switch between username and secret fields for HTTP/HTTPS prompts.Enterto submit.Escto cancel the network operation.
For SSH passphrase prompts, focus stays on the secret field.
In settings, selecting a keybinding opens key capture.
- Press a new key combination to preview it.
Enterconfirms if there is no conflict.EscorCtrl+Ccancels.
If a normal-mode binding is also present in action mode for the same command, rebinding the normal key syncs the matching action-mode binding.
Defaults are written to keymap.json on first run. User-edited keymaps can differ.
| Command | Default keys |
|---|---|
| Widen Scope | h, Left |
| Narrow Scope | l, Right |
| Select | Enter |
| Back | Esc |
| Focus Previous Pane | Ctrl+p, Shift+BackTab |
| Focus Next Pane | Ctrl+n, Tab |
| Focus Pane Left | Ctrl+h |
| Focus Pane Down | Ctrl+j |
| Focus Pane Up | Ctrl+k |
| Focus Pane Right | Ctrl+l |
| Resize Pane Left | Ctrl+Alt+h |
| Resize Pane Down | Ctrl+Alt+j |
| Resize Pane Up | Ctrl+Alt+k |
| Resize Pane Right | Ctrl+Alt+l |
| Scroll Down | j, Down |
| Scroll Up | k, Up |
| Scroll Down Half | Ctrl+Alt+d |
| Scroll Up Half | Ctrl+Alt+u |
| Scroll Half Page Down | Ctrl+d |
| Scroll Half Page Up | Ctrl+u |
| Scroll Page Up | PageUp |
| Scroll Page Down | PageDown |
| Go To Beginning | g, Home |
| Go To End | Shift+G, End |
| Find | / |
| Scroll Up Branch | { |
| Scroll Down Branch | } |
| Scroll Up Commit | [ |
| Scroll Down Commit | ] |
| Toggle Hunk Mode | m |
| Toggle Split Diff Mode | v |
| Toggle Zen Mode | z |
| Reset Layout | 0 |
| Toggle Branches | 1 |
| Toggle Tags | 2 |
| Toggle Stashes | 3 |
| Toggle Status | 4 |
| Toggle Inspector | 5 |
| Toggle Worktrees | 6 |
| Toggle Reflogs | 7 |
| Toggle SHAs | 8 |
| Toggle Graph Reflogs | 9 |
| Toggle Help / Settings | ? |
| Action Mode | Ctrl+a |
| Minimize | . |
| Reload | r |
| Exit | q |
| Remove Recent Repository | d |
| Move Recent Repository Up | Shift+K |
| Move Recent Repository Down | Shift+J |
| Stage | s |
| Unstage | u |
| Commit | c |
| Fetch All | f |
| Create Branch | b |
| Create Worktree | w |
| Tag | t |
| Toggle Selected Branch | Shift+T |
| Solo Selected Branch | Space |
Press Ctrl+a, then one of these keys.
| Command | Default key after Ctrl+a |
|---|---|
| Drop Stash | x |
| Pop Stash | p |
| Stash Worktree | Shift+S |
| Checkout | o |
| Hard Reset | Shift+H |
| Mixed Reset | Shift+M |
| Force Push | Shift+P |
| Push Tags | Shift+V |
| Delete Branch | Shift+D |
| Remove Worktree | Shift+W |
| Toggle Worktree Lock | Shift+L |
| Delete Tag | Shift+U |
| Cherry-pick | y |
| Rebase | r |
| Merge | m |
| Continue Rebase/Cherry-pick/Merge | Shift+C |
| Abort Rebase/Cherry-pick/Merge | Shift+A |
Operations depend on the focused pane and selected row. Most operations call reload on success so the graph, status, panes, and recent path state refresh.
Normal key: s.
- Graph focus on the uncommitted row stages all unstaged changes, including untracked files and deletes.
- Status bottom focus stages the selected unstaged file.
- Conflict rows cannot be staged from the UI. Resolve conflicts externally, then continue the active operation.
Ignored files are not staged.
Normal key: u.
- Graph focus on the uncommitted row unstages all staged files with a mixed reset to
HEAD. - Status top focus unstages the selected staged file.
- In a repository without
HEAD, unstaging a file removes it from the initial index. - Conflict rows cannot be unstaged from the UI.
Normal key: c.
Commit opens a single-line commit message prompt when staged changes exist. The commit uses the configured user.name and user.email. If the branch is unborn, the commit becomes the root commit.
Normal key: f.
Fetch runs as a background network operation against origin.
It fetches:
refs/heads/*intorefs/remotes/origin/*.refs/tags/*into local tags.
Pruning is enabled.
Action key: Ctrl+a, then o.
Checkout is forceful and uses libgit2 checkout options with conflicts allowed.
- Branch pane focus checks out the selected branch.
- If the selected branch is local, it is checked out directly.
- If the selected branch is remote,
guitarmaterializes a local branch using the remote branch's short name, sets upstream to the remote branch, and checks it out. - Graph focus checks out the selected commit.
- If the commit has no branch label, graph checkout uses detached HEAD.
- If the commit has one branch label, that branch is checked out.
- If the commit has multiple branch labels, a checkout modal lets you choose.
The uncommitted row cannot be checked out.
Normal keys:
Shift+T: toggle selected branch visibility.Space: solo selected branch.
Branch visibility filters graph roots and branch labels.
- From branch pane focus, the action applies to the selected branch.
- From graph focus, the action applies to branch labels on the selected commit.
- If multiple branch labels are present, a modal lets you choose.
- When no branches are hidden, toggling one branch creates an explicit "all except this branch" visibility set.
- If filtering would hide every branch, the filter resets to all visible.
Normal key: b.
- Graph focus creates a local branch at the selected commit.
- Reflog focus creates a local branch at the selected reflog entry's new commit.
- Branch creation does not check out the new branch.
- The selected uncommitted row is not a branch target.
Action key: Ctrl+a, then Shift+D.
- Branch pane focus deletes the selected branch.
- Graph focus deletes a branch label attached to the selected commit.
- If multiple deletable labels exist, a modal lets you choose.
- The current branch cannot be deleted.
- Local branch deletion removes the local branch ref.
- Remote branch deletion pushes an empty source refspec to the selected remote branch.
Remote deletion derives the remote from the branch name. For example, origin/topic deletes topic from origin.
Create tag: normal key t.
Delete tag: action key Ctrl+a, then Shift+U.
- Tag creation creates a lightweight local tag at the selected commit.
- If the graph is on the uncommitted row, tag creation targets the first real commit.
- Tag deletion from the tag pane deletes the selected local tag.
- Tag deletion from the graph deletes a tag attached to the selected commit. If multiple tags exist, a modal lets you choose.
guitarcan push local tags, but it does not delete remote tags.
Force push current branch: action key Ctrl+a, then Shift+P.
Push tags: action key Ctrl+a, then Shift+V.
- Branch push targets
origin. - Branch push is force push only and updates the current local branch on the remote branch with the same name.
- Detached HEAD cannot be pushed.
- Tag push pushes all local tags to
origin. - If no local tags exist, push-tags succeeds without changing anything.
Stash current work: action key Ctrl+a, then Shift+S.
Pop selected stash: action key Ctrl+a, then p.
Drop selected stash: action key Ctrl+a, then x.
- Stash includes untracked files.
- Stash messages are generated from the current
HEADshort SHA and summary. - Pop applies the stash and drops it.
- Drop removes the stash without applying it.
- Pop/drop operate only when graph focus is on a stash row.
Hard reset selected commit: action key Ctrl+a, then Shift+H.
Mixed reset selected commit: action key Ctrl+a, then Shift+M.
Discard selected status file: focus a status row and use action key Ctrl+a, then Shift+H.
- Graph hard reset moves the current branch or detached
HEADto the selected commit and rewrites index and working tree. - Graph mixed reset moves the current branch or detached
HEADto the selected commit and rewrites the index while leaving working tree contents. - File hard reset removes staged and working tree changes for the selected path by restoring it from
HEAD.
Action key: Ctrl+a, then y.
- Graph focus on a commit opens a single-line message prompt.
- The default message is
cherrypicked: <selected summary>. - The working tree must be clean before starting.
- If there are no conflicts,
guitarcommits immediately with the provided message. - If conflicts occur,
guitarstops and shows a conflict modal. - Resolve files externally, then continue with
Ctrl+a,Shift+C. - Abort with
Ctrl+a,Shift+A.
During an in-progress conflicted cherry-pick, the message is stored at .git/GUITAR_CHERRYPICK_MSG and removed on commit or abort.
Action key: Ctrl+a, then r.
- Rebases the current local branch onto the selected graph commit.
- Detached HEAD cannot be rebased.
- The selected commit cannot already be
HEAD. - The working tree must be clean before starting.
- Commits are driven through libgit2's rebase API.
- If conflicts occur, resolve files externally, then continue with
Ctrl+a,Shift+C. - Abort with
Ctrl+a,Shift+A.
If a rebase, cherry-pick, or merge is already in progress, pressing the rebase action attempts to continue the active operation.
Action key: Ctrl+a, then m.
- Merges the selected graph commit into the current local branch.
- Detached HEAD cannot be merged into.
- Another in-progress Git operation blocks merge start.
- The working tree must be clean before starting.
- Merge analysis honors Git's fast-forward preferences, including
merge.ff=only. - Fast-forward, up-to-date, normal merge commit, conflict, and abort states are surfaced in the UI.
- Continue with
Ctrl+a,Shift+C. - Abort with
Ctrl+a,Shift+A.
If a rebase, cherry-pick, or merge is already in progress, pressing the merge action attempts to continue the active operation.
Continue active operation: action key Ctrl+a, then Shift+C.
Abort active operation: action key Ctrl+a, then Shift+A.
These apply to active rebase, cherry-pick, or merge states.
On continue, guitar checks the index for conflicts. For conflicted paths, it inspects the worktree file:
- If the file still contains conflict markers, it remains conflicted.
- If the file exists and conflict markers are gone, it is added to the index.
- If the file was removed, it is removed from the index.
Then the active Git operation continues.
Create worktree: normal key w.
Remove worktree: action key Ctrl+a, then Shift+W.
Lock or unlock worktree: action key Ctrl+a, then Shift+L.
Open worktree: focus a worktree row and press Enter; or press Enter on a graph worktree badge.
Create worktree flow:
- Focus the graph on a real commit.
- Press
w. - Enter a worktree name.
- Confirm or edit the default path.
The worktree name becomes a new local branch name. Names cannot be empty, ., .., or contain path separators. If worktree creation fails after branch creation, guitar attempts to delete the branch it created.
Default worktree paths are based on the current repository path:
<repo-parent>/<repo-name>-<worktree-name>
Removal rules:
- Only linked worktrees can be removed.
- The current worktree cannot be removed.
- The main worktree cannot be removed.
- Locked worktrees cannot be removed.
- Valid worktrees are pruned with working-tree removal enabled.
Locking rules:
- Only valid linked worktrees can be locked.
- Locking opens a reason prompt. Empty reasons are allowed and become no reason.
- Locked linked worktrees can be unlocked with the same action.
Opening a worktree reloads the app at the selected worktree path.
Network auth is used for fetch, push current branch, push tags, and remote branch deletion.
For SSH remotes, guitar tries:
- Username from the URL or callback, falling back to
git. ssh-agentvia libgit2.- A default private key without passphrase.
- An in-app passphrase prompt if a default private key exists.
Default private key search order:
~/.ssh/id_ed25519
~/.ssh/id_ecdsa
~/.ssh/id_rsa
If no ssh-agent credential works and none of those keys exist, the operation fails with an SSH auth error.
For HTTP/HTTPS remotes, guitar tries:
- Any matching secret already entered during the current
guitarsession. - Git credential helper through libgit2.
- Username callback if requested by libgit2.
- In-app username/password or username/token prompt.
Use a personal access token as the password when your hosting provider requires token auth.
- A network operation allows up to 3 auth prompt attempts.
- Rejected in-memory secrets are evicted before retry.
- Prompted secrets are stored only in memory for the running process.
- No prompted SSH passphrases, HTTPS passwords, or HTTPS tokens are written to
guitarconfig files. - Existing Git credential helpers may store credentials according to your Git configuration; that storage is outside
guitar.
Only one network operation can run at a time.
Open settings with ?.
The settings view includes:
- App version.
- Commit heatmap.
- Config file paths.
- Recent repositories.
- Git
user.nameanduser.email. - Auth behavior notes.
- Theme list.
- Layout visibility toggles.
- Normal-mode shortcuts.
- Action-mode shortcuts that differ from normal mode.
Selectable rows:
- Recent repository rows:
dremoves,Shift+Kmoves up, andShift+Jmoves down. - Theme rows:
Enteractivates and saves the selected theme. - Layout visibility rows:
Entertoggles the row or resets layout. - Keybinding rows:
Enteropens key capture.
Settings reuses normal navigation. Use j/k, page keys, g, Shift+G, or mouse wheel to move. Use h, Esc, or ? to return to the graph.
Available built-in themes:
classic
ansi
monochrome
dracula dark
dracula light
monokai dark
monokai light
catppuccin dark
catppuccin light
atom dark
atom light
vscode dark
vscode light
solarized dark
solarized light
gruvbox dark
gruvbox light
nord
tokyo night
tokyo night storm
tokyo night light
github dark
github light
github dark dimmed
night owl
light owl
ayu dark
ayu mirage
ayu light
material
palenight
rose pine
rose pine moon
rose pine dawn
kanagawa wave
kanagawa dragon
kanagawa lotus
everforest dark
everforest light
zenburn
horizon
synthwave 84
base16 tomorrow
base16 ocean
base16 eighties
matrix
Saved app files live under your platform config directory in a guitar folder.
Common examples:
Linux: ~/.config/guitar
macOS: ~/Library/Application Support/guitar
Windows: %APPDATA%\guitar
The app writes:
keymap.json: keyboard mappings.layout.json: pane visibility, widths, weights, SHA display, graph reflog setting, zen/minimal state.theme.json: active theme and all color slots.recent.json: recent repository paths.
The app may also temporarily write .git/GUITAR_CHERRYPICK_MSG inside a repository during a conflicted cherry-pick.
Not persisted by guitar:
- SSH key passphrases entered in the auth modal.
- HTTPS usernames, passwords, or tokens entered in the auth modal.
- Branch visibility filters. They are preserved across reloads during a session, but not written to config.
- Current selection, scroll positions, open modal state, or current viewport.
Reset all saved app config:
guitar --resetkeymap.json has normal and action arrays.
Example entry:
{
"key": "Char(j)",
"modifiers": [],
"command": "ScrollDown"
}Supported key strings include:
Backspace
Enter
Left
Right
Up
Down
Home
End
PageUp
PageDown
Tab
BackTab
Delete
Insert
Null
Esc
CapsLock
ScrollLock
NumLock
PrintScreen
Pause
F(n)
Char(x)
Supported modifiers:
Shift
Control
Ctrl
Alt
Command
Meta
Supported commands are the command names listed in the keymap tables, without spaces, for example ToggleSplitDiffMode, FocusPaneRight, ResizePaneRight, RemoveRecentRepository, CreateWorktree, ContinueOperation, and AbortOperation.
When an old keymap is loaded, guitar attempts small migrations for newly added default bindings.
Default layout:
{
"is_shas": true,
"is_minimal": false,
"is_branches": true,
"is_tags": false,
"is_stashes": false,
"is_reflogs": false,
"is_graph_reflogs": false,
"is_worktrees": false,
"is_status": true,
"is_inspector": true,
"is_zen": false,
"width_left_pane": 45,
"width_right_pane": 46,
"weight_branches": 100,
"weight_tags": 100,
"weight_stashes": 100,
"weight_reflogs": 100,
"weight_worktrees": 100,
"weight_inspector": 100,
"weight_status": 100,
"weight_status_top": 100,
"weight_status_bottom": 100,
"weight_viewer_split_left": 100,
"weight_viewer_split_right": 100
}Width values are clamped to a minimum of 16 columns. The center pane keeps at least 20 columns when possible. Stacked pane weights are normalized to at least 1. Split viewer weights may exist in older configs, but the split divider is always centered.
The graph reflog toggle requires a reload because it changes graph roots.
theme.json stores a label and full color map. Loading a known preset label without custom colors resolves to that preset. Unknown labels or color overrides become a custom theme.
Example:
{
"label": "solarized dark",
"colors": {
"red": "#dc322f",
"green": "#859900",
"blue": "#268bd2",
"grey_950": "#002b36",
"border": "#073642",
"text": "#839496",
"highlighted": "#93a1a1"
}
}Color values can be:
- Hex colors like
#268bd2. - Terminal color names such as
red,green,blue,gray,dark_gray,light_red,white, orreset. - Indexed terminal colors like
indexed:42orindexed_42.
Color slots:
red, pink, purple, durple, indigo, blue, cyan, teal, green, grass,
lime, yellow, amber, orange, grapefruit, brown, dark_red,
light_green_900, grey_50, grey_100, grey_200, grey_300, grey_400,
grey_500, grey_600, grey_700, grey_800, grey_900, grey_950,
border, text, highlighted
Malformed theme files fall back to classic and are rewritten.
recent.json is a JSON array of absolute repository root paths:
[
"/home/me/src/project-a",
"/home/me/src/project-b"
]Recent repositories are appended when a repository opens successfully. They can be removed or reordered from the splash screen or the settings recent repositories section.
Build:
cargo build
cargo build --releaseRun from source:
cargo run -- .
cargo run -- ../path/to/repositoryTest:
cargo testFormat:
cargo fmtThe value printed by guitar --version comes from Cargo package metadata. Release builds can override it at compile time with GUITAR_BUILD_OVERWRITE_VERSION.
Important source areas:
src/main.rs: CLI flags and app startup.src/app/app.rs: main app state, event loop, draw orchestration, reload, graph worker sync.src/app/input/: keyboard, mouse, modal, navigation, Git, and worktree input handlers.src/app/draw/: TUI drawing for graph, panes, viewer, settings, status, and modals.src/core/: graph worker, walker, topology buffer, pane data, render helpers.src/git/actions/: mutating Git operations.src/git/queries/: repository reads, diffs, commits, reflogs, worktrees.src/git/auth.rs: network credential classification, prompting, and session cache.src/helpers/: keymaps, layout persistence, themes, recent repos, symbols, text, colors.
- No filesystem watcher. Use reload when repository state changes outside the app.
- Network operations are remote-name limited and mostly assume
origin. - Current branch push is force push only.
- No pull UI.
- Conflict resolution editing is external.
- Worktree move/repair and custom separate worktree branch names are not implemented.
- Submodules are ignored in commit diffs.
- Merge commit file lists and file diffs compare against the first parent only.
- The graph renderer models ordinary two-parent merges; octopus merges are not a first-class display target.
- Tag creation is lightweight only.
- No annotated-tag message flow.
- No remote tag deletion flow.
- Branch rename, remote management, and branch upstream editing are not implemented.
- Search matches loaded commit SHA prefixes only.
- Search does not match commit messages, authors, branches, tags, filenames, or unloaded history.
- Recent repositories are append-only from inside the app.
- Branch visibility is not persisted between app launches.
- Text prompts are single-line.
Planned or desired features include jujutsu integration, richer worktree management, richer in-app conflict resolution, and more.
Follow the project board for current work: