Add a web backend and optional Ghostty terminal sessions
Nobody has claimed this yet.
- Dominant language
- Elixir
- Stars
- 205
- Forks
- 16
- Avg merge
- 27m
- Merged PRs (30d)
- 5
Description
Summary
Add a browser delivery path for TermUI applications, and evaluate an optional Ghostty-powered terminal session that can appear inside a TermUI frame.
These are two related but separate capabilities:
- A
TermUI.WebBackenddisplays normalTermUI.Frameoutput in a browser and converts browser input intoTermUI.Eventvalues. - An optional Ghostty integration runs a real shell or terminal program and converts its emulated screen into frame content.
Ghostty must not become the web backend itself. It must remain an optional source of terminal-session content.
Motivation
TermUI v2 already has a backend contract for local TTY, raw terminal, SSH, and deterministic test delivery. A browser backend would let the same Elm application, widgets, layout, frame model, and event model run in a web browser.
Some applications, including Jido Console, can also benefit from an embedded terminal pane. This pane must support real terminal programs such as shells, IEx, vim, and top. The ghostty Hex package provides a BEAM wrapper for libghostty-vt, a PTY, terminal emulation, scrollback, resize reflow, cursor state, key encoding, and mouse encoding.
Proposed architecture
TermUI application
|
v
TermUI.Frame
|
v
TermUI.WebBackend
|
WebSocket or LiveView
|
v
Browser renderer
An optional embedded terminal follows this path:
Shell / IEx / terminal program
|
Ghostty.PTY
|
VT output bytes
|
Ghostty.Terminal
|
render state / cells
|
TermUI.Frame region
|
TermUI.WebBackend
The normal TermUI frame remains the only browser rendering contract.
Design constraints
- Keep the existing
TermUI.Backendcontract focused on the host display and input transport. - Do not replace
TermUI.Backend.Raw,TermUI.Backend.TTY, or the current escape parser with Ghostty. - Keep Ghostty optional. TermUI must continue to work without native Ghostty binaries.
- Keep the widget model pure. A parent application or session owner process must own
Ghostty.TerminalandGhostty.PTYprocesses. - Preserve the deterministic backend and current frame-based test path.
- Do not require Ghostty for normal TermUI applications in a browser.
- Provide a clear unsupported-platform result. Ghostty currently has precompiled binaries for Linux x86-64, Linux ARM64, and macOS ARM64, but not Windows or Intel macOS.
- Avoid two permanent browser renderers. Ghostty's LiveView component can be reference code or a prototype, but normal and embedded-terminal content should converge on the TermUI frame renderer.
Proposed phases
Phase 1: Browser backend prototype
- Define a wire representation for full frames, cell or row changes, cursor state, and terminal dimensions.
- Send browser keyboard, mouse, paste, focus, and resize input as normalized
TermUI.Eventvalues. - Implement a simple DOM renderer first.
- Support connection setup, cleanup, and resize.
- Add deterministic protocol tests that do not require a browser.
Phase 2: Browser integration tests
- Run a small TermUI application in a real browser.
- Verify keyboard input, mouse input, paste, focus, resize, Unicode, wide cells, colors, cursor state, and shutdown.
- Measure full-frame and incremental-frame performance.
- Decide whether DOM rendering is sufficient or Canvas is necessary.
Phase 3: Optional Ghostty terminal session
- Add a session owner that manages one
Ghostty.Terminaland oneGhostty.PTY. - Route PTY output into the terminal emulator.
- Route terminal query responses back to the PTY.
- Convert Ghostty cells, styles, cursor state, and wide-cell tails into a
TermUI.Frameregion. - Convert applicable
TermUI.Eventvalues into Ghostty key, mouse, and focus input. - Resize the PTY and emulator together.
- Support scrollback and terminal-session shutdown.
- Ensure that multiple sessions have unambiguous message ownership.
Acceptance criteria
- A TermUI v2 application can render in a supported web browser without changes to its Elm application callbacks.
- The browser path uses
TermUI.Frameas its rendering contract. - Browser input is normalized to existing
TermUI.Eventvalues. - Resize, Unicode, wide cells, colors, attributes, and cursor state work.
- The backend has automated protocol tests and at least one browser integration test.
- Ghostty is an optional dependency or a separate integration package.
- A Ghostty session can run a shell and at least one alternate-screen application.
- A Ghostty session renders through the same TermUI frame path as other widgets.
- Local TTY, raw, SSH, and deterministic backends continue to work without Ghostty.
- Unsupported Ghostty platforms fail clearly without affecting normal TermUI use.
Open decisions
- Use Phoenix LiveView, Phoenix Channels, or a transport-neutral WebSocket protocol for the first backend.
- Put the Ghostty adapter in TermUI as an optional integration or publish a separate
term_ui_ghosttypackage. - Send row changes, cell changes, or encoded frame operations over the wire.
- Use a DOM renderer or Canvas after the prototype measurements.
Reference
- Hex package: https://hex.pm/packages/ghostty
- Ghostty BEAM wrapper: https://github.com/dannote/ghostty_ex
- Ghostty terminal API: https://ghostty.hexdocs.pm/Ghostty.Terminal.html
- Ghostty PTY API: https://ghostty.hexdocs.pm/Ghostty.PTY.html
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the existing TermUI.Backend contract, Raw and TTY backends, current escape parser, deterministic backend, Frame model, and Event model. Define the first browser transport and frame protocol before evaluating the Ghostty.PTY and Ghostty.Terminal references. Done requires a tested browser backend, browser integration coverage, and an optional Ghostty session that preserves existing backends.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- elixir
- Domain
- backend, testing-qa, web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 18/100