Goblin Skiff

Goblin Skiff

Goblin Skiff is a fork of Mosh, optimized for bandwidth-constrained links. Skiff keeps Mosh's roaming and predictive typing, and adds UDP jump relays for sessions where the client cannot reach the destination directly over UDP. It also adds zstd-22 compression, directional bandwidth pacing, repairable file transfers, and modern terminal graphics. The changes target very low-bandwidth satellite, radio, and metered links: fewer unnecessary bytes, with input and screen updates ahead of background copies.

Source version
1.4.0-goblin20260919.2 · Goblin protocol 1 ·
Status
working branch · packages available

01 / Artifacts

What changed, in the source.

Each entry starts with the implementation artifact, then states the reason for the change and the practical effect it is intended to have.

A01

Authenticated UDP jump relays

Changed

-J and SSH ProxyJump routes now carry the Mosh UDP session through up to four jump-host servers. SSH configures each fixed-destination relay, then exits.

Why

Jumping only for login does not help when the client cannot reach the destination over UDP. Adjacent hosts can relay that traffic while the terminal session remains encrypted end to end.

Why it matters

Each hop has an independent key, replay protection and authenticated client roaming. Framing adds 24 bytes per hop, or 36 with FIPS crypto, budgeted in both directions. Relays reuse Mosh's idle pings and expire after a configurable period of client silence.

A02

Negotiated zstd-22 state compression

Changed

Once both peers advertise zstd, every serialized state update uses zstd level 22. Initial packets stay with zlib for negotiation.

Why

Screen updates are small but frequent, and satellite bandwidth is expensive. State compression is a core part of the link strategy.

Why it matters

There is no size threshold, zlib comparison, or codec-level tuning. After negotiation, the state codec is always zstd-22.

A03

Session-specific state dictionaries

Changed

State updates can be sampled, compiled into a zstd dictionary, and supplied during session setup.

Why

Terminal applications repeat structures, prompts, status lines, and escape sequences that a trained dictionary can represent compactly.

Why it matters

Dictionary compression activates only when both peers advertise the same dictionary ID, keeping the choice explicit and verifiable.

A04

Directional pacing and stream priorities

Changed

Each direction estimates its own delivery budget. A session-wide pacer covers terminal, forwarding and FEC traffic; -L/-R/-D/-A/-X streams have separate priorities.

Why

Uplink and downlink capacity can differ substantially. A file copy or tunnel must not fill the queue needed by an interactive shell.

Why it matters

Clean, busy links ramp up quickly; loss or a slower path cuts the budget. The menu shows traffic, send budgets and outgoing loss. Estimates are not guaranteed link capacity.

A05

File browser, recursive copies and delta sync

Changed

A persistent two-pane browser queues file or directory copies. Matching files use librsync signatures and deltas, with zstd-22 and background FEC in both directions.

Why

Resending an existing file wastes bandwidth. Shipping a complete large-directory listing wastes it before the copy even starts.

Why it matters

Helpers sort names locally and send bounded metadata windows. Live updates, queues and progress stay responsive over loss; SHA-256 checks reconstructed files before replacement.

A06

Clipboard lanes and consent-aware downloads

Changed

OSC 52 and MIME-aware OSC 5522 stay outside screen state. Goblin inline downloads use binary zstd-22/FEC and forward to a supporting Goblin parent, then Kitty, or a local save prompt.

Why

A paste is interactive; a large unsolicited remote blob is not. Applications also need a way to offer a file without silently writing into Downloads.

Why it matters

Local-to-remote and plain-text clipboard data stay fast. Remote non-text writes above a configurable 64 KiB cutoff go in the background. Local download saves require approval and never overwrite.

A07

Retained Kitty and sixel image state

Changed

Static Kitty and sixel images use WebP or negotiated palette/DjVu state plus placement deltas. Images with up to 16 colors can use lossless DjVu bitplanes. Kitty uploads accept inline, file, temporary-file and shared-memory media on the server.

Why

Pixel data is expensive. Moving text or an existing image should not require retransmitting all its pixels.

Why it matters

Encoding stays lossless by default, with WebP fallback for older peers. --lossy=0..100 opts into lossy WebP; --djvu-lossy separately enables lossy two-color DjVu. Sixel stays sixel on a capable client, with conversion on Kitty-only clients. Tests cover 5,120-pixel-wide images.

A08

Geometry, keyboard events and sized text

Changed

The remote session receives the local TERM and attachment geometry. Cell-size queries, Kitty keyboard events and OSC 66 text sizing have explicit handling.

Why

Terminal identity alone does not describe current cell pixels or enabled protocols. Resizing must update geometry without making it persistent screen content.

Why it matters

Applications can size images and position the cursor below them. Configured Alt events pass through; unsupported sized text falls back to ordinary text. Remote terminfo is still required.

A09

Prefixed packages and an explicit FEC policy

Changed

Programs and man pages use the goblin- prefix. Debian/Ubuntu, RPM and Homebrew recipes ship built-in Reed–Solomon FEC and reject RaptorQ-enabled binaries.

Why

The fork needs to coexist with stock Mosh, preserve its GPL-3.0-or-later license, and keep RaptorQ out of distributed binary packages.

Why it matters

Stock mosh remains separate. RaptorQ is off even in ordinary source builds; enabling it requires explicit custom compilation and review of its patent terms.

A10

Native scrollback and tmux control mode

Changed

Native scrolling uses the primary screen by default. Optional --tmux-control transports tmux -CC as reliable ordered bytes.

Why

Earlier output and the local startup mascot should scroll into history. A terminal's native tmux tabs need the control protocol, not a rendered screen diff.

Why it matters

Received rows can stay in local history. Skipped intermediate output cannot be recovered. tmux control mode preserves protocol bytes but can cost more bandwidth.

A11

Lower redraw rate and idle backoff

Changed

Sustained screen updates run at 10–4 frames per second according to RTT. Negotiated idle pings back off from 15 seconds through 30, 60, 120, 240, 480 and 900 seconds.

Why

An unattended terminal should not keep paying for frequent state heartbeats. Fast redraws also consume bandwidth even when newer frames replace older ones.

Why it matters

The first update after idle still leaves promptly. Activity resets the ping interval; compact authenticated pings avoid screen serialization. Long idle intervals can let NAT mappings expire.

A12

Fail-closed FIPS-provider crypto option

Changed

--fips-crypto requires an installed OpenSSL 3 FIPS provider for AES-128-GCM, HKDF-SHA-256 and random generation. Setup fails if either endpoint cannot use it.

Why

A future FIPS-oriented deployment needs an explicit alternative to the normal OCB transport, without silently falling back to it.

Why it matters

This is a deployment building block, not FIPS certification. It adds 12 IV bytes per datagram; the validated module, SSH bootstrap and operating environment remain deployment responsibilities.

Release record

20260919.2: Goblin Skiff is released.

The new package name, longer startup deadlines and negotiated radio pacing are available in the signed Linux repositories and Homebrew tap.

Versions on connection

Connections display the client and server releases and retain both build identities in authenticated session traffic. Compatible releases keep Goblin protocol 1; optional features are negotiated separately. Earlier builds are identified as unversioned.

Compatibility policy · Changelog

Userspace proxy networking

--socks5-proxy=127.0.0.1:1055 carries SSH setup and session UDP through an existing SOCKS5 proxy, including proxy-side DNS and jump routes. A userspace Tailscale setup can connect without a TUN device or kernel changes.

Setup and limitations

Smaller palette images

Negotiated palette/DjVu transport targets small-color images. Lossless remains the default; WebP quality and two-color DjVu lossiness have separate opt-in flags. Builds now require DjVuLibre and its encoder tools.

02 / Comparison

What each tool provides.

Goblin Skiff adds integrated low-bandwidth features to Mosh. SSH remains a general-purpose secure transport; Eternal Terminal resumes a byte stream; autossh supervises SSH. These are different tradeoffs, not a performance ranking.

Reviewed . Goblin column: release 20260919.2, built from 04f2e1d, including authenticated UDP jump relays. Upstream Mosh: 1.4.0. Other columns follow the linked project documentation. “—” means no equivalent built-in feature documented, not that an external tool cannot supply it. Scroll the table horizontally on smaller screens; row and column headings stay visible.

Features and transport behavior. Source references are linked from each column.
Feature Goblin Skiff
this branch
Mosh [1]
upstream 1.4.0
OpenSSH [2]
ssh client/server
Eternal Terminal [3] autossh [4]
SSH supervisor
Session transport Authenticated UDP, direct or through Goblin relays; SSH for setup onlyAuthenticated UDP; SSH bootstrap SSH over TCPReconnectable TCP; SSH bootstrapRuns and monitors SSH
Roaming / temporary loss Session continues with the running client, directly or through relays; relay lease appliesSession continues with the running client No built-in session resumptionReconnects to the same sessionRestarts SSH; does not preserve the remote PTY by itself
Predictive local typing Yes, inherited from MoshYes———; uses SSH
Catching up after congestion Latest screen state; can skip intermediate framesLatest screen state; can skip intermediate frames Ordered byte deliveryReplays buffered bytes after reconnectSSH byte delivery; restart is not replay
Compression zstd-22 state updates; optional trained dictionarieszlib state updates Optional -C stream compressionNo Mosh-style state compressionSSH's -C option
Local terminal scrollback Native received-row history by default; skipped output is absentIncomplete; remote tmux/screen is the documented workaround Terminal-controlled byte-stream historyTerminal-controlled byte-stream historyAs SSH; remote persistence needs tmux/screen
Carry Kitty / sixel graphics protocols Yes — supported static graphics via image/placement state and client-side re-encoding No — neither graphics protocol is carried Yes — inline protocol byte passthroughYes — inline protocol byte passthroughYes — through SSH's byte passthrough
File copying and deltas Two-pane file/directory copy, librsync deltas and goblin-skiffcpSeparate SSH/SFTP/rsync workflow SFTP/scp; rsync as a separate toolNo built-in two-pane delta-copy workflow documentedNo file browser; can supervise SSH tunnels used by other tools
Background file FEC Reed–Solomon, paced below interactive work——; TCP retransmission—; TCP retransmission—; uses SSH/TCP
TCP / SOCKS forwarding Experimental -L/-R TCP and -D SOCKS5 CONNECT, carried over Mosh UDP— in the Mosh session -L/-R/-DTCP port pairs via -tSSH forwards with restart monitoring
Agent / X11 forwarding -A/-X; experimental, medium priority— in the Mosh session -A/-XNo SSH agent/X11 channel equivalent documentedSSH options
Session traffic through jump hosts Yes — authenticated UDP relay through 1–4 Goblin servers via -J / ProxyJump No built-in session relay — SSH setup can jump, but Mosh UDP still travels directly to the destination Yes — TCP through ProxyJump / -JYes — TCP, with an ET server on each hopYes — through SSH's TCP jump-host path
Native tmux -CC Explicit --tmux-control ordered channel—; ordinary remote tmux still works Protocol passthroughProtocol passthroughAs SSH; reattachment needed after restart
Interactive vs bulk scheduling Separate directional estimates; terminal first, background files lastRTT-adaptive terminal updates; no built-in bulk file path SSH channels over TCPResumable byte stream over TCPNo new transport scheduler

The graphics row compares carrying a remote application's graphics protocol to the local terminal, not whether the connection can run inside Kitty. Goblin Skiff interprets supported static graphics, synchronizes image and placement state, then re-emits graphics client-side; it is not byte-for-byte passthrough. Sixel is re-emitted as sixel when supported locally, or converted client-side to Kitty on a Kitty-only terminal. SSH and Eternal Terminal carry the inline protocol bytes without interpreting the images. Display still requires a capable local terminal; byte passthrough alone does not resolve a remote filename or shared-memory reference locally. Native tmux integration also needs a supporting local terminal. None of the rows claims that Goblin Skiff implements every SSH feature or every Kitty extension.

The jump-host row compares the session's data path, not just SSH login. Goblin Skiff no longer needs direct client-to-destination UDP reachability when using its relays; UDP must pass between adjacent hops. The client, every jump and the destination need updated Goblin binaries. Session encryption remains end to end; each hop adds its own authentication. This is not arbitrary UDP port forwarding: -L/-R and SOCKS5 -D carry TCP streams. The new source option --socks5-proxy uses an external proxy's UDP ASSOCIATE support for the Mosh session itself. Idle relays expire after a configurable period of client silence (24 hours by default). Relay setup and wire format.

  1. Mosh's transport design, scrollback FAQ, and upstream issues for Kitty graphics, sixel and forwarding. Roaming and predictive typing are upstream Mosh features, not new inventions of this branch.
  2. OpenSSH ssh(1) and sftp(1) document forwarding, compression, jump hosts, PTYs and file transfer. Graphics/history entries describe byte-stream behavior, not an OpenSSH graphics renderer.
  3. Eternal Terminal usage and transport design describe reconnect/replay, TCP forwarding, jump hosts and tmux control mode. Passthrough entries follow from its byte-stream design.
  4. autossh features and README describe monitoring and restarting SSH. It is included as a practical related utility, not as another Mosh protocol implementation.

03 / Wire behavior

Which traffic goes first.

Compression reduces the amount of data. Scheduling determines which data gets the scarce send opportunity when several features are active at once.

Traffic Class Send rule
Terminal state + input primary Scheduled before forwarded streams and bulk transfer.
Directory requests control Reliable bounded metadata on reserved stream 0; filesystem work runs in a separate helper.
Interactive clipboard fast Separate authenticated FEC lane; local-to-remote and plain-text data do not wait behind background copies.
SSH agent + X11 medium Shares a medium-priority token bucket.
TCP + SOCKS low Uses a separate low-priority token bucket.
Files + large remote blobs background Uses remaining paced opportunities. Due foreground work runs first; a screen waiting for its next frame timer need not stall a copy.

04 / Distribution

Published packages.

Install goblin-skiff on both endpoints. These are the published binary targets, not a list of every platform upstream Mosh supports.

SystemBinary architectureSetup and artifacts
Ubuntu 22.04, 24.04, 26.04amd64APT setup · release 20260919.2
Debian 12, 13amd64APT setup · release 20260919.2
Fedora 44; Rocky Linux 9, 10x86_64RPM setup · release 20260919.2
macOS 26 TahoeApple Silicon / arm64Homebrew tap · 1.4.0-goblin20260919.2
Inkline / reMarkable 2, firmware 3.27ARMv7 hard floatTablet bundle · 20260919.2.rm2.1

Inventory checked 19 September 2026 against the public APT/RPM catalog and Homebrew catalog. ARM APT/RPM packages are not published. All listed Goblin Skiff binaries exclude RaptorQ. Catalogs and repository setup pages provide exact versions, matching source, checksums and verification records. These packages include the directory-cache fixes and authenticated UDP jump relays. Install the updated server on every jump host as well as the destination.

05 / Inspect

Inspect or build the source.

The prefixed binaries are intentional: they let this patch set live beside an ordinary Mosh installation. See the README and packaging recipes for build dependencies. The package setup pages are the simpler installation route.

shell low-bandwidth-mosh
$ git clone --branch low-bandwidth-mosh --single-branch \
    https://github.com/adamdeprince/goblin-skiff.git
$ cd goblin-skiff
$ ./autogen.sh
$ ./configure --with-zstd --with-librsync \
    --without-libraptorq
$ make
$ make check
$ sudo make install

# Run the prefixed client.
$ goblin-skiff user@host

# In the session: Ctrl-^, release, then 0 opens files.

06 / Limits

Evaluation notes.

The branch is a working patch series, not an upstream Mosh release.

Endpoints and jump hosts

Enhanced features require compatible client and server builds. Starting with source version 1.4.0-goblin20260915.1, compatible releases share Goblin protocol 1 and negotiate optional features. UDP jump routes also need an updated Goblin server on every jump, with UDP reachability between adjacent hops. SSH-only jump hosts do not relay Mosh UDP.

Four-hop transfer ramp-up

In four-hop release stress checks with one in seven datagrams dropped plus reordering, first-file completion took up to 141 seconds while keyboard input remained live. Conservative pacing plus relay overhead still needs tuning; the file-completion test window is 300 seconds.

Sensitive samples

State sample logs contain uncompressed terminal updates and may include commands, output, or other sensitive terminal contents.

Not implemented yet

Session audio, live forwarding edits in the popup, arbitrary UDP port forwarding and automatic drag-and-drop uploads remain outside the implemented feature list. Founsure has not been added.

Open the file menu with Ctrl-^, release, then 0 (usually Ctrl-6 in Kitty). Enter starts a copy without leaving the browser; Tab or Shift-Tab swaps panes, Left goes up, and Right enters a directory. Hiding the menu preserves its state; ending the session does not. Large directory workers and transfer queues have bounds, but a slow filesystem can still delay its own results.