Skip to content

Repository files navigation

floeterm

Open-source terminal infrastructure for product teams.
Embed a real terminal into your product with a PTY-backed Go backend, a headless web terminal wrapper, and a runnable reference app.

CI Release npm Go Reference License

Headless UI PTY-backed History Replay IME Ready Multi-view resize Reference App

Why floeterm · Packages · Quick Start · Development

🎯 Why floeterm

floeterm is built for teams that want terminal workflows inside their own product, not inside someone else's UI shell.

  • Product-first: ship your own terminal experience while floeterm handles PTY lifecycle, history replay, resize coordination, and browser-facing terminal plumbing.
  • Composable: use terminal-go as the backend engine, terminal-web as the headless browser layer, or start from the end-to-end reference app in app/. FloeTerm also owns the versioned beamterm-renderer WebGL2 distribution used by the web package.
  • User-ready: mobile-friendly input bridging, IME support, reconnect-friendly history replay, configurable clipboard behavior, and first-class shell bell/title plus link-provider extension points are already in the stack.
  • Operationally sane: one make check path matches CI for Go race tests, govulncheck, web lint/test/build, and npm audit.

Typical use cases:

  • AI coding workspaces and browser IDEs
  • Cloud admin consoles and internal ops tools
  • Remote development environments
  • Embedded terminals inside dashboards, drawers, tabs, or dedicated terminal pages

✨ Feature Tags

Tag What it means in practice
🧩 HEADLESS UI terminal-web exposes TerminalCore, createTerminalInstance, and TerminalSessionsCoordinator without forcing a component library or design system.
🌱 DORMANT-FIRST Sessions can be created before the PTY starts, then activated with the real viewport size on first attach.
📚 HISTORY REPLAY Scrollback is buffered, filtered, and replayed safely after reconnects or remounts.
⌨️ IME READY The web layer bridges the hidden textarea used by ghostty-web, keeping soft keyboard and composition input usable on touch devices.
📐 MULTI-VIEW Responsive resize controls help keep one remote session usable across panes, tabs, and focused terminal views.
🔗 ACTIONABLE OUTPUT Custom link providers and bell/title forwarding let products turn terminal output into file navigation, alerts, and richer UX without patching internals.
🧪 REFERENCE APP A runnable HTTP + WebSocket app shows the full integration path end to end.

📦 Packages

Package Best for What you get
terminal-go Go backends that need PTY sessions Session lifecycle, history buffering/filtering, explicit workdir and foreground-command signals, low-frequency output activity metadata, resize coordination, and event callbacks
terminal-web Web clients that want terminal plumbing without UI lock-in TerminalCore, createTerminalInstance, TerminalSessionsCoordinator, strict Agent CLI classification, config helpers, and a headless ghostty-web wrapper
beamterm-renderer FloeTerm's WebGL2 rendering release A versioned, reproducible Beamterm fork with upstream provenance and browser warning/performance gates
app/ Teams that want a working reference before integrating HTTP APIs, WebSocket streaming, and a Solid.js demo UI that wires the stack together

Install the building blocks you need:

go get github.com/floegence/floeterm/terminal-go
npm i @floegence/floeterm-terminal-web

👀 What Problems It Solves

You need to... floeterm gives you...
Start a session before layout is stable Dormant-first session creation via CreateSession, then shared PTY activation with real cols/rows via ActivateSession, ActivateSessionContext, or first attach
Restore terminal output after reconnect or remount History chunks, replay windows, and filtering that removes problematic terminal auto-responses
Support touch devices and IME input A browser input bridge that keeps composition and soft keyboard flows working with ghostty-web
Reuse one session across multiple surfaces Per-connection sizing on the backend plus focus-aware responsive resize options in the web layer
Distinguish a running command from active terminal output Independent foreground-command and unknown / streaming / settled output metadata, without subscribing every session to its PTY byte stream
Turn terminal output into product interactions Custom link providers, bell events, and title updates surfaced through TerminalCore
Evaluate quickly before integrating A reference app you can run locally in minutes

🚀 Quick Start

1. Run the reference app

make run

Then open http://localhost:8280.

  • make run serves the bundled app and is also reachable from other devices on your LAN via http://<your-ip>:8280.
  • make dev starts the Go backend on 0.0.0.0:8080 and the Vite dev server on 0.0.0.0:5173 for HMR and cross-device debugging.

2. Start a PTY-backed session in Go

package main

import (
	"log"

	terminal "github.com/floegence/floeterm/terminal-go"
)

func main() {
	manager := terminal.NewManager(terminal.ManagerConfig{})

	session, err := manager.CreateSession("", "")
	if err != nil {
		log.Fatal(err)
	}

	if err := manager.ActivateSession(session.ID, 120, 40); err != nil {
		log.Fatal(err)
	}

	if err := session.WriteDataWithSource([]byte("ls\n"), ""); err != nil {
		log.Fatal(err)
	}
}

3. Mount the terminal in the browser

import { createTerminalInstance } from '@floegence/floeterm-terminal-web';

const controller = createTerminalInstance({
  sessionId: 'session-1',
  isActive: true,
  transport: myTransport,
  eventSource: myEventSource,
});

await controller.mount(container);

🧭 Integration Notes

Topic Notes
Platform terminal-go relies on a POSIX PTY and is tested on macOS/Linux.
Lifecycle CreateSession creates a dormant logical session. The first attach or an explicit activation should provide the real terminal viewport size. ActivateSessionContext lets a request stop waiting without cancelling another caller's shared activation; delete and cleanup cancel the session-owned activation.
Multi-view sizing Every live connection reports its own viewport cols/rows. Because one PTY has one real window size, the shared PTY uses the minimum live column count and minimum live row count. terminal/live_v1 publishes that effective geometry to every renderer, so differently sized pages keep one terminal grid and identical screen state; detaching the limiting view expands the PTY and all remaining renderers together.
Working directory tracking terminal-go follows explicit local cwd OSC markers and buffers incomplete frames across PTY reads. Remote OSC 7 authority/path hints remain display-only execution context and never overwrite local session resource metadata.
Context, command, and output awareness Shell integration exposes atomic location/application context, revision-fenced semantic work, a bounded foreground executable basename, and independent output activity. Long-lived SSH/Agent processes do not imply loading; settled only means visible output is quiet.
UI ownership terminal-web is intentionally headless. You own the surrounding layout, session list, controls, and product experience.
Input model Every TerminalCore owns an isolated ghostty-web WASM runtime and supports explicit-copy-only clipboard behavior when you disable copy-on-select.
Extension points TerminalCore exposes link providers, shell bell/title callbacks, buffer line reads, touch-scroll helpers, and explicit runtime font updates so downstream apps do not need any-based terminal mutations.
Reference transport The sample app uses HTTP APIs for control operations and one bidirectional binary WebSocket for live terminal input, resize, and output.

🛠 Development

Command What it does
make check Runs the same hard gates as CI: Go race tests, govulncheck, renderer Rust/WASM/package checks, web lint/test/build, real-process E2E, and npm audit
make run Builds and serves the reference app from the Go backend
make dev Runs backend + Vite dev server separately for local iteration
make app-web-build Builds the reference web app only
cd e2e && npm run perf:standalone -- --url=http://127.0.0.1:8280 Runs the headed hardware WebGL2 performance gate, including two differently-sized views on one session

Renderer and web releases are coupled: terminal-web pins one exact @floegence/beamterm-renderer version. The release workflow validates that pin, builds the Rust/WASM package with the repository's fixed toolchain, publishes the renderer first, and only then validates and publishes terminal-web.

🗂 Repository Layout

Path Purpose
terminal-go/ Go PTY session manager
terminal-web/ Framework-neutral web terminal package
beamterm-renderer/ FloeTerm-maintained Beamterm WebGL2 renderer fork and npm package
app/backend/ HTTP + WebSocket backend reference implementation
app/web/ Solid.js reference UI
e2e/ Real-process unit, Playwright functional, and hardware performance gates

📄 Notices

About

PTY-backed terminal sessions for Go, plus a headless xterm.js core and a reference web app.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages