jj-commit is a command-line tool designed to simplify and standardize commit messages in Jujutsu (jj) workflows. It provides interactive prompts that enforce either Conventional Commits or Gitmoji conventions, eliminating the need to remember formatting rules.
Key Features:
Auto-Detection: Automatically identifies the project's preferred convention by analyzing recent commit history.
Interactive Prompts: Guides users through creating consistent and well-formatted commit messages.
Convention Support: Supports both Conventional Commits (e.g., feat, fix) and Gitmoji conventions (e.g., ✨, 🐛).
Pre-Fill Options: Allows pre-filling of commit types, scopes, or descriptions for efficiency.
Cross-Platform Compatibility: Built in Rust for reliability and performance.
Audience & Benefit:
Ideal for developers using Jujutsu to maintain consistency across projects. jj-commit helps reduce errors, saves time, and ensures that commit messages adhere to established standards, making collaboration more efficient.
README
jj-commit
> A guided, convention-aware commit-message builder for Jujutsu.
jjc wraps the jj workflow with interactive prompts that enforce a consistent commit style — either Conventional Commits or Gitmoji — so you never have to remember the format again.
🎯 Convention auto-detection — Inspects the last 10 commits and picks the convention used most often. No flags needed for the common case.
✍️ Two conventions, one tool — Full support for Conventional Commits (feat:, fix(scope):, …) and Gitmoji (✨, 🐛, …).
🔀 Interactive prompts — Type, scope(s), and description are gathered through prompts with sensible defaults and pre-fill support.
🧩 Pre-fill everything — Pass --message, --type, and --scopes to seed the prompts or skip them entirely. Great foraliases and editor integrations.
🏷️ Bookmarks — Advance the nearest ancestor bookmark, or create/move named bookmarks to the new commit. Supports interactive selection when multiple ancestors match.
git clone https://github.com/Odonno/jj-commit
cd jj-commit
cargo build --release
# binary is at ./target/release/jjc
Get started
Auto-detect convention
With no flags, jjc inspects the last 10 commits and picks the convention used most often.
jjc
? Commit type
> feat
fix
chore
docs
style
refactor
perf
[↑↓ to move, enter to select]
? Scope (leave empty to finish): auth
? Description: add OAuth2 login support
--message works with Gitmoji too, accepting both the shortcode (:bug:) and raw emoji (🐛) forms.
Gitmoji workflow
jjc --convention gitmoji
? Gitmoji
> ✨ Introduce new features.
🐛 Fix a bug.
🚑️ Critical hotfix.
📝 Add or update documentation.
♻️ Refactor code.
🔥 Remove code or files.
[↑↓ to move, enter to select]
? Description: streaming support for chat API
Use --advance-bookmark (-a) to find the closest ancestor that holds a local bookmark and move it onto the newly created commit — handy for keeping a moving "main"-style bookmark pinned to your latest work:
jjc -a
If that ancestor carries several bookmarks, you get an interactive multi-select:
? Select bookmarks to advance to the new commit:
> [x] main
[x] release
[ ] wip
[↑↓ to move, space to toggle, enter to confirm]
With a single bookmark the choice is applied automatically. If no ancestor has any bookmark, jjc prints a warning instead of failing.
Create or move named bookmarks
Use --bookmarks (-b, repeatable) to point one or more bookmarks at the new commit, creating them if they don't exist:
jjc -b feature-x -b v2
Combine the two
The two flags cooperate: --bookmarks destinations are applied directly, while --advance-bookmark discovers ancestors interactively. They can be used together in a single invocation:
jjc reads the same configuration the jj CLI does, in the same order:
Built-in defaults from jj-lib.
User config file — $JJ_CONFIG (colon-separated, like $PATH), or otherwise $XDG_CONFIG_HOME/jj/config.toml (falling back to ~/.config/jj/config.toml), the legacy ~/.jjconfig.toml, and %APPDATA%\jj\config.toml on Windows.
Environment overrides — JJ_USER sets user.name and JJ_EMAIL sets user.email, taking precedence over the config file.
So if you've already configured jj, you're configured for jjc — nothing extra to do.
Supported conventions
Conventional Commits types
The --type / --convention conventional flow knows these types:
Type
Use for
feat
A new feature
fix
A bug fix
chore
Maintenance tasks that don't touch src/docs
docs
Documentation only changes
style
Formatting, whitespace, semicolons, etc.
refactor
Code changes that neither fix a bug nor add a feature
perf
Performance improvements
test
Adding or correcting tests
build
Build system or external dependencies
ci
CI configuration files and scripts
revert
Reverting a previous commit
The breaking-change marker (feat!:) is parsed from --message but not added by a prompt — use --message when you need it.
Gitmoji
The Gitmoji flow ships the full gitmoji.dev table (80+ entries), presented with their description. Both the shortcode (:sparkles:) and raw emoji (✨) forms are recognized when pre-filling with --message.
How it works
Unlike a thin wrapper that calls out to the jj binary, jjc links against jj-lib and performs the commit transaction in-process:
Loads your real jj stacked config and workspace (mirroring the jj CLI's lookup rules).
Snapshots the working copy — respecting .gitignore and auto-tracking new files, just like jj's default snapshot.auto-track = "all()".
Rewrites the open working-copy commit with the snapshotted tree and your crafted message.
Rebases any descendants, then checks out a fresh empty working-copy commit on top.
Syncs the Git index and HEAD for co-located Git repos so the Git view matches Jujutsu.
Optionally advances bookmarks before or after the commit lands.
This means you get the same resulting topology as jj commit — without spawning jj.