- Open the zip and move Ping to Applications.
- Open Ping, and let it find devices on your local network when it asks.
brew tap mihaicristianfarcas/pingpong https://github.com/mihaicristianfarcas/pingpong
brew install --cask ping
Ping, the client, and Pong, the host, stream a desktop at up to 4K and 120 fps with the latency of Moonlight and Apollo. Every packet travels in one post-quantum WireGuard tunnel. For macOS, Windows and Linux, and open source under the GPL-3.0.
pingpong covers what a Moonlight + Apollo setup does, and adds to it: one code base in Rust, with a client and a host on all three desktops.
Picture, sound, input and the clipboard travel in one tunnel: WireGuard with ML-KEM-768. Pairing is a hybrid SPAKE2 + ML-KEM exchange over a PIN. Encrypting a 1,200-byte packet takes 0.63 µs.
Hosts publish sealed records on the BitTorrent DHT, and both sides punch through their NATs. No relay server, no VPN and no ports to forward.
Reed-Solomon parity, sized to the loss the link shows, rebuilds what Wi-Fi drops. When it cannot, Ping asks for a fresh reference frame, as Moonlight does.
Windows and macOS hosts create a virtual display at your screen’s resolution and refresh rate for the session, so nothing is scaled or letterboxed.
Text, images, files and folders, in either direction. Anything a password manager marks as concealed is never sent.
Stereo, 5.1 or 7.1 sound. Controllers reach a Windows host as Xbox 360 pads, and rumble comes back about 7 ms after the host sets it.
A real stream from a Linux host to a Linux client, both screens recorded at the same instants. The host shows a running clock, so the two halves can be compared frame by frame: the client is one frame behind the host throughout. Ping’s statistics put 5.1 ms of that between the host capturing a frame and the client’s screen showing it, and no frame was lost.
From Ping’s statistics: 1280×720 at 60 fps, H.264, encoded in software, host and client in one Linux container. On a real network, add its round trip. On the benchmark machines, capture to encoded frame takes 2.2–2.6 ms at 1080p60.
The same MacBook, the same PC and the same demanding settings: 3024×1890 at 120 fps and 100 Mbit/s, HEVC, 7.1 sound, with the host’s screen full of noise.
Client: a 14″ MacBook Pro (M4 Pro) on Wi-Fi. Host: Windows 11, RTX 3070 Ti, SudoVDA. Ping’s figures are 30-second averages; Moonlight’s, its end-of-stream statistics. The two measure network round trip differently, so it is left out here. Every figure, and how it was taken
An agent sees the screen and uses the keyboard and mouse the way you do through Ping: over the same tunnel, from anywhere. You can watch it, take over or stop it at any point.
Every action, its result and the screen after it. Log in to see the desktop live; Ctrl Alt Shift T takes the keyboard and mouse.
Before it deletes, spends, sends, installs or types a password. Rules catch rm -rf,
git push --force and DROP TABLE whether it asked or not.
Claude Code or Codex on your plan, an Anthropic, OpenAI or OpenRouter key, or a local model. Or give any MCP
client your hosts as tools with Ping mcp.
An agent pairs like a device, and its role is sealed with the PIN’s key: the host knows it by its key, not by what it claims. How agents work
Ping runs on the computer you sit at, Pong on the one you stream from. Both are native windows drawn with GPUI, follow your system’s light or dark appearance, and explain every setting in a line.
| System | Client (Ping) | Host (Pong) |
|---|---|---|
| macOS 14 and later | Daily use Ping.app | Works Pong.app: a virtual display at your size, HEVC, stereo sound; no controllers |
| Windows 10 and 11 | Works Ping.exe, less tested than on macOS | Daily use PongService: starts at boot and streams the lock screen; needs an NVIDIA GPU and SudoVDA |
| Linux X11 and Wayland | Works ping-app, tested in a container | Works pong as a user service; the screen is scaled, with no virtual display |
Phones, tablets and TVs are out of scope. Feature by feature against Moonlight + Apollo
Say which computer this is for and what it runs, and you get its download.
brew tap mihaicristianfarcas/pingpong https://github.com/mihaicristianfarcas/pingpong
brew install --cask ping
brew tap mihaicristianfarcas/pingpong https://github.com/mihaicristianfarcas/pingpong
brew install --cask pong
./install.sh in its folder: Ping goes in ~/.local/bin and in your launcher.curl -L https://downloads.ping-pong.sh/latest/Ping-linux-x86_64.tar.gz | tar xz
Ping-*-linux-x86_64/install.sh
./install.sh in its folder: Pong runs as a user service in your desktop session, now and at each login.curl -L https://downloads.ping-pong.sh/latest/Pong-linux-x86_64.tar.gz | tar xz
Pong-*-linux-x86_64/install.sh
The newest build of the main branch. SHA-256 checksums All releases
Pong on the computer you stream from, Ping on the one you sit at.
Click the host in Ping and type the PIN it shows into Pong. You do this once, on your network.
Click the host again, from anywhere. Ctrl+Alt+Shift+Q ends the stream.
Any of them builds from source with Rust 1.96 or newer. Installing, step by step