Configuration

Use this guide when the Settings screen does not expose the change you need. The configuration file supports key remapping, status layout, background fetching, custom commands, and changes to Magritte’s command menus.

Edit the configuration

Press , or choose Magritte > Settings to change common options such as themes, fonts, editors, and the keymap preset. The Settings screen writes the global configuration file:

$XDG_CONFIG_HOME/magritte/config.toml

If XDG_CONFIG_HOME is not set, Magritte uses:

~/.config/magritte/config.toml

Create the file if it does not exist. Magritte uses its defaults for every setting you omit, so a useful configuration can stay small:

appearance = "dark"
dark_theme = "Dracula"
editor = "zed"
keymap_preset = "evil"

[keymap]
"K" = "branch-delete"

For a fully annotated file with every supported section and setting type, see config.example.toml. Every entry in it is commented out, so you can copy it into place and uncomment what you want to change.

Magritte reloads the file after every save. A valid reload shows a short confirmation in the status bar. If the file is invalid, the status bar shows the error. At startup, Magritte falls back to its defaults. During a live reload, it keeps the last valid configuration instead.

An invalid theme, appearance mode, or key binding produces a warning and uses the default for that value. Fix the value and save again to clear the warning.

Choose what to customize

  • Use [keymap] to bind, remap, or unbind keys. Bindings can be one key or a sequence such as g r.
  • Use [status] to choose which sections appear in the status view and how they are ordered.
  • Use [fetch] to fetch in the background on a schedule.
  • Use [[command]] to add a shell command to the command palette and keymap.
  • Use [transient.<id>] to add, move, or remove entries in a command menu.
  • Use a per-repository configuration when one repository needs different behavior.

Magritte does not embed a scripting language. Custom commands run through the shell, and transient configuration changes the existing menu model.

Per-repo settings

Place a sparse override at .git/magritte/config.toml when one repository needs different settings. Set only the values that differ from your global configuration:

# .git/magritte/config.toml
dark_theme = "Nord Dark"

[fetch]
auto = true
interval_minutes = 10

The Settings screen’s Open repo config button creates and opens this file. Magritte watches it immediately. If you create the .git/magritte directory outside Magritte while the app is running, restart Magritte once so it can begin watching the directory.

The file is inside the Git directory, so it is not committed. Repositories with multiple worktrees share the same override.

Magritte loads the global configuration first, then applies the repository configuration using these rules:

  • A top-level value such as dark_theme, font, or editor replaces the global value.
  • [keymap], [vim.keymap], and [transient.*] merge one entry at a time. Repository entries add or replace individual bindings.
  • [[command]] entries combine. A repository command replaces a global command with the same id.

Saved transient arguments have their own global and repository files. See Saved argument defaults.

Settings

All scalar settings are top-level TOML keys. Every setting is optional.

KeyValuesDefaultMeaning
appearance"auto" / "light" / "dark"autoFollow the system or force light or dark mode.
light_themetheme nameSelenized LightTheme used in light mode.
dark_themetheme nameSelenized DarkTheme used in dark mode.
fontfont familyplatform monospaceFont for code, diffs, and aligned rows.
ui_fontfont family / "system-ui"value of fontFont for menus, headings, and labels. Use "system-ui" for the platform font.
font_sizepixelssystem defaultBase UI size, clamped to 9—24. The macOS default is 13.
app_iconson-of-man / pipe / golconda / magicson-of-manDock and app-switcher icon on macOS. This does not change the icon in Finder.
editorcommand or app nameOS defaultEditor used by Open File (Return). See External file editor.
commit_in_editortrue / falsefalseWrite commit messages in commit_editor instead of the in-app editor.
commit_editorcommandnoneBlocking command used as GIT_EDITOR, such as zed --wait, code --wait, or nvim. Only used when commit_in_editor is true.
commit_title_rulertrue / falsetrueHighlight summary text after column 50.
commit_body_wraptrue / falsetrueWrap commit bodies at column 72 while preserving indentation. Wrapping pauses in Vim Normal and Visual modes.
commit_vim_modetrue / falsefalseEnable modal editing in the in-app commit editor. See Vim mode keys.
refresh_on_focustrue / falsetrueRefresh the repository when the window regains focus.
show_tags_in_title_bartrue / falsefalseShow the nearest reachable tag in the title bar.
check_for_updatestrue / falsetrueCheck for new releases and show a quiet notification.
keymap_preset"evil" / "vanilla"evilBase keymap applied before [keymap]. The legacy value "evil-collection" is also accepted.
which_key_delay_msmilliseconds1000Time before possible continuations appear for a key prefix or Vim sequence.
published_brancheslist of refs["origin/main", "origin/master"]Branches considered shared. Magritte warns before rewriting a commit reachable from one of them. Missing refs are ignored. Use [] to disable the warning.

Magritte saves the last 10 edited commit messages for each worktree. This includes messages discarded from the editor and messages from commits rejected by a hook. Press Alt-p in the commit editor to restore the newest message. Press it again to move through older messages. You can also run Restore commit message from the : palette.

Theme names match the entries under Light theme and Dark theme in Settings. Magritte includes GitHub, Solarized, Selenized, Gruvbox, Catppuccin, Nord, Dracula, and tao variants.

External file editor

Set editor to a command such as code -w, zed, or subl -w. On macOS, you can also use an application name such as "Zed" or "Visual Studio Code". Leave it empty to use the system default application.

Magritte opens supported editors at the line under the cursor. Terminal editors are not supported for Open File because Magritte cannot attach them to your existing terminal session.

Settings example

appearance = "dark"
light_theme = "Selenized Light"
dark_theme = "Dracula"
font = "Berkeley Mono"
editor = "zed"

commit_in_editor = false
commit_title_ruler = true
commit_body_wrap = true

Status sections

Use [status] to choose which sections appear and their order:

[status]
sections = [
  "untracked", "unstaged", "staged", "stashes",
  "unpulled", "unpulled-pushremote", "unpushed", "unpushed-pushremote",
  "recent",
]
recent_count = 10

sections is an ordered list. The list order becomes the display order, and an omitted section is hidden. Omit [status] or use an empty list to restore the default order shown above. Unknown section ids produce a warning.

Section idContents
untrackedUntracked files
unstagedChanges not yet staged
stagedStaged changes
stashesSaved stashes
unpulledCommits available from the upstream
unpushedLocal commits not on the upstream
unpulled-pushremoteCommits available from the push target
unpushed-pushremoteLocal commits not on the push target
recentThe last recent_count commits
ignoredIgnored files. Hidden by default

Push-target sections are hidden when the push target and upstream are the same. All empty sections are skipped. Commit rows show labels for branches, tags, and remotes.

Actions follow the item at the cursor. Return opens a commit or stash, while Cmd+C copies its hash or reference. On a stash, a applies it, A pops it, and x in the Evil preset or k in the Vanilla preset drops it after confirmation. On a section heading, s or u acts on the whole section. Discarded untracked files are moved to the system Trash.

Set show_tags_in_title_bar = true to show the nearest reachable tag. For example, v1.0 (5) means the current commit is five commits after v1.0.

Auto-fetch

Use [fetch] to keep incoming and outgoing commit counts current. Background fetching is off by default.

[fetch]
auto = true            # default false
interval_minutes = 30  # default 30; minimum 1

Magritte runs git fetch for the current branch’s configured remote, then refreshes the status view. It skips a fetch while another operation is running. If a fetch fails, for example while you are offline, Magritte waits until the next interval and tries again.

Put this table in .git/magritte/config.toml to enable fetching only for one repository.

Large repositories

If git status takes more than about half a second and no filesystem monitor is configured, Magritte suggests enabling one. Run Enable filesystem monitor from the : palette to set core.fsmonitor and core.untrackedCache for the repository. Git can then avoid repeatedly scanning the full working tree.

Magritte shows this suggestion once per repository. It does not appear when core.fsmonitor already has a value, including false.

As a git mergetool

Use Magritte’s conflict view from terminal-driven merges and rebases by configuring it as your Git mergetool in your .gitconfig:

[merge]
    tool = magritte
[mergetool "magritte"]
    cmd = magritte --mergetool "$MERGED"
    trustExitCode = true

Run git mergetool to open each conflicted file in Magritte. Resolve the conflicts and confirm the finish prompt. Magritte returns success only when the file has no unresolved conflict markers, which lets Git stage it. Closing the window before then reports failure for that file.

Keymap

The default evil preset follows evil-collection-magit. Use vanilla for standard Magit and Emacs keys. The Vanilla preset includes P for push, X for reset, z for stash, k for discard, and n or p for section motion.

Add a [keymap] table to change either preset. Each entry maps a key to a command id. Use "unbound" to remove a binding.

keymap_preset = "evil"

# TOML requires top-level settings to appear before this table.
[keymap]
"K" = "branch-delete"   # K now deletes a branch
"x" = "unbound"         # remove the default discard binding
"E" = "commit-extend"   # E now extends the current commit
  • Keys are case-sensitive. For example, s and S are different bindings.
  • Write sequences with spaces between their keys, such as g r or ctrl-x ctrl-c. A sequence can contain any number of keys.
  • Write modifiers as ctrl-, alt-, or cmd-. Use an uppercase letter for Shift, such as G rather than shift-g.
  • Prefixes do not need separate bindings. If you bind ". c" = "commit", . automatically becomes a prefix. Magritte shows the entered prefix and, after which_key_delay_ms, its available continuations.
  • Unknown command ids produce a warning and are ignored. Pressing an unbound key also shows a short notice.

The same keymap controls the status view, logs, commit views, the rebase editor, and the command log. These secondary bindings are useful when remapping:

KeysAction
arrows, ctrl-n / ctrl-pMove the cursor
spacePage down. On a commit or stash, open it first
ctrl-d / ctrl-uMove down or up half a page
ctrl-f / ctrl-bMove down or up one page
ctrl-j / ctrl-kMove to the next or previous section in Evil
alt-j / alt-k / ] / [Move to the next or previous sibling section in Evil
n / p, alt-n / alt-pSection motions in Vanilla
alt-1 through alt-4Set fold level 1 through 4
z a, z o, z c, z O, z C, z 1 through z 4, z rVim-style folds in Evil
g z, g n, g i, g u, g s, g f u, g f p, g p u, g p pJump to status sections in Evil
y y / y s, y b, y rCopy the current value, copy the revision, or show refs in Evil
ctrl-wCopy the current value
v / VStart a visual selection in Evil
ctrl-spaceStart a visual selection in Vanilla
alt-< / alt->Move to the top or bottom in Vanilla
hOpen help in Vanilla. ? works in either preset
GRefresh in Vanilla
|Run a command in Evil
ctrl-x ctrl-cQuit Magritte

Some keys are fixed and cannot be remapped:

  • Esc and Ctrl-g cancel a job, selection, pending sequence, or popup.
  • Tab expands or collapses the current item. You can bind another key to fold, but Tab keeps this behavior.
  • ? opens help.
  • An unbound :, Alt-x, Cmd-P, or Cmd-K opens the command palette.

Transient menus, pickers, and the commit editor handle their own keys while they are active.

Vim mode keys ([vim.keymap])

Set commit_vim_mode = true to enable Normal, Insert, and Visual modes in the in-app commit editor. It supports counts, text objects, d, c, and y operators, surround commands, indentation, repeat, regex search, substitutions, prompt history, and undo.

Use ZZ or ,, to commit. Use ZQ or ,k to cancel. gq reformats a line, motion, or visual selection, while ,q reformats the whole message. For full Vim behavior, use an external editor instead:

commit_in_editor = true
commit_editor = "nvim"

A [vim.keymap] table adds your own key sequences for the editor-level commands: commit, cancel, discard (cancel without the confirmation), reflow (the whole message), and help.

[vim.keymap]
"Q" = "cancel"      # a single key
";w" = "commit"     # press ; and then w
"gz" = "help"
  • Write Vim sequences as literal characters with no spaces. Modifier chords are not supported. Case matters, so Q means Shift-Q.
  • Custom entries add to the defaults. An exact match replaces the default. For example, "ZZ" = "cancel" changes the built-in ZZ action.
  • The first key of a custom sequence shadows its normal Vim action. Mapping "dx" makes d wait for x, so it no longer starts the delete operator. Choose prefixes you do not otherwise need.
  • A pending sequence appears beside the mode indicator. After the configured delay, Magritte shows its possible continuations.
  • Repository settings merge these entries one at a time. Unknown actions are ignored. Changes apply to an editor that is already open.

Command ids

Bind any id below from [keymap]. none in the default-key column means the command has no direct binding, but you can still find it in a transient menu or the : command palette.

The palette shows only commands that apply to the current view and selection. For example, jump-to-ignored appears only when the Ignored section is visible. Some keys also change with context. On a commit, a applies that commit. On a file, it stages the file.

Search accepts common Git terms as well as Magritte’s command names. add finds Stage, restore finds Discard, yank finds Copy, and history finds Log.

iddefault keycommand
commitcCommit (transient)
branchbBranch (transient)
tagtTag (transient)
remoteMRemote (transient)
stashZStash (transient)
resetOReset (transient)
rebaserRebase (transient)
mergemMerge (transient)
ignoreiIgnore (transient)
loglLog (transient)
diffdDiff (transient)
worktreeZ (vanilla) / %Browse worktrees (visit / add / branch / move / remove)
pushpPush (transient)
pullFPull (transient)
fetchfFetch (transient)
patchWPatch (transient: create patches, apply a diff, git am a mailbox)
bisectBBisect (transient; marks good/bad/skip/reset while a bisect runs)
blamenoneBlame the file at point
run!Run a Git or shell command in the repository root or selected file’s directory
git-command| (evil) / :, Q (vanilla)Run a command directly (git by default)
stagesStage the selection
unstageuUnstage the selection
stage-allSStage all tracked changes (confirms if a file is partially staged)
unstage-allUUnstage all (confirms if a file is partially staged)
discardxDiscard the selection
untrackK (vanilla) / X (evil)Untrack the file at point (git rm --cached)
open-fileReturnOpen file at point in editor
open-commit / stash-showReturnShow the commit / stash at point
commit-applyaApply the changes of the commit at point
commit-cherry-pickACherry-pick transient for the commit at point
revert-here_ (evil) / V (vanilla)Revert transient for the commit at point
revert-changes- (evil) / v (vanilla)Revert the commit at point’s changes without committing
reset-hereo (evil) / x (vanilla)Reset HEAD (mixed) to the commit at point (confirmed)
stash-row-apply / stash-row-popa / AApply / pop the stash at point
stash-row-dropx (evil) / k (vanilla)Drop the stash at point (confirmed)
commit-details=Toggle the details panel in a commit view
foldTabFold / unfold
cycle-foldsshift-tabCycle every fold through sections, everything, and folded
fold-show / fold-hide / fold-show-children / fold-hide-childrenevil z o / z c / z O / z CExplicit fold verbs (vim’s zo/zc/zO/zC)
resolve-conflictseResolve the conflicted file at point in the smerge-style view
diff-more-context+More diff context lines
diff-less-context-Fewer diff context lines
diff-default-context0Default diff context (3 lines)
refreshg r (evil) / g (vanilla)Refresh status
visualvToggle visual selection
yanky y (evil) / Ctrl-w, Cmd+CCopy the value at point
copy-buffer-revisiony b (evil)Copy the current view’s revision
show-refsy (vanilla) / y r (evil)Browse branches, remotes, tags (Return visits the tip commit; b checkout, x/k delete, R rename)
settings,Open Settings
command-log$Open the command log
closeq (and Esc)Close the current secondary screen
commit-restore-messagenoneRestore a saved message in the commit editor
fsmonitor-enablenoneEnable Git’s filesystem monitor for the repository
check-updatesnoneCheck for updates
aboutnoneShow the About panel and version
move-downjMove cursor down
move-upkMove cursor up
goto-topg gJump to top
goto-bottomGJump to bottom
next-sectionctrl-jNext file, commit, or hunk section in the status view
prev-sectionctrl-kPrevious section start (status view)
next-sibling-sectiong jNext section at the same depth
prev-sibling-sectiong kPrevious section at the same depth
section-up^Jump to the parent section
show-level-1 through show-level-41 through 4Fold to sections, files, hunks, or everything
status-jumpvanilla jJump-to-section menu (magit-status-jump)
jump-to-untracked / jump-to-unstaged / jump-to-staged / jump-to-stashes / jump-to-ignorednoneJump to a file or stash section
jump-to-unpulled-upstream / jump-to-unpulled-pushremote / jump-to-unpushed-upstream / jump-to-unpushed-pushremotenoneJump to an incoming or outgoing commit section
half-page-downctrl-dScroll down half a page
half-page-upctrl-uScroll up half a page
page-downctrl-fScroll down a page
page-upctrl-bScroll up a page
helpvanilla hOpen the ? help menu
quitctrl-x ctrl-cQuit Magritte
commit-createnoneCreate commit
commit-amendnoneAmend commit
commit-rewordnoneReword commit
commit-extendnoneExtend commit and keep its message
branch-checkoutnoneCheck out a branch or revision
branch-createnoneCreate branch
branch-create-checkoutnoneCreate and check out a branch
branch-renamenoneRename branch
branch-deletenoneDelete branch
push-pushremote / push-upstream / push-elsewhere / push-other / push-tag / push-tagsnonePush variants
pull-pushremote / pull-upstream / pull-elsewherenonePull variants
fetch-pushremote / fetch-upstream / fetch-all / fetch-elsewherenoneFetch variants
stash-push / stash-index / stash-keep-index / stash-apply / stash-pop / stash-drop / stash-branchnoneStash variants
stash-snapshot / stash-snapshot-index / stash-snapshot-worktreenoneRecord the state on the stash list without resetting anything
merge-editmsg / merge-previewnoneEdit a merge message or preview a merge
reset-branch / file-checkoutnoneReset a branch or check out a file from a revision
tag-create / tag-deletenoneTag variants
remote-add / remote-rename / remote-removenoneRemote variants
log-current / log-all / log-other / log-file / log-reflognoneLog variants
diff-dwim / diff-range / diff-unstaged / diff-staged / diff-worktree / diff-commitnoneDiff variants
cherry-pick / cherry-pick-range / cherry-applynoneCherry-pick or apply commits
revert / revert-range / revert-no-commitnoneRevert commits with or without committing

Secondary views add scoped ids that can be remapped in the same way. These include refs-*, worktree-*, flat-*, rebase-todo-*, resolve-*, log-open, and git-log-toggle-queries. Open the : palette in a view to see every command available there.

Transients

Transient menus are the command menus opened by keys such as c, b, and p. Use [transient.<id>] to add an action or Git option, move an existing entry, or remove one. Valid ids include commit, branch, tag, remote, stash, reset, rebase, merge, ignore, log, diff, push, pull, and fetch.

[transient.branch]
"X" = "branch-delete"          # b X deletes a branch

[transient.fetch]
"-d" = "--depth=1"             # add a Git option

[transient.commit]
"A" = "commit-amend"           # add an action to the Custom group
"-v" = { flag = "--verbose", description = "Show diff in message", after = "-s" }
"W" = { command = "user.wip", group = "Create" }
"f" = { after = "c" }          # move Fixup after Commit
"F" = { group = "Edit" }       # move Instant fixup into Edit
  • An action names a command id and runs with its default arguments.
  • A switch contains a Git option such as "--depth=1". Use a table when you also want a description or placement. Switch keys begin with a dash, so -d appears under the menu’s - prefix.
  • Use before or after to place an entry beside another key. Use group to append it to a named group. Magritte creates a missing group at the end.
  • A table that contains only before, after, or group moves the built-in entry at that key.
  • Set an entry to "unbound" to remove it. For example, "-n" = "unbound" removes commit’s --no-verify option.

Entries apply in file order, with global entries before repository entries. This lets a later entry refer to one added earlier. A built-in keeps its key if a custom entry tries to reuse it. Invalid menu ids, command ids, and switch keys produce a warning.

Config-derived switches

Some switches start with the value from your Git configuration:

Menu optionGit configuration
commit --gpg-signcommit.gpgSign
pull --rebasepull.rebase or branch.<name>.rebase
fetch --prunefetch.prune
rebase --autosquashrebase.autoSquash

Turning one of these switches off passes its negated form, such as --no-gpg-sign. Magritte highlights the switch to show that it overrides your Git configuration.

Saved argument defaults

Press Ctrl-s in a transient menu to save its current options as the defaults for the next time you open it. Magritte asks where to save them:

  • Press g for all repositories. Magritte writes transient-arguments.toml beside your global configuration.
  • Press l for the current repository. Magritte writes .git/magritte/transient-arguments.toml.
  • Press Esc to cancel.

The file stores Git arguments rather than menu keys, so key remapping does not affect saved defaults:

commit = ["--all", "--signoff"]
log = ["-n50", "--grep=fix"]

A repository entry replaces the global entry for the same transient. Other global entries still apply. Delete an entry to fall back to the global or built-in defaults.

A config-derived switch is saved only when you change it from the Git-config value. Leaving it untouched continues to follow Git configuration. Both files reload automatically, and edits apply the next time you open the menu.

Commands

Use [[command]] to make a shell command available in the : palette and the keymap.

[[command]]
id = "user.sync"
title = "Sync"
run = "git pull --rebase && git push"
refresh = true                  # refresh afterward. This is the default

[[command]]
id = "user.wip"
title = "WIP commit"
run = "git commit -a -m WIP"
section = "My commands"         # group in the ? menu when bound

run executes through sh -c in the repository root. Shell operators, pipes, and redirection work, and the command can run any program. For example, run = "make test" is valid.

Command placeholders

Magritte shell-quotes each placeholder before inserting it into run:

PlaceholderValue
{file}File at the cursor
{commit}Commit at the cursor in status, log, or a commit view
{branch}Current branch
{upstream}Current branch’s upstream, such as origin/main
{push-remote}Resolved push remote, such as origin
{default-branch}Branch selected by the remote’s HEAD, such as main
{default-remote}Remote that owns the default branch, or the push remote as a fallback

If a required value is unavailable, the command does not run. For example, a command containing {file} reports an error when no file is selected.

Titles can also contain placeholders. A title such as "Rebase onto origin/{default-branch}" displays as Rebase onto origin/main. If a title placeholder cannot be resolved, it remains visible as written.

Bind a custom command by id, for example "X" = "user.wip", or run it by title from the command palette. Bound commands also appear in the ? menu under their section, which defaults to Commands.

Command output appears in a notification. Failures remain until dismissed, and long output points to the $ command log for the full text. Commands containing clean, --hard, --force, or --force-with-lease ask for confirmation.

An empty run, duplicate id, or id that matches a built-in produces a warning. Use the ! menu for a command you do not need to save.