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:
Configure an API key
For Claude (recommended):
For OpenAI:
Add to user config
Create the config file if it doesn't exist:
Then add the commit generation settings to ~/.config/worktrunk/config.toml:
[]
= "llm"
= ["-m", "claude-haiku-4.5"]
Or for OpenAI:
[]
= "llm"
= ["-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 step commit
Stages and commits with LLM-generated message:
wt step squash
Squashes branch commits into one with LLM-generated message:
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:
| Variable | Description |
|---|---|
{{ 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:
[]
= "llm"
= ["-m", "claude-haiku-4.5"]
= """
Write a commit message for this diff. One line, under 50 chars.
Branch: {{ branch }}
Diff:
{{ git_diff }}
"""
= """
Combine these {{ commits | length }} commits into one message:
{% for c in commits %}
- {{ c }}
{% endfor %}
Diff:
{{ git_diff }}
"""
Or load templates from files (supports ~ expansion):
[]
= "llm"
= ["-m", "claude-haiku-4.5"]
= "~/.config/worktrunk/commit-template.txt"
= "~/.config/worktrunk/squash-template.txt"
Template syntax
Templates use minijinja, which supports:
- Variables:
{{ branch }},{{ repo | upper }} - Filters:
{{ commits | length }},{{ repo | upper }} - Conditionals:
{% if recent_commits %}...{% endif %} - Loops:
{% for c in commits %}{{ c }}{% endfor %} - Loop variables:
{{ loop.index }},{{ loop.length }} - Whitespace control:
{%- ... -%}strips surrounding whitespace
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
[]
= "aichat"
= ["-m", "claude:claude-haiku-4.5"]
# Custom script
[]
= "./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