Pure Go mosh. Client and server. No C dependencies, no CGO.
Wire-compatible with the standard C mosh implementation. You can use the Go client against a C mosh-server, or the Go server with a C mosh-client, or go pure Go on both ends.
Implements the full mosh wire protocol: AES-128-OCB3 authenticated encryption, SSP transport with sequencing and retransmission, datagram fragmentation, and the protobuf state sync layer.
unixshells.com uses mosh-go compiled to WASM for the web terminal
go install github.com/unixshells/mosh-go/cmd/mosh@latest
go install github.com/unixshells/mosh-go/cmd/mosh-server@latest
go install github.com/unixshells/mosh-go/cmd/mosh-client@latest
The mosh command works like the C version -- SSHs to the host,
starts mosh-server, connects over UDP:
mosh user@host
mosh -p 2222 user@host # custom SSH port
mosh -i ~/.ssh/id_ed25519 user@host
Or use the server and client separately:
# On the server:
mosh-server # prints MOSH CONNECT <port> <key>
mosh-server -p 60001 # specific port
mosh-server -s /bin/zsh # specific shell
# On the client:
MOSH_KEY=<key> mosh-client <host> <port>import mosh "github.com/unixshells/mosh-go"
// Server
srv, _ := mosh.NewServer("/bin/bash", 60000, 60999)
go srv.Serve()
fmt.Println(srv.ConnectLine())
// Client
c, _ := mosh.Dial("192.168.1.5", 60001, "base64key")
c.Resize(80, 24)
c.Send([]byte("ls\n"))
out := c.Recv(time.Second)ServeRW runs the server protocol over an io.ReadWriteCloser
instead of a PTY. No shell is spawned -- the caller provides the
I/O. This is how latch bridges mosh into its session model:
srv, _ := mosh.NewServer("", 0, 0)
fmt.Println(srv.ConnectLine())
srv.ServeRW(rw, func(cols, rows uint16) {
// handle resize
})Tested against the C reference implementation:
| Client | Server | Status |
|---|---|---|
| Go | Go | always tested |
| Go | C mosh-server | tested if installed |
| C mosh-client | Go | tested if installed |
All three pass. Run go test -race ./... to verify.
The protobuf layer supports optional latch extension fields. Standard mosh clients and servers ignore them (forward-compatible).
- Capability negotiation (TransportInstruction field 8): bitfield exchanged on every datagram. Both sides AND their caps to get the intersection. No caps = classic mosh mode.
- Session control (Host/UserInstruction field 9): list, switch, and create latch sessions over the mosh connection.
The mosh client compiles to WebAssembly for use in the web terminal:
GOOS=js GOARCH=wasm CGO_ENABLED=0 go build -tags osusergo -o mosh.wasm ./cmd/mosh-wasm/
The -tags osusergo flag is required to avoid os/user CGO issues with GOOS=js.
server.go-- server, PTY lifecycle,ServeRWbridge modeclient.go-- client, send/recv loopstransport.go-- SSP sequencing, timestamps, RTT, retransmissionocb.go-- AES-128-OCB3 (RFC 7253)fragment.go-- datagram fragmentation and reassemblypb.go-- protobuf encoding (transport, host, user, latch extensions)framebuffer.go-- terminal state tracking for diff protocolpredict.go-- local echo prediction engine (speculative keystroke rendering)
creack/pty, golang.org/x/crypto, and the Go standard library.
Copyright (c) 2026 Unix Shells. MIT license. See LICENSE.