Repository navigation
Latch v4.0.0
-
On macOS and Linux the background service keeps its login item
registered without restarting itself: it only writes the launch agent or
user unit, and a copy started while another already answers on the port
exits quietly instead of failing, so launchd no longer respawns a
duplicate every ten seconds for the rest of the session and a service
launchd started at login is no longer killed by its own registration.
Turning the login item off in the panel leaves the running service alone. -
Only a Windows PC accepts a pushed
brolink-host.exe; a Mac or a
container answers 400 instead of trying to swap it in, and the Mac only
sends one to Windows machines. -
Elevated Windows setup approved with another administrator's password
reads and writes the launching user's Latch folder, so the engine login
it configures is that user's. -
The updater takes the window's locks in the window's order; the reverse
could hang the app when an update was ready just as a stream ended. -
Docker desktops now publish a valid streaming app catalog. The missing
environment object made a healthy-looking VPS report "offers nothing to
stream"; node self-tests now check the catalog and persisted login setup.
Startup waits for the engine before launching the control service, which
prevents two engine processes racing to bind the same ports. -
On Windows, the streaming engine runs as the signed-in user and the
only active speakers stay the default. The engine's own startup was
clearing Steam Streaming Speakers on a PC with no other playback
device, which leftCouldn't get default audio endpointand a silent
stream. Startup probe errors are no longer reported as a missing sound
device. -
Software encode (a VPS with no GPU) uses every CPU core and the
ultrafast preset so 1080p60 holds instead of collapsing to ~30 fps and a
trickle of bitrate. AMD encode prefers speed, with preanalysis off, so
the target rate does not sit at ~18 Mbps on a still desktop. -
The stream protocol always treats Tailscale as a LAN: no 1024-byte
packets, no extra 500 kbps tax, and the bitrate is sent at launch as
well as over RTSP. -
The streaming engine is not a second app. Status, logs, the Dock and
the app list say Latch; only Desktop is launched. -
Latch is a mesh. Every install lists every other machine on the
Tailscale account — Windows, Mac, Linux, a VPS container — and Connect
opens that desktop. The same app shares this machine: Mac and Linux
install the streaming engine; Windows still does. There is no designated
host or client role. -
deploy/node/is a Docker kit for a VPS or any container: a virtual
desktop, the streaming engine, Latch's control service, and optional
Tailscale userspace so the container is its own machine. Several copies
on one host are several machines. The packet relay staysdeploy/relay/. -
Stream bitrate holds the target instead of swinging with the scene.
Sunshine is set to constant bitrate (AMD CBR+HRD, NVENC VBV, VA-API CBR),
Tailscale is treated as a LAN so moonlight does not tax 500 kbps or shrink
packets to 1024, packets stay 1184 bytes for WireGuard's MTU, and the
moonlight cap is 150 Mbps. Recommended quality is 50 Mbps; Sharp is 100. -
Settings and pairing no longer wipe each other. The window, discovery and
pairing used to rewrite all ofclient.tomlfrom a stale copy, so a
bitrate change could drop the PC's certificate and its wake details, and
a reconnect right after the first pair could ask for a PIN again. Every
write is now one read-modify-write under a lock: the window overlays its
preferences, discovery and pairing edit only what they learned, and the
host panel does the same withhost.toml. Config files are written 0600
in a 0700 folder, and a damaged file is kept beside the new one as
.bad-*instead of being replaced. -
An update no longer installs while a connect is waking, pairing or
launching, a connect refuses to start while an install is under way, and
a cancelled connect cannot finish into the next one. Cancel takes effect
while the PC is still being asked for the PIN. The update cache keeps
this release and the previous one only. -
Connecting no longer overwrites the Mac clipboard with whatever the PC
already held. Ctrl+Alt (the host key) is never sent to the PC, and it
works even when a control has focus; while the mouse is captured, keys go
to the PC rather than to a focused control. Captured mouse movement is
scaled to the stream's pixels, so a hand movement crosses the same share
of the PC's desktop as of the picture. -
Every Tailscale CLI call is bounded (10 s; the per-request
whois2 s),
and its output is drained while it runs, so a slow or chatty CLI cannot
hang the window or the control service. -
Host setup runs
brolink-host --setup-elevatedafter UAC, writes its
script under%SystemRoot%\Temp(administrators only) and passes the
engine take-over helper as an encoded command, instead of running a
user-writablesetup.ps1. Repair setup registers the engine service when
files exist but the service is down, and stops a leftover service before
deleting it. Firewallprogram=paths are single-quoted so a$in the
username is not expanded. The logon task for the take-over helper runs
with limited rights. -
The engine login is written as the engine's own hashed credentials file
(brolink-web.json,credentials_file =insunshine.conf) instead of
sunshine --credson a command line, and the engine's web API is called
with the password on stdin (curl --config -), so neither the setup log
nor the process list shows it. The Docker node does the same through
deploy/node/bootstrap.py, which also keeps an existinghost.toml
(preferences, pairing) intact across restarts. -
Auto-update refuses a GitHub asset with no SHA-256. The Mac installer
checks that digest, verifies the signature, and swaps/Applications
without deleting the live app first.git credentialis killed if its
stdin closes early. -
Stream teardown waits for in-flight input and keeps the session alive
until moonlight's detached termination thread has nowhere to call; a
decode unit whose buffer list overruns its declared length is refused. -
The migration check reads the installed engine's real kind instead of
labelling every install "Latch". The macOS launch agent and Linux user
unit escape the executable path, and a failure to register them is
reported instead of ignored. Spawned engine and service processes are
reaped. A settings save failure shows in the window. -
One pointer. Freeing the mouse showed the Mac cursor behind egui's back,
and it stayed on top of the PC's own cursor in the picture until the
pointer left the window; the cursor is now hidden the one way egui
keeps track of. -
The mouse is captured by default: a click on the picture hides the
cursor, holds it in place and sends raw movement, which is what games
read for the camera. A game that ignores the cursor's position (Genshin
Impact) turned only in the old Captured mode; Honkai: Star Rail happened
to follow the position too. Free in the Mouse menu is the old
behaviour, and the choice is remembered. -
The stream is the whole window, nothing over it. Ctrl+Alt is the
host key, as in a hypervisor: it frees the mouse and drops the toolbar
over the picture; a click on the picture, or Ctrl+Alt again, puts it
away and takes the mouse back. The toolbar no longer sits above the
picture in a window, which is what left the bars either side, and a
window takes the stream's proportions when a session starts. -
1080p, 1440p and 4K are 1920×1080, 2560×1440 and 3840×2160, not those
widths at this display's shape (1920×1246 on a 14" MacBook Pro), and the
list shows the pixel size of each. Match screen is unchanged. On a
display of another shape the standard sizes leave a bar above and below. -
Less delay between the PC and the eye. A decoded frame is presented as
soon as it is drawn instead of waiting for the display's next refresh,
up to a refresh interval sooner, and the decoder fills the same few
buffers over and over instead of taking nine fresh megabytes per frame. -
The Dock icon is the bundle icns, in macOS's rounded app-icon shape.
eframe was replacing it at runtime with a 64-pixel square of the logo,
and the icns had been pre-masked with transparent corners, which macOS
26 draws as a square plate.scripts/make-macos-icon.pynow fills the
canvas and lets the system apply the shape. -
The Windows host icon (Explorer, taskbar, Alt-Tab, the window, and the
in-app header) is the same filled tile. The logo's outer pad had left a
square plate around the mark;icon::rendernow crops it.