foxglove
The remote/web visualization tool for robium: foxglove_bridge exposes a
live ROS 2 graph over a WebSocket, and the Foxglove app (desktop or
app.foxglove.dev in a browser) connects to it or opens a recorded MCAP
file — the answer environments and gazebo route to whenever a robot or
sim runs headless/remote and RViz2's local-display requirement doesn't fit.
Two things changed over time and matter for how this skill is used: the
bridge itself (foxglove_bridge, MIT-licensed, open source) moved its
active development from foxglove/ros-foxglove-bridge (now ROS 1-only,
maintenance mode) to the foxglove/foxglove-sdk monorepo, and the app
that used to be free/open-source "Foxglove Studio" was discontinued in
February 2024 (last open-source release v1.87.0, MPL-2.0) in favor of the
current closed-source, commercial "Foxglove" 2.x app — which does still
ship a free tier the product page states is "free forever" for local/live
visualization, separate from its paid Data Platform/cloud features. The
bridge migration was confirmed via direct fetch of the
foxglove/ros-foxglove-bridge and foxglove/foxglove-sdk GitHub repos this
session; the free-tier claim was confirmed via direct fetch of
foxglove.dev's pricing page, while the Studio-to-2.x licensing history was
reconstructed via search-synthesis after the source blog post 404'd on
direct fetch (see References) — re-verify before repeating either claim,
since licensing terms are exactly the kind of thing that drifts.
When to use this skill
- Setting up
foxglove_bridge on a robot or sim host, building a layout,
recording or replaying an MCAP file, or viewing a robot's data from a
machine that isn't the robot itself.
- The trigger phrases in the description: 'foxglove', 'mcap', visualizing a
robot running on a remote server, sharing visualization with others,
recording sessions for later analysis.
- Any time
environments or gazebo has already concluded the target is
headless/remote and the next question is "how do I actually see it" —
this skill is that answer.
- Cross-references — go to the sibling skill instead when the question is:
- Whether headless/remote is the deployment target at all, GPU
passthrough, or the general local-vs-remote strategy →
environments
(load first if not already decided; this skill assumes that decision is
made and just delivers the viz half of it).
- Local desktop ROS debugging with a display attached →
rviz2.
- ML/data-centric logging outside ROS message types (policy rollouts,
LeRobot episodes) →
rerun.
- Choosing which viz tool fits the situation at all →
visualization
(routes here once Foxglove is the right choice).
Key directives
- Delegation posture: embed + links. The core mechanics this skill
exists for — bridging a robot, recording MCAP, connecting the app
remotely — are embedded here because that's the whole reason
environments and gazebo point at this skill by name; anything beyond
that (panel-by-panel layout editing, the full MCAP CLI, Data Platform
cloud features) is a link out to Foxglove's own docs, not re-typed here.
- The bridge runs on the robot/server; the app runs wherever the viewer
is. These are two different machines in the remote case, and mixing them
up is the most common setup mistake —
foxglove_bridge is a ROS 2 node
that must be launched on the robot or sim host (it needs access to the
ROS graph), while the Foxglove app connects to it from wherever a human
is looking, local or remote. See Quick start and Usage patterns.
- Never re-teach the local-vs-remote/headless decision itself. That
decision — and the general "don't default to X11 forwarding" guidance —
belongs to
environments; this skill starts from "remote/headless is
already the answer" and only covers the Foxglove-specific mechanics of
acting on it.
- Don't expose the bridge's WebSocket port to the open internet.
foxglove_bridge has no built-in authentication — reach it over a VPN,
SSH tunnel, or private network, the same way any other unauthenticated
service on a robot would be secured, not by opening the port publicly.
See Platform gotchas.
- Never write foxglove_bridge's supported-distro list or the app's
licensing/pricing terms from memory. Both have changed — the bridge's
home repo moved, and the app went from open-source to a closed-source
product with a free tier — verify against
index.ros.org's
foxglove_bridge package page and foxglove.dev's own site before
repeating either claim in a real project.
Quick start
1. Install and launch the bridge on the robot/sim host (verified via
index.ros.org's foxglove_bridge package page this session: v3.4.2, MIT
license, released for Humble, Jazzy, Kilted, Lyrical, and Rolling — no
distro gap the way Nav2 has):
sudo apt install ros-$ROS_DISTRO-foxglove-bridge
ros2 launch foxglove_bridge foxglove_bridge_launch.xml
This starts a WebSocket server on port 8765 (default) that auto-discovers
and exposes every topic currently on the ROS graph.
2. Connect the Foxglove app. Open the desktop app or
app.foxglove.dev in a browser, and add a connection:
ws://localhost:8765 if the app runs on the same machine as the bridge, or
ws://<ROBOT_IP>:8765 over a VPN/tunnel for a remote view (see Platform
gotchas — don't expose this port directly to the internet).
3. Save a layout once panels are arranged the way a given task needs
(3D view + a couple of plots + raw topic panels is a common start), so the
next session reopens the same view instead of rebuilding it.
Usage patterns
Bridge a live robot. Launch foxglove_bridge on the robot/server as in
Quick start, then connect from the app. All ROS 2 topics are exposed
automatically — no per-topic bridge configuration needed for the common
case; the bridge's own parameters (address, port, topic allow/deny lists)
are set as ROS 2 launch arguments if the defaults need narrowing (e.g.
excluding a high-bandwidth topic from remote viewing).
Record MCAP. MCAP is ROS 2's default bag storage format as of recent
distros, so the standard ros2 bag record path already writes it:
ros2 bag record -a -s mcap -o my_session
(-a records all topics; scope to specific topic names instead for a
large graph.) The resulting .mcap file opens directly in the Foxglove
app — drag it onto the window, or File > Open Local File — for offline
playback and scrubbing, no bridge or live robot needed. This is the
recording path the visualization umbrella's live-vs-recorded directive
points at for ROS 2 data.
Drive Nav2 from the app (publish goals). The 3D panel's Publish tool
can send PoseStamped goals straight into a running Nav2 stack, but its
Pose-topic default is the ROS 1-era /move_base_simple/goal — clicking a
goal publishes into the void with no error (Nav2 subscribes /goal_pose).
In the 3D panel settings → Publish, set Pose topic to /goal_pose; the
Pose-estimate default /initialpose is already right for AMCL. Verified
end-to-end 2026-07-11 (nav-trial: click-to-navigate against Jazzy Nav2
through foxglove_bridge). Note topics only stream when some panel displays
them — a topic missing from the 3D view usually just isn't toggled visible
in the panel's Topics list (latched topics like /map arrive on subscribe;
transient-local durability is handled by the bridge).
Ship a preconfigured layout with the app. Layouts export/import as
JSON files (Layout menu → Export/Import from file), so an app repo can
commit one that pre-sets the display frame, topic visibility, and the
Publish-tool topics — one import and the robot is drivable by click,
account-persistent thereafter. Verified 2026-07-11 (nav-trial:
apps/nav-trial/foxglove/nav-trial-layout.json in robium-applications is a
working sample, incl. publish: {poseTopic: "/goal_pose"}).
View remotely in the web app. Point app.foxglove.dev (no desktop
install needed) at ws://<ROBOT_IP>:8765 over a VPN/SSH tunnel/tailnet —
this is the answer environments' headless-first guidance and gazebo's
headless-operation section both defer to: a teammate or a CI dashboard can
watch a robot or sim running on a server with no display attached, using
only a browser. The same connection works for a temporary SSH port-forward
(ssh -L 8765:localhost:8765 robot-host) if a persistent VPN isn't set up
for a one-off debugging session.
Platform gotchas
- No built-in auth on the bridge's WebSocket. Treat
8765 like any
other unauthenticated robot service — reachable only over a VPN, SSH
tunnel, or private network, never bound to a public interface.
- The desktop app and the web app (
app.foxglove.dev) are the same
product, different delivery — either works for the same
live-bridge-or-MCAP-file workflow; the web app needs nothing installed
and is the lower-friction choice for a teammate who just needs to look
once.
- The bridge itself is open source (MIT); the app is not. Don't assume
Foxglove's viewer code is inspectable/forkable the way it was under the
old "Foxglove Studio" — that ended February 2024. The bridge running on
the robot is unaffected by this; only the client app's license changed.
- Safari can't open
ws://localhost from the https web app. The
mixed-content block yields a generic "check that the WebSocket server is
reachable" even when the bridge is healthy — use Chrome (which exempts
localhost), the desktop app, or Lichtblick. Verified 2026-07-11
(nav-trial).
- "Bridge unreachable" usually isn't the bridge. Before debugging
foxglove_bridge, check the container runtime/host is actually up (a
stopped Docker Desktop presents as a closed socket in the app) and that
the port is reachable (
nc -z <host> 8765) — the bridge has no failure
mode that looks like a silently closed listener while its process runs.
- A high topic/message rate can saturate a remote link. Over a slow or
high-latency connection (a robot on cellular, a distant VPN hop), narrow
the bridge to the topics actually needed for the session (bridge launch
arguments, or a scoped
ros2 bag record topic list) rather than
streaming the full graph and fighting lag in the viewer.
Customization
- Different topic scope per session: override
foxglove_bridge's
launch arguments (e.g. an allow-list) when a remote link can't carry the
full graph, rather than always bridging everything and filtering in the
app — filtering upstream saves bandwidth, filtering in the app only saves
screen space.
- Self-hosted vs.
app.foxglove.dev: the web app is a hosted client
pointed at whatever WebSocket URL is given to it — no project files here
assume the hosted URL specifically; swap in a self-managed deployment if
that's the team's policy, the connection mechanics (ws:// URL, VPN/
tunnel) are unchanged either way.
- Layouts per task: keep a saved layout per debugging task (nav
debugging vs. sensor calibration vs. a demo view) the same way
rviz2
keeps a config per task, rather than one layout trying to cover every
use case.
References
- Upstream: Foxglove documentation
(primary source for app/bridge usage), foxglove_bridge package page,
index.ros.org (fetched
directly this session — source of the distro-coverage and
version/license facts above; re-check before a new install), foxglove/
foxglove-sdk (current home of
bridge development; fetched directly this session), foxglove/
ros-foxglove-bridge
(older repo, now ROS 1-only/maintenance — fetched directly this session,
confirms the move), Foxglove pricing
page and "Foxglove vs. Foxglove Studio:
Two Years On"
(source of the open-source-to-closed-source history above — the pricing
page was fetched directly this session; the Studio-transition history was
confirmed via search-synthesis of Foxglove's own blog posts and should be
re-verified by reading that post directly before repeating the exact
dates in a real project), MCAP format (fetched
directly this session). Sibling skills:
environments (headless/remote
decision this skill assumes is already made), rviz2 (local desktop
debugging), rerun (ML/data-centric logging), visualization (umbrella,
routes here).
Changelog
- 1.1.0 (2026-07-11): nav-trial absorption — new usage patterns: publishing
Nav2 goals from the app (ROS1-default
/move_base_simple/goal →
/goal_pose fix) and committing a layout JSON per app repo; gotchas:
Safari ws://localhost mixed-content block, "unreachable ≠ broken, check
the container runtime". Quick-start bridge flow confirmed ✓ under real
load (browser + headless arm64 container).
1---2name: foxglove-33description: Foxglove for robotics visualization: foxglove_bridge setup for live ROS 2 robots, layouts, MCAP recording and playback, and remote/web visualization of robots running on servers. Use when: 'foxglove', 'mcap', visualizing a robot running on a remote server, sharing visualization with others, or recording sessions for later analysis. The remote-viz answer in the robium stack — key to the local-vs-remote workflow (cross-ref environments). Not for: ROS desktop debugging (rviz2) or ML logging (rerun).4---56# foxglove78The remote/web visualization tool for robium: `foxglove_bridge` exposes a9live ROS 2 graph over a WebSocket, and the Foxglove app (desktop or10`app.foxglove.dev` in a browser) connects to it or opens a recorded MCAP11file — the answer `environments` and `gazebo` route to whenever a robot or12sim runs headless/remote and RViz2's local-display requirement doesn't fit.13Two things changed over time and matter for how this skill is used: the14bridge itself (`foxglove_bridge`, MIT-licensed, open source) moved its15active development from `foxglove/ros-foxglove-bridge` (now ROS 1-only,16maintenance mode) to the `foxglove/foxglove-sdk` monorepo, and the *app*17that used to be free/open-source "Foxglove Studio" was discontinued in18February 2024 (last open-source release v1.87.0, MPL-2.0) in favor of the19current closed-source, commercial "Foxglove" 2.x app — which does still20ship a free tier the product page states is "free forever" for local/live21visualization, separate from its paid Data Platform/cloud features. The22bridge migration was confirmed via direct fetch of the23`foxglove/ros-foxglove-bridge` and `foxglove/foxglove-sdk` GitHub repos this24session; the free-tier claim was confirmed via direct fetch of25`foxglove.dev`'s pricing page, while the Studio-to-2.x licensing history was26reconstructed via search-synthesis after the source blog post 404'd on27direct fetch (see References) — re-verify before repeating either claim,28since licensing terms are exactly the kind of thing that drifts.2930## When to use this skill3132- Setting up `foxglove_bridge` on a robot or sim host, building a layout,33 recording or replaying an MCAP file, or viewing a robot's data from a34 machine that isn't the robot itself.35- The trigger phrases in the description: 'foxglove', 'mcap', visualizing a36 robot running on a remote server, sharing visualization with others,37 recording sessions for later analysis.38- Any time `environments` or `gazebo` has already concluded the target is39 headless/remote and the next question is "how do I actually see it" —40 this skill is that answer.41- Cross-references — go to the sibling skill instead when the question is:42 - Whether headless/remote is the deployment target at all, GPU43 passthrough, or the general local-vs-remote strategy → `environments`44 (load first if not already decided; this skill assumes that decision is45 made and just delivers the viz half of it).46 - Local desktop ROS debugging with a display attached → `rviz2`.47 - ML/data-centric logging outside ROS message types (policy rollouts,48 LeRobot episodes) → `rerun`.49 - Choosing which viz tool fits the situation at all → `visualization`50 (routes here once Foxglove is the right choice).5152## Key directives5354- **Delegation posture: embed + links.** The core mechanics this skill55 exists for — bridging a robot, recording MCAP, connecting the app56 remotely — are embedded here because that's the whole reason57 `environments` and `gazebo` point at this skill by name; anything beyond58 that (panel-by-panel layout editing, the full MCAP CLI, Data Platform59 cloud features) is a link out to Foxglove's own docs, not re-typed here.60- **The bridge runs on the robot/server; the app runs wherever the viewer61 is.** These are two different machines in the remote case, and mixing them62 up is the most common setup mistake — `foxglove_bridge` is a ROS 2 node63 that must be launched *on* the robot or sim host (it needs access to the64 ROS graph), while the Foxglove app connects to it *from* wherever a human65 is looking, local or remote. See Quick start and Usage patterns.66- **Never re-teach the local-vs-remote/headless decision itself.** That67 decision — and the general "don't default to X11 forwarding" guidance —68 belongs to `environments`; this skill starts from "remote/headless is69 already the answer" and only covers the Foxglove-specific mechanics of70 acting on it.71- **Don't expose the bridge's WebSocket port to the open internet.**72 `foxglove_bridge` has no built-in authentication — reach it over a VPN,73 SSH tunnel, or private network, the same way any other unauthenticated74 service on a robot would be secured, not by opening the port publicly.75 See Platform gotchas.76- **Never write foxglove_bridge's supported-distro list or the app's77 licensing/pricing terms from memory.** Both have changed — the bridge's78 home repo moved, and the app went from open-source to a closed-source79 product with a free tier — verify against `index.ros.org`'s80 `foxglove_bridge` package page and `foxglove.dev`'s own site before81 repeating either claim in a real project.8283## Quick start8485**1. Install and launch the bridge on the robot/sim host** (verified via86`index.ros.org`'s `foxglove_bridge` package page this session: v3.4.2, MIT87license, released for Humble, Jazzy, Kilted, **Lyrical**, and Rolling — no88distro gap the way Nav2 has):8990```bash91sudo apt install ros-$ROS_DISTRO-foxglove-bridge92ros2 launch foxglove_bridge foxglove_bridge_launch.xml93```9495This starts a WebSocket server on port `8765` (default) that auto-discovers96and exposes every topic currently on the ROS graph.9798**2. Connect the Foxglove app.** Open the desktop app or99`app.foxglove.dev` in a browser, and add a connection:100`ws://localhost:8765` if the app runs on the same machine as the bridge, or101`ws://<ROBOT_IP>:8765` over a VPN/tunnel for a remote view (see Platform102gotchas — don't expose this port directly to the internet).103104**3. Save a layout** once panels are arranged the way a given task needs105(3D view + a couple of plots + raw topic panels is a common start), so the106next session reopens the same view instead of rebuilding it.107108## Usage patterns109110**Bridge a live robot.** Launch `foxglove_bridge` on the robot/server as in111Quick start, then connect from the app. All ROS 2 topics are exposed112automatically — no per-topic bridge configuration needed for the common113case; the bridge's own parameters (address, port, topic allow/deny lists)114are set as ROS 2 launch arguments if the defaults need narrowing (e.g.115excluding a high-bandwidth topic from remote viewing).116117**Record MCAP.** MCAP is ROS 2's default bag storage format as of recent118distros, so the standard `ros2 bag record` path already writes it:119120```bash121ros2 bag record -a -s mcap -o my_session122```123124(`-a` records all topics; scope to specific topic names instead for a125large graph.) The resulting `.mcap` file opens directly in the Foxglove126app — drag it onto the window, or `File > Open Local File` — for offline127playback and scrubbing, no bridge or live robot needed. This is the128recording path the `visualization` umbrella's live-vs-recorded directive129points at for ROS 2 data.130131**Drive Nav2 from the app (publish goals).** The 3D panel's Publish tool132can send `PoseStamped` goals straight into a running Nav2 stack, but its133Pose-topic default is the ROS 1-era `/move_base_simple/goal` — clicking a134goal publishes into the void with no error (Nav2 subscribes `/goal_pose`).135In the 3D panel settings → Publish, set Pose topic to `/goal_pose`; the136Pose-estimate default `/initialpose` is already right for AMCL. Verified137end-to-end 2026-07-11 (nav-trial: click-to-navigate against Jazzy Nav2138through foxglove_bridge). Note topics only stream when some panel displays139them — a topic missing from the 3D view usually just isn't toggled visible140in the panel's Topics list (latched topics like `/map` arrive on subscribe;141transient-local durability is handled by the bridge).142143**Ship a preconfigured layout with the app.** Layouts export/import as144JSON files (Layout menu → Export/Import from file), so an app repo can145commit one that pre-sets the display frame, topic visibility, and the146Publish-tool topics — one import and the robot is drivable by click,147account-persistent thereafter. Verified 2026-07-11 (nav-trial:148`apps/nav-trial/foxglove/nav-trial-layout.json` in robium-applications is a149working sample, incl. `publish: {poseTopic: "/goal_pose"}`).150151**View remotely in the web app.** Point `app.foxglove.dev` (no desktop152install needed) at `ws://<ROBOT_IP>:8765` over a VPN/SSH tunnel/tailnet —153this is the answer `environments`' headless-first guidance and `gazebo`'s154headless-operation section both defer to: a teammate or a CI dashboard can155watch a robot or sim running on a server with no display attached, using156only a browser. The same connection works for a temporary SSH port-forward157(`ssh -L 8765:localhost:8765 robot-host`) if a persistent VPN isn't set up158for a one-off debugging session.159160## Platform gotchas161162- **No built-in auth on the bridge's WebSocket.** Treat `8765` like any163 other unauthenticated robot service — reachable only over a VPN, SSH164 tunnel, or private network, never bound to a public interface.165- **The desktop app and the web app (`app.foxglove.dev`) are the same166 product, different delivery** — either works for the same167 live-bridge-or-MCAP-file workflow; the web app needs nothing installed168 and is the lower-friction choice for a teammate who just needs to look169 once.170- **The bridge itself is open source (MIT); the app is not.** Don't assume171 Foxglove's viewer code is inspectable/forkable the way it was under the172 old "Foxglove Studio" — that ended February 2024. The bridge running on173 the robot is unaffected by this; only the client app's license changed.174- **Safari can't open `ws://localhost` from the https web app.** The175 mixed-content block yields a generic "check that the WebSocket server is176 reachable" even when the bridge is healthy — use Chrome (which exempts177 localhost), the desktop app, or Lichtblick. Verified 2026-07-11178 (nav-trial).179- **"Bridge unreachable" usually isn't the bridge.** Before debugging180 foxglove_bridge, check the container runtime/host is actually up (a181 stopped Docker Desktop presents as a closed socket in the app) and that182 the port is reachable (`nc -z <host> 8765`) — the bridge has no failure183 mode that looks like a silently closed listener while its process runs.184- **A high topic/message rate can saturate a remote link.** Over a slow or185 high-latency connection (a robot on cellular, a distant VPN hop), narrow186 the bridge to the topics actually needed for the session (bridge launch187 arguments, or a scoped `ros2 bag record` topic list) rather than188 streaming the full graph and fighting lag in the viewer.189190## Customization191192- **Different topic scope per session:** override `foxglove_bridge`'s193 launch arguments (e.g. an allow-list) when a remote link can't carry the194 full graph, rather than always bridging everything and filtering in the195 app — filtering upstream saves bandwidth, filtering in the app only saves196 screen space.197- **Self-hosted vs. `app.foxglove.dev`:** the web app is a hosted client198 pointed at whatever WebSocket URL is given to it — no project files here199 assume the hosted URL specifically; swap in a self-managed deployment if200 that's the team's policy, the connection mechanics (`ws://` URL, VPN/201 tunnel) are unchanged either way.202- **Layouts per task:** keep a saved layout per debugging task (nav203 debugging vs. sensor calibration vs. a demo view) the same way `rviz2`204 keeps a config per task, rather than one layout trying to cover every205 use case.206207## References208209- Upstream: [Foxglove documentation](https://docs.foxglove.dev/docs)210 (primary source for app/bridge usage), [foxglove_bridge package page,211 index.ros.org](https://index.ros.org/p/foxglove_bridge/) (fetched212 directly this session — source of the distro-coverage and213 version/license facts above; re-check before a new install), [foxglove/214 foxglove-sdk](https://github.com/foxglove/foxglove-sdk) (current home of215 bridge development; fetched directly this session), [foxglove/216 ros-foxglove-bridge](https://github.com/foxglove/ros-foxglove-bridge)217 (older repo, now ROS 1-only/maintenance — fetched directly this session,218 confirms the move), [Foxglove pricing219 page](https://foxglove.dev/pricing) and ["Foxglove vs. Foxglove Studio:220 Two Years On"](https://foxglove.dev/blog/foxglove-vs-foxglove-studio-two-years-on)221 (source of the open-source-to-closed-source history above — the pricing222 page was fetched directly this session; the Studio-transition history was223 confirmed via search-synthesis of Foxglove's own blog posts and should be224 re-verified by reading that post directly before repeating the exact225 dates in a real project), [MCAP format](https://mcap.dev/) (fetched226 directly this session). Sibling skills: `environments` (headless/remote227 decision this skill assumes is already made), `rviz2` (local desktop228 debugging), `rerun` (ML/data-centric logging), `visualization` (umbrella,229 routes here).230231## Changelog232233<!-- One dated line per battle-tested change, added by skill-author hardening sessions. -->234235- 1.1.0 (2026-07-11): nav-trial absorption — new usage patterns: publishing236 Nav2 goals from the app (ROS1-default `/move_base_simple/goal` →237 `/goal_pose` fix) and committing a layout JSON per app repo; gotchas:238 Safari ws://localhost mixed-content block, "unreachable ≠ broken, check239 the container runtime". Quick-start bridge flow confirmed ✓ under real240 load (browser + headless arm64 container).