Mainstream messaging
Enabling the imsg private API
Private API mode unlocks the native iMessage actions. It needs SIP off, library validation relaxed, and a successful helper injection.
Enabling the imsg private API
imsg ships in two operational modes. For OpenClaw, Private API mode is the recommended setup because it gives the channel the native iMessage actions users expect. Basic mode remains useful for low-risk installs, initial verification, or hosts where SIP cannot be disabled.
- Basic mode (default, no SIP changes needed): outbound text and media via
send, inbound watch/history, chat list. This is what you get out of the box from a freshbrew install steipete/tap/imsgplus the standard macOS permissions. - Private API mode:
imsginjects a helper dylib intoMessages.appto call internalIMCorefunctions. This unlocksreact,edit,unsend,reply(threaded),sendWithEffect,pollandpoll-vote(native Messages polls),renameGroup,setGroupIcon,addParticipant,removeParticipant,leaveGroup, plus typing indicators and read receipts.
The recommended action surface on this page requires Private API mode. The imsg README is explicit about the requirement:
Advanced features such as
read,typing,launch, bridge-backed rich send, message mutation, and chat management are opt-in. They require SIP to be disabled and a helper dylib to be injected intoMessages.app.imsg launchrefuses to inject when SIP is enabled.
The helper-injection technique uses imsg's own dylib to reach Messages private APIs. There is no third-party server or BlueBubbles runtime in the OpenClaw iMessage path.
Setup
-
Install (or upgrade)
imsgon the Mac that runs Messages.app:bash brew install steipete/tap/imsgbrew update && brew upgrade imsgimsg --versionimsg status --jsonThe
imsg status --jsonoutput reportsbridge_version,rpc_methods, and per-methodselectorsso you can see what the current build supports before you start. -
Disable System Integrity Protection, and (on modern macOS) Library Validation. Injecting a non-Apple helper dylib into the Apple-signed
Messages.appneeds SIP off and library validation relaxed. The Recovery-mode SIP step is macOS-version-specific:- macOS 10.13-10.15 (Sierra-Catalina): disable Library Validation via Terminal, reboot to Recovery Mode, run
csrutil disable, restart. - macOS 11+ (Big Sur and later), Intel: Recovery Mode (or Internet Recovery),
csrutil disable, restart. - macOS 11+, Apple Silicon: power-button startup sequence to enter Recovery; on recent macOS versions hold the Left Shift key when you click Continue, then
csrutil disable. Virtual-machine setups follow a separate flow, so take a VM snapshot first.
On macOS 11 and later,
csrutil disablealone is usually not enough. Apple still enforces library validation againstMessages.appas a platform binary, so an adhoc-signed helper is rejected (Library Validation failed: ... platform binary, but mapped file is not) even with SIP off. After disabling SIP, also disable library validation and reboot:bash sudo defaults write /Library/Preferences/com.apple.security.libraryvalidation.plist DisableLibraryValidation -bool truemacOS 26 (Tahoe), verified on 26.5.1: SIP off plus the
DisableLibraryValidationcommand above is sufficient to inject the helper across 26.0 through 26.5.x. No boot-args are required. The plist is the decisive factor and the most common missing step when injection fails on Tahoe:- With the plist:
imsg launchinjects andimsg statusreportsadvanced_features: true. - Without the plist (even with SIP off):
imsg launchfails withFailed to launch: Timeout waiting for Messages.app to initialize. AMFI rejects the adhoc helper at load, so the bridge never becomes ready and the launch times out. That timeout is the symptom most people hit on Tahoe; the fix is the plist above, not anything more drastic.
If
imsg launchinjection or specificselectorsstart returning false after a macOS upgrade, this gate is the usual cause. Check your SIP and library-validation state before assuming the SIP step itself failed. If those settings are correct and the bridge still cannot inject, collectimsg status --jsonplus theimsg launchoutput and report it to theimsgproject instead of weakening additional system-wide security controls. - macOS 10.13-10.15 (Sierra-Catalina): disable Library Validation via Terminal, reboot to Recovery Mode, run
-
Inject the helper. With SIP disabled and Messages.app signed in:
bash imsg launchimsg launchrefuses to inject when SIP is still enabled, so this also doubles as a confirmation that step 2 took. -
Verify the bridge from OpenClaw:
bash openclaw channels status --probeThe iMessage entry should report
works, andimsg status --json | jq '{rpc_methods, selectors}'should show the capabilities exposed by your macOS build. Poll creation requiresselectors.pollPayloadMessage; voting requires bothselectors.pollVoteMessageand thepoll.voteRPC method. The OpenClaw plugin advertises only actions supported by the cached probe, while an empty cache stays optimistic and probes on first dispatch.
If openclaw channels status --probe reports the channel as works but specific actions throw "iMessage <action> requires the imsg private API bridge" at dispatch time, run imsg launch again — the helper can fall out (Messages.app restart, OS update, etc.) and the cached available: true status will keep advertising actions until the next probe refreshes.
When SIP stays enabled
If disabling SIP is not acceptable for your threat model:
imsgfalls back to basic mode — text + media + receive only.- The OpenClaw plugin still advertises text/media send and inbound monitoring; it hides
react,edit,unsend,reply,sendWithEffect, and group ops from the action surface (per the per-method capability gate). - You can run a separate non-Apple-Silicon Mac (or a dedicated bot Mac) with SIP off for the iMessage workload, while keeping SIP enabled on your primary devices. See Dedicated bot macOS user (separate iMessage identity).