Ghostty.LiveTerminal.Component (Ghostty v0.4.7)

Copy Markdown View Source

Stateful LiveComponent for rendering a terminal in the browser.

Handles keyboard events internally — no handle_event wiring needed in the parent LiveView. The parent owns the terminal and optionally a PTY; this component owns the UI interaction.

Usage

# In your LiveView mount:
{:ok, term} = Ghostty.Terminal.start_link(cols: 80, rows: 24)
{:ok, pty} = Ghostty.PTY.start_link(cmd: "/bin/bash", cols: 80, rows: 24)
{:ok, assign(socket, term: term, pty: pty)}

# In your LiveView template:
<.live_component
  module={Ghostty.LiveTerminal.Component}
  id="term"
  term={@term}
  pty={@pty}
/>

# Forward PTY output to the terminal and trigger a refresh:
def handle_info({:data, data}, socket) do
  Ghostty.Terminal.write(socket.assigns.term, data)
  send_update(Ghostty.LiveTerminal.Component, id: "term", refresh: true)
  {:noreply, socket}
end

Assigns

  • :id — required
  • :term — required, a Ghostty.Terminal pid
  • :pty — optional, a Ghostty.PTY pid; key input is written here when present
  • :cols — terminal width (default: 80)
  • :rows — terminal height (default: 24)
  • :fit — auto-fit terminal size to the rendered container (default: false)
  • :autofocus — focus the hidden terminal input on mount (default: false)
  • :class — CSS class for the container div (default: "")

Global HTML attributes (data-*, aria-*, etc.) are passed through.

Refreshing

To push updated cells after writing to the terminal from the parent, use send_update/3:

Ghostty.Terminal.write(socket.assigns.term, data)
send_update(Ghostty.LiveTerminal.Component, id: "term", refresh: true)

The component also pushes an initial render automatically when the LiveView socket is connected.