Skip to content

Custom keybindings

This page lists every rebindable action in gitoui, global UserEvents first, then each per-view scope, with the default keys, what each action does, and how to override them.

Two layers : the global map covers everything ([keybind] in TOML), scopes override the global map inside a specific view ([keybind.scope.<path>]).

When you press a key in a given view, gitoui walks this chain:

  1. Leaf scope, the deepest scope the view exposes (e.g. pr.conversation, rebase.resume). If the key is bound here, fire the action.
  2. Parent scopes, walk up one level at a time. From pr.conversation → pr. From rebase.resume → rebase.
  3. Global, the [keybind] section.
  4. Literal forward, neither matched → the view gets the raw key event for its own char-level matches (rare).

The key fires the first action it matches. Once a leaf binds a key, parents are skipped.

Inheritance, sub-views see their parent’s bindings

Section titled “Inheritance, sub-views see their parent’s bindings”

A sub-view automatically inherits every key its parent scope defines. You only need to list a binding in the leaf scope if you want it to override the parent.

For example, in the PR view:

  • r is reload (defined in [scope.pr]).
  • The Conversation tab inherits that, pressing r there still reloads the PR.
  • But r is also bindable inside [scope.pr.conversation]. If you set it there, the conversation-level binding wins only on that tab.
  • Once you leave the tab, r falls back to the PR-wide reload.

The same chain runs in: pr.list → pr → global, issues.detail → issues → global, rebase.resume → rebase → global, etc.

By contrast, the same key across different scopes is fine, that’s the whole point of scopes:

[keybind]
stage = ["a"] # global: `a` stages a file in Uncommitted
[keybind.scope.pr]
approve = ["a"] # in PR: `a` approves, overrides the global `stage`
[keybind.scope.issues]
assignees_picker = ["a"] # in Issues: `a` opens the assignees picker

When you’re in the PR view, a fires approve (and the global stage is silent). The global stage only fires in views without a scoped binding on a.

Merge semantics, overrides REPLACE, not extend

Section titled “Merge semantics, overrides REPLACE, not extend”

If your config sets approve = ["ctrl-a"], the default a → approve binding is dropped, only Ctrl+A triggers approve. To keep both, list them both explicitly:

[keybind.scope.pr]
approve = ["a", "ctrl-a"] # both keys fire approve

Anything you don’t touch keeps its full default key list.

gitoui accepts at most one modifier prefix per key ctrl-X alt-X shift-X. Chained combos like ctrl-shift-a are rejected at config-load.

Each key is a string. Format: [modifier-]base. Examples: q, ctrl-s, shift-h, f5, enter, esc, space.

Base key Accepted spellings
Letters a, b, … z (case-insensitive, shift-a and A are the same event).
Digits 0–9
Function f1 … f12
Arrows up, down, left, right
Whitespace space, tab, backtab
Editing enter, esc, backspace, delete, insert
Page nav home, end, pageup, pagedown
Punctuation The character itself: ], +, #, =, -
Modifiers ctrl-, alt-, shift- (max one prefix).

Empty array unbinds a default key entirely:

[keybind]
go_to_parent = [] # no key fires GoToParent

Available from every view. Use the action name on the left, give it any list of keys.

Action Default What it does
force_quit ctrl-c Hard-quit, bypass any confirmation.
quit q Quit from the list / close the active view.
help_toggle ? f1 Open / close the in-app Help page.
cancel esc Cancel current action, close overlays, back out.
close (unbound) Alternate “close view” hook for custom flows.
config p Open the Configuration view.
pull_requests shift-r Open the PR list (needs GitHub auth).
issues shift-i Open the Issues list (needs GitHub auth).
Action Default What it does
navigate_up k up Move cursor up.
navigate_down j down Move cursor down.
navigate_left h left Move cursor / focus left.
navigate_right l right Move cursor / focus right.
go_to_parent alt-j alt-down Drill into the parent commit / branch.
select_up shift-k Extend selection up.
select_down shift-j Extend selection down.
go_to_top g Jump to the top of the list.
go_to_bottom shift-g Jump to the bottom.
scroll_up ctrl-y Scroll one line up (cursor stays).
scroll_down ctrl-e Scroll one line down.
page_up ctrl-b pageup Page up.
page_down ctrl-f pagedown Page down.
half_page_up ctrl-u Half-page up.
half_page_down ctrl-d Half-page down.
select_top (unbound) Position cursor at the top of the viewport.
select_middle shift-m Position cursor at the middle of the viewport.
select_bottom shift-l Position cursor at the bottom of the viewport.
confirm enter Drill into the focused item.
go_to_next n Jump to the next search match.
go_to_previous shift-n Jump to the previous search match.
ref_list tab Toggle the refs panel from the list view.
Action Default What it does
search f Open the search bar in the list / diff view.
ignore_case_toggle s Toggle case-insensitive search in active mode.
fuzzy_toggle z Toggle fuzzy search.
Action Default What it does
refresh r Reload the view’s state from disk / API.
mark_compare space Mark an endpoint for the 2-commit comparison flow.
push shift-p git push (current branch).
pull shift-u git pull, also doubles as unstage_all / pull_branch in their respective views.
short_copy shift-c Copy short hash / short ref.
full_copy c Copy full hash / commit message / path.
Action Default What it does
add_tag t Add a tag on the focused commit.
create_branch shift-b Create a new branch starting at the focused commit.
blame b Open blame for the focused file.
checkout o Checkout the focused commit / branch.
cherry_pick shift-o Cherry-pick the focused commit.
drop d Drop the focused commit (interactive rebase).
merge m Merge the focused branch into current.
rebase e Open the interactive rebase plan editor.
reset shift-s git reset to the focused commit (mixed by default).
squash ctrl-s Squash the focused commit into its parent.
amend_commit ctrl-m Amend HEAD’s commit message (HEAD only).
file_history shift-h git log --follow on the focused file.
abort_operation ctrl-a Abort an in-progress rebase / merge / cherry-pick.
Action Default What it does
rename_branch ctrl-r Rename the focused branch.
delete_branch shift-d Delete the focused branch.
push_branch shift-q Push the focused branch.
pull_branch (unbound) Pull the focused branch, aliased on shift-u via the pull action in the BranchDetail view.
set_upstream ctrl-t Set / change the upstream for the focused branch.
create_archive shift-e git archive the focused branch / tag.
unselect_branch shift-t Clear the branch-detail selection.
copy_branch_name shift-v Copy the focused branch name.
delete_tag shift-f Delete the focused tag.
push_tag shift-w Push the focused tag.
copy_tag_name shift-y Copy the focused tag name.
Action Default What it does
stage a Stage the focused file (or open the conflict editor if the file is unmerged).
stage_all shift-a Stage every unstaged + untracked file.
unstage u Unstage the focused file.
unstage_all (unbound) Unstage every staged file, aliased on shift-u via pull in the Uncommitted view.
discard x Discard the focused unstaged change (confirmation).
discard_all shift-x Discard every unstaged + staged change (confirmation).
stash i Stash the working tree.
commit w Open the commit message editor.
clean_untracked v Clean (delete) the focused untracked file.
Action Default What it does
apply_stash y Apply the focused stash.
pop_stash ctrl-p Pop the focused stash.
drop_stash ctrl-x Drop the focused stash.
create_branch_from_stash ctrl-n Create a new branch from the stash.
copy_stash_name ctrl-i Copy the stash name.
copy_stash_hash ctrl-o Copy the stash hash.
Action Default What it does
cycle_file_next + Jump to the next file in the current diff.
cycle_file_prev - Jump to the previous file.

User-defined shell commands (configured under [core.user_command]) bind through synthetic actions named user_command_N, where N matches the commands_N entry. None ship with a default key, every binding is user-set.

[keybind]
user_command_1 = ["f5"]
user_command_2 = ["f6"]

Full setup, placeholders and execution types live on the User commands page.

Each scope below ships with its own default key map. Anything you don’t list there keeps its parent / global default, you only need to write the action you want to change.

Inherits from: [keybind] (global).

Action Default What it does
select_head_commit h Scroll to and center the HEAD commit in the viewport.

h is navigate_left globally; in the list view it has no left/right semantics so the scope reuses it for “jump to HEAD”.

Inherits from: [keybind] (global).

Action Default What it does
revert v Open the Revert confirmation dialog for the focused commit.

v globally is clean_untracked (uncommitted view). In commit-detail there’s nothing to clean, so the scope re-purposes v for revert matches the action shown in the Git Actions panel (Revert (v)).

Inherits from: [keybind] (global). Applies on any tab inside an open PR.

Action Default What it does
reload r Reload PR data from the GitHub API.
approve a Submit an approving review.
request_changes x Submit a changes-requested review.
merge m Open the merge dialog.
open_in_browser o Open the PR’s URL via xdg-open / open.
labels_picker l Open the labels picker.
reviewers_picker v Open the reviewers picker.
close_pr ctrl-x Close the PR (confirmation).
reopen_pr ctrl-o Reopen a closed PR.
toggle_draft ctrl-d Toggle ready ↔ draft state.

Inherits from: [keybind.scope.pr] → [keybind].

Action Default What it does
new_pr n Open the new-PR compose form.

[keybind.scope.pr.conversation], PR Conversation tab

Section titled “[keybind.scope.pr.conversation], PR Conversation tab”

Inherits from: [keybind.scope.pr] → [keybind].

Action Default What it does
new_comment c Open the comment editor overlay.
quote_reply shift-r Quote-reply to the focused comment.
edit_own e Edit your own focused comment.
delete_own d Delete your own focused comment (confirmation).
react + Open the emoji picker on the focused comment.

Inherits from: [keybind] (global). Applies on any tab of an open issue.

Action Default What it does
reload r Reload issue data from the GitHub API.
labels_picker l Open the labels picker.
assignees_picker a Open the assignees picker.
milestone_picker m Open the milestone picker.
close_or_reopen x Close an open issue / reopen a closed one (confirmation).
open_in_browser o Open the issue’s URL in the browser.

Inherits from: [keybind.scope.issues] → [keybind].

Action Default What it does
new_issue n Open the new-issue compose form.

[keybind.scope.issues.detail], Issue Conversation / Timeline

Section titled “[keybind.scope.issues.detail], Issue Conversation / Timeline”

Inherits from: [keybind.scope.issues] → [keybind].

Action Default What it does
new_comment c Open the comment editor overlay.
quote_reply shift-r Quote-reply to the focused comment.
reference_in_new_issue shift-n Open Compose pre-filled with a back-reference link.
edit_own e Edit your own focused comment.
delete_own d Delete your own focused comment (confirmation).
react + Open the emoji picker on the focused comment.

[keybind.scope.rebase], Interactive rebase plan editor

Section titled “[keybind.scope.rebase], Interactive rebase plan editor”

Inherits from: [keybind] (global).

Action Default What it does
pick p Pick, keep the focused commit.
reword r Reword, keep but open the inline subject editor.
edit e Edit, pause the rebase at this commit.
squash s Squash into the previous commit, keep both messages.
fixup f Fixup, combine + drop this message.
drop d Drop, remove the commit.
grab space Grab the focused row to reorder it with ↑↓.
abort_previous shift-a Abort a stale rebase that’s still active on disk.

[keybind.scope.rebase.resume], Resume prompt

Section titled “[keybind.scope.rebase.resume], Resume prompt”

Inherits from: [keybind.scope.rebase] → [keybind]. Shown when a rebase is paused.

Action Default What it does
continue_rebase c shift-c git rebase --continue.
skip_commit s shift-s git rebase --skip.
abort a shift-a git rebase --abort.

[keybind.scope.rebase.reword_editor], Reword inline editor

Section titled “[keybind.scope.rebase.reword_editor], Reword inline editor”

Inherits from: [keybind.scope.rebase] → [keybind]. Word-jump keys inside the inline subject editor.

Action Default What it does
delete_word_left ctrl-h ctrl-w ctrl-backspace Delete one word to the left.
delete_word_right ctrl-delete Delete one word to the right.
word_left ctrl-left Jump cursor one word left.
word_right ctrl-right Jump cursor one word right.

[keybind.scope.conflict], 3-way conflict editor

Section titled “[keybind.scope.conflict], 3-way conflict editor”

Inherits from: [keybind] (global).

Action Default What it does
pick_ours o Pick OURS for the focused hunk.
pick_theirs t Pick THEIRS.
pick_both_ours_first b Keep BOTH, OURS lines first.
pick_both_theirs_first shift-b Keep BOTH, THEIRS lines first.
next_hunk n Move to the next conflict hunk.
prev_hunk p Move to the previous conflict hunk.

Inherits from: [keybind] (global). Shared by new PR / new Issue / new comment / reply editors.

Action Default What it does
submit ctrl-s Submit the compose form to the GitHub API.

The mention popup (#), word-jump editing keys, and Esc to cancel stay hardcoded, they’re shared text-input semantics, not view actions.

Keep h/j/k/l pure for navigation, move scrolling off the home row.

[keybind]
half_page_up = ["ctrl-u"]
half_page_down = ["ctrl-d"]
[keybind.scope.list]
# Free `h` if you don't want the HEAD-jump action. An empty array drops
# it, the global `navigate_left` (still `h`) wins.
select_head_commit = []

gitoui validates the full keybind tree at boot and refuses to start on:

  • Duplicate key in the same scope, a bound to two different actions under the same [keybind.scope.<path>].
  • Unknown action name, typo in a TOML key.
  • Unknown key spelling, e.g. superkey-a.
  • More than one modifier, ctrl-shift-a.

The diagnostic block points at the offending line, column, scope, and expected schema, same style as the TOML-syntax + theme validators.