Project wiki — https://github.com/go-gui-org/go-term/wiki.
A full-featured, embeddable terminal-emulator widget for the
go-gui framework. Spawns a real shell
over a PTY, renders through a GPU-accelerated gui.DrawCanvas, and covers the
protocol surface expected by modern CLI tools and TUI frameworks.
Targets macOS, Linux, and Windows (ConPTY).
The screenshot above is falcon, the example app: a full terminal emulator
with tabs, splits, workspace save/restore, themes, session replay, command
palette, broadcast input, and copy mode. It is the reference embedder for
term/workspace and a daily driver on macOS. Falcon is a trademark of Mike
Ward.
cd examples/falcon && go run .See examples/falcon/README.md for flags, key bindings, bundling, and how the pieces fit together.
Fonts, theme, scrollback, bell, scrollbar and every keyboard shortcut can be set
in an optional INI file — ~/.config/falcon/config for falcon,
~/.config/go-term/config for a bare term/workspace embedder — reloadable at
runtime with Cmd+Shift+,:
[font]
family = JetBrainsMono NFM
size = 13
[general]
theme = Tokyo Night
scrollback = 20000
[keybindings]
workspace.splitVertical = Cmd+D
term.find = Cmd+GSee docs/config.md for every section, key, default, and the full list of rebindable actions.
term is a library; falcon is its proof. The public surface froze at v0.9.0
(the export audit and Godoc pass landed there) and was amended once since, by
the v0.10.0 CursorBlink bool change. Build against v0.15.1; further breaking
changes before 1.0 ship as a new minor.
import "github.com/go-gui-org/go-term/term"
func embed(win *gui.Window) error {
t, err := term.New(win, term.Cfg{
ScrollbackRows: 10000,
Themes: append(
[]term.NamedTheme{{Name: "Default", Theme: term.DefaultTheme}},
term.BundledThemes()...,
),
})
if err != nil {
return err
}
defer func() { _ = t.Close() }()
win.SetView(t.View)
return nil
}term.NewReplay plays a recorded session back in a widget; StartRecording
captures one. For a multi-pane window — tabs, splits, save/restore — embed
term/workspace instead and let it own the Terms:
ws, err := workspace.New(win, workspace.Cfg{
TextStyle: gui.TextStyle{Family: "JetBrainsMono NFM", Size: 13},
Themes: themes,
SavePath: defaultSavePath, // where Cmd+S writes the layout
})The kept surface is deliberately small — widget, themes, actions,
recording/replay, the live setters, and the activity/input taps. Everything
documented on pkg.go.dev is stable; names not documented there are internal.
Prompt jumping, jump-to-last-failure, whole-output selection, and the
long-running-command notification all need the shell to mark where commands
begin and end. Source the hook for your shell — bash, zsh, and fish are in
scripts/shell-integration/ — and add one line to
your rc file:
source /path/to/go-term/scripts/shell-integration/goterm.bashDetails, including what fish 4.x already does for itself, are in docs/config.md.
Record a terminal session to a .gtr file and play it back through the emulator
itself — useful for demos, and for bug reports that reproduce the problem
instead of describing it.
falcon --record session.gtr # or Cmd+Shift+R to toggle on the focused pane
falcon --replay session.gtr # space pauses, +/- speed, . steps, 0 restarts
go run ./term/gotermrec info session.gtr # geometry, duration, frame counts
go run ./term/gotermrec cat session.gtr # raw output bytes to stdout
go run ./term/gotermrec play session.gtr # timed playback in any terminal
go run ./term/gotermrec fixture session.gtr -name session # replay-test fixture
go run ./term/gotermrec export session.gtr -cast session.cast # asciicast v2Recordings store the pty's bytes verbatim, so malformed output survives the
round trip; keystrokes are captured only when explicitly enabled
(Cfg.RecordInput).
go test ./...
go test -race ./... # same suite with the race detector
go vet ./...
go test ./term -run EmulatorReplay # replay-style emulator checks
go test ./term -run TestConformance # vttest-parity smoke testsThe emulator checks run against JSON fixtures in term/testdata/ — recorded
byte streams plus the grid state they should produce, so parser behaviour is
verified without a live PTY. See
docs/fixture-capture.md for capturing a real terminal
session and converting it into a fixture, and
docs/terminal-verification.md for the
capability matrix and the manual checks that still need a window.
