tty-proxy is a Zig 0.15.2 executable that owns terminal handling and forwards
bytes between a terminal and a local Common Lisp peer over a Unix socket.
This project uses Zig's standard build system (build.zig). The build script
installs the executable into zig-out/bin/tty-proxy.
zig buildCommon build commands:
zig build # compile and install tty-proxy
zig build test # run unit tests
zig build run -- [args] # run tty-proxy with optional argumentsYou can also pass Zig's standard build options, for example:
zig build -Dtarget=x86_64-linux -Doptimize=ReleaseSafeRun zig build --help to see the full list of project-specific and standard
options.
- Zig 0.15.2
- A Unix-like system with Unix sockets,
termios, andpselect
At runtime, tty-proxy reads a plain-text config file from either:
TTY_PROXY_CONFIG, or~/.config/tty-proxy/config
Entries map an executable name to a peer socket path. Resolution prefers the
exact argv[0] key and falls back to the basename of argv[0].
Example:
# comments and blank lines are ignored
tty-proxy = socket:/tmp/tty-proxy.sock
Only socket: values are used. Other values are ignored.
On startup, tty-proxy:
- verifies that
stdinis a tty - resolves and connects to the configured Unix socket
- sets
stdin,stdout,stderr, and the peer socket non-blocking - queues startup info to the peer as a Lisp plist:
(:args (...) :tty "/dev/tty..."
:env ((NAME VALUE) ...)
:size (:rows R :cols C :xpixels X :ypixels Y))After reading startup info, the peer sends a single operation-mode byte:
R—tty-proxyenables raw mode onstdinand restores the original terminal settings on exitC—tty-proxyleaves the terminal mode unchangedE—tty-proxyleaves the terminal mode unchanged and treats peer output as an error stream
In C and E, tty-proxy does not call tcsetattr(2). The peer still can
change terminal settings itself, for example by opening the reported :tty
path and configuring it directly.
tty-proxy consumes that first byte, then forwards the remaining peer payload.
tty-proxy uses a single-threaded pselect(2) loop with two internal buffers:
to_lisp— bytes pending to the peerto_term— bytes pending to terminal output
Behavior by mode:
- In
RandC, terminal input is read and forwarded to the peer. - In
R,tty-proxyenables raw mode before forwarding interactive input and restores the original terminal settings on exit. - In
C,tty-proxyleaves the existing terminal mode untouched. - Peer output is written to
stdoutinRandC. - In
E, no further bytes are sent to the peer. - In
E, peer output is written tostderr. - On peer EOF,
tty-proxydrains buffered output before exiting. - If the final mode was
E,tty-proxyexits with status1after flushing the error message.
Signals:
SIGINTandSIGTERMare handled- signal exit status is
128 + signal