Worktree-isolation guard refuses every jj git <subcommand>, including in a correct jj workspace
Version: 2.1.268 (Claude Code), jj 0.45.1
Platform: macOS 26.1, arm64, zsh via the Bash tool
Related: #85118 (jj commands in an isolated session can target the parent workspace)
Summary
While a session is isolated in a worktree, the guard refuses jj git root, jj git fetch, jj git push, and jj git export. It refuses them even when jj root inside that session resolves to the worktree itself, which means jj targets the correct workspace.
An isolated session can therefore neither fetch nor push a bookmark. No jj-native command reaches a remote from inside a worktree.
Bare jj git runs. The guard refuses it as soon as a subcommand follows.
Precondition
The worktree must be a real jj workspace, not a git worktree carved out of a jj repository. A WorktreeCreate hook that runs jj workspace add produces one. #85118 covers the case where the worktree is not a jj workspace, and in that case the refusal is correct.
This report is about the case where the workspace is correct.
Repro
mkdir repo && cd repo
jj git init
echo x > a.txt && jj describe -m init
claude --worktree probe -p \
"Run each command below via the Bash tool, exactly as written, one per call. \
Report the command then its FIRST LINE of output or error, verbatim. \
Do not fix, retry, or work around anything. \
1. pwd 2. jj root 3. jj git 4. jj git root \
5. jj git fetch 6. jj git push 7. jj git export" \
--allowed-tools Bash
Results, where <wt> is the worktree path:
| Command | Result |
|---|---|
| pwd | <wt> |
| jj root | <wt> |
| jj git | Runs. Prints the subcommand help. |
| jj git root | Refused. |
| jj git fetch | Refused. |
| jj git push | Refused. |
| jj git export | Refused. |
Rows 1 and 2 are the point. jj resolves to the worktree, so every jj command that follows targets this workspace and no other.
Refusal text, identical for rows 4 to 7:
This session is isolated in the worktree \<wt\>, but this command runs jj with a git command among its operands: what runs it, and from which directory or root, cannot be read here (name git right after the launcher and its options) in a plain command, so what it runs cannot be shown not to be git. Refusing to run it — a worktree-isolated session's git operations must target its own worktree. Run the plain command from \<wt\>.
The remedy names the directory the session already runs in, so the reader cannot follow it. jj git root is also read-only. It prints a path and writes nothing.
What the guard reads
Two results show that the guard reads the spelling rather than the target:
- Bare
jj gitruns andjj git rootdoes not. Both reach the same repository. - A jj alias that expands to
gitruns all four refused commands unchanged. The name of the alias contains nogit.
Neither result gives the guard any information about which repository the command writes to.
jj git fetch writes to the Git store that the main workspace shares, because jj workspaces share one store by design. It does not write to another workspace's working copy, and the working copy is what worktree isolation protects.
Suggested fix
#85118 named a check that covers both cases:
in an isolated session, blockjjwhenjj rootdoes not resolve to the worktree root.
That check reads the target rather than the spelling. It keeps the behavior #85118 asked for, and it lets a correct workspace reach its remote. It must also account for jj's own repository flags, such as -R and --repository.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗