Multi-Content Tabs
Boo supports multiple content types within tabs — not just terminals. A tab can host a terminal, browser, text editor, image viewer, or markdown preview.
Supported Content Types
| Type | Description | Icon |
|---|---|---|
terminal | Default. Ghostty terminal emulator | Terminal icon |
browser | WebKit-based web browser | Globe icon |
editor | Code editor (Monaco in WKWebView) | Document icon |
imageViewer | Image preview | Image icon |
markdownPreview | Rendered markdown | Markdown icon |
pluginView | Ephemeral custom SwiftUI view | Puzzle piece icon |
Agent review (diff + comments) and agent timeline tabs are pluginView tabs, not separate content types — see Agents.
Creating Tabs
Menu
- File → New Terminal Tab (default)
- File → New Browser Tab
Auto-Detection
When opening a file from the file explorer, Boo routes to the correct tab type:
- Image files → Image viewer tab (configurable)
- Markdown files → Markdown preview tab (configurable)
- PDF files → Browser tab (configurable)
- HTML files → Browser tab, if enabled (off by default)
- Text/code files matching
editorFilePatterns→ Editor tab (configurable) - URLs cmd+clicked in terminal → Browser tab
Plugin API
Plugins can open any tab type using the openTab action:
// Open a browser tab
actions.openTab?(.browser(url: url))
// Open a file in the appropriate viewer
actions.openTab?(.file(path: "/path/to/file.swift"))
// Open a custom ephemeral SwiftUI view
actions.openTab?(.customView(title: "My Panel", icon: "star", view: AnyView(MyView())))Plugin Multi-Content Tab API
For persistent, deduplicated custom tabs use the typed registration API:
// In plugin setup — register a factory once
actions.registerMultiContentTab?("my-diff-view") { ctx in
AnyView(MyDiffView(context: ctx))
}
// Open the tab (or focus it if already open)
let ctx = PluginTabContext(title: "Diff", icon: "doc.badge.plus", key: filePath)
actions.openMultiContentTab?("my-diff-view", ctx)Deduplication: two calls with the same type ID and context.key focus the existing tab in the active workspace rather than opening a duplicate.
Browser Features
- Back/Forward: trackpad swipe gestures (macOS native
allowsBackForwardNavigationGestures) - URL Autocomplete: history-based suggestions shown as you type in the address bar
- Copy/Paste: fully functional via standard keyboard shortcuts
- History: configurable in Settings → Browser
Editor Features
- Syntax Highlighting: powered by the Monaco editor, bundled and hosted in a
WKWebView - Theme Integration: follows the active Boo theme
- Save: Cmd+S writes to disk; new (unsaved) files prompt with a save dialog
- File Routing: files matching Settings → Plugins → Files → "Open in editor (file patterns)" open in the built-in editor tab
File Explorer Settings
Image Opening Mode
Settings → Plugins → Files → "Open images as":
| Value | Behavior |
|---|---|
imageViewer (default) | Opens in a Boo image viewer tab |
kitty | Displays inline via Kitty Graphics Protocol |
external | Opens in the system default image app |
Text File Opening Mode
Settings → Plugins → Files → "Open text files as":
| Value | Behavior |
|---|---|
editor (default) | Opens in the built-in editor tab |
terminalEditor | Opens in a terminal using $EDITOR |
external | Opens in the system default app |
Markdown Opening Mode
Settings → Plugins → Files → "Open markdown files as":
| Value | Behavior |
|---|---|
preview (default) | Opens in a markdown preview tab |
builtInEditor | Opens in the built-in editor tab |
editor | Opens in a terminal using $EDITOR |
external | Opens in the system default app |
Browser Opening
| Setting | Default | Behavior |
|---|---|---|
pdfOpenInBrowser | true | PDFs open in a browser tab (else external) |
htmlOpenInBrowser | false | HTML files open in a browser tab |
Mixing Tabs
Tabs of different types can coexist in the same pane. Each tab shows a type-specific icon in the tab bar.
Sidebar Behavior
- Terminal tabs: Full plugin functionality (FileTree, Git, Docker, etc.)
- Non-terminal tabs: Sidebar visible; future: content-type-specific plugins
Architecture
Tab content type is stored in TabState.contentType (ContentType enum). The ContentViewProtocol abstracts the view layer for each content type. Factories are in ContentViewFactory.
Tab close confirmation only appears for terminal tabs — browser, editor, and image viewer tabs close immediately.
