Skip to content

Custom commands

Bind your own shell commands to keys, in the panels where they make sense.

A custom command is a key, a panel, and a shell command. stage runs it with the thing under your cursor.

The commands use lazygit’s own template syntax, so a lazygit command: string works here without a change.

Add customCommands to the configuration file:

{
"customCommands": [
{
"key": "b",
"context": "commits",
"command": "git branch --contains {{ .SelectedCommit.Hash }}",
"description": "branches with this commit",
"output": "terminal"
}
]
}
Field Meaning
key The key you press
context The panel it works in: files, commits, branches, and the rest
command The shell command
description The text in the footer and in ?. The command itself, when absent
output terminal gives the command the screen. none runs it quietly
prompts Questions asked before the command runs

A placeholder takes its value from what is selected when the command runs:

{{ .SelectedFile.Name }} {{ .SelectedCommit.Hash }}
{{ .SelectedLocalBranch.Name }} {{ .SelectedTag.Name }}
{{ .SelectedStashEntry.Index }} {{ .RepoRoot }}

There are 32 of them, and they are the names lazygit uses. Every one is available in every context, so a command bound to the files panel can still read the selected commit.

{{ .X }} puts the value in as it is. {{ .X | quote }} puts it in quoted for the shell.

"command": "code {{ .SelectedFile.Name | quote }}"

CAUTION: Use | quote for anything that reaches a shell. A file name with a space or a quote in it changes what the command does.

stage matches lazygit here. lazygit interpolates raw and offers quote, so copying a working lazygit command gives you the behavior you already had.

prompts collects answers first. Each answer is available to the command, and to later prompts, as {{ .Form.<key> }}.

{
"key": "n",
"context": "branches",
"prompts": [
{ "type": "input", "key": "Name", "title": "New branch name" }
],
"command": "git switch -c {{ .Form.Name | quote }}"
}
Type Asks with
input A text field
menu A list of options you write
menuFromCommand A list built from the output of another command
confirm A yes or no question

A command with prompts shows the final command and asks you to confirm it. The confirmation takes y only, so an enter that repeats from the last prompt cannot run the command by accident.

This is lazygit’s syntax, not its engine. There is no {{if}}, no {{range}}, and no runCommand.

A template that names something stage does not know is an error at startup, and stage names the field. It never passes the text through to your shell.

stage --import copies your custom commands over, and the command strings stay exactly as they are. Read Coming from lazygit.

A command that uses a field stage does not have is reported by the import instead of being guessed at.