Summary
Add opt-in jujutsu (jj) support as an alternative VCS backend for muzzle's session isolation. When a repo has .jj/, muzzle uses jj workspace commands instead of git worktree. Git remains the default; jj is activated by auto-detection or explicit opt-in.
Research
Full feasibility analysis: .agents/research/2026-03-23-jujutsu-feasibility.md
Motivation
jj's architecture eliminates several categories of complexity muzzle currently handles:
- 5 of 8 git safety regex patterns become unnecessary —
immutable_heads() enforces branch protection at the VCS level
- Ephemeral branch management disappears — jj workspaces aren't branch-bound
- Dirty worktree handling simplified — conflicts are first-class commits, not blocking states
- Lost work on crash eliminated — jj auto-snapshots the working copy
- Worktree prune/retry logic removed — jj workspace management has no stale metadata issues
- Operation log provides a free audit trail with point-in-time rollback
Design
VcsBackend trait
Extract current git logic behind a VcsBackend trait, then implement a JjBackend:
trait VcsBackend {
fn workspace_add(&self, repo: &Path, dest: &Path, rev: Option<&str>) -> Result<()>;
fn workspace_remove(&self, repo: &Path, name: &str, force: bool) -> Result<()>;
fn workspace_list(&self, repo: &Path) -> Result<Vec<WorkspaceInfo>>;
fn is_clean(&self, path: &Path) -> Result<bool>;
fn fetch(&self, repo: &Path) -> Result<()>;
fn default_branch(&self, repo: &Path) -> Result<String>;
fn check_safety(&self, command: &str, session: &Session) -> Result<Verdict>;
}
Auto-detection
.jj/ only → JjBackend (non-colocated)
.jj/ + .git/ → JjBackend (colocated, set GIT_DIR for gh CLI, jj git export before gh ops)
.git/ only → GitBackend (current behavior)
Colocated workaround
jj workspace add in colocated repos creates non-colocated children. Muzzle handles this by:
- Setting
GIT_DIR + GIT_WORK_TREE env vars pointing to parent's .git/
- Running
jj git export before gh CLI invocations
Phased implementation
- Phase 1: Extract
VcsBackend trait from current git code (pure refactor)
- Phase 2: Implement
JjBackend via Command::new("jj") CLI calls
- Phase 3: Auto-detection in
session_start.rs and ensure_worktree.rs
- Phase 4: Colocated mode (GIT_DIR injection,
jj git export hook)
Acceptance criteria
Summary
Add opt-in jujutsu (jj) support as an alternative VCS backend for muzzle's session isolation. When a repo has
.jj/, muzzle usesjj workspacecommands instead ofgit worktree. Git remains the default; jj is activated by auto-detection or explicit opt-in.Research
Full feasibility analysis:
.agents/research/2026-03-23-jujutsu-feasibility.mdMotivation
jj's architecture eliminates several categories of complexity muzzle currently handles:
immutable_heads()enforces branch protection at the VCS levelDesign
VcsBackend trait
Extract current git logic behind a
VcsBackendtrait, then implement aJjBackend:Auto-detection
Colocated workaround
jj workspace addin colocated repos creates non-colocated children. Muzzle handles this by:GIT_DIR+GIT_WORK_TREEenv vars pointing to parent's.git/jj git exportbeforeghCLI invocationsPhased implementation
VcsBackendtrait from current git code (pure refactor)JjBackendviaCommand::new("jj")CLI callssession_start.rsandensure_worktree.rsjj git exporthook)Acceptance criteria
VcsBackendtrait withGitBackendandJjBackendimplementations.jj/vs.git/presenceimmutable_heads(), blockjj git pushto protected bookmarks)GIT_DIRinjection +jj git exportforghCLI compatibilitymise run cipasses