Private remote shells for machines you own—without opening inbound ports or operating a VPN. Pair once with a short code, then reconnect by name from a terminal.
zuko runs a real PTY over Iroh, which provides dial-by-key reachability, NAT traversal, relay fallback, and end-to-end encryption. The supported core is deliberately small: a Linux/macOS host, the Rust CLI, explicit device authorization, and short reconnects.
Install the CLI on a Linux or macOS host:
curl --proto '=https' --tlsv1.2 -LsSf https://zuko.adonm.dev/install.sh | sh
# Relaunch your shell here if the installer asks.
zuko installPair from another machine with the CLI installed:
# host: prints a one-time two-word code
zuko share
# client: claims, saves, and connects
zuko iridescent-hilton
# later
zuko homeThe installer bootstraps and activates mise when needed, then installs Zuko as a mise-managed global tool. Relaunch your shell first if it asks. See Getting started for mise, version selection, service logs, and first connection. Windows hosts can use the documented WSL2 setup, with lifecycle limitations.
| Tier | Surface | Commitment |
|---|---|---|
| Core | Linux/macOS host and Rust CLI | Primary supported workflow |
| Beta | Flutter Android, iOS/iPadOS, macOS, and Linux clients | Shared graphical client with store, preview, or community package delivery paths |
| Labs | Flutter web/Windows clients and Linux zuko app |
Deployed or buildable, with channel-specific gaps documented below |
See Clients for the exact capabilities and delivery channel of each target, and the client build guide for fresh Android, Apple, web, Linux, and Windows builds.
Fully signed public-store delivery across the graphical targets is still being worked on. For testing, the checksummed artifacts on the latest GitHub Release are the preferred source; the Clients page documents platform-specific gaps and the separate internal TestFlight channel.
zuko is not a durable session manager, full remote desktop, or centralized
fleet-access system. Use tmux, zellij, or screen for work that must survive
disconnects and host restarts.
zuko <name> # connect
zuko # TTY picker / non-TTY list
zuko share # authorise a new client
zuko claim <code> --as x # explicit claim form
zuko doctor # check service, ticket, state, and network
# inside a connected host shell:
zuko tunnel 8000 # client loopback → host 127.0.0.1:8000Session notes:
- Real host PTY; bytes are forwarded verbatim.
- Detached PTY lease: 5 minutes. No replay buffer.
- Use
tmux,zellij, orscreenfor durable work. - CLI force-exit: Ctrl-C three times within ~1s with no remote output.
Run zuko tunnel <port> inside a shell opened through Zuko. The native client
binds an ephemeral loopback port, prints it, and opens its HTTP URL for the
common local-web-server case. Traffic is raw TCP: Zuko does not parse HTTP or
terminate TLS, so the printed port also works with HTTPS, WebSockets, SSH, and
other TCP clients.
# On the host, inside the connected shell:
python3 -m http.server 8000 --bind 127.0.0.1 &
zuko tunnel 8000The command remains in the foreground and reports connection/byte totals.
Ctrl-C closes the Iroh tunnel and client port. See
docs/tunnel.md.
Run a GUI app inside an existing zuko shell. Output is Kitty graphics over the same PTY/Iroh connection. This is an optional Labs feature, not a remote-desktop goal.
zuko app --list
zuko app firefox
zuko app --doctorSee docs/app.md.
mise install
just check
just test-e2e # live Iroh network + PTY
cargo build --releasePlatform prerequisites, Windows PowerShell commands, signing behavior, and artifact paths are in Building clients.
| Path | Contents |
|---|---|
src/ |
Rust crate: host, CLI client, handoff, service, and app streaming |
flutter/ |
Shared Android, iOS, macOS, web, Linux, and Windows client |
Justfile |
Human-facing build, test, package, and release recipes |
mise.toml |
Pinned tools, environment, and bootstrap system dependencies |
docs/ |
mdBook docs |
tests/e2e.rs |
ignored live-network integration test |
.github/workflows/ |
Rust, Flutter, release, TestFlight, and docs CI |
Shell access requires both host connection information and an authorized client
token. zuko share transfers the former and registers the latter over an
end-to-end-encrypted handoff. Keep both private and revoke lost clients with
zuko rm <name>.
Report vulnerabilities via GitHub Security Advisory. Details:
docs/security.md.
Apache-2.0. See LICENSE.