Elyra
Elyra The coding agent Elyra Conductor Local project conductor Elyra SQL Anywhere Replication-ready SQL engine
Elyra integration
Elyra agent
Elyra
Terminals & panes

Terminals & panes

Every terminal in Conductor is a real PTY: one portable-pty session per pane in Rust, rendered with xterm.js in the webview. Your login shell runs with TERM=xterm-256color, rooted at the pane's working directory.

Tabs

Each tab is an open session — either a terminal (with its own split layout) or an Elyra agent panel. Open a new terminal tab with the button, ⌘KNew terminal tab, or by selecting a project.

  • Drag to reorder tabs — grab a tab and drag it sideways; a blue insertion marker shows where it will land. (Reordering uses pointer events, so it works reliably inside the webview.)
  • Jump to a tab with ⌘1⌘9 (its position in the bar, left to right). The shortcuts follow whatever order you've dragged the tabs into.
  • Close a tab with its , or close the focused pane with ⌘W (closing the last pane closes the tab).
  • A tab is labelled by its project name, so you can always tell which project it belongs to. When a foreground command is running (e.g. ⌘R / npm run dev), a pulsing marker and a small process chip (vite, php, …) appear next to the name.

Split panes

Split any pane to run multiple processes side by side:

Action Shortcut
Split right (vertical divider) ⌘D
Split down (horizontal divider) ⇧⌘D
Close active pane ⌘W

Splits nest freely, and you can drag the dividers to resize. Each pane also has hover controls in its top-right corner (split right / split down / close).

Move between panes with ⌘⌥ + the arrow keys, and zoom the active pane to fill the tab with ⌘⌥Z (press again to restore) — tmux-style. Switching tabs, splitting, or navigating unzooms automatically.

Global scrollback search

Press ⇧⌘F (or the command palette → Search all terminals) to search the buffer of every open terminal at once — not just the focused one. Matches are grouped by pane with a count and a sample line; pick one to jump straight to that tab/pane with the match highlighted. Great for “which of my six running services logged that error?”

Why splitting never loses your session

Terminals live in a flat, absolutely-positioned layer keyed by terminal id. A pure layout module (layout.js) computes each pane's geometry from a split tree. Because the DOM node for a terminal is never remounted when the tree changes, the PTY session and scrollback survive every split and divider drag. (Rendering the tree recursively would have killed and respawned shells on every relayout.)

See Architecture & boundaries for the full data flow.

Notification rings

Background tabs pulse green when their terminal produces new output, and the indicator clears when you switch to the tab. All tabs stay alive in the background, so nothing is lost when you switch away from a long-running process.

Finished-command notifications

When a long-running command in a background tab returns to the shell — a build, test run, or deploy completing while you're in another app — Conductor fires a native notification (e.g. “✓ cargo finished · my-project · ran 54s”). It watches the foreground-process titles it already polls, so there's nothing to configure per command:

  • Only fires for commands that ran at least ~8 seconds (no noise from quick commands).
  • Never fires for the tab you're actively watching (focused window + active tab).
  • Toggle it from the command palette — Notify when a background command finishes / Disable finished-command notifications. The choice persists across restarts.

First use asks for macOS notification permission; you can also manage it later under System Settings → Notifications → Elyra Conductor.

Shell integration (zsh)

On by default, shell integration makes new terminals capture the real command line and exit code of each command you run, via OSC 133/633 sequences. Toggle it from the command palette (⌘KEnable/Disable shell integration); your choice is remembered. It powers the command timeline, the persisted history, and "Fix it".

It's safe with your existing setup: Conductor points ZDOTDIR at a small shim that sources your own .zshenv / .zprofile / .zshrc (so your prompt — powerlevel10k, instant prompt, aliases — is untouched) and then adds precmd/preexec hooks.

With it on:

  • The command timeline (🕘) shows the full command and a ✓ / ✗ exit-code badge, and every command is saved to a searchable history — see Command history & insights.
  • The sidebar shows a per-project ✓ / ✗ test badge from the last test run (pest, phpunit, vitest, jest, pytest, cargo/go test, …).

Only zsh is supported for now; other shells keep the lighter, process-name-based timeline.

In-terminal search

Press ⌘F while a terminal is focused to open a find bar. Use / ⇧↵ to step through matches and Esc to close. Powered by the xterm search addon.

Newline vs. submit (⇧↵)

Many TUIs use ⇧↵ to insert a newline while submits. Plain xterm.js can't send a distinct sequence for modified Enter — it collapses ⇧↵, ⌥↵, and ⌃↵ to a bare carriage return. Conductor fixes this by emitting the Kitty keyboard-protocol CSI u sequence for modified Enter, so apps like the Elyra CLI receive ⇧↵ as a real newline instead of submitting. No configuration is needed.

Broadcast input (synchronize panes)

Toggle ⌁ Sync in the top actions (or ⌘KBroadcast input to all panes) to mirror your keystrokes to every pane in the active tab — tmux synchronize-panes-style. Useful for running the same command across several services in a monorepo. Toggle it off to return to typing in just the focused pane.

Scrollback across restarts

Each pane's recent output is persisted and replayed as read-only history the next time Conductor launches, with a fresh shell started beneath it. A live PTY cannot be revived once the app closes, so this restores context, not a live process. Details and limits are in State & persistence.

Running a command on open

Tabs opened for a task (or a file run) start a shell and then run the chosen command once. This is the same mechanism behind Run: … in the command palette.