From jj-vcs
Load this skill BEFORE running any jj command (jj log, jj diff, jj new, jj commit, jj describe, jj split, jj squash, jj edit, jj rebase, jj bookmark, jj git push, jj abandon, jj restore, jj status, ...).
How this skill is triggered — by the user, by Claude, or both
Slash command
/jj-vcs:jjThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Jujutsu is a Git-compatible VCS. The working copy is automatically snapshotted
Jujutsu is a Git-compatible VCS. The working copy is automatically snapshotted
as a commit on every jj command — there is no staging area. All changes live
in @ (the working-copy commit) until you finalize them.
@ — The working-copy commit. @- is its parent..gitignore to exclude files.--ignore-immutable to
commands. Never modify immutable changes unless specifically instructed to do
so.| Command | Purpose |
|---|---|
jj st | Show working-copy status |
jj log | Show commit graph (defaults to non-remote commits) |
jj log -r ::@ | Show ancestors of working copy |
jj log -r 'all()' | Show all commits |
jj diff | Diff of current revision (@) |
jj diff -r <rev> | Diff of a specific revision |
jj diff --from A --to B | Diff between two revisions |
jj show <rev> | Show a revision's changes and metadata |
jj evolog | Show how a change evolved over time |
| Command | Purpose |
|---|---|
jj new | Finalize @ and start a new empty change on top |
jj new main | Start a new change from main |
jj new A B | Create a merge commit with parents A and B |
jj commit -m "msg" | Describe @ and start a new change (= describe + new, but atomic) |
jj describe -m "msg" | Set/edit the description of @ |
jj describe <rev> -m "msg" | Set/edit the description of any revision |
Squash moves changes from one commit into another.
| Command | Purpose |
|---|---|
jj squash | Move all changes from @ into its parent (@-) |
jj squash -i | Interactively select which changes to move into parent |
jj squash <paths>... | Move only specific files into parent |
jj squash --into <rev> | Move changes from @ into an arbitrary ancestor |
jj squash --from <rev> | Move changes from <rev> into its parent |
jj squash --from <rev> --into <rev> | Move changes between arbitrary revisions |
jj squash -i --from X --into Y | Interactively move selected changes between arbitrary revisions |
Note: --from defaults to @, --into defaults to the parent of --from.
The flags -r and --into cannot be combined.
DO NOT squash immutable commits unless specifically asked to.
Split divides a commit into two or more sequential commits.
| Command | Purpose |
|---|---|
jj split | Interactively split @ — select changes for the first commit; the rest go into a second |
jj split -r <rev> | Split a revision other than @ |
jj split <paths>... | Split by putting the listed files into the first commit |
CRITICAL: Always pass -m "message" when splitting. Without -m, jj opens
an interactive editor that blocks execution and requires manual user
intervention. The -m flag sets the description of the first (selected) commit;
the second (remaining) commit keeps its current description. If the remaining
commit has no description yet, describe it separately with jj describe after
the split completes. The only exception is when the user explicitly asks for an
interactive split.
| Command | Purpose |
|---|---|
jj edit <change-id> | Check out a previous change for editing (becomes @) |
jj edit @- | Edit the parent of the current change |
jj diffedit -r <rev> | Edit a revision's diff without checking it out |
jj abandon | Discard @ and rebase its descendants onto @- |
jj restore <paths>... | Restore files in @ from its parent |
jj restore --from <rev> <paths>... | Restore files from a specific revision |
jj duplicate <rev> | Copy a commit to a new change |
jj revert -r <rev> -B @ | Create a reverse-patch of a revision before @ |
| Command | Purpose |
|---|---|
jj next --edit | Move to the next (child) change |
jj prev --edit | Move to the previous (parent) change |
| Command | Purpose |
|---|---|
jj rebase -s <src> -o <onto> | Rebase <src> and descendants onto <onto> |
jj rebase -b <rev> -o <onto> | Rebase the branch containing <rev> onto <onto> |
jj rebase -r <rev> -o <onto> | Rebase only <rev> (re-parents descendants) |
jj rebase -r <rev> --before <target> | Insert <rev> before <target> |
jj rebase -r <rev> --after <target> | Insert <rev> after <target> |
Note: -d/--destination is a legacy alias for -o/--onto.
| Command | Purpose |
|---|---|
jj bookmark list / jj b l | List bookmarks |
jj bookmark create <name> -r <rev> / jj b c <name> | Create bookmark |
jj bookmark move <name> --to <rev> / jj b m <name> -t <rev> | Move bookmark |
jj bookmark move <name> --to <rev> --allow-backwards | Move bookmark backwards |
jj bookmark delete <name> | Delete bookmark |
jj bookmark track <name>@<remote> | Track a remote bookmark |
| Command | Purpose |
|---|---|
jj git init | Initialize jj repo with git backend |
jj git clone <url> <dir> | Clone a git repository |
jj git fetch | Fetch from remote (updates tracked bookmarks) |
jj git push | Push tracked bookmarks to remote |
jj git push --bookmark <name> | Push a specific bookmark |
jj git push --change <rev> | Push a change (auto-creates bookmark) |
jj git push --all | Push all bookmarks |
Conflicts are stored in commits and don't block operations.
jj new <conflicted-rev> — create a child to work in<<<<<<< / %%%%%%% / +++++++ / >>>>>>>)jj squash — fold the resolution back into the conflicted commitOr use jj resolve to open a merge tool.
| Command | Purpose |
|---|---|
jj undo | Undo the last operation |
jj op log | Show operation history |
jj op restore <op-id> | Restore repo to a previous operation state |
.git/index.lock ErrorsIf a jj command fails with Could not acquire lock for index file /
.git/index.lock, do NOT blindly delete the lock file. This usually means
a concurrent jj or git process is still running (e.g. a background watchman
snapshot, another jj command in a subagent, or an IDE integration). Deleting the
lock while the other process is active risks corrupting the repo.
Instead:
lsof .git/index.lock or
ps aux | grep jj.rm .git/index.lock) if you are certain no other
process holds it (e.g. lsof returns nothing and the lock file is older
than a few seconds).Use -r flag on most commands to select revisions.
| Expression | Meaning |
|---|---|
@ | Working copy |
@- | Parent of working copy |
@-- | Grandparent |
x- | Parents of x |
x+ | Children of x |
::x | Ancestors of x (inclusive) |
x:: | Descendants of x (inclusive) |
x..y | Commits in y but not in x (like git x..y) |
x | y | Union |
x & y | Intersection |
~x | Negation |
trunk() | The remote repository's HEAD |
bookmarks() | All bookmarked commits |
remote_bookmarks() | All remote-tracked commits |
heads(x) | Commits in x with no descendants in x |
roots(x) | Commits in x with no ancestors in x |
description(pattern) | Commits matching description |
author(pattern) | Commits matching author |
empty() | Empty commits |
conflicts() | Commits with conflicts |
files(pattern) | Commits touching files matching pattern |
String patterns: exact:, glob: (default), regex:, substring:. Append
-i for case-insensitive (e.g. glob-i:"fix*").
For full revset docs: jj help -k revsets
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub romainmuller/claude-marketplace --plugin jj-vcs