factorial-io/skills · Archived

jujutsu

This document instructs Claude Code to use `jj` (Jujutsu) instead of `git` for version control operations. jj is a Git-compatible VCS that provides a simpler mental model and powerful history editing.

First seen Jan 25, 2026

Installation

$ npx skills add factorial-io/skills --skill jujutsu

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from factorial-io/skills.

npx skills add factorial-io/skills

Browse all from factorial-io/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,232 B
  • docs SUMMARY.md 215 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 17 installs

SKILL.md

Jujutsu (jj) Usage Guide for Claude Code

Use jj (Jujutsu) instead of git for version control. jj is Git-compatible with a simpler model and powerful history editing.

Delegate noisy work to a subagent

For multi-step VCS work — history cleanup, rebase, conflict resolution, splitting commits — spawn a subagent (Sonnet) to do it and return a one-line summary. This keeps verbose jj log/diff/op log output and this reference out of the parent's context, saving tokens. Tell the subagent exactly what changed and what the end state should be.

Do NOT delegate trivial one-shots (jj describe -m … && jj git push) — spawn overhead exceeds the saving. Run those inline.

Mental model

  • No staging area — every change is part of the working copy commit.
  • Working copy is a commit — @ is your current working copy commit.
  • Bookmarks, not branches — commits are anonymous; name a bookmark only to push.
  • Conflicts are values — they don't block operations; resolve them later.
  • Automatic rebasing — descendants rebase automatically when you edit history.
Git jj
branch bookmark
HEAD @ (working copy)
checkout edit / new
stash not needed — just jj new
commit --amend just edit @, changes auto-apply

Command reference

Action Command
Status jj st
Log jj log (jj log -r 'all()' for everything)
Diff working copy / a commit jj diff --git / jj diff --git -r <rev>
Show a commit jj show <rev>
Describe @ jj desc -m "feat: …"
New commit on @ / on a rev jj new [-m "…"] / jj new <rev>
Edit an existing commit jj edit <rev> (descendants auto-rebase)
Squash into parent jj squash -m "…" (-r <rev> for a specific one)
Squash paths across commits jj squash --from <src> --into <dst> <paths>
Restore paths from a rev jj restore --from <rev> <paths>
Split by file jj split <path>... (--parallel for siblings)
Absorb into ancestors jj absorb (see caveat below)
Rebase jj rebase -d <dest> (-r one, -s +descendants, -b branch)
Bookmarks `jj bookmark create\ set\ delete <n> · jj bookmark track <n>@origin`
Fetch / push jj git fetch / jj git push -b <n>
Conflicts / undo jj log -r 'conflicts()' / jj op undo

Workflow

Atomic commits by construction. The cheapest path is to create commits as you go, not to split afterward. Start work with a description in place and run jj new between logical steps:

jj new main -m "refactor: extract auth helper"   # start from main
# ...edit...
jj new -m "feat: use helper in login flow"
# ...edit...

Adjust later with jj describe -m "…"; merge two commits with jj squash -m "…".

Before push:

jj log -r 'conflicts()'          # 1. no conflicts
jj st                            # 2. clean status
jj git fetch && jj rebase -d main # 3. onto latest main
jj log -r '::@ ~ ::main'         # 4. review your changes
jj bookmark create <n> && jj git push -b <n>  # 5. push

Update a PR after review: jj edit <commit>, make changes (descendants auto-rebase), jj new <tip> to return to the tip, jj git push -b <n>.

Bookmark naming: feat/user-dashboard, fix/issue-123-auth-bug, claude/<feature>-<session-id>.

Judgment notes

  • jj absorb only moves hunks into ancestor commits that already touch the

same lines. It won't create commits; split mixed unrelated changes in @ first.

  • Recovery: jj op log shows every operation; jj op undo reverts the last,

jj op restore <id> jumps to a known-good state. Nothing is ever truly lost.

  • Colocate with git: jj git init --colocate shares the .git dir, so `jj

git fetch/push` keep both in sync and git commands still work for edge cases.

Avoiding interactive editors

LLMs can't drive TUIs, so always use non-interactive forms:

  • Inline messages — pass -m "…" to describe, squash, commit, new.

jj split takes -m "first" -m "second" for both halves.

  • Squash / restore specific paths without an editor — the --from/--into

and --from <rev> <paths> forms above.

  • Split by file — jj split <path>... opens no editor when boundaries align

with files. Prefer it over the hunk-level TUI.

Hunk-level split within one file (no file boundary to use):

  1. Split before you mess up — jj new -m "next thing" between steps; you never

need split.

  1. Compose — jj new; edit @ to part A's state; `jj squash --from <original>

--into @ <paths>`; the original now holds only part B.

  1. Patch round-trip (last resort, scriptable):

`` jj diff -r <rev> --git > /tmp/full.patch # hand-split into partial/rest jj restore -r <rev> && jj new -r <rev>- git apply /tmp/partial.patch && jj commit -m "part A" git apply /tmp/rest.patch && jj commit -m "part B" ``