Skip to content

Repository files navigation

ttyx

Warning

ttyx is a slop fork of ttyd.

It is an unofficial, Bun-flavored rewrite made by slopping modern web technology onto ttyd's excellent idea and protocol. If you want the established, serious implementation, use ttyd.

ttyx runs a command in a real PTY and exposes it as a browser terminal using Bun, WebSockets, React, shadcn, and wterm.

Upstream and credit

This project exists because tsl0922/ttyd exists. ttyd supplied the concept, CLI shape, and binary WebSocket protocol that ttyx imitates. All credit for the original project belongs to ttyd and its contributors.

ttyx is not an official ttyd release, is not endorsed by ttyd, and is not a drop-in guarantee of identical behavior. Bugs introduced here belong here, not upstream. When reporting an issue, reproduce it with ttyd first and report it upstream only if it also occurs there.

Features

  • Native Bun.serve() HTTP, TLS, Unix sockets, and WebSockets
  • Native Bun.Terminal PTYs with resize, signals, cwd, uid/gid, and custom TERM
  • wterm's accessible DOM renderer powered by libghostty WASM, with full grapheme, VT, mouse, focus, synchronized-output, scrollback, and OSC 8 hyperlink support
  • Drag files anywhere onto the terminal to upload them directly into its current working directory
  • ZMODEM and trzsz upload/download compatibility
  • Automatic reconnect, automatic responsive fitting, flow control, heartbeat, query-string preferences, and URL command arguments
  • PTY-preserving reconnects with a configurable grace period and bounded output buffering
  • A shadcn sign-in screen, optional HTTP Basic/trusted proxy auth, origin checking, client limits, and one-shot operation
  • Filesystem directory routes: opening /home/user/project/ starts that terminal in /home/user/project
  • Reverse-proxy base paths, custom HTML, IPv4/IPv6, TLS, and optional client certificates
  • React 19 + Tailwind + shadcn interface
  • Compatible with ttyd's binary WebSocket protocol

Run

bun install
bun src/index.ts /bin/bash
# http://localhost:7681

After the package is published, install and start ttyx in the background for the current user with:

bunx @beanarchy/ttyx install

Arguments after install become the persistent server arguments, for example bunx @beanarchy/ttyx install -p 8080 -c user:secret. Linux uses a systemd user service, macOS uses a LaunchAgent, and Windows uses a logon Scheduled Task. The Bun executable and ttyx package location used during installation must remain available. By default ttyx only listens on 127.0.0.1:7681; Linux uses system-login authentication, while macOS and Windows should use -c user:password when authentication is wanted.

Terminal input is always enabled.

Every absolute directory is also a route. For example:

http://localhost:7681/home/pingu/Work/bun/ttyx/
http://localhost:7681/tmp/

Each route starts an independent PTY with that directory as its working directory. Paths without a trailing slash are redirected automatically. The root route uses --cwd when provided, otherwise the server's current directory.

When the shell changes directory (for example, cd /tmp), ttyx updates the browser URL with history.replaceState. The terminal and WebSocket stay connected, so no navigation or page reload occurs.

Drop one or more files anywhere on the terminal to upload them into that route's current directory. The upload uses the authenticated route-specific /upload endpoint and strips directory components from filenames.

Direct uploads default to a 64 MiB limit and reject existing filenames. The behavior is configurable:

# Disable direct uploads entirely
bun src/index.ts --no-upload bash
# Raise the limit and preserve both files on a name collision
bun src/index.ts --upload-max-size 134217728 --upload-mode rename bash

--upload-mode accepts reject, overwrite, or rename. These controls apply to direct drag-and-drop uploads; terminal-driven ZMODEM and trzsz transfers are controlled separately by their client options.

Development mode starts a writable shell:

bun run dev

ttyx is writable by default and authenticates as the current Linux user through PAM, the same authentication stack used by the computer login. Use --no-auth only on a trusted network, or -c user:password to configure separate credentials.

Install the published package without creating a background service with:

bunx @beanarchy/ttyx /bin/bash

Examples

# Share your default shell
bun src/index.ts
# Share a login shell
bun src/index.ts bash -l
# Basic authentication and a specific directory
bun src/index.ts -c user:secret -w /srv/projects bash
# Use the browser's native HTTP Basic prompt instead of the default shadcn form
bun src/index.ts -c user:secret --auth-mode basic bash
# Reverse proxy mounted at /terminal
bun src/index.ts -b /terminal bash
# TLS
bun src/index.ts -S -C cert.pem -K key.pem bash
# Enable ZMODEM and trzsz file transfer
bun src/index.ts \
-t enableZmodem=true \
-t enableTrzsz=true bash
# Pass repeated URL arguments to the command: ?arg=one&arg=two
bun src/index.ts -a ./my-command

Run bun src/index.ts --help for all ttyd-compatible options.

When --credential user:password is set, ttyx shows its shadcn sign-in screen by default. A successful login creates a 12-hour opaque HttpOnly, SameSite=Strict session cookie. Add Secure automatically by serving with TLS. Use --auth-mode basic when HTTP Basic authentication is required for compatibility with an existing client or proxy.

Transient WebSocket disconnects retain the PTY for 10 seconds by default. Use --reconnect-grace 0 to restore immediate teardown or --max-output-buffer to change the one MiB detached/paused output cap. When the cap is reached, ttyx keeps the newest output.

Compatibility notes

ttyx uses ttyd's binary WebSocket command framing and supports its commonly used server and client options. It is not a byte-for-byte ttyd implementation: reconnect retention and direct HTTP uploads are ttyx extensions, and unsupported ttyd flags fail explicitly instead of being silently ignored. --browser uses the platform opener on Linux, macOS, and Windows.

Build

bun run build
./dist/ttyx

The build produces browser assets and a standalone dist/ttyx executable for the current operating system and CPU architecture.

See SECURITY.md before exposing ttyx outside the local machine.

Client options

Use repeated -t key=value flags or URL parameters. Values are JSON-decoded when possible. Supported ttyx client options include:

  • theme=default|monokai|solarized-dark|light
  • disableLeaveAlert=true
  • disableResizeOverlay=true
  • disableReconnect=true
  • enableZmodem=true
  • enableTrzsz=true
  • closeOnDisconnect=true
  • titleFixed=My terminal
  • fontSize=15 and fontFamily=JetBrains Mono
  • A ttyd-style theme color object is mapped to wterm CSS color variables

Protocol

The WebSocket subprotocol is tty. Frames are binary and begin with a one-byte ASCII command:

  • Server: 0 output, 1 title, 2 preferences
  • Client: 0 input, 1 resize JSON, 2 pause, 3 resume
  • The first client message is JSON containing AuthToken, columns, and rows.

About

No description, website, or topics provided.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages