Jujutsu for AI Coding Agents

thcipriani1 pts0 comments

Avoid Losing Work with Jujutsu (jj) for AI Coding Agents - Anthony Panozzo's Blog

Avoid Losing Work with Jujutsu (jj) for AI Coding Agents

Someone in the Indy Hackers Slack shared the following post:

My first Gemini CLI experience: "I messed up. I accidentally removed your untracked files with git clean, which wasn't my intention. I'm truly sorry. Since they weren't in git, I can't restore them easily."

— rands (@rands@mastodon.social) View on Mastodon

I had also run into this problem while coding with AI agents. This seemed like an opportune time to write up some thoughts to hopefully save others some time and agony.

Sometimes this issue happens to me because I get too confident in the current work direction and have not committed in a while. And then one or two prompts later, I have a broken or confusing set of changes.

Or, as Rands's post mentions, sometimes the AI agent purposely or accidentally reverts some changes and can't recover them. Also, when Claude Code compacts context, it clears the terminal, so it often can't remember changes, and then we would be unlikely to recover.

Enter jj

To try to combat this problem, I've been setting up and using Jujutsu (henceforth jj) instances for the repos that I have. jj snapshots the working copy whenever you run a jj command, so you can use its history to see and restore changes that might have otherwise gotten lost. It also works fairly seamlessly with git, which basically all of my projects use at this point. It also doesn't affect other users of your projects. So in my mind there are basically no downsides to setting it up.

It's easy to set up jj alongside an existing git repo with jj git init --colocate.

Then there are a few commands that I've been using. I just set it up on my blog repo, and have the following info:

$ jj<br>@ lrklqzxy panozzaj@gmail.com 2025-11-22 16:06:25 b76e8471<br>│ (no description set)<br>◆ qppwxvzp panozzaj@gmail.com 2025-11-06 10:57:53 master master@origin git_head() e9476b33<br>│ Add site perf audit document<br>...

$ git log --oneline --graph --decorate | head 1<br>* e9476b3 (HEAD -> master, origin/master, origin/HEAD) Add site perf audit document

So you can see from the jj command output that it knows about git commit e9476b3 (jj's identifier for that commit is qppwxvzp).

One thing I almost immediately picked up on is that jj commit identifiers use characters in the range of [g-z], which is nice since git uses the hex characters ([0-9,a-f]) for its commit hashes. So this makes it easier to not mix up the two systems' unique identifiers. jj also highlights the unique starting characters in a different color, so it's easy to type out a couple of characters:

From above, jj has a working set of changes that it currently describes with lrklqzxy/b76e8471. Or, at least it did, until I just saved this draft. Now the git identifier is something else, since the hash of the underlying filesystem changed.

The uncommitted set of changes is aliased to @. It's similar to the git working directory, but each filesystem change is actually "committed" under the hood. To save the current set of changes in jj and change @s identifier, we'd use jj describe to write a commit message.

Here's where the work-saving ability comes in. With jj, we can view the last couple of repo changes:

$ jj obslog --revision @ --patch --limit 2<br>@ lrklqzxy panozzaj@gmail.com 2025-11-22 16:16:46 2583d144<br>│ (no description set)<br>│ -- operation 213466f024c9 snapshot working copy<br>│ M _drafts/using-jujutsu-jj-with-ai-coding-agents.markdown<br>│ Modified regular file _drafts/using-jujutsu-jj-with-ai-coding-agents.markdown:<br>│ ...<br>│ 37 37: * e9476b3 (HEAD -> master, origin/master, origin/HEAD) Add site perf audit document<br>│ 38 38: ```<br>│ 39 39:<br>│ 40 : So you can see from the `jj` command output that it knows about git commit `e9476b3` (`jj`'s version of this is `qppwxvzp`), and has a working set of changes that it currently describes with `b76e8471`. Or, at least it did, until I just saved this draft. Now it's something else. So that working set is nicknamed `@`, and it's a pretty useful concept.<br>│ 40: So you can see from the `jj` command output that it knows about git commit `e9476b3` (`jj`'s version of this is `qppwxvzp`).<br>│ 41:<br>│ 42: One thing I almost immediately picked up on is that the `jj` commit descriptors uses characters in the range of `[g-z]`, which is nice since `git` uses the hex characters (`[0-9][a-f]`) for its commit hashes. So this means that you'll never get the two systems' identifiers mixed up. It's not visible here, but `jj` also highlights the unique starting characters in a different color, so it's easy to type out a couple of characters.<br>│ 43:<br>│ 44: From above, `jj` has a working set of changes that it currently describes with `lrklqzxy`/`b76e8471`. Or, at least it did, until I just saved this draft. Now the git portion of it is something else, since the hash of the underlying filesystem changed. The uncommitted set of changes is nicknamed `@`, and it's a...

changes commit characters working jujutsu coding

Related Articles