Skip to content

Brew formula doesn't ship imsg-bridge-helper.dylib — advanced features fail OOTB #111

@omarshahine

Description

@omarshahine

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:

  1. The release artifact imsg-macos.zip doesn't contain imsg-bridge-helper.dylib (CI only ships the CLI binary + bundles).
  2. 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

  1. 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.

  2. 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.

  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions