Skip to content

Panes, Tabs & Workspaces

luvus is mouse-native: everything here works by click and drag, and every action also has a key behind the Ctrl+Space prefix. Nothing is modal, so what you type always goes to the focused pane.

A pane is a real terminal. Inside a tab you can split it as many ways as you like, and luvus tiles them automatically.

Do thisMouseKey
Split side by sideright-click a pane → SplitCtrl+Space v
Split top / bottomright-click a pane → Split downCtrl+Space s
Focus a paneclick itarrows or hjkl
Move a pane to another tabright-click → Move to Tabn/a
Zoom (fullscreen) a panen/aCtrl+Space z
Close a panethe × on its title, or right-click → CloseCtrl+Space x

Each split pane shows a title bar with a status dot and its working directory. The focused pane’s frame is brighter.

Three ways, whichever fits your hands:

  • Drag a divider. Hover the border between two panes (it brightens) and drag.
  • Ctrl+drag anywhere inside a pane to nudge its edges. (Ctrl+click on a URL or a file path opens it instead, see Opening links and files.)
  • Keyboard resize mode: Ctrl+Space r, then the arrow keys grow/shrink the focused pane. Esc or Enter leaves the mode.

Each workspace has a strip of tabs at the top. A tab holds one pane layout (or a special dashboard, such as the ⎇ git tab or the ◇ orch board).

Do thisMouseKey
New tabthe + on the tab barCtrl+Space c
Next / previous tabclick a tabCtrl+Space n / p /
Close a tabthe × on the tabCtrl+Space x (on a dashboard)
Rename a tabright-click the tab → Rename, type a name, luvus tab rename <name>
Move a tab one positionright-click the tab → Move Left / Move Rightluvus tab move left / right
Swap two tab positionsright-click a tab → Swap With, choose the other tabluvus tab swap <first> <second>

A renamed tab shows your label instead of its number (empty reverts to the number). Dashboard tabs keep their fixed labels. Swap With lists every other tab in the workspace, including tabs hidden by tab-bar overflow. Choosing one exchanges its position with the right-clicked tab without changing which tab is active.

The CLI exposes the same pane move plus tab reordering for scripts and agents:

Terminal window
luvus pane move 7 --tab 2 # existing tab in pane 7's workspace
luvus pane move 7 --new-tab # append a fresh tab for pane 7
luvus tab focus 4 # focus exact tab 4
luvus tab move left # move the active tab one position left
luvus tab move right --tab 4 # move exact tab 4 one position right
luvus tab move 3 1 # move current workspace tab 3 to position 1
luvus tab swap 1 4 # exchange the tabs in positions 1 and 4

All tab numbers are 1-based and validated; missing, zero, or out-of-range positions fail instead of silently selecting a different tab. A pane move keeps its process running and follows it with focus. Tab reordering uses the requested final position and preserves whichever tab was active.

A workspace is one project folder, fixed at its cwd (see Core Concepts). They live in the sidebar’s top list.

  • Open one: the + button above the list, or Ctrl+Space N, opens a folder picker. Browse with the arrows / wheel, use the Home row to jump home, or press g (also clickable in the footer) to type an absolute, relative, or ~/… path without leaving the picker. in Go to only navigates; select Open this folder afterward to confirm the workspace. Press n to create-and-open a new folder, or w to open a repo as a new worktree. Running luvus inside a folder also adds it automatically.
  • Switch: click a row, or Ctrl+Space w / W to cycle.
  • Jump to its git tab: click the branch name next to a workspace.

Right-click any workspace row for its menu:

  • Close the workspace
  • Rename its label (this changes the sidebar name only, never the folder on disk)
  • Pin / Unpin it at the top of the list. A linked worktree stays with its parent, so pinning either one moves the complete group.
  • New Git Worktree / Open Worktree (for git repos)
  • Open Git Tab · Open Task Board · Open Mission Control

The same organization actions are available from the CLI using stable 0-based workspace indices:

Terminal window
luvus workspace list
luvus workspace rename 2 "Luvus website"
luvus workspace pin 2
luvus workspace unpin 2

workspace list reports both the stable API index and display_position, so a pin never changes which workspace a later command targets.

The sidebar shows your workspaces and your live agents. Collapse it to give the panes the full width:

  • Click the « chevron in the sidebar header (or Ctrl+Space b).
  • When hidden, a » appears at the tab bar’s left edge to bring it back.

The sidebar’s sections are docks, relocatable panels. The built-ins are Workspaces and Agents, and luvus has two sidebars (left and right), so you can split reference content from live content across both edges. Modules can add their own docks too (see Writing a Module).

Arrange them in Settings → Layout, under the ── Docks ── divider:

  • Each side has a visible toggle and a width.
  • Every dock has [Left] [Right] [Off] buttons. Click to put it on the left sidebar, the right sidebar, or hide it. The current placement is highlighted.
  • Toggle the right sidebar any time with Ctrl+Space B (and the left with Ctrl+Space b).

For example, move Agents to the right so your agent statuses sit on one edge and your project list on the other. If you hide the left sidebar entirely, the Menu button moves to the right sidebar so Settings is always reachable.

Luvus Bar lets built-ins and modules use the otherwise flexible space beside the tabs and in the middle of the bottom status row. It never adds a row or changes pane/PTY dimensions. Tabs, sidebar toggles, the left prefix guidance, and the clickable version always keep priority.

Arrange declared widgets in Settings → Layout → Luvus Bar:

  • Top places a compact widget beside the tabs.
  • Bottom places it between the fixed shortcut hint and version.
  • Off hides it without deleting module state or its placement declaration.

The declaration rows stay in a stable order while you change placement, so the selected widget does not jump under the pointer.

The built-in Runtime status widget shows NORMAL · 1 pane · tab 2/4 in Bottom by default and can be moved or hidden. At narrow widths, widgets use their compact content and then move into a read-only … +N overflow popup; they never overlap navigation. See the dedicated Luvus Bar guide for installation, placement, CLI control, module publishing, and troubleshooting.

Both Top and Bottom are capped at 100 display columns. They may be narrower when the viewport has less room: Top reserves the active tab, scroll arrows, and new-tab button, while Bottom reserves the fixed shortcut guidance and version. Extra tabs enter their existing scroll window. A single widget may use all 100 columns when its region has room. These are terminal columns rather than Unicode character counts; wide glyphs such as CJK and many emoji consume two.

Drag across any pane to select, and releasing auto-copies to your clipboard. Full details, plus scrollback, are in Scrollback & Copy.

Agents print references all day: the PR they opened, the doc they read, the file they just changed, the test that failed at line 42.

Hold Ctrl and whatever is under your cursor underlines. Ctrl+click follows it. If you would rather not hold a modifier, right-click and pick Open Link or Open File.

Under the cursorWhat a Ctrl+click does
https://luvus.dev/docsopens in your browser
luvus.dev/docssame, with https:// filled in
localhost:3000opens your dev server, over http
src/main.rsopens in a luvus tab, like clicking it in FILES
src/main.rs:42opens in a tab, scrolled to line 42

A file path opens in luvus, not in some other app. It goes through exactly the same path as clicking the file in the FILES tree, so it respects your Settings → General → Open files with choice: the built-in read-only viewer by default, or your terminal editor if you set one.

A path only underlines if the file is really there. Paths are resolved against that pane’s working directory, so src/main.rs means what it means to the shell you are looking at. Text that merely looks like a path stays inert, and so do directories. That means a link you can see is always a link that works.

Compiler and test output usually prints file:line, and that whole reference is one link. The line number is honoured by the built-in viewer. A terminal editor opens the file at the top instead, since the flag for jumping to a line is different for every editor.

You do not need the https://. A bare luvus.dev or google.com/search works, and localhost:3000 opens your dev server over plain http.

Bare domains are matched conservatively, so ordinary text does not turn into links: the name has to be lower case, end in a TLD luvus knows, and localhost needs a port on it. If a domain of yours is not recognised, writing the https:// always works.

One consequence worth knowing: a filename can also be a domain. .rs is Serbia, .md is Moldova. So main.rs is ambiguous, and luvus settles it by looking at the disk: if the file is there, it opens the file. If not, and the name is a real domain, it opens the site. If neither, nothing happens.

Only http and https URLs open. Everything else is ignored on purpose: the text comes from whatever is running in the pane, and a click would end up at whatever your system has registered for that scheme.

Two more details:

  • A URL that wrapped onto the next line still opens as one link. This is the part your terminal cannot do for you, because it only sees the finished screen.
  • The browser that opens is on the machine you are sitting at, even when you attached to a remote server with --remote.

Ctrl+drag still resizes panes as it always did. The two never collide, because a link only opens when you release without moving.

Closing your terminal never loses work, because the server keeps every pane alive. Run luvus again to reattach, or Ctrl+Space d to detach on purpose. See Your First Session.