Guides agents through using the Jujutsu (jj) version control system. Activate when the user mentions jj, jujutsu, or when working in a repository with a .jj directory...
This skill helps you work with Jujutsu, a Git-compatible VCS with mutable commits and automatic rebasing.
Tested with jj v0.37.0 - Commands may differ in other versions.
When running as an agent, always use -m flags to provide messages inline rather than relying on editor prompts:
# Always use -m to avoid editor prompts
jj desc -m "message" # NOT: jj desc
jj new -m "message" # NOT: jj new (then describe separately)
jj squash -m "message" # NOT: jj squash (which opens editor)
jj commit -m "message" # NOT: jj commit
Editor-based commands will fail in non-interactive environments.
In jj, your working directory is always a commit (referenced as @). Changes are automatically snapshotted when you run any jj command. There is no staging area.
CRITICAL: Unlike git, jj commits can be freely modified. This enables a high-quality commit workflow:
squash, split, or absorb as neededtqpwlqmp) that persists when a commit is rewritten3ccf7581) that changes when commit content changesPrefer using Change IDs when referencing commits in commands.
Always create your commit message before writing code:
# First, describe what you intend to do
jj desc -m "Add user authentication to login endpoint"
# Then make your changes - they automatically become part of this commit
# ... edit files ...
# Check status
jj st
Each commit should represent ONE logical change. Use this format for commit messages:
"Verb object" - exactly one sentence, no period
Examples:
- "Add validation to user input forms"
- "Fix null pointer in payment processor"
- "Remove deprecated API endpoints"
- "Update dependencies to latest versions"
# View recent commits
jj log
# View with patches
jj log -p
# View specific commit
jj show <change-id>
# View diff of working copy
jj diff
# Create a new empty commit on top of current
jj new
# Create new commit with message
jj new -m "Commit message"
# Edit an existing commit (working copy becomes that commit)
jj edit <change-id>
Move changes from current commit into its parent:
# Squash all changes into parent
jj squash
# Squash interactively (choose what to move)
jj squash -i
Divide a commit that does too much:
# Split current commit interactively
jj split
# Split a specific commit
jj split -r <change-id>
Automatically distribute changes to the commits that last modified those lines:
# Absorb working copy changes into appropriate ancestor commits
jj absorb
Remove a commit entirely (descendants are rebased to its parent):
jj abandon <change-id>
Bookmarks are jj's equivalent to git branches:
# Create a bookmark at current commit
jj bookmark create my-feature
# Move bookmark to a different commit
jj bookmark move my-feature -r <change-id>
# List bookmarks
jj bookmark list
# Delete a bookmark
jj bookmark delete my-feature
# Clone a git repository
jj git clone <url>
# Initialize jj in an existing git repo
jj git init --colocate
In a colocated repository (where both .jj/ and .git/ exist), you can use both jj and git commands. However, there are important considerations:
Switching to git mode (e.g., for merge workflows):
# First, ensure your jj working copy is clean
jj st
# Then checkout a branch with git
git checkout <branch-name>
Switching back to jj mode:
# Use jj edit to resume working with jj
jj edit <change-id>
# Or simply run any jj command - it will snapshot the working copy
jj st
Important notes:
NOTE: You are likely working on a mirrored clone of the repository, not the original. This mirror has its own remote configured.
When the user asks you to push changes:
# Push a specific bookmark to the remote
jj git push -b <bookmark-name>
# Example: push the main bookmark
jj git push -b main
Before pushing, ensure:
IMPORTANT: Unlike git branches, jj bookmarks do not automatically move when you create new commits. You must manually update them before pushing:
# Move an existing bookmark to the current commit
jj bookmark move my-feature --to @
# Then push it
jj git push -b my-feature
If no bookmark exists for your changes, create one first:
# Create a bookmark at the current commit
jj bookmark create my-feature
# Then push it
jj git push -b my-feature
jj allows committing conflicts - you can resolve them later:
# View conflicts
jj st
# Resolve conflicts with external tool
jj resolve
# Continue working despite conflicts - jj allows this
IMPORTANT: Because commits are mutable, always refine them:
jj show @ or jj diffjj split to separate themjj squash or jj absorb| Action | Command |
|---|---|
| Describe commit | jj desc -m "message" |
| View status | jj st |
| View log | jj log |
| View diff | jj diff |
| New commit | jj new -m "message" |
| Edit commit | jj edit <id> |
| Squash to parent | jj squash |
| Split commit | jj split |
| Auto-distribute | jj absorb |
| Abandon commit | jj abandon <id> |
| Create bookmark | jj bookmark create <name> |
| Push bookmark | jj git push -b <name> |