Jujutsu (jj) Workflows
Jujutsu is a next-generation version control system that improves on Git's design. This skill provides patterns for common workflows.
Quick Reference
Essential Commands
# Status and inspection
jj status # View current state
jj log # View history
jj diff # View changes
# Committing
jj commit -m "message"
# Bookmark management
jj bookmark create <name>
jj bookmark track <name> --remote=origin # Required before push!
jj git push --bookmark <name>
Common Workflow
# 1. Commit changes
jj commit -m "feat: description"
# 2. Create and track bookmark
jj bookmark create feat/my-feature
jj bookmark track feat/my-feature --remote=origin
# 3. Push
jj git push --bookmark <name>
# 4. Create PR
gh pr create --head feat/my-feature --base main --title "Title"
Automated Workflows with Mask
This skill includes a maskfile.md with automated workflows. Mask is a task runner that uses markdown files.
Installation
brew install mask
Usage
All mask commands require pointing to the maskfile in the skill directory:
mask --maskfile ~/.claude/skills/jujutsu/maskfile.md <command>
Tip: Create a shell alias for convenience:
alias jj-mask='mask --maskfile ~/.claude/skills/jujutsu/maskfile.md'
Complete Workflow: Commit and PR
mask --maskfile ~/.claude/skills/jujutsu/maskfile.md commit-and-pr \
--bookmark feat/add-auth \
--message "feat(auth): implement user authentication" \
--title "Add user authentication" \
--body "Implements JWT-based auth"
This automates: commit → create bookmark → track → push → create PR.
Individual Tasks
# Using full path
mask --maskfile ~/.claude/skills/jujutsu/maskfile.md commit -m "message"
mask --maskfile ~/.claude/skills/jujutsu/maskfile.md create-bookmark -n feat/name
mask --maskfile ~/.claude/skills/jujutsu/maskfile.md push -b feat/name
mask --maskfile ~/.claude/skills/jujutsu/maskfile.md status
# Or with alias
jj-mask commit -m "message"
jj-mask create-bookmark -n feat/name
jj-mask push -b feat/name
jj-mask status
See maskfile.md for all available commands and options.
Key Concepts
Bookmarks Must Be Tracked
Critical: Bookmarks are NOT automatically tracked for remote push. Always run:
jj bookmark track <name> --remote=origin
Without this, jj git push will fail with "Refusing to create new remote bookmark".
Changes vs Commits
- Change: A snapshot (like a draft), persists across operations
- Commit: Finalized change with message
- After commit, working copy becomes empty (new change on top)
The @ Symbol
@= current working copy@-= parent of current@--= grandparent
Common Patterns
Untracking Files Before Committing
When jj status shows files that should not be committed (e.g., build artifacts, secrets, uploaded files):
# 1. Add the path to .gitignore first
echo "uploads/" >> .gitignore
# 2. Untrack the file(s) from the working copy
jj file untrack uploads/some-file.png
jj file untrack uploads/ # untrack entire directory
# 3. Verify they're gone from status
jj status
Note: jj file untrack removes the file from jj's tracking without deleting it from disk. Always add to .gitignore first so it stays untracked on future snapshots.
Multi-line Commit Messages
jj commit -m "$(cat <<'EOF'
feat(scope): title
Detailed explanation.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
EOF
)"
Creating PR with Body
gh pr create \
--head feat/name \
--base main \
--title "Title" \
--body "$(cat <<'EOF'
## Summary
Description
## Changes
- Item 1
- Item 2
EOF
)"
Conventional Commits
Format: <type>(<scope>): <subject>
Types: feat, fix, docs, refactor, test, chore
Example: feat(api): add new endpoint
Reference Documentation
For detailed information, see:
- jj-basics.md - Core concepts, differences from Git
- workflows.md - Feature development patterns
- github-integration.md - PR creation, bookmark naming
Troubleshooting
"Refusing to create new remote bookmark"
jj bookmark track <name> --remote=origin
jj git push --bookmark <name>
"not on any branch" (GitHub CLI)
jj bookmark create feat/my-work
jj bookmark track feat/my-work --remote=origin
Changes Disappeared After Commit
Normal behavior! Your commit is at @-. Working copy is now empty (@), ready for next change.
jj show @- # View your commit