Originally published on 2026-01-08
Original article (Japanese): jj-desc: Rust製のjjコミットメッセージ自動生成ツールをリリース
We have released a CLI tool called jj-desc that automatically generates commit messages for Jujutsu (jj) using LLMs.
jj is a Git-compatible version control tool developed by Google, known for its powerful undo functionality and flexible commit operations through revset (revision set). The generated commit messages adhere to the Conventional Commits format. A significant feature of jj-desc is its ability to generate multiple commit messages in bulk, leveraging the unique characteristics of jj.
Main Features of jj-desc
Support for Multiple LLM Providers
jj-desc supports the following LLM providers:
- OpenRouter (default)
- OpenAI
- Anthropic
- Google Gemini
- Custom endpoints (Azure OpenAI, Ollama, etc.)
You can easily switch between them using environment variables or CLI options:
export LLM_PROVIDER=anthropic
export ANTHROPIC_API_KEY="sk-ant-..."
jj-desc
Backfill Functionality Utilizing revset
The greatest strength of jj-desc is its backfill functionality, which allows for bulk generation of commit messages by utilizing revset.
Revset is jj's unique query language that allows for flexible specification of a set of commits (revisions). It provides powerful features not found in Git, enabling you to freely select targets by combining set operations (&, |, ~) and condition filters.
# Current commit
jj-desc -r @
# Process all of my commits in bulk
jj-desc -r "mine()"
# Range from the main branch to HEAD
jj-desc -r "@..main"
# Mutable commits without descriptions (default)
jj-desc -r "::@ & mutable()"
# Process 5 commits without descriptions in bulk
jj-desc -r "::@ & mutable()" -n 5
Why is backfill important?
During development, it's common to "commit for now" and want to organize messages later. In Git, rewriting commit messages with git rebase -i can be cumbersome. Tools like aicommits primarily generate messages for "the content being committed now."
jj-desc is different. By combining jj's editable commit history with revset, it allows for bulk message generation for past commits. You can focus on your work, accumulate commits, and then simply run jj-desc when you’re ready. This is the true value of jj-desc.
The following demo shows jj-desc being executed on multiple commits without descriptions, generating messages in bulk:
Immediate Application Without Confirmation Prompts
jj-desc applies the generated commit messages immediately without confirmation. While this may seem bold, it is designed with jj's powerful undo functionality (jj undo, jj op log) in mind.
In Git tools, it's common to ask, "Do you really want to apply this?" However, in the jj ecosystem, the natural workflow is "try it, and if it doesn't work, undo." All operations are recorded in history and can be easily reverted, making confirmation prompts an unnecessary friction.
Of course, if you prefer to confirm carefully, options like --dry-run (preview) and -i (interactive mode) are also available:
# Preview only (do not apply)
jj-desc --dry-run
# Apply while confirming one by one
jj-desc -i -r "mine()"
Diff Optimization and Token Savings
Before sending diffs to the LLM, the following optimizations are automatically performed:
- Automatic exclusion of lock files (
Cargo.lock,package-lock.json, etc.) - Simplification of binary files (
Binary file {path} changed) - User-specified exclusion patterns (using the
--excludeoption) - Warning for diffs exceeding 50KB
This balances cost reduction for LLM API calls and avoidance of context limits.
# Exclude specific files
jj-desc --exclude "*.json" --exclude "*.yaml"
# Shortened form
jj-desc -x "docs/*" -x "*.lock"
Automatic Detection of Merge Commits
In jj, many merge commits are treated as "empty" (see jj FAQ). jj-desc automatically detects merge commits and sets appropriate descriptions ("Merge commit") without needing an LLM API call.
Installation
Homebrew (Recommended)
brew install tumf/tap/jj-desc
Prebuilt Binaries
You can obtain binaries for each platform from the release page:
# macOS (Apple Silicon)
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/tumf/jj-desc/releases/latest/download/jj-desc-installer.sh | sh
# Linux (x86_64)
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/tumf/jj-desc/releases/latest/download/jj-desc-installer.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -c \
"irm https://github.com/tumf/jj-desc/releases/latest/download/jj-desc-installer.ps1 | iex"
Build from Cargo
cargo install --git https://github.com/tumf/jj-desc
Basic Usage
Setting Up LLM Provider
First, set the API key for the LLM provider you wish to use:
# OpenRouter (default)
export OPENROUTER_API_KEY="your-api-key"
# Or OpenAI
export LLM_PROVIDER=openai
export OPENAI_API_KEY="sk-..."
# Or Anthropic
export LLM_PROVIDER=anthropic
export ANTHROPIC_API_KEY="sk-ant-..."
# Ollama (local LLM)
export LLM_PROVIDER=openai
export OPENAI_API_KEY="dummy"
export OPENAI_BASE_URL="http://localhost:11434/v1"
export LLM_MODEL="llama2"
Generating Commit Messages
# Default: Process all mutable commits without descriptions
jj-desc
# Only the current commit
jj-desc -r @
# All of my commits
jj-desc -r "mine()"
# Preview
jj-desc --dry-run
# Interactive mode
jj-desc -i
Differences from aicommit2
As an AI commit message generation tool for jj, aicommit2 has been around longer. aicommit2 is a TypeScript-based general tool that supports Git, YADM, and jj.
The main difference between the two is the presence of the backfill functionality:
| Feature | jj-desc | aicommit2 |
|---|---|---|
| Backfill (bulk processing of past commits) | ✅ Freely specified with revset | ❌ Current commits only |
| Supported VCS | jj only | Git, YADM, jj |
| Implementation Language | Rust | TypeScript |
| Confirmation Prompt | None (based on undo) | Yes |
| Diff Optimization | ✅ Automatic filtering | - |
aicommit2 is geared towards a "committing now" workflow. jj-desc is designed for a workflow where you "commit in bulk and organize messages later."
If you want to leverage jj's features to the fullest, use jj-desc; if you want to integrate with existing Git workflows, aicommit2 is recommended.
Conclusion
jj-desc's standout feature is its backfill functionality utilizing jj's revset. Focus on your work, accumulate commits, and generate messages later—this workflow is unique to jj and cannot be achieved with Git tools.
If you're a jj user, be sure to give it a try. We welcome feedback and feature suggestions on our GitHub repository.
Reference Links
- jj-desc GitHub Repository
- Jujutsu (jj) Official Documentation
- aicommit2 - AI commit tool supporting Git/YADM/jj
- OpenRouter
- Anthropic
- Google AI Studio

Top comments (0)