A host management hub for fleets of Linux machines. Install the Platypus agent on every host you own; the agent dials back to your Platypus server over TLS + protobuf; from the server you get an interactive shell, file management, and network tunnelling on every managed host — through one central control plane.
A Vercel-style flat-nav UI with a project dashboard, a host/listener/session
browser, a multi-host dispatch console, and an admin user manager. See the
full gallery at docs/screenshots/. Re-run
make screenshots to regenerate them from the live app.
Platypus ships as two backend binaries plus a standalone desktop client:
| Binary | Role |
|---|---|
platypus-server |
Daemon. Accepts inbound agent connections on TLS ingress ports; exposes a REST + WebSocket API for admin tooling; serves agent binaries for distribution. |
platypus-agent |
The process that runs on each managed host. Dials back to the server over TLS + protobuf. |
platypus-desktop |
Native (Wails v2) desktop GUI. Connect to any reachable server with URL + secret; tabbed UI for sessions, terminals, listeners, files, tunnels. See desktop/. |
The server is purely an API — no embedded web UI. Multiple desktops can connect to the same server simultaneously.
- TLS + protobuf channel between agent and server
- Multiple ingress ports so fleets in different networks share one hub
- Interactive shell per host, streamed over WebSocket
- File read / write / upload / download with chunked transfer
- Network tunnels: local-port-forward, remote-port-forward, dynamic SOCKS5
- Bearer-token-authenticated REST API
- Python SDK
- Auto-start listeners from
config.yml - Graceful shutdown (drains connections on SIGINT/SIGTERM within 30s)
The fastest way to get a full Platypus system running (including the Server, Web UI, and a MinIO-backed Agent Distributor) is using Docker Compose:
git clone https://github.com/WangYihang/Platypus
cd Platypus
docker-compose up -d- Web UI: Open
http://localhost:7331in your browser. - Login: Use the
bootstrap_secretprinted in the server logs (docker-compose logs platypus-server). - Add Agents: Click "Add Agent" in the UI to get a one-line
curlcommand to deploy agents to your fleet.
Requires Go 1.24+ and protoc (only if you regenerate protobuf code).
git clone https://github.com/WangYihang/Platypus
cd Platypus
make build # → ./build/{platypus-server,platypus-agent}Other useful targets: make test, make lint, make snapshot (cross-platform via goreleaser), make help.
Contributors should install the git hooks so gofmt / goimports / go vet /
golangci-lint run before each commit:
pip install pre-commit # or: pipx install pre-commit
make hooks # one-time: wires .git/hooks/pre-commit
make pre-commit # optional: run all hooks against every file nowRequires Node 22+, Wails CLI dependencies (wails doctor), and the platform's WebView libraries (webkit2gtk-4.1 on Linux, WebView2 on Windows, WKWebView on macOS).
make desktop-deps # one-time: install Wails CLI + pnpm packages
make desktop-build # → desktop/build/bin/platypus-desktop
make desktop-dev # hot-reload dev modeSame pages, same features (minus real-time event push), runs in any browser:
make web-ui # → desktop/frontend/dist-web/ (static bundle)
make web-ui-serve # preview at http://localhost:8080dist-web/ is fully static; drop it on GitHub Pages / S3 / nginx. Point it at any platypus-server via the login form.
Full notes in desktop/README.md.
Download the appropriate archive for your OS/arch from the Releases page, extract, and run.
docker build -t platypus-server .
docker run --rm -p 7331:7331 -p 13337:13337 -v $(pwd)/config.yml:/config.yml platypus-server./build/platypus-server # foreground; Ctrl-C for graceful shutdownFor production, run the server under systemd rather than backgrounding it manually.
- Server:
192.168.88.129- Agent ingress (TLS):
0.0.0.0:13337 - Distributor (agent binary downloads):
0.0.0.0:13339 - REST API:
127.0.0.1:7331
- Agent ingress (TLS):
- Managed host:
192.168.88.130(runsplatypus-agent)
First, run ./platypus-server. A config.yml is generated from
assets/config.example.yml if none exists. Defaults are sensible:
listeners:
- host: "0.0.0.0"
port: 13337
hashFormat: "%i %u %m %o %t"
disable_history: true
public_ip: ""
shell_path: "/bin/bash"
restful:
host: "0.0.0.0"
port: 7331
enable: true
distributor:
host: "0.0.0.0"
port: 13339
url: "http://127.0.0.1:13339"
openBrowser: falseOn startup the server prints, for every interface it's binding, the
curl command an admin can run on a managed host to fetch and launch
the agent:
curl -fsSL http://<server>:13339/agent/<server>:13337 -o /tmp/platypus-agent \
&& chmod +x /tmp/platypus-agent && /tmp/platypus-agentThe distributor patches the connect-back target into the prebuilt agent
binary in-place, so the same build serves every ingress. Once the agent
starts, it dials server:13337, the TLS handshake completes, and the
session appears in the server's session list.
Open the desktop app (platypus-desktop) or the web UI (make web-ui-serve),
fill in the server URL and secret, and you're in. Tabs: Sessions (every
agent that's dialled in), Terminal, Files, Tunnels, Listeners.
- REST API
- Python SDK
This project exists thanks to all the people who contribute.
Thank you to all our backers! 🙏 [Become a backer]
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
