Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
154 changes: 154 additions & 0 deletions src/app/blog/iroh-language-support/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { BlogPostLayout } from '@/components/BlogPostLayout'

export const post = {
draft: false,
author: 'okdistribute',
date: '2026-06-18',
title: 'iroh language support',
description:
'Announcing Swift, Kotlin, Python, and JavaScript bindings with first-party support for iroh.',
}

export const metadata = {
title: post.title,
description: post.description,
}

export default (props) => <BlogPostLayout article={post} {...props} />

We’re excited to announce [Swift], [Kotlin], [Python], and [JavaScript] bindings with first-party support for iroh!

To get started with the bindings, follow the [getting-started guide for your language of choice].

The bindings expose **QUIC data streams**. From any device, you can quickly open a direct connection to any other device, either across the room or across the world, as long as you know its [**EndpointId**][EndpointId].

As endpoints connect, you can monitor their direct data rate: the percentage of traffic sent directly between devices instead of over [relays]. Expect a 95–99% direct connection rate, depending on your use case and where in the world you deploy. Connections are always end to end encrypted using TLS.

## Platforms supported

Iroh supports all major platforms:

- iOS
- macOS (arm64, no Intel build)
- Android
- Linux
- Windows
- FreeRTOS

For per-language details, see the [platform support matrix].

## Quick accelerometer demo

For an out-of-the-box demo, check out our [accelerometer demo].

Each peer controls one dot in a shared coordinate space. You move your dot by tilting the phone or dragging on the desktop, and you stream its position to the other peer at ~60 Hz over an iroh bi-directional stream. The peer renders your dot at the same coordinates next to its own, so both screens show the two dots tracking each other in real time.

The two peers are fully symmetric. While connected, a line under the status shows the connection's [live network paths] — direct vs. relay, remote address, and RTT — so you can watch iroh [hole-punch] its way from a relayed connection to a direct one.

![The accelerometer demo connected to a peer, showing both dots and the connection's live network paths](/blog/iroh-language-support/accelerometer-demo.gif)

## Sending streaming data

Once [two endpoints are connected], you talk over plain QUIC streams. Open a bi-directional stream with `openBi()` on the dialing side and accept it with `acceptBi()` on the other, then write bytes into one end and read them out the other. Streams are ordered, backpressured, and end-to-end encrypted, and a single connection can carry as many of them as you need. There's no broker or polling loop in the middle.

Most apps will have a similar shape in every language:

- a **send loop**
- a **receive loop**

Here's what that looks like in Swift for the accelerometer demo:

```swift
// Dial a peer anywhere in the world by its EndpointId
let addr = EndpointAddr(id: peerId, relayUrl: nil, addresses: [])
let conn = try await endpoint.connect(addr: addr, alpn: WireFormat.alpn)
let bi = try await conn.openBi() // the other side calls conn.acceptBi()

// Send loop: stream your dot's position at ~60 Hz
Task {
let send = bi.send()
while !Task.isCancelled {
let frame = WireFormat.encodePosition(x: game.myPos.x, y: game.myPos.y)
try await send.writeAll(buf: frame)
try await Task.sleep(nanoseconds: 16_666_000)
}
}

// Receive loop: read the peer's frames as they arrive
Task {
let recv = bi.recv()
while !Task.isCancelled {
let body = try await recv.readExact(size: WireFormat.positionFrameSize)
if let pos = WireFormat.decodePosition(body) {
game.receivedTheirPos(x: pos.x, y: pos.y)
}
}
}
```

## Monitor your application performance

In any of the languages, you can also diagnose application performance and see direct data rate per endpoint by connecting an [Iroh Services] [API key].

In Swift, for example, it’s one call to enable services monitoring:

```swift
Comment thread
rklaehn marked this conversation as resolved.
let client = try await ServicesClient.create(
endpoint: endpoint,
options: ServicesOptions(apiSecret: "YOUR_API_KEY", name: "my-endpoint")
)
```

The [metrics dashboard] helps you answer questions like:

- How many endpoints are online right now?
- How much of my traffic is direct vs. relayed? High relay usage can signal application code or deployment issues.
- What is my throughput over time: data sent and received, broken down by connection type (direct IPv4, direct IPv6, or relayed)?
- What version of iroh are my endpoints running?

### Diagnosing a connectivity issue

From any of the bindings, you can manually submit a network diagnostics report to iroh services:

```swift
try await client.submitNetworkDiagnostics(send: true)
```

This sends a [network diagnostics report], covering NAT type, UDP connectivity, relay latency, port mapping protocol availability, and direct addresses. Everything you need to debug connection issues.

## Future work

Right now, the bindings support creating real-time data streams between two or more devices. In the future, we’d like to also add support for popular use cases, such as [RPC], [gossip], [blobs] and [documents].

Soon we will also introduce out of the box [mDNS] and [Bluetooth] support in the FFI; right now, these are Rust-only features because the custom address-lookup and transport APIs they build on aren't 100% stable yet. Stay tuned.

You don’t have to wait, though: the stream API is already everything you need to build production-grade powerful, low-latency apps today.
Comment thread
okdistribute marked this conversation as resolved.

If you need help getting started or just want to chat, please join us on [Discord]! And to keep up with all things iroh, check out our [Twitter], [Mastodon], and [Bluesky].

[Swift]: https://docs.iroh.computer/languages/swift
[Kotlin]: https://docs.iroh.computer/languages/kotlin
[Python]: https://docs.iroh.computer/languages/python
[JavaScript]: https://docs.iroh.computer/languages/javascript
[getting-started guide for your language of choice]: https://docs.iroh.computer/languages/
[EndpointId]: https://docs.iroh.computer/concepts/endpoints
[relays]: https://docs.iroh.computer/concepts/relays
[platform support matrix]: https://docs.iroh.computer/languages#platform-support
[accelerometer demo]: https://github.com/n0-computer/hello-iroh-ffi
[live network paths]: /blog/iroh-on-QUIC-multipath
[hole-punch]: https://docs.iroh.computer/concepts/nat-traversal
[two endpoints are connected]: https://docs.iroh.computer/connect-two-endpoints
[Iroh Services]: https://services.iroh.computer
[API key]: https://docs.iroh.computer/iroh-services/quickstart
[metrics dashboard]: https://docs.iroh.computer/iroh-services/metrics
[network diagnostics report]: https://docs.iroh.computer/iroh-services/net-diagnostics/quickstart
[RPC]: https://docs.rs/irpc
[gossip]: https://docs.rs/iroh-gossip
[blobs]: https://docs.rs/iroh-blobs
[documents]: https://docs.rs/iroh-docs
[mDNS]: https://docs.rs/iroh-mdns-address-lookup
[Bluetooth]: https://github.com/mcginty/iroh-ble-transport
[Discord]: https://discord.com/invite/DpmJgtU7cW
[Twitter]: https://x.com/iroh_n0
[Mastodon]: https://mastodon.social/@n0iroh
[Bluesky]: https://bsky.app/profile/iroh.computer
Loading