Home: github.com/ttyzero/ttybus
(moved from tjstebbing/ttybus).
________
|[][][]|_\_
| TTYBus |
=-OO----OO-=
A text message bus for TUIs, CLIs, and shell scripts.
Unix programs compose with pipes. TUIs cannot: stdin is the keyboard and stdout is the screen. ttybus is the side channel. TUIs never join a pipeline. A small CLI does.
ttybus serve # user daemon; also auto-started by pub/sub
ttybus pub files main.go
echo main.go | ttybus pub files
ttybus sub files # lines on stdout until Ctrl-C
ttybus sub files --limit 1 # one line, then exit 0
# compose like any Unix filter
ttybus sub animals | grep --line-buffered '^cat' | ttybus pub cats
ttybus ls
ttybus send --to yazi-1 files main.go
ttybus plumb main.go:42grep block-buffers when its stdout is a pipe. Use GNU
grep --line-buffered, or awk '/^cat/ { print; fflush() }'.
Speak the protocol yourself:
nc -U "$XDG_RUNTIME_DIR/ttybus/bus.sock"
HELLO name=demo pid=$$
SUB files
PUB files /tmp/hello.gocurl -fsSL https://raw.githubusercontent.com/ttyzero/ttybus/main/install.sh | shInstalls to ~/.local/bin. Pin a release or put the binary somewhere else:
VERSION=v0.1.0 PREFIX=/usr/local curl -fsSL https://raw.githubusercontent.com/ttyzero/ttybus/main/install.sh | shLinux amd64/arm64 and macOS amd64/arm64. Needs curl, tar, and a GitHub release (tag v*).
Companion TUIs (gitwing, peek, buscope, ttythemer) are a second, optional
step — same PREFIX / BINDIR:
curl -fsSL https://raw.githubusercontent.com/ttyzero/ttybus/main/install-kit.sh | shSubset: sh -s -- gitwing peek, or TOOLS=ttythemer. Pin with VERSION=v0.1.0.
SOURCE=go builds from module source instead of release tarballs.
From source:
go install github.com/ttyzero/ttybus/cmd/ttybus@latest
# or
make build
./ttybus serve --foregroundA TUI running in one tmux pane has no Unix-native way to tell a TUI in
another pane "open this file", or to let a shell script inject an event,
or to emit something grep can see without trashing the alternate screen.
Each TUI that has solved this has grown a private bus (Yazi DDS, lf -remote, Kakoune sockets). ttybus is the shared one: text lines over a
unix stream socket, a CLI that behaves like cat/tee for named
channels, an optional plumber for "this looks like a file:line → editor".
This is a clean-room take on an idea from 2018
(ttyzero/minibus). Clients
connect in; the protocol is newline-delimited text; the CLI is
pipeline-correct (line-flushed, logs on stderr, never opens /dev/tty).
- TUIs never participate in pipelines. stdin = keys, stdout = screen, socket = bus.
- The CLI is a Unix filter. Logs go to stderr. Every message is one
line, flushed.
--limitand--timeoutexist so scripts can block withoutheadraces. Timeout exits124like GNUtimeout. - Text on the wire.
PUB files {"path":"…"}is fine; JSON as the envelope is not.nc,grep, andawkmust work. - One user daemon, socket at
$XDG_RUNTIME_DIR/ttybus/bus.sock(or$TMPDIR/ttybus-<uid>/bus.sock). Named buses (--bus NAME/$TTYBUS_BUS) isolate multiplexer sessions.
A TUI can export TTYBUS_ID so shells it spawns identify themselves.
Full contract: docs/PROTOCOL.md.
c, err := ttybus.Dial(ttybus.DefaultSocket())
_ = c.Hello(ttybus.Info{Name: "mytui"})
ch, _ := c.Sub("files")
_ = c.Pub("files", path)See client/ and examples/bubbletea.
~/.config/ttybus/plumb (or $TTYBUS_PLUMB):
match ^([^\s:]+):(\d+)$
pub editor.open
match ^https?://
exec open $0
match \.(go|rs|py)$
pub editor.open
$0 is the whole text; $1… are capture groups. First match wins.
cmd/ttybus/ serve | pub | sub | ls | send | plumb
internal/protocol/ line parser
internal/daemon/ socket server, subscriptions, fan-out
internal/socket/ path resolution, flock, auto-start
internal/plumb/ rule file
client/ Go helper for TUI authors
examples/bubbletea/ bus messages as Bubble Tea Msg
contrib/ tmux.conf, systemd --user unit
docs/PROTOCOL.md wire spec
install.sh ttybus binary
install-kit.sh optional companion TUIs
PLAN.md implementation notes
Closest production system is Yazi DDS
(ya pub / ya sub), which is Yazi-only. Philosophical ancestor is
Plan 9 plumber. D-Bus is the desktop
equivalent and is the thing we are deliberately not.
MIT. See LICENSE.