Excited to share that swift-ros2 — the wire layer that powers the Conduit iOS app:
is now available as a standalone open-source Swift package under Apache 2.0:
Since its App Store debut in January, Conduit peaked at #4 in the Developer Tools category and has been used by over 10,000 ROS 2 developers worldwide. The feedback from that community made it clear: the real value wasn’t only the iOS app — it was the Swift-side ROS 2 wire stack underneath it. So as part of this open-source release, that stack has been extracted, hardened, extended with a full CycloneDDS transport alongside the original Zenoh one, and ported to Linux — so any Swift project, on any Apple platform or on Ubuntu, can now speak ROS 2 natively without dragging in rcl/rclcpp.
Zenoh Pub/Sub between Mac and Ubuntu using swift-ros2:
DDS Pub/Sub between Mac and Ubuntu using swift-ros2:
What it does
swift-ros2 is a pure-Swift ROS 2 client library that publishes and subscribes directly at the wire level — no bridge, no RCL, no Python, no C++ glue in your app.
- Dual transport, same API. Talk to
rmw_zenoh_cppviazenoh-pico, or tormw_cyclonedds_cppvia CycloneDDS. Swap between them with a single config change. - Multi-distro wire format. Humble, Jazzy, Kilted, Rolling — all four are covered by the built-in wire codecs.
- Pure-Swift XCDR v1 codec. Serialization is verified against golden-byte fixtures extracted from real ROS 2 traffic.
- 20 built-in message types across
sensor_msgs,geometry_msgs,std_msgs,audio_common_msgs, andtf2_msgs. Custom messages are a singleROS2Messageconformance away. - Swift-native API.
async/await,AsyncStreamsubscriptions,Sendableconformance, structured concurrency — the kind of API Swift developers actually want.
Platforms
| Platform | Integration |
|---|---|
| iOS / iPadOS 16+ | Pre-built xcframework via SPM |
| macOS 13+ | Pre-built xcframework via SPM |
| Mac Catalyst 16+ | Pre-built xcframework via SPM |
| visionOS 1.0+ | Pre-built xcframework via SPM |
| Linux (Ubuntu 22.04 / 24.04, x86_64 + aarch64) | swift build from source |
CI exercises the full matrix — Swift 6.0.2 on Ubuntu with Humble (22.04), Jazzy (24.04), and Rolling (24.04), on both x86_64 and aarch64 — plus Xcode 16.2 on Apple Silicon:
Publish in five lines
import SwiftROS2
let context = try await ROS2Context(
transport: .zenoh(locator: "tcp/192.168.1.100:7447"), // or: .ddsMulticast(domainId: 0)
distro: .jazzy
)
let node = try await context.createNode(name: "sensor_node", namespace: "/macos")
let pub = try await node.createPublisher(Imu.self, topic: "imu")
try pub.publish(Imu(header: .now(frameId: "imu_link"), linearAcceleration: .init(x: 0, y: 0, z: 9.81)))
Switching to DDS is a one-line change to the transport: argument. Subscribers use the same Node API and expose an AsyncStream of typed messages.
Runnable talker / listener demos modeled on demo_nodes_cpp ship in Sources/Examples/ and interop directly with ros2 topic echo.
Today
- Publishers and subscribers for both Zenoh and DDS transports
- XCDR v1 serialize + deserialize
- Jazzy / Humble / Kilted / Rolling wire codecs
- 20 built-in message types
- Custom message support via
ROS2Messageprotocol
Roadmap
- Services (request/reply) and Actions (goal/feedback/result)
-
swift-ros2-gen— code generator for.msg/.srv/.actionfiles, so any ROS 2 package’s interfaces can be consumed without hand-porting - Expanded message catalog —
nav_msgs,visualization_msgs, and more - Continued hardening of the DDS subscriber path and wider distro coverage
Who this is for
- iOS / macOS / visionOS developers who want to ship ROS 2 apps without a sidecar bridge
- Robotics teams looking for a lightweight Linux Swift client (agents, microservices, tooling)
- Anyone who’s wanted a Swift-native way to speak to
rmw_zenoh_cpporrmw_cyclonedds_cpp
Issues, PRs, and wire-format war stories are all welcome!