LLM Commit Messages

Worktrunk generates commit messages by building a templated prompt and piping it to an external command. This integrates with wt merge, wt step commit, and wt step squash.

Setup

Install llm

llm from Simon Willison is recommended:

$ uv tool install -U llm

Configure an API key

For Claude (recommended):

$ llm install llm-anthropic
$ llm keys set anthropic

For OpenAI:

$ llm keys set openai

Add to user config

Create the config file if it doesn't exist:

$ wt config create

Then add the commit generation settings to ~/.config/worktrunk/config.toml:

[commit-generation]
command = "llm"
args = ["-m", "claude-haiku-4.5"]

Or for OpenAI:

[commit-generation]
command = "llm"
args = ["-m", "gpt-4o-mini"]

How it works

When worktrunk needs a commit message, it builds a prompt from a template and pipes it to the configured LLM command. The default templates include the git diff and style guidance.

Usage

These examples assume a feature worktree with changes to commit.

wt merge

Squashes all changes (uncommitted + existing commits) into one commit with an LLM-generated message, then merges to main:

$ wt merge
🔄 Squashing 3 commits into a single commit (5 files, +48)...
🔄 Generating squash commit message...
   feat(auth): Implement JWT authentication system
   ...

wt step commit

Stages and commits with LLM-generated message:

$ wt step commit

wt step squash

Squashes branch commits into one with LLM-generated message:

$ wt step squash

See wt merge and wt step for full documentation.

Prompt templates

Worktrunk uses minijinja templates (Jinja2-like syntax) to build prompts. There are sensible defaults, but templates are fully customizable.

Template variables

All variables are available in both templates:

VariableDescription
{{ git_diff }}The diff (staged changes or combined diff for squash)
{{ branch }}Current branch name
{{ recent_commits }}Recent commit subjects (for style reference)
{{ repo }}Repository name
{{ commits }}Commit messages being squashed (chronological order)
{{ target_branch }}Branch being merged into

Custom templates

Override the defaults with inline templates or external files:

[commit-generation]
command = "llm"
args = ["-m", "claude-haiku-4.5"]

template = """
Write a commit message for this diff. One line, under 50 chars.

Branch: {{ branch }}
Diff:
{{ git_diff }}
"""

squash-template = """
Combine these {{ commits | length }} commits into one message:
{% for c in commits %}
- {{ c }}
{% endfor %}

Diff:
{{ git_diff }}
"""

Or load templates from files (supports ~ expansion):

[commit-generation]
command = "llm"
args = ["-m", "claude-haiku-4.5"]
template-file = "~/.config/worktrunk/commit-template.txt"
squash-template-file = "~/.config/worktrunk/squash-template.txt"

Template syntax

Templates use minijinja, which supports:

See wt config create --help for the full default templates.

Alternative tools

Any command that reads a prompt from stdin and outputs a commit message works:

# aichat
[commit-generation]
command = "aichat"
args = ["-m", "claude:claude-haiku-4.5"]

# Custom script
[commit-generation]
command = "./scripts/generate-commit.sh"

Fallback behavior

When no LLM is configured, worktrunk generates deterministic messages based on changed filenames (e.g., "Changes to auth.rs & config.rs").

Resources: llm documentation | aichat