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
Any command that reads a prompt from stdin and outputs a commit message works. Add to ~/.config/worktrunk/config.toml:
Claude Code
[commit.generation]
command = "CLAUDECODE= MAX_THINKING_TOKENS=0 claude -p --model=haiku --tools='' --disable-slash-commands --setting-sources='' --system-prompt=''"
CLAUDECODE= unsets the nesting guard so claude -p works from within a Claude Code session. The other flags disable tools, skills, settings, and system prompt for fast text-only output. See Claude Code docs for installation.
Codex
[commit.generation]
command = "codex exec -m gpt-5.1-codex-mini -c model_reasoning_effort='low' -c system_prompt='' --sandbox=read-only --json - | jq -sr '[.[] | select(.item.type? == \"agent_message\")] | last.item.text'"
Uses the fast mini model with low reasoning effort and an empty system prompt for faster output. Requires jq for JSON parsing. See Codex CLI docs.
Other tools
# opencode — use a fast model variant
command = "opencode run -m anthropic/claude-haiku-4.5 --variant fast"
# llm
command = "llm -m claude-haiku-4.5"
# aichat
command = "aichat -m claude:claude-haiku-4.5"How it works
When worktrunk needs a commit message, it builds a prompt from a template and pipes it to the configured command via shell (sh -c). Environment variables can be set inline in the command string.
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 the default branch:
$ 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 commitwt step squash
Squashes branch commits into one with LLM-generated message:
$ wt step squash
See wt merge and wt step for full documentation.
Branch summaries (experimental)
With summary = true and a [commit.generation] command configured, Worktrunk generates LLM branch summaries — one-line descriptions of each branch's changes since the default branch.
Summaries appear in:
wt switchinteractive picker — preview tab 5wt list --full— the Summary column (seewt list)
Enable in user config:
[list]
summary = true
Disabled by default — when enabled, each branch's diff is sent to the configured LLM for summarization. Results are cached until the diff changes.
Prompt templates
Worktrunk uses minijinja templates (Jinja2-like syntax) to build prompts. There are sensible defaults, but templates are fully customizable.
Custom templates
Override the defaults with inline templates:
[commit.generation]
command = "llm -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 }}
"""Template variables
| Variable | Description |
|---|---|
{{ git_diff }} | The diff (staged changes or combined diff for squash) |
{{ git_diff_stat }} | Diff statistics (files changed, insertions, deletions) |
{{ branch }} | Current branch name |
{{ repo }} | Repository name |
{{ recent_commits }} | Recent commit subjects (for style reference) |
{{ commits }} | Commits being squashed (squash template only) |
{{ target_branch }} | Merge target branch (squash template only) |
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.
Fallback behavior
When no LLM is configured, worktrunk generates deterministic messages based on changed filenames (e.g., "Changes to auth.rs & config.rs").