/fɛʁ.nɔ.mad/ — from French fer (“iron”) and nomade (“nomadic”).
A pure-Rust Mosh client for stock mosh-server.
English · 简体中文
FerNomade is an independent, pure-Rust Mosh client. It
speaks the standard Mosh wire protocol directly to an unmodified mosh-server,
including AES-128-OCB3 authenticated datagrams, state synchronization,
fragmentation, acknowledgements, roaming, and terminal paint instructions.
It does not contain an SSH client or a Mosh server.
It is designed to be useful in two places:
- as a standalone network client launched after an SSH bootstrap;
- as an embeddable runtime inside another terminal or host application.
Project status: the protocol path interoperates with the unmodified Debian
mosh-server1.4.0 package. The API is still pre-release and compatibility claims are deliberately limited to exact versions tested in the lab.
FerNomade occupies the same network-client position as the conventional
mosh-client executable. SSH is used only to start the remote server and obtain
the MOSH CONNECT port and session key; FerNomade then runs the Mosh session
over authenticated UDP.
SSH or host application
│ MOSH CONNECT <port> <key>
▼
FerNomade / mosh-client
│ Mosh protocol over authenticated UDP
▼
stock mosh-server 1.4.x
The current compatibility target is the standard Mosh 1.4.x protocol family.
Automated black-box interoperability is presently pinned to the unmodified
Debian mosh-server 1.4.0 package; other 1.4.x releases remain compatibility
targets until individually recorded in the lab.
Release archives include both fernomade and a mosh-client-named copy for
SSH bootstrap tools and terminal applications that expect that executable
name. The reusable runtime can also be embedded directly into applications
such as terminal emulators.
Remote shells tend to feel worst exactly when they matter most: on mobile networks, unstable Wi-Fi, VPN transitions, and machines waking from sleep. FerNomade synchronizes terminal state over authenticated UDP instead of treating the session as one fragile byte stream.
- Roaming: continue after the client address or UDP source port changes.
- Loss recovery: retransmit logical state without reusing packet nonces.
- Fast feedback: predict only safe printable input and roll it back against the authoritative server screen.
- Native integration: embed the protocol runtime without giving it control of SSH, sockets, clocks, or credentials.
- Portable Rust: no bundled C or C++ protocol runtime.
FerNomade starts after a standard server has supplied a UDP port and ephemeral key. An SSH command, terminal manager, or another host application can perform that bootstrap.
$ cargo build --release --package fernomade-client
$ MOSH_KEY='SESSION_KEY' ./target/release/fernomade SERVER_IP UDP_PORTFor example, a bootstrap typically obtains a line shaped like:
MOSH CONNECT 60001 SESSION_KEY
Pass the port and key directly to FerNomade without writing the key to disk or placing it in command-line arguments.
| Keys | Action |
|---|---|
Ctrl-^ . |
End the local session |
Ctrl-^ ^ |
Send a literal Ctrl-^ |
Ctrl-^ Ctrl-Z |
Suspend locally on Unix and restore after resume |
Ctrl-^ ? |
Show local command help |
Set MOSH_ESCAPE_KEY to one literal ASCII character to choose another local
command prefix. Printable prefixes follow the conventional newline-prefix
behavior; control-character prefixes are recognized directly.
FerNomade uses the local alternate screen by default so the original terminal
contents return after exit. Set MOSH_NO_TERM_INIT=1 to keep the current screen.
If the operating system cannot report the viewport, positive COLUMNS and
LINES environment variables are used as a fallback.
| Environment | Effect |
|---|---|
MOSH_KEY |
Required 128-bit session key from MOSH CONNECT |
MOSH_ESCAPE_KEY |
One literal ASCII local-command prefix |
MOSH_PREDICTION_DISPLAY |
adaptive, always, or never |
MOSH_PREDICTION_OVERWRITE=yes |
Overwrite instead of insert predicted cells |
MOSH_TITLE_NOPREFIX |
Disable the default [mosh] remote-title prefix |
MOSH_NO_TERM_INIT=1 |
Skip local alternate-screen initialization |
- AES-128 OCB3 authenticated datagrams
- Bounded packet replay window and fragment reassembly
- Acknowledgements, retransmission backoff, heartbeat, and liveness tracking
- Stale-state suppression and recoverable indefinite network interruption
- IPv4 and IPv6 endpoints
- Client UDP rebinding and suspend/resume recovery
- Bounded local, peer, and simultaneous SSP shutdown handshakes
- UTF-8 terminal output and authoritative VT screen tracking
- Keyboard, function keys, mouse, focus, bracketed paste, and resize
- Conservative local prediction with line-local insert rollback and an authoritative overwrite fallback
- Terminal restoration after exit, error, panic unwinding, and supported signals
- English and Simplified Chinese command-line diagnostics
- Native source checks for macOS, Linux, and Windows targets
- Static MSVC runtime in Windows release binaries
mosh-client -c,-v, and standard Mosh client environment parsing
-v, -vv, and -vvv enable lifecycle, SSP summary, and aggregate packet
metadata diagnostics respectively. Diagnostics never include session keys,
input, terminal output, authenticated plaintext, or datagram contents. Higher
levels saturate at -vvv.
Without terminfo, -c is necessarily heuristic. FerNomade uses TERM,
COLORTERM, and the platform-reported color capability; unknown terminals are
reported conservatively. POSIX clients require the effective
LC_ALL/LC_CTYPE/LANG locale to name UTF-8.
On Windows, console control events for Ctrl+C and Ctrl+Break are ignored by the local process so their input can be forwarded to the remote session. This path is compile-checked in CI but has not yet been claimed as end-to-end validated under every Windows terminal host.
The workspace keeps protocol concerns separate from operating-system concerns:
| Crate | Responsibility |
|---|---|
fernomade-wire |
Fragment framing, bounded Protobuf decoding, and compression |
fernomade-crypto |
Session-key ownership and OCB3 packet envelopes |
fernomade-session |
State numbers, acknowledgements, replay handling, and reassembly |
fernomade-state |
Cloneable bounded remote terminal states for SSP history reconstruction |
fernomade-runtime |
Deterministic timers, queues, retransmission, and host actions |
fernomade-terminal |
Terminal lifecycle and input encoding |
fernomade-predict |
Non-authoritative local prediction overlay |
fernomade-client |
UDP and local-console command-line application |
fernomade-lab |
Black-box compatibility probes and synthetic fixtures |
The embeddable API is described in docs/EMBEDDING.md.
The checked-in laboratory verifies FerNomade against Debian
mosh-server 1.4.0-1+b1 on arm64. It exercises bidirectional state exchange,
packet loss, retransmission, reordering, and UDP rebinding.
$ ./lab/verify-fernomade-to-standard-server.sh
standard server exchanged FerNomade state: ... roamed=trueSee docs/COMPATIBILITY.md for the pinned artifact and the exact scope of the compatibility claim.
Rust 1.85 or later is required.
$ cargo build --workspace --locked
$ cargo test --workspace --locked
$ cargo clippy --workspace --all-targets --locked -- -D warnings
$ cargo deny checkRun the real PTY lifecycle check:
$ cargo build --package fernomade-client
$ ./lab/verify-terminal-restoration.expCreate a self-contained release archive:
$ ./scripts/package-release.sh 0.1.0 aarch64-apple-darwinThe archive contains fernomade, a mosh-client compatibility copy, the
license, copyright and attribution notices, third-party notices, and a SHA-256
checksum.
Pushing a semantic version tag builds native archives for Linux x86_64/arm64, macOS x86_64/arm64, and Windows x86_64, then publishes them to a GitHub Release:
$ git tag -a v0.1.0 -m "FerNomade 0.1.0"
$ git push origin v0.1.0The release workflow runs the test and Clippy gates before packaging. A failed platform build prevents the GitHub Release from being created.
- Compatibility and tested artifact
- Independent implementation policy
- Embedding contract
- Prediction policy
- Project governance
- Attribution notice
- Third-party notices
FerNomade is licensed under Apache-2.0. Attribution information is recorded in NOTICE. It is an independent implementation and is not affiliated with or endorsed by the Mosh project. Mosh is a registered trademark of its respective owner.