From jj
Jujutsu (jj) VCS workflow guidance. MUST activate on ANY VCS operation when `jj root` succeeds or when `.jj/` exists in the repo root. Use when the user mentions jj, jujutsu, or when a colocated jj repo is detected.
npx claudepluginhub fzymgc-house/fzymgc-house-skills --plugin jjThis skill is limited to using the following tools:
- [Detection](#detection)
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Before any VCS operation, check for a jj repository:
if jj root >/dev/null 2>&1; then echo "jj repo detected"; fi
If jj is detected:
jj for all version control operationsgit commit, git checkout, git branch,
git merge, git rebase, etc.) -- they are blocked by a PreToolUse guard hookjj log over git log,
jj diff over git diff, etc.)git rev-parse, git ls-files) and gh CLIAgents run non-interactively. These rules prevent common failures:
jj git fetch at the start of any task, not just before push-m for commit/describe messages -- never open an editorjj describe or rewrite commits that have already been pushedjj commit -m "..." before jj new -- jj new moves @ to a new change;
without a description or bookmark, the old change is effectively lostjj st after any mutationjj rebase --skip-emptied over manual jj abandon -- it's idempotent and handles chains--no-pager on every jj command (e.g., jj --no-pager log).
Agent environments cannot interact with pagers. Alternatively, pass
--config ui.paginate=never as a flag./dev/null (2>/dev/null) on jj commands.
jj reports errors and important warnings on stderr. Suppressing it hides
failures silently (e.g., jj workspace add appears to succeed but creates
nothing). If jj output is noisy, use --quiet instead.(divergent) markers in jj log, you MUST abandon the stale local copy
and rebase remaining work onto mainParallel agent safety:
@ and cause orphaned branches. Each parallel agent MUST work
in its own workspace created via jj workspace add. The orchestrating skill
is responsible for workspace creation before dispatch and cleanup after.
See references/workflows-reference.md "Agent Fan-Out" for the full pattern.You MUST NOT use these interactive commands (they hang in agent environments):
| Command | Why | Alternative |
|---|---|---|
jj split | Opens editor to select hunks | Manually edit files, commit separately |
jj resolve | Opens merge tool | Edit conflict markers directly |
jj squash -i | Interactive hunk selection | Use jj squash (non-interactive) |
In jj, the working copy is always a commit (@). There is no staging area. Every file change
is automatically part of the working-copy commit.
| Property | Change ID | Commit ID |
|---|---|---|
| Format | Short alpha string (e.g., kxryzmsp) | SHA hex (e.g., a1b2c3d4) |
| Stability | Stable across rewrites | Changes on rewrite |
| Use for | Referring to logical changes | Pinpointing exact versions |
You MUST prefer change IDs when referring to revisions -- they survive squash, rebase, and amend.
| Symbol | Meaning |
|---|---|
@ | Working copy (current change) |
@- | Parent of working copy |
@-- | Grandparent of working copy |
root() | Root commit |
trunk() | Main branch tracking commit |
# Describe current change and start a new empty one (like git commit)
jj commit -m "feat(scope): add new feature"
# Create a new empty change on top of current
jj new
# Update description of current change without creating a new one
jj describe -m "fix(scope): correct the bug"
# View commit log (default: mutable revisions with context)
jj log
# View log with all revisions
jj log -r '::' # all() also works but :: is canonical
# Show diff of current working copy
jj diff
# Show diff of a specific revision
jj show <rev>
# Status of working copy
jj st
# Move all changes from @ into @- (squash into parent)
jj squash
# Move changes from @ into a specific revision
jj squash --into <rev>
# Auto-distribute working copy changes to the commits that last modified those lines
jj absorb
# Absorb only specific files
jj absorb src/auth/ tests/
# Review what absorb did
jj op show -p
This automatically routes each hunk to the right ancestor commit using blame data. Ambiguous hunks (spanning multiple ancestors) stay in the source. Source is abandoned if it becomes empty and has no description.
# Trace all versions of a change (including auto-snapshots)
jj evolog --patch
Use jj evolog to find a lost intermediate state, then jj new <commit-id> to recover.
# Remove a commit (descendants rebased onto its parent; changes are discarded)
jj abandon <rev>
# Undo the last jj operation
jj undo
# Discard all changes in the working copy
jj restore
# Restore a specific file from a revision
jj restore --from <rev> <path>
Warning — op log semantics: The op log only records successful operations.
A failed jj command leaves no trace in the op log (unlike git's reflog). jj undo
always targets the most recent successful operation — do NOT "undo twice" to
account for a failure. If you need to recover from a bad state, use
jj op log to find the right operation ID, then jj op restore <op-id>.
See references/jj-reference.md for the full op log reference.
Note: You MUST NOT use jj split -- it is interactive and hangs in agent environments. To split a commit
(extract specific files into a new child):
jj new <commit> — create a new empty change after the targetjj squash --from <commit> <path1> <path2> — move only those files from the target into the new changeThe target commit retains everything except the moved files.
Bookmarks are jj's equivalent of git branches.
# Create a bookmark at the current change
jj bookmark create <name>
# Move a bookmark to a specific revision (creates if missing)
jj bookmark set <name> -r <rev>
# List all bookmarks
jj bookmark list
# Delete a bookmark
jj bookmark delete <name>
Short forms: jj b c, jj b s, jj b l, jj b d.
Bookmarks do NOT auto-advance when you create new commits. You MUST explicitly update them before pushing:
jj bookmark set my-feature -r @
jj git push -b my-feature
Workspaces provide isolated working copies sharing the same repo storage. You SHOULD
create a workspace for each feature or task — they are near-instant and cost almost
no disk space. See references/workflows-reference.md "Workspace-Per-Feature Workflow"
for the full end-to-end pattern including push-from-primary and cleanup.
You MUST use jj workspace add — you MUST NOT use git worktree add. This applies
to both colocated and pure jj repos.
# Create a workspace
jj workspace add ../my-workspace --name my-workspace
# List workspaces
jj workspace list
# Forget a workspace (de-register, does NOT delete files — callers must rm -rf the directory after)
jj workspace forget <name>
rm -rf <path>
# Fix a stale workspace after concurrent edits
jj workspace update-stale
Key behaviors:
jj workspace list shows all workspaces (format: <name>: <change-id-prefix> <commit-id-prefix> <description>,
e.g. default: rwoumssn 094ee48c (empty) (no description set)); there is no
(current) marker — identify the current workspace from the working directory
path (sibling worktrees use <repo>_worktrees/<workspace-name>/)@)jj workspace update-stale if a workspace falls behindFor full details, read references/jj-git-interop.md.
# Push a bookmark to its remote
jj git push -b <bookmark>
# Push the current change (auto-generates a bookmark named push-<id>)
jj git push --change @
# Fetch from all remotes
jj git fetch
In colocated repos (both .jj/ and .git/ present), every jj command auto-syncs
with the underlying git repo. The gh CLI works normally because it reads .git/.
# Ensure bookmark exists and is at the right revision
jj bookmark set my-feature -r @
jj git push -b my-feature
# Create PR via GitHub CLI
gh pr create --head my-feature --title "..." --body "..."
GitHub squash-merge creates a new commit on main with a different hash than your local
commits. jj cannot detect that your work has "landed," causing local commits to appear
alive/divergent after fetch.
After a PR is squash-merged on GitHub:
jj git fetch
jj rebase -o main --skip-emptied
jj bookmark delete <merged-bookmark>
--skip-emptied is critical -- it automatically abandons commits that become empty after
rebase (their content is already in main via the squash merge).
If you had commits A -> B -> C -> D (each a separate PR) and A's PR was just squash-merged:
jj git fetch
jj rebase -s <change-id-of-B> -o main --skip-emptied
jj bookmark delete <a-bookmark>
A becomes empty and is auto-abandoned. B, C, D rebase cleanly onto new main.
# 1. Start work
jj new main
# ... make changes ...
jj describe -m "feat: my feature"
jj bookmark create my-feature -r @
jj git push
# 2. Address review comments
jj new my-feature # new child of bookmark tip
# ... make fixes ...
jj squash # fold fixes into parent
jj git push --bookmark my-feature
# 3. After squash-merge on GitHub
jj git fetch
jj rebase -o main --skip-emptied
jj bookmark delete my-feature
# 4. Start next piece of work
jj new main
For detailed workflows and aliases, see references/workflows-reference.md.
Divergent changes appear as (divergent) in jj log when a commit is modified both locally and remotely.
jj describe or jj squash to tweak the commitjj git fetch -> two commits with the same change ID = divergencejj git fetch before starting new workIf divergence occurs, abandon the stale local copy:
jj abandon <stale-commit-hash>
Or use the idempotent approach -- rebase with --skip-emptied to clean up automatically.
jj allows committing conflicts -- they are tracked as part of the commit, not blocking.
jj st # Shows "Conflict" markers if present
jj log # Conflicted commits show a conflict icon
%%%%%%% diff sections):
<<<<<<< Conflict N of M — conflict block start (includes commit references)+++++++ Contents of side #1 — snapshot of the first side (full content)%%%%%%% Changes from base to side #2 — diff from base to second side\\\\\\\ — separator between the diff header and the 'to' snapshot section>>>>>>> Conflict N of M ends — conflict block endjj st to verify the conflict is resolvedYou MUST NOT use jj resolve -- it launches an interactive merge tool that hangs in
agent environments.
| Task | Command |
|---|---|
| Commit and start new change | jj commit -m "msg" |
| Describe current change | jj describe -m "msg" |
| New empty change | jj new |
| New change on specific parent | jj new <rev> |
| New merge change | jj new <rev1> <rev2> |
| Insert change mid-chain | jj new -A <after> -B <before> |
| View log | jj log |
| View diff | jj diff |
| Show revision | jj show <rev> |
| Status | jj st |
| Squash into parent | jj squash |
| Squash into specific rev | jj squash --into <rev> |
| Absorb into ancestors | jj absorb |
| Trace change history | jj evolog --patch |
| Abandon change | jj abandon <rev> |
| Undo last operation | jj undo |
| Redo after undo | jj redo |
| Revert specific past op | jj op revert <op-id> |
| Restore working copy | jj restore |
| Rebase onto new parent | jj rebase -s <src> -o <dest> |
| Rebase single rev (extract) | jj rebase -r <rev> -o <dest> |
| Insert rev after target | jj rebase -r <rev> -A <target> |
| Rebase all branches | jj rebase -s 'all:roots(trunk()..@)' -o trunk() |
| Create bookmark | jj bookmark create <name> |
| Move bookmark | jj bookmark set <name> -r <rev> |
| Advance bookmark to @ | jj bookmark advance <name> |
| Push bookmark | jj git push -b <name> |
| Push with auto-bookmark | jj git push --change @ |
| Push all tracked | jj git push --tracked |
| Fetch remotes | jj git fetch |
| List files | jj file list |
| Current location | jj log -r @ --no-graph -T 'change_id.short(8)' |
| Manual snapshot | jj util snapshot |
| Add workspace | jj workspace add <path> --name <name> |
| List workspaces | jj workspace list |
| Remove workspace | jj workspace forget <name> + rm -rf <path> |
references/jj-reference.md -- detailed jj command reference, revsets, absorb, evolog, and advanced operationsreferences/workflows-reference.md -- end-to-end workflow recipes, aliases, stacked PR patterns, agent fan-out, megamergereferences/jj-git-interop.md -- colocated repo behavior, auto-sync sequence, conflict storage, and git compatibilityreferences/jj-agent-config.md -- recommended jj configuration for non-interactive agent environments