Add zellij multiplexer support to agent-cli dev#590
Conversation
Zellij >= 0.44.0 gained stable tab IDs, initial commands for new tabs, and detached-session control, enabling tmux-parity support: - New Multiplexer ABC (shared session naming, open_in_session, attach_command); Tmux and Zellij both implement it - --multiplexer zellij on dev new/agent: creates or reuses a detached repo-scoped session when outside zellij - --zellij-session flag mirroring --tmux-session - Worktree cleanup closes zellij tabs by matching pane cwd, across all live sessions, skipping the current tab - Legacy write-chars tab opening kept for zellij < 0.44 inside a session - Evidence-backed verification tests (docs/PRs + live probes on 0.44.3)
Greptile SummaryAdds zellij >= 0.44.0 as a first-class multiplexer in
Confidence Score: 5/5Safe to merge — the new zellij path is well-isolated behind version gating and the fail-safe current-tab protection addresses the main hazard in cleanup. The core logic is straightforward: version-gated subprocess calls with clear error propagation, deterministic session-name derivation shared from the base class, and worktree cleanup correctly skips the caller's own tab even when pane lookup fails. Previous reviewer concerns (session-name space handling, version-check caching, current-tab fail-safe) are all addressed. No regressions to existing tmux behaviour were found. Tests are comprehensive and cover all edge cases. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant CLI as dev agent / dev new
participant NMS as _normalize_multiplexer_session
participant LA as launch_agent
participant LIM as _launch_in_multiplexer
participant Z as Zellij
participant T as Tmux
CLI->>NMS: (tmux_session, zellij_session, multiplexer)
NMS-->>CLI: (multiplexer_session, multiplexer_name)
CLI->>LA: launch_agent(..., multiplexer_name, multiplexer_session)
LA->>LIM: _launch_in_multiplexer(requested, session_override)
alt "zellij >= 0.44 or tmux"
LIM->>Z: open_in_session(path, cmd, session_name)
alt session does not exist
Z->>Z: _ensure_session
end
Z-->>LA: TerminalHandle
LA-->>CLI: attach hint
else "zellij < 0.44 fallback"
LIM-->>LA: None
LA->>Z: open_new_tab legacy
end
Note over T,Z: dev clean
T->>T: kill_windows_for_worktree
Z->>Z: _live_session_names
Z->>Z: _list_panes per session
Z->>Z: _current_tab fail-safe
Z->>Z: close-tab-by-id
Reviews (4): Last reviewed commit: "Fix zellij tests on Windows: compare aga..." | Re-trigger Greptile |
- Parse session names from list-sessions with a regex so names containing spaces are preserved (was: first token only) - Fail safe in close_tabs_for_worktree: when inside zellij and the current tab cannot be resolved, skip all tabs in the current session instead of risking closing our own tab - Cache the zellij version check per instance to avoid repeated `zellij --version` subprocess calls
Summary
Adds zellij as a fully supported multiplexer in
agent-cli dev, alongside tmux. Zellij 0.44.0 introduced the programmatic control this needs: stable tab IDs returned fromnew-tab, initial commands for new tabs,list-panes --json, andclose-tab-by-id— all working against detached sessions.What's new
--multiplexer zellijondev newanddev agent: when run outside zellij, creates or reuses a detached repo-scoped session (zellij attach --create-background) and reports the tab handle plus azellij attach <session>hint--zellij-session NAME: mirrors--tmux-session, implies--multiplexer zellij; the two session flags are mutually exclusive and validated earlydev clean/ worktree removal now inventories tabs across all live sessions by matchingpane_cwdagainst the worktree path (zellij's equivalent of tmux window tagging) and closes them viaclose-tab-by-id, skipping the tab the process itself runs in (resolved viaZELLIJ_PANE_ID)new-tab --cwd ... -- sh -c <cmd>instead of the oldwrite-charshack (which needed asleepand typed into the focused pane)Implementation
MultiplexerABC interminals/base.pywith a shared deterministicsession_name_for_repo, plus abstractopen_in_session/current_session_name/attach_command;TmuxandZellijboth implement itlaunch.py's tmux-specific launch path is generalized to anyMultiplexerzellij --version); on older versions the multiplexer path declines gracefully and the legacy--layout default+write-charsin-session path is kept as a fallback, so existing behavior is preservedEvidence
Per the repo convention, every external CLI assumption is documented in
tests/dev/test_verification.pydocstrings with sources (zellij docs, CHANGELOG entries, and PR links: zellij-org/zellij#4690, #4846, #4273, #3257) and was verified live against zellij 0.44.3, including detached-session behavior (attach --create-backgroundon an existing session exits 1 with "Session already exists" instead of blocking).Testing
jscpdpre-commit hook fails on the dev machine due to a missingcpd-darwin-arm64platform package; verified it also fails on the untouched tree (environment issue, unrelated)