OpenDisplay:免费开源的 Mac iPhone/iPad 副显示器方案
英文标题:🔥 peetzweg/opendisplay
OpenDisplay 是一款免费、开源且无需订阅的 Sidecar、Duet Display 和 Luna Display 替代方案,可通过 USB 或 WiFi 将 iPhone、iPad 甚至闲置 Mac 作为 Mac 的真正扩展显示器。项目支持 Retina/HiDPI、触控与滚动输入、横竖屏切换,并通过硬件 H.264 编解码、TCP_NODELAY 和帧丢弃恢复机制降低延迟。其采用自托管直连架构,屏幕内容不会经过第三方服务器;通信协议已公开,开发者可据此实现 Android 接收端、Linux 发送端等客户端。Mac 发送端需要 macOS 14+,iPhone/iPad 官方接收端支持 iOS/iPadOS 16.4+,而作为显示器的旧 Mac 接收端可运行在 macOS 12+。
19.2 KB
16.1 KB
12.1 KB
中文
将闲置的 Apple 设备变成 Mac 的第二台显示器——免费、开源、无需订阅。
iPhone、iPad 和闲置 Mac 均可使用。这是一款 Apple Sidecar、Duet Display 和 Luna Display 的自托管替代方案:提供真正的扩展显示(而非仅镜像),支持 Retina 清晰度、USB 或 WiFi 连接,以及触控和滚动输入。
网站 · 快速开始 · 工作原理 · 常见问题 · 参与贡献
将 iPhone 或 iPad 变成 Mac 外接显示器并非新问题——但现有的每一种方案都有缺憾:
- Apple Sidecar 虽然免费,但要求两台设备使用_同一个 Apple ID_,完全不支持 iPhone,并且仅适用于受支持的硬件组合。
- Duet Display 已转为订阅制。
- Luna Display 需要硬件加密狗。
OpenDisplay 填补了这一空白:它是一种免费、开源、无需账户、无需加密狗的方式,可将你已有的 iOS 设备用作真正的第二块显示器。如果你正准备自己实现一个——不如别从头开始,来这里参与贡献;关键难题(虚拟显示器创建、低延迟 H.264 管线、USB 传输、输入注入)均已实现。
- 🖥️ 真正的显示器扩展——macOS 会将该设备视为真实的第二台显示器(可将窗口拖到上面,也可在系统设置中排列),而不是镜像显示器。也提供镜像模式。
- 🔌 USB 有线连接,获得最低延迟——通过 macOS 内置的
usbmuxd经 Lightning/USB-C 线缆传输;插上即可使用,无需网络、没有 WiFi 抖动、无需辅助工具。 - 📶 零配置 WiFi——iPhone 通过 Bonjour 广播自身;在 Mac 的下拉菜单中选择即可。
- 🔍 Retina / HiDPI——虚拟显示器与设备面板逐像素匹配(@2x),因此文字清晰锐利。
- 👆 内置触控输入——你的 iPhone 将成为 macOS 的触摸屏:轻点即点击、拖动即拖拽,以及如同触控板般自然的双指滚动。(Apple Pencil 支持已列入路线图。)
- 🔄 纵向或横向显示——旋转设备后,虚拟显示器会以原生分辨率重建为竖屏显示器。
- ⚡ 低延迟管线——硬件 H.264 编码(VideoToolbox、实时模式、无 B 帧)、TCP_NODELAY、带关键帧恢复的帧丢弃背压,以及通过
AVSampleBufferDisplayLayer解码和渲染。 - 💻 使用闲置 Mac 作为显示器——在旧 Mac 上安装小巧的_OpenDisplay Receiver_应用(macOS 12+),任意其他 Mac 即可通过 WiFi 或 Thunderbolt/以太网线缆将显示器扩展到它,且支持原生 Retina 分辨率。
- 🔒 自托管与隐私保护——你的屏幕内容绝不会经过任何人的服务器。两个小型应用、一条 TCP 连接,仅此而已。
| OpenDisplay | Apple Sidecar | Duet Display | Luna Display
---|---|---|---|---
价格 | 免费、开源 | 免费 | 订阅制 | $$$ + 加密狗
iPhone 作为显示器 | ✅ | ❌(仅 iPad) | ✅ | ✅
支持不同 Apple ID | ✅ | ❌ | ✅ | ✅
有线(USB) | ✅ | ✅ | ✅ | ❌
真正的扩展显示 | ✅ | ✅ | ✅ | ✅
触控输入 | ✅ | ✅ | ✅ | ✅
自托管 / 可审计 | ✅ | — | ❌ | ❌
为什么菜单栏中会出现紫色的屏幕录制指示器? 这是 macOS 为_所有_捕获屏幕的应用显示的隐私指示器——Duet、Luna、OBS 和 Zoom 同样会触发它。Apple Sidecar 不会触发,仅仅是因为它在操作系统内部实现,而非使用公开的捕获 API。应用无法(也不应该)隐藏它;这是 macOS 告知你正在进行屏幕捕获的方式。
Mac 应用没有在 Connection 菜单中显示我的 iPhone(WiFi)。 两端都需要授予本地网络权限,且如果没有该权限,两端都会_静默失败_:请在 Mac 和 iPhone 上检查“隐私与安全性 → 本地网络”,确保两台设备连接至同一个 WiFi 网络,并让 iPhone 应用保持在前台打开状态。USB 模式不受影响。
我需要什么 USB 线缆或版本? 你的线缆必须支持数据传输——仅充电 USB 线缆无法使用。请选择标有_数据_、_同步_或_充电及数据传输_的线缆。支持数据的 USB 2.0 线缆已足够;不需要 USB 3、Thunderbolt 或视频 Alt Mode。OpenDisplay 通过 macOS 内置的 usbmuxd,在 TCP 连接上流式传输 H.264,并非作为 USB 视频设备工作。其最高质量预设使用 18 Mb/s,远低于 USB 2.0 480 Mb/s 的高速链路速率,因此 USB 2.0 的带宽完全足以承载该视频流。USB 1.x 不受支持,也未经测试。为获得最佳可靠性,请使用已知可用的数据/同步线缆,解锁设备,如出现提示则接受信任此电脑,并避免使用不可靠的集线器或适配器。
支持 iPad 吗? 接收端应用是通用应用(iPhone + iPad);iPad 使用相同代码库。iPad 专属优化(Pencil、压感)已列入路线图。
另一台 Mac 能作为显示器吗? 可以。在闲置 Mac 上安装 OpenDisplay Receiver(同一发行版中独立且小巧的应用)。它只需要 macOS 12 Monterey 或更高版本,因此大约 2015 年以后的 Mac 都符合要求,尽管发送端 Mac 需要 macOS 14。接收端会像手机一样出现在发送端 Mac 中,并成为真正的 Retina 扩展显示器。通过 WiFi 可直接使用。如需使用线缆,可通过 Thunderbolt 或 USB4 线缆连接两台 Mac(macOS 会在它们之间创建_Thunderbolt Bridge_网络)、使用以太网线缆或适配器,或者——在两台 Mac 都运行较新 macOS 的情况下——使用普通的 USB-C 数据线(macOS 会在其上运行小型网络链路;请在每台 Mac 上批准_允许配件连接_提示,该提示是否出现取决于哪台 Mac 插接到另一台)。发送端会自动将会话切换到线缆上,即使线缆是在会话中途接入;设备行会显示_Cable_。带有 Mini DisplayPort 外形 Thunderbolt 1 或 2 接口的旧 Mac,可使用 Thunderbolt 3 转 2 适配器和 Thunderbolt 2 线缆。接收 Mac 键盘和鼠标的输入支持仍是后续事项(#147)。
为什么使用 H.264,而不是 HEVC/AV1? 硬件 H.264 编码/解码在所有设备上都很快,且延迟表现出色。计划将 HEVC 作为选项,以获得更佳的每比特质量。
我的屏幕内容会被发送到任何地方吗? 不会。仅在你的 Mac 与设备之间建立一条直接 TCP 连接,经由线缆或局域网传输。没有服务器、没有账户、没有分析追踪。完整细节——包括应用在本地存储的内容及当前 WiFi 加密注意事项——请参见隐私页面。
许可证是什么?我可以 fork 或商用吗? GPL-3.0。你可以自由使用、研究和修改它——也可用于商业用途。如果你分发修改后的版本,它必须以相同许可证保持开源,并保留原始署名,从而让改进回流而非流入封闭分支。(截至 v0.4.x 的发行版采用 MIT 许可证,并仍可按该条款使用。)
macOS 更新后会失效吗? 有这种可能——CGVirtualDisplay 是私有 API。每一个虚拟显示器产品都面临相同风险。捕获/流传输管线本身则仅使用公开 API。
音频? 目前不在范围内。
官方应用涵盖 Mac 发送端和运行 iOS 16.4+ 的 iPhone/iPad 接收端。其他人已经开发了使用同一协议的客户端,因此你也可以使用 Android 设备或旧 iPad 作为显示器,或通过 Linux 驱动显示器。线路协议在 PROTOCOL.md 中定义,因此新客户端可根据规范开发,而无需从 Swift 源码逆向工程。如果你的硬件尚未被覆盖,请从这里开始:
Android 接收端
旧版 iOS 接收端
Linux 发送端
这些是爱好者制作的项目,并非官方构建版本。它们与 OpenDisplay 没有关联,也不由我们维护、审查或支持,因此请在各自的仓库中报告相关问题。在此列出它们也并不代表我们的计划:未来官方 OpenDisplay 应用仍可能登陆其中任何平台。
MAC(发送端) iPHONE / iPAD(接收端)
CGVirtualDisplay ← macOS believes a monitor is attached
→ ScreenCaptureKit (capture the virtual display)
→ VideoToolbox H.264 (hardware, real-time)
→ TCP [4-byte length][Annex B frame] ═══════→ NWListener :9000
→ AVSampleBufferDisplayLayer
← JSON control messages (hello, touch, scroll) ═══
→ CGEvent injection (click / drag / scroll)
手机监听,Mac 连接——这一顺序使得完全相同的代码可同时用于 USB(通过每个 macOS 安装中内置的 usbmuxd 守护进程)和 WiFi。手机会公布其原生面板尺寸;Mac 则以一半的点尺寸(@2x HiDPI)创建 CGVirtualDisplay,并将像素流回设备。
所有经过 socket 的内容——帧封装、发现机制、视频格式、每一条控制消息——均在 PROTOCOL.md 中定义。协议如何跨版本演进,请参阅 COMPATIBILITY.md。
CGVirtualDisplay 是私有 CoreGraphics API(BetterDisplay 和 DeskPad 使用的也是同一 API)——这正是该项目无法在 App Store 上发布、而是托管于 GitHub 的原因。
你需要两个应用:一个 Mac 应用(捕获和发送)以及一个 iOS 应用(接收和显示)。如需将第二台 Mac作为显示器,请在其上安装 OpenDisplay Receiver,而不是 iOS 应用。
从最新发行版获取 OpenDisplay.dmg。该应用使用 Developer ID 证书签名,并已通过 Apple 公证,因此可在 macOS 14+ 上直接双击打开——不会出现 Gatekeeper 警告。打开 .dmg 后,将应用拖入 Applications 文件夹。
如需让一台 Mac_作为_显示器,请从同一发行版获取 OpenDisplayReceiver.dmg。它可运行于 macOS 12+,同样经过签名和公证;两个应用都通过 Sparkle 自行更新。
需要 iOS / iPadOS 16 或更新版本——包括 16.7.x 分支,这是 Apple 为 iPad 5(2017)、第一代 iPad Pro、iPhone 8 和 iPhone X 提供的最终版本。即使你的 iPad 无法更新至 16.7 之后,它仍可作为第二块显示器(#72)。
- TestFlight(推荐):在 testflight.apple.com/join/3NYaY11c 加入公开测试版。
- 从源代码构建:在 Xcode 中打开项目,在 Signing 中选择你的免费 Apple ID,然后点击 Run。约需 2 分钟。
快速开始(从源代码构建)
brew install xcodegen # project generation
需要 Xcode 15+ 以及免费或付费的 Apple 开发者账户(用于将 iOS 应用侧载到你的设备)。
git clone https://github.com/peetzweg/opendisplay.git
cd opendisplay
echo "DEVELOPMENT_TEAM=YOURTEAMID" > .env # your Apple team ID, for signing
./generate.sh # runs xcodegen with your .env
xcodebuild -project OpenSidecar.xcodeproj -scheme OpenSidecarMac \
-configuration Debug -derivedDataPath build build
xcodebuild -project OpenSidecar.xcodeproj -scheme OpenSidecariOS \
-configuration Debug -destination 'generic/platform=iOS' \
-derivedDataPath build -allowProvisioningUpdates build
(或者在 Xcode 中打开 OpenSidecar.xcodeproj,并在每个目标上点击 Run。你的团队 ID 显示在 developer.apple.com/account 的 Membership 下,或者直接在 Xcode 的 Signing 面板中选择你的团队。)
- 在 iPhone 上安装并打开 OpenDisplay(它监听 9000 端口)。
- 在 Mac 上运行
./run.sh(或直接打开应用)——它会直接与 macOS 内置的usbmuxd通信,并通过线缆自动连接。无需隧道工具。 - 当 macOS 请求时,授予屏幕录制(用于捕获)和辅助功能(用于触控)权限——各一次即可。
- 将窗口拖到你的新显示器上。完成。
打开 iPhone 应用,然后在 Mac 应用的 Connection 菜单中选择 "iPhone (WiFi)"。通过 Bonjour 自动发现设备。USB 延迟更低;WiFi 则无需线缆。
macOS 和 iOS 会限制此应用所需的若干功能——大多数会在首次使用时提示,但如果被拒绝或遗漏,有些功能会静默失败。Mac 应用会显示实时权限状态面板;iPhone 应用提供设置页面(摇晃手机,或在空闲时点击 Settings & Help)。
| 位置 | 权限 | 用途 | 缺失时的表现 |
|---|---|---|---|
| Mac | 屏幕录制 | 捕获显示器 | 手机上的画面为黑屏 |
| Mac | 辅助功能 | 触控/滚动输入 | 轻点没有反应 |
| Mac | 本地网络 | WiFi 发现 | Connection 菜单中没有设备 |
| iPhone | 本地网络 | WiFi 发现 | Mac 找不到手机 |
以上权限均位于系统设置中的隐私与安全性(Mac)/ 设置(iPhone)。本地网络权限仅 WiFi 模式需要——USB 无需这些权限。如果提示从未出现,请手动切换相应条目,或强制退出并重新打开应用。
获取用于错误报告的日志
两个应用都会在本地保存连接事件日志。不会上传任何内容;只有当你分享日志时,它们才会离开设备。
- **Mac:**在应用面板中点击 Logs。Finder 会打开并选中
~/Library/Logs/OpenDisplay。 - **iPhone/iPad:**摇晃设备(或在空闲时点击 Settings & Help),然后打开 Connection log。点击 Share 会将文件交给 Mail、Messages 或 Files;点击 copy 会将文本放入剪贴板,以便直接粘贴到 issue 中。
手机日志通常是 WiFi 报告中缺失的一半信息:接收端是否曾广播自身、其监听器是否重启、解码器是否发生故障。如果可以,请同时附上两端日志。
已作为[路线图议题](https://gith
English / 原文
Turn your spare Apple devices into second monitors for your Mac — free, open source, no subscription.
iPhone, iPad, and spare Macs. A self-hosted alternative to Apple Sidecar, Duet Display, and Luna Display: true extended display (not just mirroring), Retina-sharp, over USB or WiFi, with touch and scroll input.
Website · Quick start · How it works · FAQ · Contributing
Turning an iPhone or iPad into an external display for a Mac is a solved problem — but every existing option has a catch:
- Apple Sidecar is free but requires both devices on the same Apple ID , doesn't support iPhones at all, and only works on supported hardware pairs.
- Duet Display moved to a subscription.
- Luna Display requires a hardware dongle.
OpenDisplay is the missing option: a free, open-source, no-account, no-dongle way to use the iOS device you already own as a true second display. If you were about to write your own — don't! Contribute here instead; the hard parts (virtual display creation, low-latency H.264 pipeline, USB transport, input injection) are already working.
- 🖥️ True display extension — macOS treats the device as a real second monitor (drag windows to it, arrange it in System Settings), not a mirror. Mirroring is also available as a mode.
- 🔌 USB-wired for lowest latency — streams over the Lightning/USB-C cable via macOS's built-in
usbmuxd; plug in and go, no network, no WiFi jitter, no helper tools. - 📶 WiFi with zero config — the iPhone advertises itself via Bonjour; pick it from a dropdown on the Mac.
- 🔍 Retina / HiDPI — the virtual display matches the device panel pixel-for-pixel (@2x), so text is sharp.
- 👆 Touch input built in — your iPhone becomes a touchscreen for macOS: tap to click , drag to drag , and two-finger scroll that feels like a trackpad. (Apple Pencil support is on the roadmap.)
- 🔄 Portrait or landscape — rotate the device and the virtual display rebuilds itself as a vertical monitor at native resolution.
- ⚡ Low-latency pipeline — hardware H.264 encode (VideoToolbox, real-time mode, no B-frames), TCP_NODELAY, frame-drop backpressure with keyframe recovery, decode-and-render via
AVSampleBufferDisplayLayer. - 💻 A spare Mac as a display — install the small OpenDisplay Receiver app (macOS 12+) on an old Mac and any other Mac extends onto it over WiFi or a Thunderbolt/Ethernet cable, at native Retina resolution.
- 🔒 Self-hosted & private — your screen never touches anyone's server. Two small apps, one TCP connection, that's it.
| OpenDisplay | Apple Sidecar | Duet Display | Luna Display
---|---|---|---|---
Price | Free, open source | Free | Subscription | $$$ + dongle
iPhone as display | ✅ | ❌ (iPad only) | ✅ | ✅
Different Apple IDs | ✅ | ❌ | ✅ | ✅
Wired (USB) | ✅ | ✅ | ✅ | ❌
True extension | ✅ | ✅ | ✅ | ✅
Touch input | ✅ | ✅ | ✅ | ✅
Self-hosted / auditable | ✅ | — | ❌ | ❌
Why do I see the purple screen-recording indicator in the menu bar? That's a macOS privacy indicator shown for any app that captures the screen — Duet, Luna, OBS, and Zoom trigger it too. Apple Sidecar doesn't, only because it's implemented inside the OS rather than on public capture APIs. It cannot (and shouldn't) be hidden by an app; it's how macOS tells you a capture is running.
The Mac app doesn't show my iPhone in the Connection menu (WiFi). Both sides need Local Network permission, and both fail silently without it: check Privacy & Security → Local Network on the Mac and on the iPhone, make sure both are on the same WiFi network, and keep the iPhone app open in the foreground. USB mode is unaffected.
What USB cable or version do I need? Your cable must support data — a charge-only USB cable will not work. Look for a cable described as a data , sync , or charging and data-transfer cable. A data-capable USB 2.0 cable is enough; USB 3, Thunderbolt, and video Alt Mode are not required. OpenDisplay streams H.264 over a TCP connection through macOS's built-in usbmuxd, not as a USB video device. Its highest-quality preset uses 18 Mb/s, well below USB 2.0's 480 Mb/s high-speed link rate, so USB 2.0 has ample bandwidth for the stream. USB 1.x is not supported or tested. For best reliability, use a known-good data/sync cable, unlock the device, accept the Trust This Computer prompt if it appears, and avoid unreliable hubs or adapters.
Does it support iPad? The receiver app is universal (iPhone + iPad); iPad is the same codebase. iPad-specific polish (Pencil, pressure) is on the roadmap.
Can another Mac be the display? Yes. Install OpenDisplay Receiver (a separate, small app from the same release) on the spare Mac. It only needs macOS 12 Monterey or newer, so Macs from around 2015 onward qualify even though the sending Mac needs macOS 14. The receiver shows up on the sending Mac like a phone does and becomes a real extended Retina display. Over WiFi it works out of the box. For a cable, connect the two Macs with a Thunderbolt or USB4 cable (macOS creates a Thunderbolt Bridge network between them), with an Ethernet cable or adapters, or — on recent macOS on both Macs — a plain USB-C data cable (macOS runs a small network link over it; approve the allow accessory to connect prompt on each Mac, which appears depending on which Mac is plugged into which). The sender moves the session onto the cable automatically, even one plugged in mid-session, and the device row says Cable. Older Macs with a Mini DisplayPort-shaped Thunderbolt 1 or 2 port work with a Thunderbolt 3 to 2 adapter and a Thunderbolt 2 cable. Input from the receiving Mac's keyboard and mouse is a follow-up (#147).
Why H.264 and not HEVC/AV1? Hardware H.264 encode/decode is universally fast and the latency is excellent. HEVC is a planned option for better quality-per-bit.
Is my screen content sent anywhere? No. One direct TCP connection between your Mac and your device, over your cable or your LAN. No servers, no accounts, no analytics. Full details — including what the apps store locally and the current WiFi-encryption caveat — on the privacy page.
What's the license? Can I fork it or use it commercially? GPL-3.0. Use, study, and adapt it freely — commercially too. If you distribute a modified version it must stay open source under the same license with the original attribution intact, so improvements flow back instead of into closed forks. (Releases up to v0.4.x were MIT-licensed and remain available under those terms.)
Will it break on a macOS update? Possibly — CGVirtualDisplay is private API. The same risk applies to every virtual-display product. The capture/streaming pipeline itself uses only public APIs.
Audio? Out of scope for now.
The official apps cover a Mac sender and an iPhone/iPad receiver on iOS 16.4+. Other people have built their own clients that speak the same protocol, so you can also use an Android device or an older iPad as a display, or drive one from Linux. The wire protocol is specified in PROTOCOL.md, so a new client can be written against the spec instead of reverse-engineered from the Swift sources. If your hardware is not covered yet, start here:
Android receivers
Older iOS receivers
Linux senders
These are fan-made projects, not official builds. They are not affiliated with OpenDisplay and are not maintained, reviewed, or supported by us, so please report issues with them in their own repositories. Listing them here also says nothing about our own plans: an official OpenDisplay app may still ship for any of these platforms later.
MAC (sender) iPHONE / iPAD (receiver)
CGVirtualDisplay ← macOS believes a monitor is attached
→ ScreenCaptureKit (capture the virtual display)
→ VideoToolbox H.264 (hardware, real-time)
→ TCP [4-byte length][Annex B frame] ═══════→ NWListener :9000
→ AVSampleBufferDisplayLayer
← JSON control messages (hello, touch, scroll) ═══
→ CGEvent injection (click / drag / scroll)
The phone listens and the Mac connects — that ordering is what makes the exact same code work over USB (via the usbmuxd daemon built into every macOS install) and WiFi. The phone announces its native panel size; the Mac creates a CGVirtualDisplay at exactly half that in points (@2x HiDPI) and streams the pixels back.
Everything that crosses the socket — framing, discovery, the video format, every control message — is specified in PROTOCOL.md. How the protocol evolves across releases is covered in COMPATIBILITY.md.
CGVirtualDisplay is a private CoreGraphics API (the same one used by BetterDisplay and DeskPad) — which is precisely why this project can't ship on the App Store and lives on GitHub instead.
You need two apps : a Mac app (captures and sends) and an iOS app (receives and displays). To use a second Mac as the display, install OpenDisplay Receiver on it instead of the iOS app.
Grab OpenDisplay.dmg from the latest release. The app is signed with a Developer ID certificate and notarized by Apple, so it opens with a plain double-click on macOS 14+ — no Gatekeeper warning. Open the .dmg and drag the app to Applications.
For a Mac that should be the display, grab OpenDisplayReceiver.dmg from the same release instead. It runs on macOS 12+ and is signed and notarized the same way; both apps update themselves via Sparkle.
Needs iOS / iPadOS 16 or newer — including the 16.7.x line, which is where Apple left the iPad 5 (2017), the iPad Pro 1st gen, the iPhone 8 and the iPhone X. If your iPad can't be updated past 16.7, it can still be a second display (#72).
- TestFlight (recommended): join the public beta at testflight.apple.com/join/3NYaY11c.
- Build from source : open the project in Xcode, select your free Apple ID under Signing, hit Run. Takes ~2 minutes.
Quick start (from source)
brew install xcodegen # project generation
Xcode 15+ and a free or paid Apple developer account (to sideload the iOS app onto your device).
git clone https://github.com/peetzweg/opendisplay.git
cd opendisplay
echo "DEVELOPMENT_TEAM=YOURTEAMID" > .env # your Apple team ID, for signing
./generate.sh # runs xcodegen with your .env
xcodebuild -project OpenSidecar.xcodeproj -scheme OpenSidecarMac \
-configuration Debug -derivedDataPath build build
xcodebuild -project OpenSidecar.xcodeproj -scheme OpenSidecariOS \
-configuration Debug -destination 'generic/platform=iOS' \
-derivedDataPath build -allowProvisioningUpdates build
(Or open OpenSidecar.xcodeproj in Xcode and hit Run on each target. Your team ID is shown at developer.apple.com/account under Membership, or just pick your team in Xcode's Signing pane.)
- Install + open OpenDisplay on the iPhone (it listens on port 9000).
- On the Mac, run
./run.sh(or just open the app) — it talks to macOS's built-inusbmuxddirectly and auto-connects over the cable. No tunnel tools needed. - Grant Screen Recording (for capture) and Accessibility (for touch) when macOS asks — one time each.
- Drag a window onto your new display. Done.
Open the iPhone app, then pick "iPhone (WiFi)" from the Connection menu in the Mac app. Discovery is automatic via Bonjour. USB has lower latency; WiFi has no cable.
macOS and iOS gate several things this app needs — most prompt on first use, but some fail silently if denied or missed. The Mac app shows a live permission status panel; the iPhone app has a settings screen (shake the phone, or tap Settings & Help when idle).
| Where | Permission | Needed for | If missing |
|---|---|---|---|
| Mac | Screen Recording | capturing the display | black screen on the phone |
| Mac | Accessibility | touch/scroll input | taps do nothing |
| Mac | Local Network | WiFi discovery | no device in the Connection menu |
| iPhone | Local Network | WiFi discovery | Mac can't find the phone |
All live under Privacy & Security in System Settings (Mac) / Settings (iPhone). The Local Network ones are only needed for WiFi mode — USB works without them. If the prompt never appeared, toggle the entry manually or force-quit and reopen the app.
Getting the logs for a bug report
Both apps keep a local log of connection events. Nothing is uploaded anywhere; the logs only leave a device when you share them.
- Mac: click Logs in the app panel. Finder opens with
~/Library/Logs/OpenDisplayselected. - iPhone/iPad: shake the device (or tap Settings & Help when idle), then open Connection log. Share hands the file to Mail, Messages or Files; copy puts the text on the clipboard for pasting straight into an issue.
The phone log is the half usually missing from a WiFi report: whether the receiver ever announced itself, whether its listener restarted, whether the decoder was failing. Attach both if you can.
Tracked as roadmap issues — pick one up if you'd like to contribute!
Connectivity & distribution
Input
- #4 Apple Pencil with pressure and tilt
- #5 Right-click and multi-touch gestures
- #6 Hardware keyboard passthrough
- #7 On-screen modifier key sidebar
Display & media
Experience
Exploratory
Done: prebuilt releases, built-in USB connectivity (no helper tools), WiFi via Bonjour, portrait mode, touch + two-finger scroll, performance overlay, iPad support, multiple devices at once (#8 — every connected device becomes its own extended display), a Mac as the display (#17, WiFi or Thunderbolt/Ethernet cable).
The macOS app updates itself with Sparkle — an open-source framework, not a hosted service. Update checks hit only our own infrastructure:
- The app reads an appcast feed hosted on the landing-page site:
https://opendisplay.app/appcast.xml(SUFeedURLinproject.yml). - The release workflow (
.github/workflows/release.yml,build-macjob) runs Sparkle'sgenerate_appcastagainst the notarizedOpenDisplay.dmg, signs it with the EdDSA key, commits the result topublic/appcast.xml, and dispatches the Pages deploy — so the published feed points download links at the GitHub Release assets. - Sparkle verifies both the EdDSA signature and Apple's notarization before installing. The app checks automatically in the background (
SUEnableAutomaticChecks) and offers a manual "Check for Updates…" button next to Quit in the menu-bar window.
Maintainer prerequisites (before auto-update goes live)
Auto-update is scaffolded but inert until the signing keys are in place. The private signing key is never committed — it lives only as a CI secret. To switch it on:
- Generate the key pair. Run Sparkle's
generate_keysonce (it ships in the Sparkle SPM artifact bundle and in the release tarball atbin/generate_keys). It prints a public key and stores the private key in your login keychain. - Public key → paste it into
SUPublicEDKeyinproject.yml(replace theREPLACE_WITH_SUPUBLICEDKEY_FROM_generate_keysplaceholder), then re-runxcodegen generateand commit. - Private key → add it as the
SPARKLE_PRIVATE_KEYGitHub Actions secret (export it withgenerate_keys -x private_key.pemif needed). The appcast step inrelease.ymlno-ops gracefully while this secret is absent, so releases keep working until you're ready. - The first appcast publishes on the next release after both keys are set. Confirm
https://opendisplay.app/appcast.xmlresolves, then test the full update flow on a real signed/notarized build (check → download → verify → relaunch) — this can't be validated in CI.
Issues and PRs are very welcome — especially for the roadmap items above. The codebase is intentionally small: ~4 Swift files per platform, with Sparkle (SPM) as the macOS app's only runtime dependency, for auto-update. The How it works section above is the architecture doc; see Mac/CGVirtualDisplayPrivate.h for the private API surface.
Releases are automated with release-please: use Conventional Commits (feat:, fix:, docs:, …) and a release PR with a generated changelog appears automatically — merging it tags the release and attaches prebuilt artifacts.
GPL-3.0 — Copyright (c) 2026 Philip Poloczek.
Free to use, study, and adapt. If you distribute a modified version it must remain open source under the same license, with the original attribution intact — improvements flow back to everyone instead of into closed forks. (Versions up to v0.4.x were MIT-licensed; those releases remain available under MIT.)
Keywords: iPhone second monitor Mac, iPad external display, free Sidecar alternative, Duet Display alternative, open source screen extension macOS, use iPhone as extra screen, virtual display Mac, USB second display.
