Library Usage
Embed TUIOS in your own Bubble Tea application
TUIOS ships as a Go package as well as a binary. pkg/tuios exposes the window manager as a Bubble Tea model, so you can run it standalone, embed it, or serve it over a PTY of your own.
Installation
go get github.com/Gaurav-Gosain/tuiosThe package is pre-1.0 and the API can change between releases. Model is a type alias for an internal type, so any method the internal model gains or loses is visible to you immediately. Pin a version in your go.mod.
Basic Usage
tuios.New returns a *Model that implements tea.Model. You construct the Bubble Tea program yourself, which means you keep control of the program options and the error handling.
package main
import (
"log"
tea "charm.land/bubbletea/v2"
"github.com/Gaurav-Gosain/tuios/pkg/tuios"
)
func main() {
model := tuios.New()
p := tea.NewProgram(model, tuios.ProgramOptions()...)
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
}There is no tuios.Run function. Constructing the model and running the program are separate steps.
Options
Configuration uses functional options passed to New. Each corresponds to a field on the Options struct, and DefaultOptions() returns the defaults.
model := tuios.New(
tuios.WithTheme("dracula"),
tuios.WithShowKeys(true),
tuios.WithAnimations(false),
tuios.WithWorkspaces(4),
tuios.WithBorderStyle("thick"),
tuios.WithScrollbackLines(50000),
)| Option | Type | Default | Notes |
|---|---|---|---|
WithTheme | string | empty | Theme name. Empty uses standard terminal colors. |
WithShowKeys | bool | false | Show the pressed-keys overlay. |
WithAnimations | bool | true | When off, windows snap instantly. |
WithASCIIOnly | bool | false | Use ASCII instead of Nerd Font icons. |
WithWorkspaces | int | 9 | Clamped to 1-9. |
WithBorderStyle | string | "rounded" | See Configuration. |
WithDockbarPosition | string | "bottom" | bottom, top, or hidden. |
WithHideWindowButtons | bool | false | Hide minimize, maximize, and close. |
WithWindowButtonStyle | string | "pill" | pill (glyphs on a filled pill) or dots (macOS traffic lights). |
WithWindowButtonPosition | string | "right" | right or left end of the title bar. |
WithScrollbackLines | int | 10000 | Clamped to 100-1000000. |
WithSize | int, int | auto | Initial size, detected if unset. |
WithSSHMode | bool | false | Adjusts behaviour for SSH serving. |
WithUserConfig | *config.UserConfig | loaded from disk | Supply a config instead of reading the user's file. |
Out-of-range values are clamped rather than rejected. WithWorkspaces(50) gives you 9 and WithScrollbackLines(10) gives you 100, with no error.
Serving a PTY
NewForPTY sizes the model from a PTY. Anything with Width() int and Height() int satisfies the PTY interface, which keeps the package independent of any particular SSH or web terminal library.
type PTY interface {
Width() int
Height() int
}
func NewForPTY(pty PTY, opts ...Option) *ModelThe doc comment above the PTY interface in the source still refers to a NewForSession constructor. No such function exists; the constructor is NewForPTY.
Program Options
ProgramOptions() returns the Bubble Tea options TUIOS expects, currently the frame rate. Pass them through rather than writing your own, so you inherit later additions.
FilterMouseMotion is a tea.WithFilter function that drops mouse motion events when nothing is being dragged, resized, or selected. Terminal applications generate a lot of motion events and forwarding all of them costs measurable CPU.
p := tea.NewProgram(
model,
tea.WithFilter(tuios.FilterMouseMotion),
)Motion passes through during window drags and resizes, overlay panel drags, scrollback browser selection, text selection, and when the focused window is an alt-screen application tracking the mouse itself. Everything else is filtered out.
Modes
Mode is an alias for the internal mode type, with two exported constants. WindowManagementMode is what TUIOS starts in.
if model.Mode == tuios.TerminalMode {
// input is going to the focused terminal
}Configuration Access
tuios.Config re-exports three configuration functions so you can work with user configuration without importing an internal package:
cfg, err := tuios.Config.LoadUserConfig()
if err != nil {
cfg = tuios.Config.DefaultConfig()
}
model := tuios.New(tuios.WithUserConfig(cfg))tuios.Config.GetConfigPath() returns the path the configuration is read from.
Limitations
Worth knowing before you build on this:
- Daemon mode is not available through the library. Sessions, detach and reattach, and the control protocol live in an internal package and are reachable only through the
tuiosbinary.pkg/tuiosgives you an in-process window manager. - SSH serving is not exported. The binary's
tuios sshis implemented internally. You can serve TUIOS over SSH by wiringNewForPTYinto your own server, but there is noRunSSHhelper. - Several options set process-global state.
WithASCIIOnly,WithBorderStyle,WithDockbarPosition,WithHideWindowButtons,WithWindowButtonStyle,WithWindowButtonPosition,WithScrollbackLines, andWithAnimationswrite to package-level variables in the config package. Two models in one process do not get independent values for these, and the last one constructed wins. This matters if you serve several sessions from a single process. - There is no Go example directory. The repository's
examples/directory holds.tapescripts for the tape player, not Go programs.