Ghast: The terminal that files your tabs by directory

A macOS multiplexer built on Ghostty that turns the filesystem into a living workspace map, then layers native SwiftUI tooling on top.

9 min read • View on GitHub • More from aidenybai

A wide macOS desktop scene rendered like an editorial engraving. Terminal tabs are shown as folded cards being sorted into separate filing drawers by directory context, with one tab moving out of a cluttered stack and into the matching project drawer. The image explains that Ghast treats the filesystem as the thing that decides where a tab belongs.
Ghast turns directory changes into workspace routing, so tabs move with context instead of staying in a generic stack.
Key Takeaways

When cd changes the UI

Most terminals treat cd as a local act. Ghast treats it as a routing signal.

If the shell changes directories, the app can re-home the tab into the matching Workspace. That is a small behavior with a big consequence: the filesystem becomes the source of truth for the UI.

Workspaces, not just tabs

The core abstraction in the repo is a workspace keyed by directory, not a loose pile of tabs. In TabManager.swift and Workspace.swift, the app watches for directory changes and can move a tab into the workspace that matches the current path.

A directory change becomes a workspace move. The app is not just tracking where the shell is, it is deciding where the tab belongs.

That matters because developers rarely think in anonymous panes. They think in projects, repos, scratch spaces, and the place where active work should live. Ghast makes that mental model visible.

Why this feels native on macOS

A precision cutaway of a macOS application window rendered in black ink on white paper. The outer shell is clean and minimal, with an AppKit hosting layer inside it and a dense Ghostty terminal core at the center, all connected by narrow mechanical conduits. The image explains why Ghast can feel native without rebuilding the terminal engine from scratch.
SwiftUI handles the shell, AppKit hosts the terminal surface, and Ghostty supplies the engine underneath.

That split is pragmatic. SwiftUI is a strong fit for sidebars, tab chrome, and workspace state, while AppKit is still the safer home for a high-frequency NSView terminal surface.

The trade-off is build complexity. The repo leans on xcodegen, Zig, and the Ghostty build path, so the payoff in polish comes with more moving parts than a plain terminal wrapper.

The bridge to Ghostty

The most technical part of Ghast is not the chrome. It is the bridge. TerminalView.swift maps keyboard and mouse events into Ghostty-compatible structures, while GhosttyManager.swift owns the global lifecycle and callback plumbing.

Swift object references cross the C boundary through unmanaged pointers so the engine can call back into the right view. That is the classic native-app trick here: keep the fast engine in C, keep the state in Swift, and make the glue invisible to the user.

Splits as a tree, not a pile of panes

A close-up of a recursive split-pane structure drawn like a branching mechanical tree. One terminal leaf divides vertically, one child divides horizontally again, and nested divider bars and frame joints show the layout growing in depth instead of spreading into a flat grid. The image explains why Ghast models panes as a tree.
Ghast treats splits as nested structure, which keeps complex layouts manageable.

Ghast treats splits as a tree. A terminal leaf can divide vertically or horizontally, and that branch can split again without flattening the layout into a messy grid.

That recursive model matters because it keeps deep layouts readable. The app is managing nested containers, not a pile of unrelated panes, which makes divider logic and resize behavior easier to reason about.

Ghast vs tmux, iTerm2, and Ghostty

The cleanest way to place Ghast is by its organizing principle. It is not trying to beat every terminal tool at the same job.

ToolPrimary organizing unitDirectory awareRendering coreWhat it optimizes
GhastWorkspace tied to a directoryYes. Tabs can migrate when cwd changesGhostty inside a native macOS shellProject context and tab routing
tmuxSession and paneNoTerminal-agnosticPersistence and multiplexing
iTerm2Window and tabOnly indirectlyNative macOS terminal UIPolished GUI control
GhosttyTerminal surfaceNoGhostty itselfSpeed and compatibility

tmux is session-first. iTerm2 is window-first. Ghostty is engine-first. Ghast is workspace-first, which is why it feels like a new layer rather than a replacement.

What this repo is really testing

Ghast is testing a simple but nontrivial idea: the directory should be the primary noun in terminal UX. If the project folder is where work lives, then the UI should organize around that fact instead of around arbitrary tab order.

That is why the repo is interesting even if you never adopt it as-is. It is a bet that the filesystem can be more than a path string. It can be the map for your attention.