An unofficial native macOS menu bar app for Ring doorbells and cameras
OpenRing brings your Ring devices to your Mac's menu bar. View live streams, get notifications, talk to visitors, control your devices, and even ask AI what's happening—all without opening a browser or phone app.
Ring's official app is phone-first. There's no native Mac app, just a web dashboard that's clunky and slow. OpenRing fixes that:
- Native performance — Built with SwiftUI, feels like a first-party Apple app
- Menu bar access — One click (or hotkey) to see your cameras
- Real-time streaming — WebRTC video with sub-second latency, faster than the phone app
- Instant access — No waiting for the Ring app to load—click and stream
- AI-powered — Ask "What's at the door?" and get an instant answer
- Privacy-focused — Your credentials stay in Keychain, no telemetry
Stream video from any Ring device in real-time using WebRTC.
- Multi-camera support — Switch between cameras with swipe gestures or keyboard shortcuts (⌘1-4)
- Portrait mode — Doorbells display in their native vertical orientation
- Zoom controls — Use +/- keys or scroll to zoom in/out (1x-3x)
- Connection status — Visual indicators for ICE/signaling state
- Auto-reconnect — Handles network interruptions gracefully
The video pipeline uses Ring's WebRTC infrastructure with proper ICE candidate handling and codec negotiation (H.264).
Two-way audio communication with visitors.
- Hold-to-talk — Hold the microphone button to speak, release to listen
- Visual feedback — Button animates to show when transmitting
- Low latency — Audio streams via WebRTC alongside video
Ask questions about what your cameras see using Claude's vision capabilities.
Live Analysis:
- "What's at the door?" — Captures current frame and describes the scene
- "Is there a package?" — Detects objects in view
- "Describe what you see" — General scene understanding
Event Queries:
- "Who came today?" — Summarizes events from history
- "Show me the last motion" — Plays back most recent motion event
- "Any deliveries this week?" — Searches event history
How it works:
- Captures a frame from the live WebRTC stream (or fetches from event history)
- Sends to Anthropic's Claude API with your question
- Returns natural language response with option to play related video
Requires an Anthropic API key (stored securely in Keychain).
Control your Ring devices directly from the app.
| Control | Description | Devices |
|---|---|---|
| Floodlight | Toggle flood/spotlight on/off | Spotlight Cam, Floodlight Cam |
| Siren | Activate 30-second alarm | Cameras with siren capability |
| Motion Detection | Enable/disable motion alerts | All cameras |
Controls appear contextually—doorbells won't show floodlight toggle since they don't have one.
Browse and play back recorded events.
- Filter chips — View All, Ring (doorbell presses), or Motion events
- Inline playback — Tap any event to play its recording without leaving the app
- Export — Save any recording to disk (downloads MP4 from Ring's servers)
- Relative timestamps — "2 min ago", "Yesterday at 3:42 PM"
Get alerted when something happens.
- Native macOS notifications — Integrates with Notification Center
- Motion & ring alerts — Separate toggles for each type
- Snooze — Temporarily silence notifications
- Background polling — Checks for new events every 15-120 seconds (configurable)
| Shortcut | Action |
|---|---|
| ⌘` | Open OpenRing (global, works from any app) |
| ⌘1-4 | Switch to camera 1/2/3/4 |
| +/- | Zoom in/out |
| ←/→ | Previous/next camera |
| Space | Toggle push-to-talk |
The global hotkey is customizable in Settings (⌘⇧R, ⌘⌥O, ⌃⌥Space, etc.).
| Setting | Options | Default |
|---|---|---|
| Polling interval | 15s, 30s, 60s, 2min | 30s |
| Motion alerts | On/Off | On |
| Notification sound | On/Off | On |
| Global hotkey | ⌘`, ⌘⇧R, ⌘⌥O, ⌃⌥Space | ⌘` |
| Show battery level | On/Off | On |
| Anthropic API key | Securely stored | — |
- Go to Releases
- Download
OpenRing-x.x.x.dmg - Open the DMG and drag OpenRing to Applications
- Launch from Applications (you may need to right-click → Open the first time)
# Clone the repository
git clone https://github.com/abracadabra50/open-ring.git
cd open-ring/app
# Open in Xcode
open OpenRing.xcworkspace
# Build and run (⌘R)Requirements:
- Xcode 15.0+
- macOS 14.0+ (Sonoma)
- Swift 5.9+
- Login — Enter your Ring email and password
- 2FA — Ring will send an SMS code, enter it in the app
- Grant Permissions:
- Notifications — For motion/ring alerts
- Accessibility — For global hotkey (optional but recommended)
- Done — Your devices appear automatically
Your credentials are stored in macOS Keychain. The app maintains a session token and refreshes it automatically.
open-ring/
├── app/
│ ├── OpenRing/ # macOS app shell
│ │ └── OpenRingApp.swift # App entry, MenuBarExtra, Settings
│ │
│ └── OpenRingPackage/ # Swift Package with all modules
│ │
│ ├── Sources/
│ │ ├── OpenRingFeature/ # Main UI and features
│ │ │ ├── PopoverView.swift
│ │ │ ├── MultiStreamVideoView.swift
│ │ │ ├── LoginView.swift
│ │ │ ├── EventTimelineView.swift
│ │ │ ├── AIOverlayPanel.swift
│ │ │ ├── DrawerPanel.swift
│ │ │ ├── KeyboardShortcutManager.swift
│ │ │ └── NotificationManager.swift
│ │ │
│ │ ├── RingClient/ # Ring API client (reusable)
│ │ │ ├── RingClient.swift # API methods
│ │ │ ├── RingTypes.swift # Data models
│ │ │ ├── RingWebRTC.swift # WebRTC session
│ │ │ ├── LiveViewSession.swift
│ │ │ └── KeychainManager.swift
│ │ │
│ │ ├── DesignSystem/ # UI components & tokens
│ │ │ ├── Colors.swift
│ │ │ ├── Typography.swift
│ │ │ └── Components/
│ │ │
│ │ └── Storage/ # Local persistence (GRDB)
│ │
│ └── Package.swift
RingClient — The Ring API wrapper. Handles:
- OAuth2 authentication with 2FA
- Device discovery (
/clients_api/ring_devices) - Event history (
/clients_api/doorbots/{id}/history) - Live streaming via WebRTC
- Device controls (floodlight, siren, motion detection)
OpenRingFeature — All UI and app logic:
- SwiftUI views for every screen
- WebRTC video rendering with Metal
- AI integration with Anthropic
- Notification handling
- Keyboard shortcut management
DesignSystem — Consistent styling:
- Ring-inspired color palette
- Typography scale
- Reusable components (chips, buttons, cards)
The RingClient module can be used independently in your own projects.
import RingClient
// Initial login (triggers 2FA)
try await RingClient.shared.login(email: "you@example.com", password: "secret")
// Complete 2FA
try await RingClient.shared.verify2FA(code: "123456")
// Session persists in Keychain
// On subsequent launches:
let restored = try await RingClient.shared.restoreSession()
if restored {
// Good to go
}
// Logout
try await RingClient.shared.logout()// Fetch all devices (doorbells, cameras, chimes)
let devices = try await RingClient.shared.fetchDevices()
for device in devices {
print("\(device.name) - \(device.deviceType)")
print(" Battery: \(device.batteryLevel ?? -1)%")
print(" Online: \(device.isOnline)")
}// Get recent events for all devices
let events = try await RingClient.shared.fetchAllRecentEvents(limit: 20)
for event in events {
print("\(event.kind.displayName) at \(event.createdAt)")
print(" Device: \(event.deviceName ?? "Unknown")")
}
// Get recording URL for an event
let url = try await RingClient.shared.getEventVideoURL(eventId: event.id)// Create a live view session
let session = LiveViewSession(
device: device,
onVideoTrack: { track in
// Attach to your video view
},
onAudioTrack: { track in
// Handle audio
},
onConnectionState: { state in
print("WebRTC state: \(state)")
}
)
// Start streaming
session.start()
// Push-to-talk
session.startTalking()
session.stopTalking()
// Stop
session.stop()// Floodlight (for Spotlight/Floodlight cameras)
try await RingClient.shared.setFloodlight(deviceId: device.id, enabled: true)
// Siren (30-second alarm)
try await RingClient.shared.setSiren(deviceId: device.id, enabled: true)
// Motion detection
try await RingClient.shared.setMotionDetection(deviceId: device.id, enabled: false)- POST to Ring OAuth endpoint with email/password
- Ring responds with
tsv_stateindicating 2FA required - User enters SMS code
- POST code + tsv_state to complete auth
- Receive
access_tokenandrefresh_token - Tokens stored in Keychain
- Access token used in
Authorization: Bearerheader - Refresh token used when access token expires
- Request live view ticket from Ring API
- Receive SDP offer and ICE servers
- Create local peer connection with answer
- Exchange ICE candidates via Ring's signaling
- Video track attached to
RTCMTLVideoView - Audio handled via WebRTC's audio session
- User types question or taps capture button
- App captures current frame from WebRTC video track
- Frame encoded as base64 JPEG
- Sent to Anthropic Claude API with vision capability
- Response streamed back and displayed
- If response references an event, show "Play" button
- Credentials — Stored in macOS Keychain, never on disk
- API Keys — Anthropic key stored in Keychain separately
- Network — All traffic over HTTPS
- No Telemetry — Zero analytics, tracking, or phone-home
- Open Source — Audit the code yourself
- Local Only — No cloud backend, speaks directly to Ring
- No subscription management — Can't change Ring Protect plan
- No device setup — Add new devices via official app
- No geofencing — Home/Away modes not implemented
- macOS only — No iOS/Windows/Linux versions
- Ring account required — Doesn't work with Ring alternatives
"Session expired" after closing app
- This is normal. Ring tokens expire. Re-login to refresh.
Video not loading
- Check your internet connection
- Try a different device
- Ring's servers occasionally have issues
Global hotkey not working
- Grant Accessibility permission in System Settings
- Check if another app uses the same shortcut
2FA code not arriving
- Ring sends via SMS only
- Check your phone number is correct in Ring account
Contributions welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing) - Open a Pull Request
git clone https://github.com/abracadabra50/open-ring.git
cd open-ring/app
open OpenRing.xcworkspaceThe project uses Swift Package Manager. Dependencies are resolved automatically.
This is an unofficial app. OpenRing is not affiliated with, endorsed by, or connected to Ring LLC or Amazon.com, Inc. Ring is a trademark of Ring LLC. Use at your own risk.
This app uses Ring's private API, which is undocumented and may change without notice. Ring could block access at any time.
MIT License. See LICENSE for details.
Built with SwiftUI, WebRTC, and Claude