# Introducing swift-ros2: a native Swift client library for ROS 2, now open source

**URL:** <https://discourse.openrobotics.org/t/introducing-swift-ros2-a-native-swift-client-library-for-ros-2-now-open-source/54205>\
**Category:** Projects\
**Tags:** ros2, ios, macos, ubuntu, swift\
**Created:** [April 21, 2026, 10:32pm UTC](https://discourse.openrobotics.org/t/introducing-swift-ros2-a-native-swift-client-library-for-ros-2-now-open-source/54205 "2026-04-21T22:32:36Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![youtalk](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/youtalk/32/31801_2.png) [@youtalk](https://discourse.openrobotics.org/u/youtalk)\
**Post date:** [April 21, 2026, 10:32pm UTC](https://discourse.openrobotics.org/t/introducing-swift-ros2-a-native-swift-client-library-for-ros-2-now-open-source/54205/1 "2026-04-21T22:32:36Z")

</div>

🚀 Excited to share that **swift-ros2** — the wire layer that powers the Conduit iOS app:

> [@The release of the Conduit iOS app—transform your Apple devices into ROS 2 sensor publishers](https://discourse.openrobotics.org/t/the-release-of-the-conduit-ios-app-transform-your-apple-devices-into-ros-2-sensor-publishers/51717):
>
> rocket Excited to announce the release of the Conduit iOS app! Transform your iPhone/iPad (and soon Mac) into a powerful sensor suite for ROS 2 robotics. After months of deep technical work on wire format compatibility and real-time performance optimization, I’m thrilled to share this tool with the robotics community. bullseye What Conduit Does: Conduit streams 12 types of high-quality sensor data from iOS devices directly to ROS 2 nodes using zenoh-pico: IMU (100Hz) - accelerometer + …

is now available as a standalone open-source Swift package under Apache 2.0:

> **[GitHub - youtalk/swift-ros2: Native Swift client library for ROS 2:...](https://github.com/youtalk/swift-ros2)**
>
> Native Swift client library for ROS 2: publish/subscribe over Zenoh or CycloneDDS without the rcl/rclcpp stack

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:

[![](https://us1.discourse-cdn.com/flex022/uploads/ros/original/3X/9/1/9146dd7339b58fcaa34380a8ee727bece7a73d48.jpeg "Zenoh Pub/Sub between Mac and Ubuntu using swift-ros2, a native Swift ROS 2 client library") ](https://www.youtube.com/watch?v=86CSrY5ECQ8)

DDS Pub/Sub between Mac and Ubuntu using swift-ros2:

[![](https://us1.discourse-cdn.com/flex022/uploads/ros/original/3X/5/5/55b8e2a200b821b3a9616379ec2c73e6d5081df4.jpeg "DDS Pub/Sub between Mac and Ubuntu using swift-ros2, a native Swift ROS 2 client library") ](https://www.youtube.com/watch?v=OcS-DxFh8LM)

## 🎯 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_cpp` via `zenoh-pico`, or to `rmw_cyclonedds_cpp` via 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`, and `tf2_msgs`. Custom messages are a single `ROS2Message` conformance away.
- **Swift-native API.** `async`/`await`, `AsyncStream` subscriptions, `Sendable` conformance, 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:

> **[CI · Workflow runs · youtalk/swift-ros2](https://github.com/youtalk/swift-ros2/actions/workflows/ci.yml)**
>
> Native Swift client library for ROS 2: publish/subscribe over Zenoh or CycloneDDS without the rcl/rclcpp stack - CI · Workflow runs · youtalk/swift-ros2

## 🧑‍💻 Publish in five lines

```swift
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 `ROS2Message` protocol

## 🛣 Roadmap

- **Services** (request/reply) and **Actions** (goal/feedback/result)
- **`swift-ros2-gen`** — code generator for `.msg` / `.srv` / `.action` files, 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_cpp` or `rmw_cyclonedds_cpp`

Issues, PRs, and wire-format war stories are all welcome!

---

<div class="post-metadata">

**Author:** ![youtalk](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/youtalk/32/31801_2.png) [@youtalk](https://discourse.openrobotics.org/u/youtalk)\
**Post date:** [April 26, 2026, 4:34am UTC](https://discourse.openrobotics.org/t/introducing-swift-ros2-a-native-swift-client-library-for-ros-2-now-open-source/54205/2 "2026-04-26T04:34:34Z")

</div>

A few notable updates have landed since the original post:

- **[Windows 10/11 (x86\_64), Zenoh only.](https://github.com/youtalk/swift-ros2/releases/tag/0.5.0)** `zenoh-pico` builds from source through SwiftPM with the Winsock + Iphlpapi backend — no `setup.bash`, no CMake bootstrap. Requires Swift 6.3.1. Targeting 0.7.0; already on `main`.
- **[Android API 28+ (arm64-v8a, x86\_64), Zenoh only.](https://github.com/youtalk/swift-ros2/releases/tag/0.6.0)** `zenoh-pico` source-builds with the Bionic unix backend, cross-compiled from macOS or Linux against the [swift.org](http://swift.org) Android Swift SDK. Shipped in 0.5.0.
- **CI now exercises every supported OS on every push.** The [`ci.yml`](https://github.com/youtalk/swift-ros2/actions/workflows/ci.yml) matrix runs `build-macos`, `build-linux` (3 distros × 2 arches), `build-windows`, and `build-android` (2 ABIs), plus an Android x86\_64 emulator job that drives the test suite end-to-end on Bionic — four CI badges in the README, one per OS family.
- **Consumer-OS coverage is now quantified.** A new [`README.md`](https://github.com/youtalk/swift-ros2#os-coverage-at-a-glance) table sourced from Statcounter (March 2026) shows swift-ros2 reaches **≈99.7%** of the mobile market (iOS + Android), **≈78.7%** of the desktop market (Windows + macOS + Linux), and **≈90.7%** across all device classes — effectively every consumer endpoint a ROS 2 graph might want to talk to.

---

<div class="post-metadata">

**Author:** ![youtalk](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/youtalk/32/31801_2.png) [@youtalk](https://discourse.openrobotics.org/u/youtalk)\
**Post date:** [May 11, 2026, 6:11pm UTC](https://discourse.openrobotics.org/t/introducing-swift-ros2-a-native-swift-client-library-for-ros-2-now-open-source/54205/3 "2026-05-11T18:11:39Z")

</div>

# swift-ros2 1.1 — Services, Actions, Parameters, IDL codegen, plus Windows & Android

Hi all — a follow-up to the original announcement from earlier this year. swift-ros2 has shipped 0.5 through 1.1 since then, and the surface area has grown enough that it felt worth a recap rather than burying it in the release notes.

Quick reminder of what swift-ros2 is: a pure-Swift ROS 2 client library that talks to `rmw_zenoh_cpp` and `rmw_cyclonedds_cpp` at the wire level — no `rcl`, no `rclcpp`, no Python/colcon. Repo: [github.com/youtalk/swift-ros2](https://github.com/youtalk/swift-ros2). Apache 2.0.

## What’s new

### Services — full Server + Client API

`rclcpp` / `rclpy`-shaped `ROS2Service<S>` / `ROS2Client<S>` with `async`/`await`, working across Humble / Jazzy / Kilted / Rolling on both Zenoh and DDS.

```swift
// Server
let svc = try await node.createService(AddTwoInts.self, name: "/add_two_ints") { req in
    AddTwoInts.Response(sum: req.a + req.b)
}

// Client
let cli = try await node.createClient(AddTwoInts.self, name: "/add_two_ints")
try await cli.waitForService(timeout: .seconds(2))
let resp = try await cli.call(.init(a: 2, b: 3), timeout: .seconds(5))

```

### Actions — full Server + Client API

Typed `ROS2ActionServer<H>` / `ROS2ActionClient<A>` with goal handles, feedback as `AsyncStream`, status, and cancellation. Built-in `example_interfaces/action/Fibonacci`. No callback shims.

```swift
let client = try await node.createActionClient(FibonacciAction.self, name: "/fibonacci")
try await client.waitForActionServer(timeout: .seconds(5))

let handle = try await client.sendGoal(.init(order: 10))

Task {
    for await fb in handle.feedback {
        print("partial: \(fb.sequence)")
    }
}

switch try await handle.result() {
case .succeeded(let r): print("got \(r.sequence)")
case .canceled: print("canceled")
case .aborted(let r): print("aborted: \(r ?? "nil")")
}

```

### Parameters — node-side storage + remote client

Every `ROS2Node` declares/gets/sets parameters, exposes the six standard parameter services, emits `/parameter_events`, and supports on/pre/post-set callbacks. `ros2 param list / get / set` from the CLI round-trips with a swift-ros2 node.

```swift
// Declare with a default and a descriptor (range / read-only / etc.)
try await node.declareParameter("max_velocity", default: 1.5)

// Read it back from anywhere in the app
let v: Double = await node.getParameterOrDefault("max_velocity", default: 0.0)

// Reject changes to "frozen" from any source — CLI, remote client, or local set
node.addOnSetParameterCallback { params in
    .init(successful: params.allSatisfy { $0.name != "frozen" })
}

```

### `swift-ros2-gen` — IDL → Swift code generation

A CLI plus SwiftPM build plugin that emit `ROS2Message` / `ROS2ServiceType` / `ROS2Action` conformances directly from `.msg` / `.srv` / `.action`. Multi-distro merging: when the same package’s IDL differs across distros (e.g. `sensor_msgs/Range.variance` arriving in Jazzy), one generated Swift file branches on `isLegacySchema`. Hash-oracle CI cross-checks every generated type hash against a live ROS 2 environment, so wire drift is a build failure, not a runtime mystery.

### 1.0.0 — API freeze

1.0 inaugurated the SemVer 1.x line. The public surface (`ROS2Context`, `ROS2Node`, `ROS2Publisher`, `ROS2Subscription`, `ROS2Service`, `ROS2Client`, `ROS2ActionServer`, `ROS2ActionClient`, `QoSProfile`, `TransportConfig`, the concrete `ZenohClient` / `DDSClient`, every `ROS2Message`/`ROS2ServiceType`/`ROS2Action`) won’t break on any 1.x minor or patch. Internal plumbing was pulled out of the public namespace at the cut — there’s a `MIGRATION.md` covering every rename.

---

<div class="post-metadata">

**Author:** ![youtalk](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/youtalk/32/31801_2.png) [@youtalk](https://discourse.openrobotics.org/u/youtalk)\
**Post date:** [October 19, 2026, 3:55pm UTC](https://discourse.openrobotics.org/t/introducing-swift-ros2-a-native-swift-client-library-for-ros-2-now-open-source/54205/4 "2026-10-19T15:55:22Z")

</div>

swift-ros2 3.0 is out: three packages in the new swift-ros2 org, generated common\_interfaces, and services/actions verified against rmw\_zenoh and rmw\_cyclonedds. Details:

> [@Swift-ros2 3.0: native Swift ROS 2 client library, now with generated common\_interfaces and its own org](https://discourse.openrobotics.org/t/swift-ros2-3-0-native-swift-ros-2-client-library-now-with-generated-common-interfaces-and-its-own-org/58955):
>
> swift-ros2 3.0.0 is out. It is the first stable 3.x release of the native Swift client library for ROS 2 that I [introduced here in April](https://discourse.openrobotics.org/t/introducing-swift-ros2-a-native-swift-client-library-for-ros-2-now-open-source/54205). swift-ros2 lets a Swift app join a ROS 2 graph directly, over Zenoh (round-trip compatible with rmw\_zenoh\_cpp) or DDS (rmw\_cyclonedds\_cpp). There is no bridge and no rcl cross-compile. [demo] What’s new in 3.0 Three packages, mirroring upstream ROS 2. The project moved to the [swift-ros2](https://github.com/swift-ros2) GitHub organization: Package What it holds [swift-ros2-rosidl](https://github.com/swift-ros2/swift-ros2-rosidl) 1…
