All Posts
EngineeringMarch 9, 20267 min read

How We Built RiftPanel: A Desktop App for AI Native Development

AI coding agents changed how we write software. Our terminal setup didn't keep up. So we built a desktop app around the way we actually work now.

The way we write software changed faster than the tools around it.

A few months ago, a typical session for our team involved Claude Code in one terminal, a shell in another, maybe a second agent instance running a parallel task in a third. We'd tile them manually, using iTerm panes, tmux splits, whatever got the job done. Tabs would pile up. Sessions would disconnect. Terminal output from an agent running a 40 step task would scroll past and disappear. Every time we restarted our machines, we rebuilt our workspace from scratch.

This is a solvable problem. So we solved it.

The Actual Problem

AI coding agents are long running, concurrent, and output heavy. A Claude Code session might run for 20 minutes, producing hundreds of lines of structured output while it reads files, writes code, runs tests, and iterates. Meanwhile, you're running a second agent on a different part of the codebase, and you need a shell open to verify things manually.

Traditional terminal emulators weren't designed for this. They're built for sequential, human driven workflows: one command, one output, one next command. The assumptions baked into their design:

  • Sessions are ephemeral. Close the tab, it's gone.
  • Layout is manual. You arrange panes yourself, every time.
  • Output is a stream. It scrolls by. If you missed it, scroll back or rerun.
  • One user, one focus. You're watching one terminal at a time.

None of these assumptions hold when your development workflow involves multiple autonomous agents working simultaneously.

What We Built

RiftPanel is a desktop app, not a web app, not an Electron wrapper, not a terminal theme. It's a Tauri v2 application with a Rust backend managing PTY processes and a React frontend rendering xterm.js terminals in a recursive split panel layout.

The core idea: your workspace is a persistent, saveable arrangement of terminal sessions and development tools, purpose built for running AI coding agents alongside everything else you need.

The Split Panel Layout Engine

The layout is a binary tree. Every panel is either a leaf (rendering content) or a split (containing two children). You can split any panel horizontally or vertically, recursively, to any depth. The tree structure means layout mutations are clean. Splitting, closing, resizing, and rearranging are all tree transformations.

This isn't novel computer science. But implementing it well required solving a specific problem: each leaf panel can render one of eleven different content types, including terminals, a Monaco code editor, a file explorer, a git graph, Firebase deploy controls, Cloud Run logs, and more. The panel system had to be generic enough to host any of these while keeping the layout engine simple.

We ended up with a PanelNode type that carries a contentType discriminator and optional metadata (session ID for terminals, file path for the editor, root path for git). A single transformNode function handles all tree mutations. The layout engine doesn't know or care what's inside each panel.

PTY Management in Rust

The Rust backend owns all process lifecycle. When you create a session (Claude Code, Codex, or a plain shell) the backend spawns a PTY process via portable-pty, starts a reader thread, and emits terminal output events over Tauri's IPC bridge.

The reader thread handles two problems that sound simple but aren't:

  1. UTF-8 byte boundaries. PTY output arrives as raw bytes, not characters. A multi byte UTF-8 character can be split across two reads. The reader buffers partial sequences and only emits valid UTF-8.
  2. Windows line ending normalization. ConPTY on Windows emits \r\r\n instead of \r\n. Every line gets a phantom carriage return that corrupts terminal rendering if you don't strip it. The reader normalizes before forwarding to the frontend.

These are the kinds of problems that don't show up in demos but make or break daily usability.

Session Persistence

Every session's output is buffered in memory (capped at 2MB per session) and debounced to localStorage. When you restart RiftPanel, your layout, sessions, and terminal history are restored. You pick up where you left off.

The persistence layer has schema versioning. We're on v4 now, with automatic migration from older schemas. This matters because we ship updates frequently and can't afford to break people's saved workspaces.

Real Time Output Scanning

Terminal output is scanned in real time for patterns we care about. When a Flutter DevTools URL appears in output, RiftPanel detects it and offers to open it in an embedded panel. Same for Firebase Emulator UI URLs.

This is a small feature that changed how we work. Instead of copying URLs from terminal output and pasting them into a browser, the tool surfaces what it detects and lets you act on it without leaving the workspace. We're expanding this pattern. There are more signals buried in agent output that are worth surfacing.

The Stack Decisions

Tauri v2 over Electron. The binary is ~15MB, not 150MB. Memory usage is dramatically lower. We get native system access through Rust without the overhead of shipping a full Chromium instance. The tradeoff is a smaller ecosystem and rougher edges. Tauri v2 is newer and less battle tested. For a developer tool used by our own team, that tradeoff is clearly worth it.

xterm.js over a custom renderer. We considered building a custom terminal renderer for tighter integration. Bad idea. Terminal emulation is a bottomless pit of edge cases: ANSI escape sequences, alternate screen buffers, mouse reporting, Unicode width calculations. xterm.js handles all of it. We added the WebGL renderer addon for performance with high output agent sessions.

React over a lighter framework. The panel system has enough interactive state (drag to resize, content type switching, session assignment, layout presets) that React's component model pays for itself. We use TanStack Query for session state management, which gives us automatic refetching and cache invalidation without hand rolling it.

No Electron IPC, real Rust. The backend isn't a Node.js process pretending to be native. PTY management, shell detection, git operations, and file system access all happen in Rust. The frontend calls typed TypeScript wrappers that invoke Rust commands over Tauri's IPC bridge. Type safety runs the full depth of the stack. Rust structs serialize to camelCase JSON via serde, TypeScript interfaces match the shape.

What We Learned Building It

Agent sessions need different UX than human sessions. A human terminal session is interactive. You type, you read, you type again. An agent session is mostly read only with occasional intervention. The UI should reflect this: larger output areas, better scroll back, status indicators for whether the agent is thinking, executing, or waiting.

Workspace presets matter more than we expected. We added named presets (1 up, 2 up, 3 up, quad) as a convenience feature. They became one of the most used features immediately. Starting a coding session with "Claude Code left, shell right, file explorer bottom right" in one click eliminated a daily friction we'd stopped noticing.

Output buffering is a design problem, not just an engineering problem. A Claude Code session can produce megabytes of output. Buffering all of it is wasteful; discarding it loses context. The 2MB cap per session with debounced persistence is a pragmatic middle ground, but the real answer is structured output parsing, extracting the meaningful actions and decisions from the raw stream. That's next.

Cross platform PTY is harder than it should be. macOS and Windows handle pseudo terminals differently in ways that surface as subtle bugs. The \r\r\n issue on Windows took longer to diagnose than it should have because the symptoms (slightly broken rendering, occasional blank lines) looked like frontend bugs. Shell detection, PATH resolution, and default shell selection all have platform specific codepaths.

What's Next

RiftPanel started as an internal tool and we're still building it primarily for our own team's workflow. A few things we're working on:

  • SQLite backed session logs. The schema is defined, the migration is written, it's not wired yet. This replaces localStorage persistence with something queryable and less size constrained.
  • Structured output parsing. Extracting agent actions, file changes, and decisions from raw terminal output into a structured timeline. This turns a wall of text into something you can actually review.
  • Multi window support. Tauri supports multiple windows natively. We want separate windows for separate projects, with independent session pools.

We built RiftPanel because the tools we had weren't designed for the way we work now. If you're running multiple AI coding agents concurrently, and increasingly, that's just what software development looks like, the terminal environment around them matters more than most people realize.

[ 02 ] — Keep Reading

More from the lab.

Jun 14, 2026Engineering

Stytch vs Magic.link: Passwordless Authentication for Modern Web Apps

Passwords are a UX tax. Every password a user creates is a support ticket waiting to happen, a security incident in the making, and a checkout abandonment rate line item your e-commerce analytics will eventually surface. The industry has known this for years. Passwordless authentication, once a niche experiment, is now table stakes for consumer-facing applications that care about conversion.

Jun 12, 2026Engineering

Cognito vs Clerk: AWS Native Auth vs Developer-First Identity in 2026

AWS Cognito is one of the most widely used authentication services in the world, and one of the most frequently replaced. Its usage stats reflect the gravitational pull of the AWS ecosystem. Its replacement frequency reflects something more honest about its developer experience. Clerk built its entire company on the premise that authentication should feel like a first-party framework feature, not a cloud service you configure through a JSON policy document.

Jun 12, 2026Engineering

Shopify Plus vs Salesforce Commerce Cloud: 2026 Enterprise Platform Decision

The enterprise commerce platform market has bifurcated sharply. On one side: Salesforce Commerce Cloud, a legacy powerhouse built for complexity and customization at a price that reflects it. On the other: Shopify Plus, a platform that has spent the last four years systematically closing the enterprise feature gap while keeping total cost of ownership radically lower. The question for most brands in 2026 is no longer whether Shopify Plus is enterprise-ready. It is whether SFCC's remaining advantages justify its cost.

Ready when you are

Want to discuss this topic?

Start a Conversation