
Download Buoy Desktop
Account required · All downloads
Buoy Desktop is a native dashboard for macOS, Windows, and Linux that mirrors your on-device Buoy tools to a full-size window in real time. It includes a live performance HUD, multi-device switching, and remote control over the running app.
React Native and Flutter devices speak the same protocol, so they show up side by side in one dashboard.
@buoy-gg/external-sync package installed in the app — it's the sync client, and it ships separately from the tools (see below).The download button above grabs the right build for your machine automatically; every build for macOS, Windows, and Linux is on the GitHub releases page. It auto-updates, so you stay on the latest build. Buoy Desktop is free to use — a Buoy Pro license unlocks full history and unlimited capture, See pricing for current plan allowances.
Buoy tools sync to a local broker on port 42831. Launch Buoy Desktop first; it starts the broker and auto-detects connected devices. Use the device switcher in the title bar to choose which device every tool inspects — every install of your app is its own entry, named after the app and hardware (Acme App (iPhone 17 Pro · 2c1d)). If no device appears, the dashboard shows a troubleshooting panel with your machine's exact URLs and a test you can run from the phone's browser.
The broker listens on your local network, so phones on the same Wi-Fi reach it without setup. Only Buoy Desktop and the Buoy MCP server on your machine can read app data or send actions to an app. They prove it with a token the broker writes when it starts, to ~/.buoy/broker-token (%APPDATA%\Buoy\broker-token on Windows), a file only your user account can read. Anything else that connects is treated as an app: it can send its own data and receive actions addressed to it, and can't see or control anything else.
Web apps served from your machine or your local network connect as usual. When a page from any other site tries to connect, such as your production site with Buoy turned on for admins, Buoy Desktop asks whether to allow that site. It remembers an Allow; a Don't Allow lasts until Desktop restarts.
To accept connections from this machine only, create broker-settings.json containing { "allowNetworkDevices": false } in Buoy Desktop's data folder (~/Library/Application Support/Buoy on macOS, %APPDATA%\Buoy on Windows, ~/.config/Buoy on Linux) and restart Desktop, or launch it with BUOY_BROKER_HOST=127.0.0.1. Simulators, emulators and Android over USB keep working; phones on Wi-Fi can't connect.
Traffic between a phone and your machine isn't encrypted, so connect over a network you trust.
First, install the sync client in your app. It's a separate package on purpose — apps that never use the desktop dashboard don't carry the sync code at all:
npm install @buoy-gg/external-syncRestart Metro after installing it. In development, FloatingDevTools detects the package and derives the broker address from Metro. The device must be able to reach that address; use the options below when the derived host is unsuitable.
Need to point somewhere else? Pass socketURL in the externalSync prop:
adb reverse tcp:42831 tcp:42831 once per cable session; no socketURL needed (the derived localhost is kept as-is on physical devices — the 10.0.2.2 rewrite only applies to emulators).http://<ip>:42831.<FloatingDevTools externalSync={{ socketURL: "http://192.168.1.20:42831" }} />
<FloatingDevTools externalSync={{ socketURL: "http://192.168.1.20:42831" }} />
Just installed a @buoy-gg package? Restart Metro with
--clear— Metro caches the "optional package missing" resolution, and a plain reload never picks the new package up.
A shipped app must never dial a broker on a customer's phone, so sync is off whenever __DEV__ is false. To profile a release build you own — a local --configuration Release run, an internal TestFlight/EAS build, a field build that ships headless — opt in explicitly. It also requires a real Pro license.
<FloatingDevTools externalSync={{ enableInRelease: true }} />
<FloatingDevTools externalSync={{ enableInRelease: true }} />
There is no Metro server in a release bundle, so the broker host can't be derived and socketURL defaults to http://localhost:42831. That is already right for the iOS Simulator, the Android emulator, and Android over USB (adb reverse tcp:42831 tcp:42831).
Release sync carries real user data, such as session tokens in network captures. So a release build won't connect over plain http:// to another machine, where anyone on the same network could read the traffic; it logs a warning instead. It connects to localhost or over https://. For a physical iOS device on a network you trust, opt in to plain http as well:
<FloatingDevTools
externalSync={{
enableInRelease: true,
socketURL: "http://192.168.1.20:42831",
allowInsecureNetwork: true,
}}
/>
<FloatingDevTools
externalSync={{
enableInRelease: true,
socketURL: "http://192.168.1.20:42831",
allowInsecureNetwork: true,
}}
/>
Most tools work the same in a release build — network capture, storage, console, the state tools, routes, images, assets, the performance HUD, and remote actions. Three things stay off, by design and not by choice:
describe_screen / tap_element / measure_renders calls) needs React's DevTools hook, which React only installs in dev builds.expo-updates; without that package installed, reload_app reports that it has no mechanism instead of reloading.Impersonate's remote actions that search users or start an impersonation are also refused in release builds, because they run with the signed-in user's credentials. Stopping an impersonation still works. To allow them from Desktop and the MCP, list the tool:
<FloatingDevTools
externalSync={{ enableInRelease: true, releaseActions: ["impersonate"] }}
/>
<FloatingDevTools
externalSync={{ enableInRelease: true, releaseActions: ["impersonate"] }}
/>
Run a debug build with BuoyDevTools mounted and your account configured. Flutter's widget does not enable this connection in profile or release mode.
localhost / 10.0.2.2).BuoyDevTools(
socketUrl: 'http://192.168.1.20:42831',
child: child ?? const SizedBox.shrink(),
)
BuoyDevTools(
socketUrl: 'http://192.168.1.20:42831',
child: child ?? const SizedBox.shrink(),
)
iOS will show the Local Network permission prompt on first connect — tap Allow. After adding a new buoy_* package, do a full restart (hot reload won't pick up new registrations).
The desktop app hosts the same local broker the MCP server uses. Your app connects as a device; the dashboard connects as a "Dashboard" client and receives live state and sends actions over the external-sync protocol. Tool data travels between the device and the configured broker, including across your LAN for physical devices. Account validation and telemetry use separate services; see Telemetry.
Download Buoy Desktop for macOS, Windows, or Linux and open your app with Buoy running. The app derives the broker address from the Metro dev server that served the bundle, so simulators, emulators, and physical devices on the same Wi-Fi connect with zero config.
Buoy tools sync to a local broker on port 42831. Launch Buoy Desktop first — it starts the broker and auto-detects devices. For Android over USB, run adb reverse tcp:42831 tcp:42831 once per cable session.
Sync is off whenever __DEV__ is false, so a shipped app never dials a broker on a customer's phone. To profile a release build you own — a local Release run, an internal TestFlight/EAS build — opt in explicitly; it also requires a real Pro license. Release builds connect to localhost or over https:// unless you set allowInsecureNetwork; see Release builds.