Skip to content

Configuration file

tt-git works with no configuration at all. When you want to change something, put it in config.toml. Every setting is optional, and anything you leave out keeps its default.

tt-git reads config.toml from the first of these that is set:

LocationWhen
$TTGIT_CONFIG_DIR/config.tomlthe variable is set
$XDG_CONFIG_HOME/tt-git/config.tomlthe variable is set
~/.config/tt-git/config.tomlLinux and macOS
%APPDATA%\tt-git\config.tomlWindows

To use a different file for one run, pass it on the command line:

Terminal window
tt-git --config ~/tt-git-dev.toml

If the file doesn’t exist, tt-git uses the defaults. The same directory also holds plugins.json and plugin config folders; see Plugins overview.

This is every setting, at its default:

config.toml
watch = true # refresh when files or refs change outside tt-git
mouse = true # click, wheel, ctrl+click links
syntax = true # color code by language in diffs, staging and blame
[graph]
max_commits = 20000 # loaded at a time; scrolling near the end loads more
max_lanes = 16 # lanes drawn before collapsing into …
current_includes_upstream = true # current-branch mode also shows HEAD's upstream
dates = "relative" # "relative" (3h, 2d) or "clock" (2026-10-17 01:30 PM); graph and blame
[branches]
unmerged_exclude = ["archive"] # hide unmerged branches whose name contains any of these
safe_branches = ["master", "main", "production", "prod"] # never listed on the merged/unmerged tabs
[plugins]
pane_release_keys = ["ctrl+\\", "f12"] # leave or close plugin panes
[editor]
# command = "nvim" # unset: $VISUAL, $EDITOR, git's core.editor, then notepad / vi
# terminal = true # unset: worked out from the program
[agent]
command = "claude" # the agent A starts
placement = "auto" # a herdr tab inside herdr, else in place of details
# system_prompt = "" # unset: tt-git's own

Two more tables, [layout] and [keys], have pages of their own: Layout and Key bindings.

SettingDefaultWhat it does
watchtrueWatch the working tree and .git, and refresh when something changes outside tt-git. See Refreshing. With false, press ctrl+r to refresh.
mousetrueClick a pane or row to focus and select it (or a branches tab, a changed file, or a Filter graph entry), double-click a commit to open its files, scroll the pane under the pointer with the wheel, and ctrl+click links in the details pane. Turn it off to let your terminal handle the mouse (for example, to select text).
syntaxtrueColor code by language in diffs, the staging view and blame, with added and removed lines on a green or red background. With false, code is plain, and diffs show added lines in green and removed lines in red. See Code colors.
SettingDefaultWhat it does
max_commits20000How many commits the graph loads at a time. When the selection gets near the end, the next batch of this size loads.
max_lanes16How many lanes are drawn. Anything wider collapses into ….
current_includes_upstreamtrueIn current-branch mode (a in the graph), also show HEAD’s upstream, so you can see what you’d push or pull.
dates"relative"How dates start out in the graph and in blame: "relative" shows ages (3h, 2d), "clock" the local date and time (2026-10-17 01:30 PM). t in either switches both.

See Graph.

SettingDefaultWhat it does
unmerged_exclude["archive"]The Unmerged tab hides branches whose name contains any of these strings.
safe_branches["master", "main", "production", "prod"]Long-lived branches that are never listed on the Merged and Unmerged tabs, matched by exact name on any remote. Set it to [] to list them too.

See Merged and unmerged.

SettingDefaultWhat it does
pane_release_keys["ctrl+\\", "f12"]Keys that give focus back to tt-git from a split plugin pane, or close an overlay or popup pane. Written the same way as key bindings.

See Plugin panes.

The editor e opens a file in, from the status pane, the staging view, details and blame.

SettingDefaultWhat it does
commandunsetThe editor to run. Unset, tt-git uses the first of $VISUAL, $EDITOR and git’s core.editor that is set, else notepad on Windows and vi elsewhere. Quote a path with spaces: '"C:\Program Files\Notepad++\notepad++.exe" -multiInst'.
terminalunsettrue if the editor runs in the terminal, false if it opens a window of its own. Unset, tt-git works it out from the program’s name, and treats editors it doesn’t know as terminal ones.

tt-git adds the file, and the line when it knows one, in the form the editor understands:

EditorArguments added
vim, nvim, vi, gvim, nano, micro, emacs, emacsclient, kakoune (kak), joe, mg, ne+12 <file>
VS Code (code, code-insiders), VSCodium, Cursor, Windsurf--goto <file>:12
Helix (hx), Zed, Sublime Text (subl)<file>:12
Notepad++-n12 <file>
JetBrains IDEs (idea, pycharm, goland, rustrover, webstorm, clion, rider, phpstorm)--line 12 <file>
anything else, including Notepad<file>

The file is a full path, and the editor starts in the repository’s root. To pass the arguments yourself, put {file} and {line} in command. tt-git then adds nothing, and {line} is 1 when there’s no line to go to:

[editor]
command = "code --reuse-window --goto {file}:{line}"

A terminal editor gets the whole terminal: tt-git steps aside until you quit the editor, then comes back and refreshes. A GUI editor (VS Code, Cursor, Zed, Sublime Text, Notepad, Notepad++, gedit, Kate, TextMate, JetBrains IDEs) opens in its own window and tt-git keeps running.

The AI agent A starts from the graph. See Agent actions.

SettingDefaultWhat it does
command"claude"The agent to run, in the repository’s root. The prompt is added as its last argument, unless command has {prompt} (the prompt’s text) or {prompt_file} (a file holding it) in it.
placement"auto"Where it runs. "auto": a new herdr tab when tt-git runs inside herdr, else in place of the details pane. "herdr-tab" and "herdr-split" (a herdr pane beside tt-git’s) fall back to the details pane outside herdr; "details" always uses it.
system_promptunsetGoes ahead of every prompt, with the same placeholders. Unset, tt-git tells the agent which repository and branch it’s in, to read history with git, and not to push or commit unless asked. "" sends none.
actionsunsetThe ready-made actions tab steps through, as [[agent.actions]] tables. Unset, tt-git offers Resolve conflicts, Explain commit, Explain branch and Review commit. Setting it replaces them all.

Each [[agent.actions]] has:

FieldRequiredWhat it is
nameyesShown in the dialog and in the agent’s tab or pane title.
promptyesWhat the agent is asked. Placeholders such as {commit}, {branch}, {base}, {conflicts} and {log} are filled in; see What the agent is told.
descriptionnoOne line shown under the input while the action is selected.
whenno"always" (the default) or "merging": only while a merge, rebase, cherry-pick or revert is stopped, and then first.
[[agent.actions]]
name = "Write release notes"
description = "user-facing notes for this branch"
prompt = "Write release notes for what {branch} adds since {base}:\n{log}"

One setting lives in each repository rather than in config.toml: the base branch the Merged, Unmerged and Tags tabs compare against. Press b in the branches pane to pick it, and tt-git saves it as tt-git.baseBranch in that repository’s own git config (.git/config). Nothing is written to your global git config. See The base branch.

The UI owns the terminal, so tt-git writes its log to a file: <state>/logs/tt-git.log. <state> is the first of these that is set:

LocationWhen
$TTGIT_STATE_DIRthe variable is set
$XDG_STATE_HOME/tt-gitthe variable is set
~/.local/state/tt-gitLinux and macOS
%APPDATA%\tt-gitWindows

Plugin state lives under the same directory, in plugins/<id>/.

Set the level with TTGIT_LOG. It takes an EnvFilter string, and the default is info:

Terminal window
TTGIT_LOG=debug tt-git
TTGIT_LOG=tt_git_core=trace tt-git

Every running tt-git appends to the same file. When it has grown past 10 MB, the next tt-git to start renames it to tt-git.log.1 (replacing an older one) and starts a fresh tt-git.log.

Plugin runs have a log of their own; see Plugin logs.