SkillAgentSearch skills...

jujutsu

Use when planning or running version-control operations: jj for every write and history edit, git for reads only. Covers non-interactive use, side-effect-free reads (templates, filesets, past operations), precise history edits (split, squash, absorb, rebase, inserting without moving @), recovering e…

Install / Use

npx skills add takeokunn/nixos-configuration --skill jujutsu

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

63/100

Category

Marketing

Supported Platforms

Universal

Our assessment of jujutsu

jujutsu scores 63/100 on our quality scale, 568th of 588 Marketing skills we index.

Its SKILL.md is 17 KB long, well organised into 13 sections and no code examples: a thorough specification that gives an agent plenty to work with.

It has no GitHub stars yet, so there is no community track record; judge it on its content.

Substance
30/30
Structure
13/20
Description
15/15
Adoption
0/20
Freshness
5/15

Maintenance, license and trust

  • We could not determine when the repository was last updated.
  • No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
  • Its trust signals score 68/100, with 3 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful.

AI review by kimi-k2.7-code on 2026-11-07. Automated pattern scan on 2026-11-07. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.

jujutsu compared with similar skills

All 4 of these similar skills score higher than jujutsu; compare them before choosing.

SkillScoreStarsUpdatedFormat
jujutsu (this skill)by takeokunn630—SKILL.md
Agent-Reachby Panniantong100109.8k1d agoCLAUDE.md
algorithmic-artby anthropics100177.9k45d agoSKILL.md
pptxby anthropics100177.9k45d agoSKILL.md
designby nextlevelbuilder100143.4k7d agoSKILL.md

Frequently asked questions

How do I install jujutsu?
Run npx skills add takeokunn/nixos-configuration --skill jujutsu. The install tabs above show the steps for each supported agent.
Which AI agents does jujutsu work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is jujutsu safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful. It declares no license and scores 68/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is jujutsu still maintained?
We could not determine when the repository was last updated.

name: jujutsu description: "Use when planning or running version-control operations: jj for every write and history edit, git for reads only. Covers non-interactive use, side-effect-free reads (templates, filesets, past operations), precise history edits (split, squash, absorb, rebase, inserting without moving @), recovering earlier versions without undo, conflicts recorded in commits, revset checks, the operation log, shared working copies, stale workspaces, bisect, bookmarks and stacks, and pre-push checks." metadata: version: "1.4.0"

Jujutsu (jj)

A .jj/ directory at the root of the checkout you work in means jj is in use: run all version-control operations through jj and keep GitHub operations on gh. Git is read-only; CLAUDE.md gives the rule, including what to do when .jj/ is missing. A .worktrees/ directory under a bare repository without its own .jj/ is not a jj workspace: jj root succeeds there but names the bare root, whose jj sees none of the directory's files, and jj status shows no changes.

Two layouts carry .jj/:

  • A non-bare clone is colocated: .jj/ and .git/ share one Git object store, jj exports its changes to Git refs, and Git's HEAD is left detached. Write through jj; read-only git subcommands also work.
  • A bare <repo>.git/ holds jj's store at its root in an empty-sparse default workspace that tracks no files. Work happens in jj workspaces under .worktrees/, which have no .git of their own. A gate that enumerates files through git (git ls-files, treefmt's default walker) there checks nothing and exits 0. Confirm its input count, or run it with a filesystem walk (treefmt --walk filesystem).

Local jj writes on a non-default change (commit, describe, split, squash, absorb, rebase of your own changes, bookmark create, fetch, workspace add) need no separate authorization when the task calls for them. Push, and any write to the default branch, need the user's confirmation; so does moving or discarding a shared working copy (CLAUDE.md hard_rules).

Before the first commit in a repository, run jj config get user.email there and confirm the value. Jujutsu does not read Git's conditional includeIf identity configuration.

The working copy is a commit

jj has no staging area. Repository commands normally snapshot files on disk into the working-copy revision @, so jj status records edits as well as reporting them. In a checkout shared with other sessions, that snapshot absorbs their edits into @ too: before describing, squashing, or pushing @, read jj diff --git and confirm every hunk is yours. Pass --ignore-working-copy to read-only commands to avoid snapshotting shared edits, but their view may be stale. To read on-disk state, run jj status or jj diff --git without the flag: before committing, to separate your changes from existing ones, or at completion to confirm the changed files, not as a routine first step.

Confirm a remote ref before relying on a fetched one: compare jj log --ignore-working-copy -r '<b>@<remote>' --no-graph -T 'commit_id' with gh api repos/<owner>/<repo>/git/ref/heads/<branch> --jq .object.sha (tags: git/ref/tags/<tag>). A remote-tracking ref left by a fetch without explicit --remote and --branch is not freshness evidence.

A change has a stable change ID (letters k-z) and a commit ID that changes on every rewrite. Refer to changes by change ID across rewrites.

Command map

Run only the jj column.

| Git habit | jj | |---|---| | git status | jj status | | git log --oneline --graph | jj log | | git diff / git diff --cached | jj diff --git (no staging, one diff) | | git show <rev> | jj show --git <rev> | | git add + git commit -m | jj commit -m "<msg>" (describes @, starts a new empty @) | | git commit --amend -m | jj describe -m "<msg>" | | git commit --amend --no-edit (fold in edits) | jj squash (moves @ into its parent) | | git add -p + commit (some files) | jj split -m "<msg>" <paths> | | git commit --fixup + autosquash | jj absorb [<paths>] | | git checkout -b <b> | jj bookmark create <b> -r @ | | git branch -f <b> <rev> | jj bookmark set <b> -r <rev> (-B to move it backwards or sideways) | | git fetch | jj git fetch --remote <r> --branch <b> (always name both) | | git push origin <b> | jj git push -b <b> (see Pushing) | | git rebase <onto> | jj rebase -b @ -o <onto> (-o is --onto) | | git cherry-pick <sha> | jj duplicate <rev> -o <dest> | | git revert <sha> | jj revert -r <rev> -o @ | | git checkout -- <path> | jj restore <path> | | git blame <file> | jj file annotate <file> | | git reflog | jj op log |

Non-interactive use

  • Always pass -m to jj commit, jj describe, and jj split; without it they open an editor. For jj squash, pass -m or -u (keep the destination's message) when both sides carry descriptions.
  • jj split with paths selects those files without a diff editor; without paths it opens one. Never run jj split without paths, jj diffedit, jj resolve without --list, or any -i/--interactive form. The guardrail hook does not catch these; an editor waiting for input hangs the call.
  • Add --no-pager to output-producing commands, and --git to diff commands whose output will be parsed: the default diff formatter here is difftastic.
  • For machine-readable output, pass --no-ext-diff to git diff so configured external diff drivers cannot alter its output.
  • For scripted reads, jj log --no-graph -r <revset> -T '<template>' gives stable output.

Reading without side effects

These read the repository without moving @ or rewriting a commit. Each still snapshots the files on disk into @ first unless you add --ignore-working-copy:

  • -T 'json(self) ++ "\n"' prints one JSON object per commit (change and commit IDs, parents, description, author, committer). For a narrower line, combine the keywords change_id.shortest(), commit_id.short(), description.first_line(), bookmarks, empty, conflict, divergent, and immutable.
  • Path arguments are filesets: jj diff --git -r <rev> 'glob:"**/*.nix" & ~glob:"flake.nix"' limits a diff to the matching files. A bare path matches that file or directory relative to the current directory.
  • jj file show -r <rev> <path> prints a file as it was in a revision, and jj file list -r <rev> lists the tracked files there. Neither touches the files on disk.
  • jj --at-op <op> log -r <revset> shows the repository as it was after an earlier operation, without restoring it. Take <op> from jj op log.

Editing history precisely

Each command below rewrites mutable commits and rebases their descendants automatically; none touches immutable() commits (by default trunk(), tags, and untracked remote bookmarks) without --ignore-immutable, which needs its own explicit request.

  • Move part of a change: jj squash --from <src> --into <dest> <paths> moves only those paths. Without paths it moves everything and abandons an emptied, undescribed source; -k keeps it.
  • Distribute fixups: jj absorb sends each hunk of @ to the closest mutable ancestor that last modified those lines, and leaves a hunk in place when the destination is ambiguous. Review where every hunk went with jj op show -p before building on the result; move a misplaced one with jj squash --from <wrong> --into <right> <path>, since the guardrail hook blocks jj undo.
  • Rebase by scope: -r <rev> moves one commit and reparents its children onto its parent; -s <rev> moves it with its descendants; -b <rev> moves the whole branch relative to the destination. -A/-B insert instead of stacking on top. Choosing -r when -s was meant strands the descendants on the old base.
  • Reorder independent commits: jj parallelize <a>::<b> makes a linear run into siblings.
  • Edit a commit other than @: most rewrites take -r. jj describe -r <rev> -m "<msg>" rewords it, jj split -r <rev> -m "<msg>" <paths> splits it (--parallel makes the two halves siblings), and jj squash -r <rev> folds it into its parent.
  • Insert without moving @: jj new --no-edit -A <rev> -m "<msg>" creates an empty commit after <rev> and rebases <rev>'s children onto it; -B inserts before. jj new --no-edit <a> <b> -m "<msg>" creates a merge of the two. --no-edit is what the guardrail hook allows: without it, jj new onto another revision moves @ and is blocked.
  • Copy content between revisions: jj restore --from <src> --into <dest> <paths> gives those paths in <dest> the content they have in <src>. Paths are required, as in every jj restore the hook allows.
  • Clean up merges: jj simplify-parents -r <rev> drops a parent that is also an ancestor through another parent, without changing any content.

Recovering an earlier version

The guardrail hook blocks jj undo and jj op restore, so recover by reading the old state and rewriting forward:

  1. jj evolog -r <change> -p --git lists each earlier commit of the change with its patch. jj op log and jj --at-op <op> log locate the state before a bad operation. A rewritten commit stays addressable by its old commit ID, as a hidden commit.
  2. jj interdiff --from <old-commit-id> --to <change> --git shows how the two versions' changes differ.
  3. jj restore --from <old-commit-id> --into <change> <paths> brings back the old content of those paths, or jj duplicate <old-commit-id> -o <dest> recreates the whole old version as a new change.

Conflicts are commits, not stops

A rebase or squash that conflicts still exits 0: jj records the conflict inside the commit and carries on, and every descendant inherits it. An exit status is therefore no evidence a rewrite succeeded. After any rewrite, compare the old and new tips with jj interdiff --from <old-tip> --to <new-tip> --git, then run jj log --no-graph -r 'conflicts()' before pushing. The conflict query must print nothing. In a clean @, jj resolve --list exits 2 with "No conflicts found", so its nonzero exit is the passing result there.

When @ is the conflicted commit, edit the conflict markers in the files directly and the next snapshot records the resolution. When the conflict sits in an ancestor, jj suggests jj new <conflicted>, which the guardrail hook blocks. If one side is right for a whole file, resolve it in place with jj resolve -r <conflicted> --tool :ours <path> (:theirs for the other side); a permission rule makes any --tool form prompt the user. For a manual resolution, keep @ on its current descendant, edit the conflict markers in its file, then run jj squash --into <conflicted> <paths> from the repository root. The squash moves the resolution into the ancestor and leaves a new empty @ child. Run jj log --no-graph -r 'conflicts()' to confirm that no conflicts remain. Otherwise report the conflicted change IDs and ask the user to resolve them or to approve a separate workspace for it.

Revsets that answer checks

Confirm what trunk() resolves to (jj log -r 'trunk()') before using it as a range bound. A clone may carry a per-repository alias (jj config list 'revset-aliases."trunk()"' shows it); otherwise the built-in tries main, master, and trunk on origin and then upstream, and with none of them it resolves to the root commit, so trunk()..@ silently spans the whole history.

| Question | Revset | |---|---| | My unpushed stack | trunk()..@ | | Anything conflicted | conflicts() | | One change rewritten by two sessions | divergent() | | Leftover empty commits | empty() & mutable() & ~merges() & ~working_copies() | | Commits touching a path | files("<path>") | | Find by message | description(substring:"<text>") | | Tips of mutable work | heads(mutable()) | | Commits whose diff mentions a string | `diff_lines("<text>", "<path>"

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars0
CategoryMarketing
UpdatedNaNy ago
Forks0

Trust signals

68/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

2 medium1 low