What's the difference between "snapshots" and git commits? In my mind a git commit is already a snapshot of the repo and the changes one staged. In what way can you move around more freely than what one can do with magit, deciding for files, hunks, or even single lines of code, whether or not they get staged and committed?

You're right that git commits are snapshots.

jj is very non-modal, that is, it doesn't tend to have a lot of state that commands rely on. As an example of what I mean, because jj does not have a staging area, everything is already committed, which makes it very easy to say, move to a different commit: you don't need to stash your working copy, as jj has already stashed it for you. Similarly, due to the auto-rebase behavior, you can be working in one part of the tree, realize something somewhere else should be moved, and go rebase that without even moving to it at all!

As a small example: say I'm working on something, and I find a typo. I want to send that typo in as a PR, but I don't want to do it as part of my work. I can do that with:

1. make the change in my current working copy (@)

2. jj split -o trunk (selecting the typo contents to split off the typo fix into a new change on top of (hence -o) trunk)

3. jj log (go check out what the change id of that change is

4. jj git push -c <change id I found in 3>

No need to even move my own HEAD (in git terms), just knock it out inline in a few steps while I'm working.

Now, as for magit, I don't use it, and I know that those that do love it and it does make some of this stuff easier. But not everyone can use magit. And there are "magit, but jj" projects as well, but I can't speak to them or which is best at the moment.

Technically, nothing. But psychologically git commits represent a unit of completed work, whereas with AI agents what's needed is a kind of agent-wise undo history such that you can revert back to the state of the repo 1 minute ago before Claude did an oopsie all over your repo.

You can definitely use git as a backend for building such a system, but some extra tooling is necessary.

Just create a new branch before you implement new features and if the agent messes up don't merge the branch.

That way you get the best of both worlds. The buggy code is still there in case it's needed but it's not in the main branch

Most of the time when I'm using Claude my working tree is already dirty because I'm mid-task. I usually try to do a throwaway commit before every interaction with Claude, but it's easy to forget, or to leave the "accept edits" mode on accidentally and my working tree gets corrupted. Also having to commit takes you out of flow because you suddenly have to deal with any new gitignores, which requires at least a glance at untracked files to make sure you're not committing anything you shouldn't be. I want to be able to undo the state of my working tree to the moment before a particular interaction with Claude, just like how I can undo a file.

jj offers "jj undo" which will undo changes to your repo, and the "oplog", which is sort of like the reflog, but on steroids. It's one of the nicest things about it.

git checkout @{1.minute.ago}

> You can definitely use git as a backend for building such a system, but some extra tooling is necessary

Is it? There’s the stash for storing patches, the index for storing good hunks, branching for trying out different experiments. You can even use worktree if you want separate working directory especially when there will be changes in the untracked files.

Git has a lot of tooling for dealing with changes, directly or at the meta layer.