Summary
A fresh brew install steipete/tap/imsg installs only the CLI binary. The injectable imsg-bridge-helper.dylib is not in the release zip and not installed by the formula, so every command that depends on the IMCore bridge (send-attachment, send-rich, send-multipart, tapback, edit, unsend, chat-create, chat-name, etc.) fails immediately with:
imsg-bridge-helper.dylib not found. Build with: make build-dylib
The user has to clone the repo, install Xcode CLT, run make build-dylib, and arrange a symlink at /usr/local/lib/imsg-bridge-helper.dylib to get those features. That's a cliff a typical brew user won't navigate.
Repro
$ brew install steipete/tap/imsg
$ imsg --version
0.8.0
$ imsg send 'iMessage;-;+15555550123' 'plain text'
# works (AppleScript path)
$ imsg send-attachment --chat 'iMessage;-;+15555550123' --file ~/Pictures/foo.png
# error: imsg-bridge-helper.dylib not found. Searched:
# - /usr/local/lib/imsg-bridge-helper.dylib
# - .build/release/imsg-bridge-helper.dylib
# - .build/debug/imsg-bridge-helper.dylib
Where it goes wrong
/opt/homebrew/Library/Taps/steipete/homebrew-tap/Formula/imsg.rb:
url "https://github.com/openclaw/imsg/releases/download/v0.8.0/imsg-macos.zip"
def install
libexec.install "imsg" # only the CLI binary
Dir["*.bundle"].each do |bundle|
libexec.install bundle # swift package bundles
end
bin.write_exec_script libexec/"imsg"
end
Two contributing facts:
- The release artifact
imsg-macos.zip doesn't contain imsg-bridge-helper.dylib (CI only ships the CLI binary + bundles).
- Even if it did, the formula has no
lib.install / libexec.install line for it.
The imsg launch binary search order is:
/usr/local/lib/imsg-bridge-helper.dylib
.build/release/imsg-bridge-helper.dylib
.build/debug/imsg-bridge-helper.dylib
A brew install populates none of these paths.
Impact
What works OOTB after brew install:
- ✅
imsg send (AppleScript text)
- ✅
imsg history, imsg chats, imsg search (chat.db reads)
- ✅
imsg watch, imsg rpc (chat.db tail / RPC server)
What fails OOTB:
- ❌
imsg send-attachment, send-rich, send-multipart
- ❌
imsg tapback, react
- ❌
imsg edit, unsend, delete-message, notify-anyways
- ❌
imsg chat-create, chat-name, chat-photo, chat-add-member, chat-remove-member, chat-leave, chat-delete, chat-mark
- ❌
imsg typing, read
Most of the advertised feature set, in other words.
Proposed fix
-
CI: build the arm64e dylib via make build-dylib alongside the CLI binary, sign + notarize as needed, and include it in imsg-macos.zip (and imsg-macos-universal.zip if applicable). Probably ~5 lines added to the existing scripts/build-universal.sh or a sibling script.
-
Formula: install it where imsg launch already searches:
def install
libexec.install "imsg"
Dir["*.bundle"].each { |b| libexec.install b }
bin.write_exec_script libexec/"imsg"
# Inject helper for IMCore bridge features
lib.install "imsg-bridge-helper.dylib"
# imsg launch looks at /usr/local/lib first; on Apple Silicon brew puts
# libs in /opt/homebrew/lib, so symlink for the legacy path:
ln_s lib/"imsg-bridge-helper.dylib", "/usr/local/lib/imsg-bridge-helper.dylib" rescue nil
end
Or, simpler: add /opt/homebrew/lib and <HOMEBREW_PREFIX>/lib to the binary's dylib search path so the symlink isn't necessary on Apple Silicon installs.
-
Caveat: the caveats block already mentions FDA + Automation. Add a note that advanced features need SIP disabled (existing requirement) and that the formula installs the helper dylib automatically on Sonoma+.
Environment
- macOS Darwin 25.4.0 (Sonoma+ on Apple Silicon arm64e)
- imsg 0.8.0 from
steipete/tap
- Reproducible on a fresh install with no prior
~/GitHub/imsg clone
Why this matters for #110
Issue #110 argues that imsg send-attachment should Just Work™ for arbitrary source paths via auto-staging + transparent transport fallback. That whole proposition presumes the dylib path is available to begin with. Today, the dylib path doesn't even exist for brew users until they clone and build manually. Fixing this packaging gap is the prerequisite for #110's UX promise to be visible to anyone who didn't get imsg from source.
Acceptance
Summary
A fresh
brew install steipete/tap/imsginstalls only the CLI binary. The injectableimsg-bridge-helper.dylibis not in the release zip and not installed by the formula, so every command that depends on the IMCore bridge (send-attachment,send-rich,send-multipart,tapback,edit,unsend,chat-create,chat-name, etc.) fails immediately with:The user has to clone the repo, install Xcode CLT, run
make build-dylib, and arrange a symlink at/usr/local/lib/imsg-bridge-helper.dylibto get those features. That's a cliff a typical brew user won't navigate.Repro
Where it goes wrong
/opt/homebrew/Library/Taps/steipete/homebrew-tap/Formula/imsg.rb:Two contributing facts:
imsg-macos.zipdoesn't containimsg-bridge-helper.dylib(CI only ships the CLI binary + bundles).lib.install/libexec.installline for it.The
imsg launchbinary search order is:A brew install populates none of these paths.
Impact
What works OOTB after
brew install:imsg send(AppleScript text)imsg history,imsg chats,imsg search(chat.db reads)imsg watch,imsg rpc(chat.db tail / RPC server)What fails OOTB:
imsg send-attachment,send-rich,send-multipartimsg tapback,reactimsg edit,unsend,delete-message,notify-anywaysimsg chat-create,chat-name,chat-photo,chat-add-member,chat-remove-member,chat-leave,chat-delete,chat-markimsg typing,readMost of the advertised feature set, in other words.
Proposed fix
CI: build the arm64e dylib via
make build-dylibalongside the CLI binary, sign + notarize as needed, and include it inimsg-macos.zip(andimsg-macos-universal.zipif applicable). Probably ~5 lines added to the existingscripts/build-universal.shor a sibling script.Formula: install it where
imsg launchalready searches:Or, simpler: add
/opt/homebrew/liband<HOMEBREW_PREFIX>/libto the binary's dylib search path so the symlink isn't necessary on Apple Silicon installs.Caveat: the
caveatsblock already mentions FDA + Automation. Add a note that advanced features need SIP disabled (existing requirement) and that the formula installs the helper dylib automatically on Sonoma+.Environment
steipete/tap~/GitHub/imsgcloneWhy this matters for #110
Issue #110 argues that
imsg send-attachmentshould Just Work™ for arbitrary source paths via auto-staging + transparent transport fallback. That whole proposition presumes the dylib path is available to begin with. Today, the dylib path doesn't even exist for brew users until they clone and build manually. Fixing this packaging gap is the prerequisite for #110's UX promise to be visible to anyone who didn't get imsg from source.Acceptance
brew install steipete/tap/imsginstalls the dylib alongside the CLI.imsg launchfinds it without needing a/usr/local/lib/imsg-bridge-helper.dylibsymlink to a clone.imsg send-attachment ...works (subject to whatever staging fix lands per send-attachment: auto-stage TCC-blocked paths and add transparent dylib→AppleScript fallback #110) without any manual build step from the user.