Local herdr plugins.
| plugin | id | what it does |
|---|---|---|
jj-status |
babariviere.jj-status |
Reports each workspace's jj working-copy status as the $jj_status Space sidebar token. |
jj-worktree |
babariviere.jj-worktree |
Makes herdr's worktree UI work with jj workspaces, and syncs ignored files into every worktree. |
herdr plugin install babariviere/herdr-plugins/jj-status --ref main --yes
herdr plugin install babariviere/herdr-plugins/jj-worktree --ref main --yesA [[startup]] poller that reports jj_status for every workspace. Render it
with a custom token:
[ui.sidebar.spaces]
rows = [
["state_icon", "workspace"],
["branch", "git_status"],
["$jj_status"],
]Requires jj 0.46+ and Git 2.42+. jj now supports native colocated
secondary workspaces, so Git tools and herdr's repository grouping work without
manually grafting .git metadata. The new action explicitly uses
jj workspace add --colocate, even if git.colocate is disabled globally.
The plugin does not create bookmarks. A disposable branch created by herdr's
native binding is forgotten after conversion. Trunk names, remote bookmarks,
and bookmarks with unique commits are kept. jj owns each worktree's HEAD and
index, and HEAD will normally be detached. Create a bookmark when ready to
publish work; use jj-status for the sidebar's working-copy identity.
| trigger | what happens |
|---|---|
new action |
jj workspace add --colocate, copy ignored files, worktree open |
| herdr's native worktree binding | convert.sh adopts the checkout and existing Git worktree as a jj workspace |
worktree.opened |
ignored files re-synced |
worktree.removed |
jj workspace forget unlinks the Git worktree, then stale entries are pruned; optional cleanup of legacy bookmarks |
convert.sh does not delete the directory herdr just populated. It renames it
aside (keeping the inode, so the pane's shell never sits in a deleted cwd),
creates the jj workspace at the real path with
--no-colocate --sparse-patterns=empty (which writes .jj and nothing else),
moves .jj in, renames the directory back, and widens the sparse patterns.
--no-colocate avoids creating a second Git worktree: the original .git is
kept intact, and jj recognises it once the directory is restored. The actual
Git HEAD determines the revision, including detached checkouts. jj finds every
file already on disk and adopts it:
Added 198 files, modified 0 files, removed 0 files
Warning: 198 of those updates were skipped because there were conflicting changes in the working copy.
The working copy ends up clean with no file rewritten by jj: git's checkout is the only one that ever wrote them.
~/.config/herdr/plugins/config/babariviere.jj-worktree/config.json, falling
back to the workspaces block of ~/.pi/agent/settings.json:
{
"root": "~/.herdr/workspaces",
"copyFiles": ["mise.local.toml", ".env.local"],
"convertNativeWorktrees": true,
"deleteBranchOnRemove": false
}mise.local.toml is always copied even if copyFiles omits it: a worktree
without it resolves the wrong toolchain, and that failure looks like a broken
repo rather than a missing file.
Set convertNativeWorktrees to false to leave herdr's native worktrees as
plain git worktrees. They still get their ignored files.
Set deleteBranchOnRemove to true to also drop the bookmark when a worktree
is removed. It is off by default because it is destructive. Even when on, the
branch is kept if it is trunk (main, master, trunk, develop), if it
exists on a remote, if the worktree was force-removed (which is exactly the
case where it was dirty), or if any commit is reachable only from it. Removal
uses jj bookmark forget, not jj bookmark delete: a delete would record a
deletion that the next jj git push propagates to the remote.
Worktree creation takes a per-repo lock (mkdir under the plugin state dir,
stolen after 120s) because conversion temporarily renames the checkout.
Steady-state work in several worktrees at once needs no lock: each
has its own index and HEAD, and jj serialises writes to the shared store
through its operation log.
python3 -m unittest discover -s tests -v runs integration tests with temporary
repositories and a stub herdr executable. It requires jj 0.46+ and Git 2.42+.