| name | jujutsu |
| description | **REQUIRED** - Always activate on any VCS operations. This repo uses Jujutsu (jj) — raw git commands can corrupt data. Essential jj workflow instructions inside. DO NOT IGNORE. |
Jujutsu (jj) Version Control System
This project uses Jujutsu (jj) as its VCS. The .jj/ directory exists at the repo root. Raw git commands can corrupt jj state — use jj for everything.
Remote: origin → git@github.com:tellmeY18/retire.nix
Current @: clean working copy on latest trunk.
Important: Agent Environment Rules
- Always use
--no-pager — prevents commands from opening less, which hangs the agent:
jj --no-pager log
jj --no-pager diff --git
jj --no-pager show <id>
jj --no-pager bookmark list
- Always use
-m flags for messages — avoids editor prompts that hang:
jj desc -m "message"
jj new -m "message"
-
Verify with jj st after mutations (squash, abandon, rebase, restore).
-
Always use jj diff --git — the default jj diff format uses side-by-side line numbers. --git gives standard unified diff with +/-.
-
On session start — create a fresh commit first. Before any work, always run:
jj new
This ensures you start on an empty anonymous commit, avoiding accidental attachment to a previous session's changes.
Core Concepts
The Working Copy is a Commit
Your working directory is always a commit (@). Changes are auto-snapshotted. There is no staging area and no need to run jj commit.
Change IDs vs Commit IDs
- Change ID (e.g.
tqpwlqmp) — stable across rewrites; prefer these
- Commit ID (e.g.
3ccf7581) — content hash, changes on rewrite
Essential Workflow: Describe First, Then Code
Always write your commit message before making changes. This principle, combined with always starting from a clean commit, gives you full control over your change history.
1. Agent initiation — start fresh
Every new agent session begins with a clean empty commit. This is already enforced by the environment rules above (rule 5). Run jj new if it hasn't been done yet.
2. Describe, then code
jj st
jj new
jj desc -m "Add user authentication to login endpoint"
jj st
jj --no-pager diff --git
Commit message format
Use imperative verb phrase, sentence case, no full stop at the end:
Add user authentication to login endpoint
Fix null pointer in payment processor
Remove deprecated API endpoints
Update dependencies to latest versions
Day-to-Day Commands
| Action | Command |
|---|
| Check status | jj st |
| View log | jj --no-pager log |
| View diff | jj --no-pager diff --git |
| Show specific commit | jj --no-pager show <change-id> |
| New empty commit | jj new |
| New commit with message | jj new -m "message" |
| Edit existing commit | jj edit <change-id> |
| Edit parent commit | jj prev -e |
| Edit next commit | jj next -e |
| Squash changes into parent | jj squash |
| Auto-distribute to ancestors | jj absorb |
| Abandon commit | jj abandon <change-id> |
| Undo last operation | jj undo |
| Restore files (discard changes) | jj restore [paths] |
| Restore files from revision | jj restore --from <change-id> [paths] |
Refining Commits
Squashing
Squash folds the current commit's changes into its parent. Before squashing, ensure you've created a fresh commit so your working copy changes don't accidentally merge with the squash:
jj new
jj squash
Do NOT use jj squash -i — it opens an interactive UI that hangs the agent.
Absorbing
Before running jj absorb, ensure you're on a fresh commit:
jj new
jj absorb
Splitting
Do NOT use jj split (interactive). Instead, use jj restore to move changes out, then create separate commits manually.
Rebasing
jj rebase -d <destination>
jj rebase -d main@origin
jj rebase -r <change-id> -d main@origin
Bookmarks (Branches)
Bookmarks are jj's bridge to git branches, but this repo uses a bookmark-free workflow. Local work is done with anonymous commits identified by change IDs, not branches.
Remote-tracking bookmarks (main@origin, develop@origin, etc.) are fetched automatically by jj git fetch and serve only as rebase targets. Do not create or move local bookmarks.
To inspect or clean up:
jj --no-pager bookmark list
jj bookmark delete <name>
Working with the Remote
GitHub hosts the canonical develop branch. Locally we stay bookmark-free — the remote develop is only touched momentarily at push time.
jj git fetch
jj git fetch --remote origin
Typical sync cycle (push to develop)
jj rebase -d develop@origin
jj bookmark set develop -r @
jj git push -b develop
jj bookmark forget develop
Before pushing
-
Confirm you're pushing the right commit:
jj --no-pager log -r @
-
Ensure commits are atomic with clear messages.
Handling Conflicts
jj allows committing conflicts. Do not use jj resolve (interactive). Instead:
- Edit the conflicted files directly to remove conflict markers
- Run
jj st to verify resolution
Preserving Commit Quality
Before considering work done:
- Review:
jj --no-pager show @ or jj --no-pager diff --git
- Atomic? One logical change per commit
- Message clear? Imperative verb phrase, no full stop
- Unrelated changes? Use
jj restore to move out, create separate commits
- Should changes be elsewhere?
jj squash or jj absorb
Git Interop
This repo uses colocated jj (both .jj/ and .git/ exist). In non-colocated repos don't use git commands at all. Here it's safe but still prefer jj.
If you must use a raw git command (e.g. jj doesn't support a particular git feature):
jj st
git <command>
jj edit <change-id>
Quick Reference
| Action | Command |
|---|
| Status | jj st |
| Log | jj --no-pager log |
| Diff (git format) | jj --no-pager diff --git |
| Show commit | jj --no-pager show <id> |
| Describe (rename) | jj desc -m "message" |
| New commit | jj new [-m "message"] |
| Edit commit | jj edit <id> |
| Squash | jj squash |
| Absorb | jj absorb |
| Rebase | jj rebase -d <dest> |
| Abandon | jj abandon <id> |
| Undo | jj undo |
| Restore files | jj restore [paths] |
| Fetch remote | jj git fetch |
| Push change | jj git push --change <change-id> |
| List bookmarks | jj --no-pager bookmark list |
| Delete bookmark | jj bookmark delete <name> |