Skip to content

Workspace Sidebar: tmux, worktree and manager sections (#331, #333) - #376

Draft
raiseCatError wants to merge 6 commits into
feature/workspace-foundationfrom
feature/workspace-sidebar
Draft

raiseCatError wants to merge 6 commits into
feature/workspace-foundationfrom
feature/workspace-sidebar

Conversation

@raiseCatError

@raiseCatError raiseCatError commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

#331 and the navigation part of #333. Stacked on the workspace foundation PR (feature/workspace-foundation). Standalone controller and renderer; TerminalApp.ts untouched.

  • SidebarController: selection by id across refreshes (a vanished one moves to the row in its place), expansion kept across refreshes, ← to the parent, a / filter showing matches with their ancestors. Moving only proposes a preview; activation returns an intent and only for an activatable resource; anything else returns its reason.
  • renderSidebar: exactly rows × width; focus, selection, active, attention, exited and stale each have their own mark in Unicode and Safe glyphs, so NO_COLOR loses nothing; compact mode for narrow docks; key help only while focused.
  • tmux.ts: one bounded list-panes -a on the server NMSh runs inside ($TMUX) — trusted executable, 1.5 s / 256 KiB, minimal environment, argv only. U+001F field separator (tmux rejects control characters in names, verified on tmux 3.7) and every row validated. Session → window → pane (two windows / five panes = one session); NMSh's own pane ($TMUX_PANE) marked active. Navigation uses tmux's own select-pane / select-window / switch-client on ids, never names. No panes, PTYs or layout changes.
  • sources.ts: worktrees from the /worktrees snapshot (open = that manager's cd intent; missing/bare listed with a reason) and links to /github, /agents, /sessions.

Not included: NMSh live sessions and Managed Targets as first-class rows (need the session service and #329 registry wired through the frontend); GitHub items (the manager is linked).

Tests: tests/workspaceSidebar.test.ts, including a real tmux server on a private socket (listing, selecting a window with the navigation argv, a missing server reported as an error); skipped only when tmux is not installed.

Update (272f302): Ubuntu CI (tmux 3.4) listed no panes: that tmux escapes control characters in format output, so the U+001F separator never arrived. The listing now uses | with names requested through tmux's q: modifier; both escapings are undone and rows with the wrong field count are dropped. The design notes moved to docs/design/workspace-sidebar.md so the workspace slices don't edit the same file.

Update (04764c9, 955d29f), quality pass: merges the foundation fixes. A worktree inside the main checkout's directory made both it and the main worktree "active"; only the innermost one holding the shell's directory is current now (regression added). The design doc now states the key order while filtering (handleSearchKey before routeWorkspaceKey) and that changeDirectory is performed like /worktrees: directoryCommand(path) staged in an empty composer. The tmux escaping test expects an escaped escape sequence to be removed whole. CI green on 955d29f.

…nd manager sections

#331, with the tmux navigation part of #333; stacked on the workspace
foundation. Standalone controller and renderer: the running app is
unchanged until the integration step.

- SidebarController: selection by id across refreshes (a vanished one moves
  to the row in its place), tree expansion kept across refreshes, parent on
  Left, a `/` filter that shows matches with their ancestors. Moving only
  proposes a preview; activation returns an intent and only for an
  activatable resource; anything else says why.
- renderSidebar: exactly rows x width; focus, selection, active, attention,
  exited and stale each have their own mark in Unicode and Safe glyphs, so
  NO_COLOR loses nothing; hostile names are inert.
- tmux.ts: one bounded `list-panes -a` on the server NMSh runs in ($TMUX),
  fields separated by U+001F and every row validated; session -> window ->
  pane with NMSh's own pane marked active; navigation with tmux's own
  select-pane/select-window/switch-client on ids, never names, as argv.
- sources.ts: worktrees (open = the /worktrees cd intent; missing or bare
  paths listed with a reason) and links to /github, /agents, /sessions.

Tests include a real tmux server on a private socket: listing, selecting a
window with the navigation argv, and a missing server reported as an error.
…-character separator

Ubuntu CI (tmux 3.4) listed no panes: older tmux builds escape control
characters in format output, so the U+001F separator never arrived as one
character. Fields are now separated by `|`, names are requested with the
`q:` modifier (which escapes `|`), and both that escaping and tmux's own
output escaping (`\\`, `\ooo`) are undone. Rows with the wrong number of
fields are dropped. Tests cover escaped separators, escaped backslashes and
an escaped control character; the real-tmux test uses a session name with
a `|`.
…rder and the cd hand-off are written down

- A worktree inside the main checkout's directory (.worktrees/feature) made both it and the main worktree "active".
  The innermost worktree holding the shell's directory is the current one.
- The tmux escaping test now expects an escaped escape sequence to be removed whole (the foundation's resourceText).
- Integration notes: handleSearchKey runs before routeWorkspaceKey while filtering; changeDirectory goes through
  directoryCommand and is staged in an empty composer, as /worktrees does.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant