Skip to content

Visual-Studio-Coder/Remote-Mac-Lock

Repository files navigation

Remote Mac Lock

Remote Mac Lock lets an iPhone ask a Mac to sleep from the app, a widget, or an iOS Control Center control. It uses the user's private CloudKit database, CloudKit push notifications, and a 15-second polling fallback while the Mac is unlocked.

The Mac performs the requested action with:

/usr/bin/pmset sleepnow

The Control Center icon reflects the last known Mac state:

  • Open lock: unlocked
  • Closed lock: locked
  • Hourglass: lock request in progress
  • Question mark: status unavailable

Requirements

  • macOS 14 or later
  • iOS 17.6 or later
  • iOS 18.6 or later for the Control Center control
  • An Apple Developer account with CloudKit, Push Notifications, and App Groups capabilities
  • The same iCloud account signed in on the Mac and iPhone

Configure your fork

The checked-in identifiers belong to the original project and cannot be used by another Apple Developer team. Before signing a fork:

  1. Open Remote Mac Lock.xcodeproj and select your development team for the app, widget extension, and SharedAssets targets.
  2. Replace the app and extension bundle identifiers in the project settings.
  3. Replace the App Group and CloudKit container identifiers in both entitlement files.
  4. Update RemoteLockConfiguration in Remote Mac Lock/MacMoteController.swift with the same App Group, CloudKit container, a device ID for your Mac, and a unique Control Widget kind.
  5. Enable iCloud with CloudKit, Push Notifications, and App Groups for the app. Enable the shared CloudKit container and App Group for the widget extension.
  6. Run the app once on the Mac and iPhone while signed into the same iCloud account.

CloudKit schema

Create these record types in the CloudKit private database:

SharedCommand

  • lastCommand: String
  • targetDevice: String
  • requestID: String
  • timestamp: Date/Time
  • processedAt: Date/Time

The app uses the stable record name SharedLockCommand.

MacState

  • deviceID: String
  • deviceName: String
  • isLocked: Int(64)
  • lastUpdate: Date/Time

Mark MacState.deviceID as queryable because the iPhone creates a subscription filtered by that field. Deploy the schema to production before distributing a release build.

How it works

  1. The iPhone updates SharedLockCommand with a new request ID and target device.
  2. CloudKit attempts silent push delivery to the Mac.
  3. While unlocked, the Mac also checks the stable command record every 15 seconds as a delivery fallback.
  4. The Mac rejects stale, duplicate, or incorrectly targeted commands.
  5. The Mac publishes its lock state and runs pmset sleepnow.

CloudKit delivery is best effort and subject to the user's iCloud quota. A CKError.quotaExceeded response means the command was not saved and cannot be delivered until account storage is available.

Privacy and security

  • No third-party server is used.
  • Commands and state stay in the signed-in user's private CloudKit database.
  • APNs device tokens are not printed.
  • The Mac only accepts commands whose target matches its configured device ID.

See SECURITY.md for the security policy and trust model.

License

Remote Mac Lock is available under the MIT License.

About

Lock or sleep your Mac remotely from iPhone and Control Center using CloudKit.

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages