jjk caused a lot of problems for me when using multiple agents. It's running some sort of jj command that snap-shotted stuff and caused divergence (might have benefited from `--ignore-working-copy`). Not sure what the precise details were, but I gave up and uninstalled it after a week.
Multiple agents is definitely tempting fate. Concurrent modification of the same git repo by multiple entities?
At that point you should use multiple repos so they can merge & resolve.
EDIT: of course, if a single agent uses git to modify a repo instead of jj, jj may have trouble understanding what's happened. You could compare it to using an app that uses an sqlite db, and then also editing that db by hand.
The point of jj is that it supports lockless concurrent writes to the same repo out of the box. It is what makes it a lot more suitable than git for agent workflows
The OP is talking about the `jj workspace create` command, which creates a separate working copy backed by the same repository. It’s not a bad way to work with multiple agents, but you do have to learn what to do about workspace divergence.
Even with multiple workspaces (like git worktrees), once you use something like jjk, both the agent and jjk in the associated VS Code are operating on the same workspace, so that doesn't isolate enough. I don't think jjk uses `--ignore-working-copy` for read-only status updates, so it's snapshotting every time it checks the repo status while the agent is editing.
On top of that, throw in whatever Claude does if you "rewind" a conversation that also "reverts" the code, and agents wrongly deciding to work on code outside their focus area.
It's possible watchman helps (I need to look into that), but I'm so rarely using jj in VS Code (all I really want is inline blame), that it was easier to remove jjk than try to debug it all.
Divergence won't hide or lose any work, but it's an annoying time-suck to straighten out.
It does look nice, I'll give it a go. Just wanted to say that "Git-out-of-the-way source control" is the best tiny description of JJ I've ever seen, because it's both true and the pun works perfectly. It brought me joy.
It uses it when you use the git backend, but not when you don’t.
Right now, the only other backend is at Google, so it’s not practical for most people. But it’s not an inherent part of jj, and that’s really important, actually.
Yes, at the moment it does not. But a well factored system is important for gaining future benefits. For example, I work at a startup that is building jj related tooling, and that the git stuff is separated out cleanly is what enables us to build better things than if it were so tied to git.
To complete the analogy, given that we haven't launched, yes, this is a theoretical benefit for now. But that doesn't mean it's useless. jj is still pre-1.0 software, there's a lot more work to do, and more interesting things coming down the pipeline. That matters, even if it's not relevant to every potential user just yet.
Not working on it (yet), but I wish the jj <-> github story was a little more ergonomic.
Additionally, I am really missing support for stacked diffs, ie, easily pushing a number of commits into one PR on github each such that they all show their incremental diff.
ezyang's gh stack was pretty useful, if a little bit fragile [0]
and graphite.dev is also very nice, but paid software with a strong VC based motivation to become everyone's everything instead of a nice focused tool.
Git's plumbing also kinda sucks (in places). Some of the current limitations of jj in what syncing state between repos is due to things missing from git that they are having a hard working around, at least based on what I've seen browsing their tickets. That inability to push the really useful jj state upstream for pulling from any machine seems like a major pain point in jj right now (was one of the major issues referenced in a jujutsu intro guide last year linked on HN)
The same issue hit the initial efforts (that I think were the inspiration for jj) when the mercurial folks, recognising git had kinda taken over the market, experimented in making a mercurial frontend backed by the git db. Limitations like the diff format (mercurial's weave one is one the jj folks also want to add at some point) and the lack of a method for tracking phases (mercurial relies on this for clean history without throwing out commits), and lack of file move/copy tracking.
I worked with JJ for half a year, and it was great. However, I've since decided to go back to GIT because of compatibility with existing workflows and AI tools.
Pre-commit hooks are not possible [yet?], which is a minor inconvenience. Worse, workspaces/worktrees use a different mechanism. This causes like Claude Desktop (which uses worktrees) to break. Also Claude and other agents are always confused about JJ and fall back to git too often.
Seeing similar comments across different articles and technologies and it makes me wonder how much AI is going to hold back the adoption of new technologies going forward.
I find it a bit ridiculous to see that people or whole teams don't want to use JJ (or any tool, for that matter) because in essence they hired a "support intern" (read: AI assistant) who doesn't know or want to use it.
Even breaking changes in a library can cause massive pain. AI constantly wants to the use the old pattern it was trained on. Up until a few months ago it would always prefer using the 2021 edition of rust rather than 2024 for instance. Overall though I don't think this is insurmountable, but it definitely adds an impediment which will overall motivate people to do things non optimally for the foreseeable future. Luckily, not everyone is bound by AI today. I just write my own commits messages instead of letting the AI do it. jj is popular enough that I'm sure it'll learn how to use it in the next year (especially Gemini because Google is using jj internally and would probably train it on it as a result)
I noticed it get a lot better with the 4.5 models specifically. Before then, I would have to tell Claude "do a web search for the docs for jj, then do XYZ." Now I just tell it to "do XYZ using jj"
I agree it will hold back new technologies, but, at the same time, I'm not sure what the value add of new technologies will be going forward. Often, as is the case with git vs. jj, the value add of a new technology is mostly ergonomic. As AI becomes more ingrained in the development flow, engineers won't engage with the underlying tech directly, and so ergonomic benefits will be diminished. New technologies that emerge will need to provide benefits to AI-agents, not to engineers. Should such a technology emerge, agent developers will likely adopt it.
For this reason, programming languages, at least how we understand them today, have reached a terminal state. I could easily make a new language now, especially with the help of Claude Code et al, but there would never be any reason for any other engineer to use it.
Even if you're not authoring changes as much, change management is likely still to be a very useful activity for a long while. Also note that not everyone is using AI today, and many that do only use it as glorified auto complete. It will take many more years for it's adoption to put us in a situation like your describing, why halt progress in the meantime? My personal productivity increased greatly by switching to jj, perhaps more than adding Gemini CLI to my workflow. I can more confidently work on several changes in parallel while waiting on things like code review. This was possible before but rebasing it and dealing with merge conflicts tended to limit me from doing it beyond a handful of commits. Now I can have 20+ outstanding commits (largely with no interdependencies) and not feel like I'm paying much management overhead while doing so. I can also get them reviewed in parallel more easily.
I'm quite surprised to hear that "programming languages have reached a terminal state": there are (imo) at least four in-progress movements in the industry right now:
Even if LLMs become capable of writing all code, I think there's a good chance that we'd want those LLMs writing code in a language with memory safety and one amenable to some sort of verification.
> For this reason, programming languages, at least how we understand them today, have reached a terminal state. I could easily make a new language now, especially with the help of Claude Code et al, but there would never be any reason for any other engineer to use it.
This is an interesting opinion.
I feel we are nowhere near the terminal state for programming languages. Just as we didn't stop inventing math after arithmetic, we will always need to invent higher abstractions to help us reason beyond what is concrete (for example, imaginary numbers). A lot of electrical engineering wouldn't be possible to reason about without imaginary numbers. So new higher abstractions -- always necessary, in my opinion.
That said, I feel your finer point resonates -- about how new languages might not need to be constrained to the limitations of human ergonomics. In fact, this opens up new space of languages that can transcend human intuition because they are not written for humans to comprehend (yet are provably "correct").
As engineers, we care about human intuition because we are concerned about failure modes. But what if we could evolve along a more theoretical direction, similar to the one Haskell took? Haskell is basically "executable category theory" with some allowances for humans. Even with those tradeoffs, Haskell remains hard for most humans to write, but what if we could create a better Haskell?
Then farther along, what if we created a LEAN-adjacent language, not for mathematical proofs, but for writing programs? We could throw in formal methods (TLA+) type thinking. Today formal methods give you a correctness proof, but are disconnected to implementation (AWS uses TLA+ for modeling distributed systems, but the final code was not generated from TLA+, so there's disconnect). What if one day we can write a spec, and it generates a TLA+ proof, which we can then use to generate code?
In this world, the code generator is simply a compiler -- from mathematically rigorous spec to machine code.
(that said, I have to check myself. I wonder what this would look like in a world full of exceptions, corner cases, and ambiguities that cannot be modeled well? Tukey's warning comes to mind: "Far better an approximate answer to the right question, than an exact answer to the wrong question")
Ah yes, the inevitable future where the only way we'll know to interact with the machine is through persuading a capricious LLM. We'll spend our days reciting litanies to the machine spirits like in 40k.
Praise and glory be to the Agentic gods. Accept this markdown file and bless this wretched body of flesh and bone with the light of working code. Long live the OpenssAIah
Pre commit hooks are complicated because jj just has a fundamentally different lifecycle than git does.
Tools that integrate with git specifically can be tough though, yeah. Some do Just Work, and some very much do not.
I’ve found a “we use jj not git for this project” in Claude.md makes falling back to git rare, but I also tend to incorporate version control into slash commands or skills directly rather than let Claude decide what to do.
I also prefer to manage version management myself directly, even with llm-gen'd CICD elements, so preferring jj hasn't been nearly as costly for me specifically :D
My team is asking the same. We are using jj with great success but tools like auto claude are designed around git and git worktrees. It's a shame - at least with git backend we can sort of make things work together.
The problem with this is that at the limit, this means "run the precommit on every save of a file," which is not really usually how people think of precommit hooks.
Given jj's rebasing tooling, rewiring precommit into "prepush" feels like the right way forward. There's a bit of a phase transition between commits on your machine and commits that are out in the wild, after all.
For me it's mostly about doing as much of CI locally as feels reasonable to do quickly to save an iteration cycle. But I live in a world of badly configured text editors and the like so I usually have some silly formatting error
I agree about hooks and workspaces, but I'm surprised your Claude is having issues with jj itself. jj is definitely in the training data now, so it might be a matter of guiding it with CLAUDE.md.
It usually works, but sometimes it'll try to use git instead of jj at random and needs a reminder. As JJ is not completely stable it tries some old commandline versions as well. This improved after I put in some lines in my agents file, but still it's much better at complex changes with git than jj.
If it helps, this was all I needed in my CLAUDE.md to make it use jj perfectly:
# Version Control
- IMPORTANT: YOU MUST assume we use Jujutsu ("jj") for version control. Check by running `jj root` (or look for a `.jj/` directory) to confirm.
- If I say "commit", "branch", "squash", etc., assume jj equivalents first.
- You can ignore any `git add` command, since jj always auto-adds.
- Use `jj` commands instead of `git`. Never run `git` in a jj repository.
- ALWAYS prefer jj change IDs over commit SHAs. jj change IDs are stable.
- jj doesn't usually require named branches
- If you need named branches, use `jj bookmark`, but you must manually update the bookmark after making new commits, since they won't automatically get updated
- When reading data from jj, always use `--ignore-working-copy` to avoid snapshotting the working copy (which is slow and unnecessary for read operations). But when writing (commit, squash, rebase, etc.), you MUST NOT use `--ignore-working-copy`.
- If you get "Error: The working copy is stale", run `jj workspace update-stale` first
I actually asked about that on the GH discussions a couple weeks ago, but based on this (https://github.com/jj-vcs/jj/issues/7229), I'm not sure it's 100% foolproof to turn on auto-updates.
It might be ok for human use, but I have definitely seen agents in one workspace start encroaching on another workspace's turf. (Rare, but it's a huge pain to fix when it happens.)
Great to see this. I played around with jj about two months ago and really enjoyed using it on the command line, but I found it difficult to understand the interaction with git and GitHub and decided to put it off until I had more time. (I don’t recall the specific issues I had…) Maybe this extension can remove some of that friction.
Strongly agree, and it's always getting better. The maintainer is a hero, and there's a few other regular contributors who do great work. They're always super responsive to feedback
I love jjui, but I feel like it's also the reason I still use him over vscode. If you already use vscode, doesn't using a vscode extension make more sense?
Of course there are some people that will want a gui not matter what. Then an extension or separate program is the only thing you can do. But i think it is really nice to have the same tool available everywhere, also in the terminal. And if you want a neat and vertical pane in vscode just drag a new terminal window next to your code and run jjui in it.
> Stay in your editor while GitHub does the rest. VisualJJ tracks pull-request status on the change tree and lets you create PRs in a couple of clicks, so moving changes from “draft” to “merged on GitHub” feels like one smooth flow.
Fair point, I thought it had been eliminated, but apparently that is pending the adoption of the project by a foundation such as Apache or the Linux foundation.
I used/use magit a lot, and rebasing is much nicer with magit. But you're still faced with having to be in git land. JJ there's a lot of "rebasing at the speed of thought" because you really are just moving nodes around and "do what I mean" kicks in.
There's this other thing too, which is that jj I've always felt comfortable modifying changes that are not what I currently have checked out. With git it's always felt like the first step for any change management is "check out the changes into the working copy".
One obvious case where magit isn’t useful as opposed to jj is if you’re not an emacs user.
jj has some additional features over just a nicer UI that I believe magit can’t do, but given that I haven’t used magit yet I am not 100% sure of how that comparison is exactly.
Because jj is vastly simpler and more powerful than git, while being compatible with git (so you can keep using Github etc). There's tons of articles and videos on the topic, and many other posts here on HN about it
Check out jjui in particular. Makes it even easier
reply