Back to projects
Coming Soon Started May 2026

Easy Terminal

Native macOS app that runs Codex, Claude, and shells as terminal panes in one window. Bundles its own PTY daemon. Pasted images become file paths agents read.

Private Repo
Swift SwiftUI SwiftTerm Rust portable-pty macOS

The Problem

Running multiple coding agents at once — Codex in one window, Claude in another, plus a shell or two — means juggling separate terminal windows, losing sessions when a window closes, and burning attention on window management instead of the work. Most terminal multiplexers are heavyweight Electron apps or fragile across multi-hour sessions. The agents have their own rough edges: Claude Code’s clipboard handling drops pasted images, so design references never make it into context.

What I Built

A native macOS app that runs Codex, Claude, and shells as terminal panes in a single window. Sessions persist and stay bounded across long runs. Paste or drop an image or PDF in a pane and the agent reads it by file path — side-stepping the clipboard bug.

Status: coming soon. A 0.1.0 build exists and the daemon stack passed a four-hour soak test (four concurrent agents, resident memory near 3 MB, no zombies, no crashes), but it isn’t released yet — it ships ad-hoc-signed and notarization waits on Apple Developer ID enrollment.

What it does

  • Runs several agents in one window. Claude, Codex, and shells render as terminal views, so full-screen programs like vim and top work the same as a standalone terminal.
  • Turns pasted images into file paths. Cmd-V on an image or PDF in a pane saves the file to a temp location and injects the path into the agent, bypassing the clipboard bug.
  • Reports agent status at a glance. A status-forward sidebar shows which agent is working, blocked, or done across workspaces, driven by live daemon state.
  • Bundles its own daemon. The app ships a small Apache-2.0 PTY daemon (ptyd), spawns it on a private socket, and owns its lifecycle.
  • Offers two layouts. A split view (default) and a workspace view with a tree, multi-pane grid, and agent context inspector. Toggle with Shift-Cmd-U.

Architecture

The stack splits into a headless daemon and a native frontend:

  • ptyd daemon (Rust) owns the PTYs (via portable-pty), handles session persistence (detach / reattach), detects agent state, and exposes a JSON socket API plus a per-pane raw PTY stream. Agent-state detection uses a small std-only screen extractor — no VT-emulator dependency — replacing hundreds of thousands of lines of legacy C/zig with under 600 lines of Rust.
  • Easy Terminal app (SwiftUI + SwiftTerm) is the only frontend. Each pane renders its raw stream in a SwiftTerm view — SwiftTerm is the xterm.js of this stack, SwiftUI is the React. A status-forward sidebar shows spaces, running agents, and status dots, driving the daemon over the socket API.

The et CLI is a thin shell wrapper around the bundled ptyd binary — single front-door command for both GUI launch (et, et app) and daemon-driven pane/agent/workspace operations (et pane, et agent, et workspace).

Design Decisions

Independent by constraint. Dropping heavyweight dependencies shrinks the binary and reduces attack surface — image decode is client-side, memory-safe Swift. SwiftTerm (pure Swift) carries terminal emulation rather than a months-long from-scratch VT emulator.

Stability is a hard requirement. One SwiftTerm view per pane. Scrollback bounded at 500 lines, event log rotates. Attachment cache capped at 256 MB and on-disk scrollback at 256 MB — both least-recently-used eviction. Sixel off, image cache capped. On close: SIGTERM, exit-code check, file descriptors held under 50, no zombies. The target is several concurrent multi-hour agent sessions with zero leaks.

Calm Precision throughout. Aurora Deep tokens, macOS HIG, status communicated through color and weight rather than badges, left-border accent selection rather than pills.

Build & Distribution

Three build paths exist for three different audiences:

What you runToolConfigOutput
./build.sh / etcommand-line xcodebuildRelease./build/ (in-repo)
build-loop agent runsbuild.sh with AGENT_BUILD_IDRelease./build-<id>/ (transient)
Cmd-R in Xcode.appXcode IDEDebug~/Library/Developer/Xcode/DerivedData/...

Convention: Xcode GUI for dev (Debug); build.sh + dist/ for shipping (Release). The .dmg ships ad-hoc-signed; right-click → Open is needed on first launch until notarization lands.

Credits and Licensing

Easy Terminal, the ptyd daemon, and the screen-extractor crate are Apache-2.0. Terminal rendering uses SwiftTerm (MIT). The daemon’s dependencies are Apache, MIT, or ISC licensed (portable-pty, serde, rustls with ring).