Visionos shareplay
SharePlay and GroupActivities development for visionOS and iOS. Use when implementing collaborative experiences, synchronizing state across participants, managing GroupSession lifecycle, or building shared immersive spaces on Apple platforms.From its SKILL.md
npx -y skills add ibrews/apple-platform-skills --skill visionos-shareplayAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.6 KB, 745 tokens by cl100k_base, as published. Nobody here has run it
visionOS SharePlay Development
GroupActivities Essentials
Core types: GroupActivity (your activity struct), GroupSession (the live session), GroupSessionMessenger (send/receive messages), AsyncStream (observe session and message events).
Activity Type Definition
struct WatchTogetherActivity: GroupActivity {
static let activityIdentifier = "com.example.app.watch-together"
var metadata: GroupActivityMetadata {
var m = GroupActivityMetadata()
m.title = "Watch Together"
m.type = .watchTogether
m.fallbackURL = URL(string: "https://example.com/watch")
return m
}
}
Session Lifecycle
// Activate (host)
let activity = WatchTogetherActivity()
switch await activity.prepareForActivation() {
case .activationPreferred:
try await activity.activate()
case .activationDisabled:
// Fallback — open locally
default: break
}
// Observe incoming sessions (all participants including host)
for await session in WatchTogetherActivity.sessions() {
configureSession(session)
}
func configureSession(_ session: GroupSession<WatchTogetherActivity>) {
// CRITICAL: always call join() or the session stays in .waiting
session.join()
// store session reference — don't let it deallocate
self.groupSession = session
Task {
for await state in session.$state.values {
if case .invalidated(let error) = state { handleEnd(error) }
}
}
}
Common pitfall: forgetting session.join() — session stays .waiting forever.
Synchronizing State with GroupSessionMessenger
let messenger = GroupSessionMessenger(session: session)
// Send
struct MoveMessage: Codable { let position: SIMD3<Float> }
try await messenger.send(MoveMessage(position: pos))
// Receive
Task {
for await (message, context) in messenger.messages(of: MoveMessage.self) {
apply(message, from: context.source)
}
}
visionOS-Specific
Spatial Personas — enabled automatically in FaceTime when app has GroupActivities entitlement. Access via session.participants.
ImmersiveSpace in SharePlay:
// Open immersive space when session becomes active
.task {
for await session in MyActivity.sessions() {
session.join()
await openImmersiveSpace(id: "SharedSpace")
}
}
Windowed vs Volumetric: Windowed windows are shared/mirrored automatically. Volumetric windows are independent per device — use messenger to keep them in sync manually.
Required Entitlements & Info.plist
In your .entitlements file:
<key>com.apple.developer.group-activities</key>
<true/>
No special entitlement request needed — available to all Apple Developer accounts.
Simulator Limitations
GroupActivities does not work in Simulator. Testing requires:
- Two physical devices (iPhone/iPad/Apple Vision Pro)
- An active FaceTime call between them
- Or: use
GroupActivitySharingControllerto test the activation UI in isolation
Common Pitfalls
| Pitfall | Fix |
|---|---|
Session stays .waiting | Always call session.join() |
| Session deallocates | Store strong reference to GroupSession |
| Messages not received | Check messenger is retained too |
| Activation does nothing | Check prepareForActivation() result first |
| visionOS persona missing | Requires FaceTime call, not just same-network |
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.