Skip to content
gwmgwmgwmv1.10.0

tmux / zellij / herdr integration

Inside an already-running multiplexer session, gwm tmux, gwm zellij and gwm herdr spawn a new window / pane / tab whose shell starts inside the matched worktree, with no manual cd round-trip needed.

Terminal window
gwm tmux auth # new tmux window inside the matched worktree
gwm tmux auth -p # split the current pane instead
gwm tmux auth --split # ...long form of -p
gwm tmux auth --direction down # ...stacked rather than side by side

Under the hood:

  • new window (default): tmux new-window -n <name> -c <path>
  • split (-p / --split): tmux split-window -h -c <path>, or -v under down, plus -b under left / up

The -n <name> arg names the new window after the worktree slug so it stands out in the status bar.

-h is tmux’s horizontal split, and it puts the new pane to the right; -v stacks it below. tmux names the axis the divider runs along, not where the pane goes, which is worth knowing before reading the two flags as the words suggest. -b (“before”) flips the side on whichever axis was picked, so left is -h -b and up is -v -b. Measured on tmux 3.7c by reading the new pane’s geometry back through split-window -P -F.

Terminal window
gwm zellij auth # new zellij tab inside the matched worktree
gwm zellij auth -p # new pane in the current tab instead
gwm zellij auth --direction down # ...stacked rather than side by side

Under the hood:

  • new tab (default): zellij action new-tab --name <name> --cwd <path>
  • new pane (-p / --split): zellij action new-pane --direction <dir> --cwd <path>

--direction is optional in zellij’s own parser: without it, zellij “will try to use the biggest available space”, which makes the pane’s position a property of the current layout rather than of the command. gwm passes it so the answer is the same every time.

The --cwd flag on new-tab requires zellij ≥ 0.40; older versions error out. new-pane --cwd has been stable longer, so use -p if you’re stuck on an older zellij.

Terminal window
gwm herdr auth # new herdr tab inside the matched worktree
gwm herdr auth -p # split the current pane instead
gwm herdr auth --direction down # ...stacked rather than side by side

Under the hood:

  • new tab (default): herdr tab create --workspace <id> --label <name> --cwd <path> --focus
  • split (-p / --split): herdr pane split --current --direction <right|down> --cwd <path> --focus, and only those two

herdr drives its own server over a socket, so both verbs are control commands rather than a new-window equivalent. Four details differ from tmux and zellij:

  • the split direction is not optional. herdr’s parser has no default for --direction, so gwm always passes one. Since #589 the value comes from --direction or from [tui] mux_pane_direction rather than from a hardcoded right. herdr declares [possible values: right, down], so the left and up that #611 added for tmux and zellij are refused here rather than translated into something else.
  • the split takes no label. A herdr pane is named after the fact with herdr pane rename, and pane split reads a bare argument as the pane to split, so gwm passes the worktree name only on tab create.
  • --focus is not the default. Both verbs come back "focused": false without it, where tmux new-window and zellij action new-tab move you to what they create. gwm passes it so herdr is not the one backend that opens the worktree out of sight.
  • the new tab is pinned to your workspace. Without --workspace, herdr targets the workspace the server has focused, which is another project’s window as often as not. gwm passes $HERDR_WORKSPACE_ID, which every managed pane carries; outside one, the flag is dropped and herdr picks. A split needs none of this, --current already resolves the workspace.

A third level exists on herdr with no CLI equivalent: herdr workspace create --label <name> --cwd <path> --focus, reachable from the TUI’s t through [tui] mux_open_in = "workspace". tmux and zellij have no level above the tab, so they refuse that setting rather than open something else.

Verified against herdr 0.8.2, against a live server rather than the help text: the focus and workspace behaviours above were both measured, and both are the opposite of what the flag names suggest.

All three commands require the corresponding multiplexer to actually be running:

  • gwm tmux checks for $TMUX in the environment.
  • gwm zellij checks for $ZELLIJ.
  • gwm herdr checks for $HERDR_ENV, which herdr sets to 1 in every pane it manages.

One caveat on that last one, upstream rather than gwm’s: a tmux server started from inside a herdr pane copies the whole HERDR_* set into its server-global environment (herdrdev/herdr#2134), so unrelated sessions on that server also claim to be herdr panes. The TUI’s t is unaffected, since those sessions have $TMUX set and tmux comes first in the cascade. gwm herdr <pattern> typed in such a session will reach a stale pane id and herdr will refuse it, which surfaces as a failed command rather than a wrong tab.

Outside a session, the command refuses with a clear error rather than spawning a stray server: the alternative (spawning detached) leads to orphaned sessions that the user never sees.

Terminal window
$ gwm tmux auth
gwm tmux requires an active tmux session ($TMUX is not set).

The <pattern> arg uses the same fuzzy matcher as gwm path / remove / bootstrap (nucleo-matcher). Ambiguous matches exit 1 and print both candidates without spawning anything.