| name | onevcat-jj |
| description | Use jj (Jujutsu) for local version control instead of git. Activate when: the repo has a .jj/ directory, the user or project config mentions jj, the user says 'use jj', or any version control operation is needed in a jj-managed repo. Also use this skill when the user asks to commit, branch, stash, rebase, or perform any git-like operation in a repo that uses jj. If unsure whether the repo uses jj, check for a .jj/ directory. |
jj (Jujutsu) — Version Control for Agent Workflows
jj is a version control tool that coexists with Git. You use jj locally; the remote is still standard Git. GitHub and collaborators see ordinary git commits and branches.
This skill teaches you how to use jj correctly and idiomatically, especially in agent-assisted development workflows.
Core Mental Model
jj revolves around changes, not branches. Key differences from Git:
- No staging area. File modifications are automatically part of the current change. There is no
git add.
- No stash. Just
jj new to start fresh work; previous changes stay where they are.
- No detached HEAD.
jj edit lets you jump to any change and keep working; descendants auto-rebase.
- Branches are called bookmarks and are only needed when pushing to a remote.
The working copy IS a change. Every file modification is instantly tracked in the current change.
Detecting a jj Repo
Before performing version control operations, check if the repo uses jj:
test -d .jj && echo "jj repo"
When a repo has both .jj/ and .git/ (colocated mode), always prefer jj commands for local operations.
Setup
To initialize jj in an existing Git repo (colocated mode — keeps .git/ alongside .jj/):
jj git init --colocate
After init, you may need to track remote bookmarks so jj knows about remote branches:
jj bookmark track master@origin
jj will usually hint you about this if it's needed.
Essential Commands
Inspect State
jj log
jj diff
jj diff -r <change>
jj log output shows @ for the current change and short Change IDs (e.g., kxryzmsp). Change IDs are stable across rebases — use them freely as references. You can use unique prefixes (e.g., kx instead of kxryzmsp) as long as they are unambiguous.
Work on Changes
jj describe -m "feat: add auth module"
jj describe -r <change> -m "new msg"
jj new
jj new <change>
jj commit -m "feat: ..."
jj edit <change>
jj abandon
jj abandon <change>
jj new is your primary "next task" command. It seals the current change and gives you a fresh workspace. No add, no commit ceremony.
jj abandon discards a change completely. The change's modifications are absorbed into its parent. Use it to clean up empty changes, throw away unwanted work, or remove a change from a chain.
jj edit is safe: if the target change is immutable (already pushed to remote), jj will refuse with an error. You do not need to check this yourself.
After jj edit, modifying files amends that change in place. All descendant changes auto-rebase — you never need to manually rebase after editing an ancestor.
Reorganize History
jj split
jj split -r <change>
jj rebase -s <source> -d <destination>
jj rebase -d <destination>
jj undo
jj op log
jj op restore <operation-id>
jj split opens an interactive editor by default (when no filesets are given). Select which files/hunks belong to the first change; the rest automatically become the second. Repeat to split further.
jj undo undoes the last operation regardless of what it was — rebase, split, describe, anything. It is always safe. Nothing is ever truly lost in jj.
Remote Interaction (Git Bridge)
jj git fetch
jj rebase -d master
jj bookmark track master@origin
jj bookmark create my-feature -r @
jj bookmark create my-feature -r <chg>
jj bookmark set my-feature -r <change>
jj git push
jj git push --bookmark my-feature
jj git push --deleted
Remote Git branches are automatically mapped to jj bookmarks on fetch. The master (or main) you see in jj log IS the remote branch, accessed via bookmark.
After jj git init --colocate or when a new remote branch appears, you may need jj bookmark track <name>@<remote> to tell jj to follow it. jj will hint you when this is needed.
Workflow for pushing:
- Finish your work (describe the change)
jj bookmark create <name> -r <change> — give it a Git branch name
jj git push — push to remote (or --bookmark <name> for just one)
Cleanup after abandoning a pushed change:
When you jj abandon a change that had a bookmark pushed to remote, the bookmark is deleted locally. Use jj git push --deleted to sync that deletion to the remote.
Parallel Workspaces
jj workspace add ../workspace-name
Each workspace gets its own directory but shares the underlying repository store. Multiple agents can work in separate workspaces simultaneously from the same base, then merge results with jj new <change1> <change2> ....
Agent Workflow Patterns
These patterns leverage jj's strengths for agent-assisted development.
Pattern 1: Start Next Task
Just jj new and begin. No need to add, commit, push, or create a branch first. The previous change is automatically preserved.
jj new
jj describe -m "feat: implement avatar upload"
Pattern 2: Interrupt and Resume
To handle an urgent task mid-work:
jj new master
jj describe -m "fix: critical auth bug"
jj edit <previous-change>
No stash, no branch switching, no state to restore.
Pattern 3: Split After the Fact
After producing a large change, split it into logical pieces:
jj split
jj split
If a split goes wrong, jj undo and try again.
Pattern 4: Skeleton Planning (Recommended for Complex Tasks)
Create empty changes as a plan, then fill them in order:
jj commit -m "refactor: extract auth module"
jj commit -m "feat: add token refresh logic"
jj commit -m "test: update auth tests"
jj commit -m "docs: update API documentation"
Then work through them:
jj edit <first-change>
jj edit <next-change>
Each change's description serves as both the commit message and the acceptance criteria. Verify your implementation matches the description before moving on.
The description field supports the same format as git commit messages: first line is the title, blank line, then body. You can write detailed specs or prompts in the body with -m.
Pattern 5: Undo and Recover
jj undo
jj op log
jj op restore <op-id>
Prefer jj undo over trying to manually reverse changes. It is always correct and safe.
Common Mistakes to Avoid
- Do not use
git add, git commit, git stash, or git checkout in a jj repo. Use jj equivalents instead.
- Do not try to
jj edit an immutable (published) change without good reason. jj will block this. If you need to fix something in published history, use jj new <change> to create a follow-up change instead.
- Do not create bookmarks for local-only work. Bookmarks are only needed when pushing to remote. Local work is tracked by Change IDs.
- Do not worry about "losing" changes. jj's operation log preserves everything. Use
jj undo or jj op restore to recover from any mistake.
Quick Reference
| Task | jj command |
|---|
| Initialize in existing git repo | jj git init --colocate |
| See what's going on | jj log |
| Describe current change | jj describe -m "..." |
| Start next task | jj new |
| Branch from specific change | jj new <change> |
| Edit an older change | jj edit <change> |
| Discard a change | jj abandon / jj abandon <change> |
| Split a change | jj split |
| Undo anything | jj undo |
| Fetch remote | jj git fetch |
| Track a remote branch | jj bookmark track <name>@<remote> |
| Rebase onto master | jj rebase -d master |
| Create bookmark for push | jj bookmark create <name> -r @ |
| Move existing bookmark | jj bookmark set <name> -r <change> |
| Push to remote | jj git push |
| Push specific bookmark | jj git push --bookmark <name> |
| Push bookmark deletions | jj git push --deleted |
| Merge multiple changes | jj new <chg1> <chg2> ... |
| Parallel workspace | jj workspace add <path> |
Beyond This Skill
This skill covers the most common operations. For advanced usage not covered here, use:
jj help
jj help <command>
jj help -k <keyword>
jj has rich functionality (revsets, templates, custom aliases, conflict resolution, etc.) that you can explore via jj help and apply based on the situation. The official documentation is at https://jj-vcs.github.io/jj/.