What
renri list, renri remove <branch>, and renri prune all surface jj's raw "stale working copy" error when the calling workspace's snapshot is behind the operation log:
Error: jj workspace list: Error: The working copy is stale (not updated since operation aa93561903e7).
Hint: Run `jj workspace update-stale` to update it.
This is a different "stale" from the one prune already handles (workspace whose root directory has been deleted). It's the op-log stale that happens when something changes git refs / jj ops out from under a workspace that already snapshotted — for example, git fetch after a remote-side merge.
Repro
From the main checkout:
gh pr merge <pr> --squash --delete-branch
git fetch origin main (or any flow that nudges jj's underlying git store)
renri remove <branch> — fails with the stale-WC error above
renri prune and renri list hit the same error (all three call jj workspace list early).
Why it matters
- The post-merge cleanup workflow documented in
CLAUDE.md (renri remove <branch> then optionally renri prune) breaks until the user manually runs jj workspace update-stale from the main checkout.
- The error message is clear, but renri swallows context (which command, which workspace) and the user has to translate the jj jargon. New jj users hit a wall.
Proposal
Detect the stale-WC error in the jj backend's command runner and either:
a) Emit a renri-flavored hint — wrap the jj error with something like:
the main checkout's jj working copy is behind. Run jj workspace update-stale in <root> and retry.
Safest option, no implicit mutation.
b) Auto-recover for read-only paths (list) and bail-with-hint for mutating paths (remove, prune). update-stale is itself read-only-ish (it only fast-forwards the current workspace's @ to match the latest op), but doing it implicitly when the user asked for remove could mask deeper conflicts.
(a) is the lower-risk default. (b) is nicer UX but warrants explicit opt-in.
Out of scope
- Making renri itself robust to target workspace staleness (i.e. "remove a stale workspace") —
prune already handles that case via is_stale || !path.exists().
- Equivalent stale-WC concept for git worktrees — git's model doesn't have an op log so there's no analog.
What
renri list,renri remove <branch>, andrenri pruneall surface jj's raw "stale working copy" error when the calling workspace's snapshot is behind the operation log:This is a different "stale" from the one
prunealready handles (workspace whose root directory has been deleted). It's the op-log stale that happens when something changes git refs / jj ops out from under a workspace that already snapshotted — for example,git fetchafter a remote-side merge.Repro
From the main checkout:
gh pr merge <pr> --squash --delete-branchgit fetch origin main(or any flow that nudges jj's underlying git store)renri remove <branch>— fails with the stale-WC error aboverenri pruneandrenri listhit the same error (all three calljj workspace listearly).Why it matters
CLAUDE.md(renri remove <branch>then optionallyrenri prune) breaks until the user manually runsjj workspace update-stalefrom the main checkout.Proposal
Detect the stale-WC error in the jj backend's command runner and either:
a) Emit a renri-flavored hint — wrap the jj error with something like:
Safest option, no implicit mutation.
b) Auto-recover for read-only paths (
list) and bail-with-hint for mutating paths (remove,prune).update-staleis itself read-only-ish (it only fast-forwards the current workspace's @ to match the latest op), but doing it implicitly when the user asked forremovecould mask deeper conflicts.(a) is the lower-risk default. (b) is nicer UX but warrants explicit opt-in.
Out of scope
prunealready handles that case viais_stale || !path.exists().