What Connector is
A console that operates other machines
Connector is a native Qt 6 application that treats every computer on a Tailscale tailnet as an addressable system with a readiness state, a shell target, and a remote display. It pairs and streams with Moonlight in-process, drives Sunshine on the far end, and exposes the whole thing as a semantic RPC surface that a CLI, a daemon, or an LLM agent can operate.
Most remote-desktop tools stop at "here is a window into that machine." Connector's premise is that the window is the least interesting part. The interesting part is the state model underneath it — is this host online in the tailnet, is its host runtime answering, does this client hold a trust record, is there a working shell path — and the fact that those four answers are independent of each other.
That model is why the app ships three separate entry points instead of one. Connector.app is the visual
cockpit. connectord is a headless control plane that keeps working when nobody is logged into a desktop.
connector-mcp.py is the bridge that lets an agent drive either one. They all speak the same JSON-line
protocol over the same style of local Unix socket.
This repository vendors two large upstream projects under vendor/ —
Moonlight (moonlight-qt) and Sunshine — both GPLv3, both other people's work.
Nothing on this site claims them. See 00.F — Provenance & licensing for the
exact boundary between what was authored here and what was imported.
Readiness model
The device rail collapses four independent signals into one visual state. Colours below are the literal hex values
returned by visualAccent().
Repository instrumentation
These are file-and-symbol counts from the repository, not performance figures. No benchmark, latency, or adoption number appears anywhere on this site, because the repository does not contain any.
Process architecture
Six executables come out of the build. They are deliberately not one binary: the daemon must survive with no desktop session, the stream helper must be a GUI process that can crash without taking the cockpit down, and the CLI must be small enough to drop on a box that only has Qt Core and Network.
QLocalServer::UserAccessOption and
re-chmoded to owner-only after listen(). Note that connectord links neither
Moonlight nor Qt Quick — when it needs a stream or a pairing it execs the helper binaries in row B.
ui.*.ui.* and host.set_* with a message telling the caller to use the desktop app.disconnect, release_mouse, toggle_fullscreen, toggle_stats, toggle_mouse, switch_display) and prints JSON events on stdout.--host, --pin, --timeout-ms. Emits searching / pairing / success / failed events as JSON lines.rpc escape hatch.First contact
The daemon wrapper resolves the socket path before it runs anything, so the same CLI binary can be pointed at the daemon or at the desktop app without recompiling.
$ scripts/ensure-connectord.py --print-socket /run/user/1000/connector/daemon.sock $ scripts/connectorctl-daemon.sh rpc app.ping { "capabilities": [ "devices.start_host", "ssh.exec", "connectorstream.launch" ], "control_protocol_version": 1, "mode": "daemon", "name": "Connector", "socket": "/run/user/1000/connector/daemon.sock", "version": "0.1.0" } $ scripts/connectorctl-daemon.sh ui tree ui.tree requires the Connector desktop app or streaming session process. The headless daemon only exposes device discovery, settings, and SSH control right now.
That last error is not a stub. ConnectorDaemonServer::desktopRequired() is a deliberate, explicit
refusal for every ui.* method plus host.set_enabled, host.set_credentials,
host.approve_pair, host.revoke_client and host.set_default_monitor — the
operations that need a live QML tree or a local desktop session. The daemon would rather tell you where to go than
half-answer.
"This is a high-trust local-owner automation surface. It is intended for the same user account that launched Connector."
Provenance & licensing
Connector is not a from-scratch streaming stack and does not pretend to be. It vendors two mature GPLv3 projects
and builds a control layer on top of them. The boundary is legible in the build system: four static libraries are
compiled out of vendor/moonlight-qt and linked into the authored executables.
| Component | Path | Origin | License posture |
|---|---|---|---|
| QML cockpit | connector-app/qml/ | Authored here | Links GPLv3 statics |
| Backend, session manager, control server | connector-app/src/ | Authored here | Links GPLv3 statics |
| Control protocol + client | shared/src/ | Authored here | Qt only |
| Linux host helpers | connector-app/resources/*.py | Authored here | Standalone Python |
| MCP server & wrappers | scripts/ | Authored here | Standalone Python / shell |
| systemd units | deploy/ | Authored here | Config |
| Moonlight client stack | vendor/moonlight-qt/ | Vendored upstream | GPLv3 |
| Sunshine host stack | vendor/sunshine/ | Vendored upstream | GPLv3 |
The Sunshine tree carries its own CONNECTOR_VENDOR_SOURCE.md recording the exact imported commit
(dfb5163c3cbaed1c8052c6d0f9d6cca4c320f405) and noting that because it was vendored as plain files rather
than a submodule, scripts/embed-sunshine-runtime.sh has to hydrate Sunshine's own third-party
dependencies into the build directory before configuring it.
One nice consequence of embedding Moonlight rather than shelling out to it: moonlightruntime.cpp
reads the standalone Moonlight client's QSettings store — organization "Moonlight Game Streaming
Project", application "Moonlight" — and copies the client certificate, private key, unique id and
saved host array into Connector's own settings namespace. If you already trusted a host in Moonlight, Connector
inherits that trust instead of re-pairing.