Self-hosted service
openclaw/imsg avatar
openclaw/imsg

openclaw/imsg: a Swift CLI that pipes Messages.app into your scripts and agents

CLI for Apple's Messages.app so your agent can send and receive text messages/iMessages.

1,342 stars182 forksSwiftMIT

At a glance

What is it?
imsg reads the local Messages database and drives Messages.app from the command line on macOS 14 or newer. It is a good fit for automation on a Mac you control, and the wrong tool if you need to send iMessages from Linux.
Who is it for?
Adopt imsg if you have a Mac that already runs Messages.app, you can grant Full Disk Access to the terminal or agent process, and you want chat history and sends as NDJSON or JSON-RPC rather than through a GUI. Do not adopt it for a Linux server that must send iMessages: the Linux build is read-only and works on a copied chat.db.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What imsg solves, and who it is actually for

Messages.app has no command line surface. Its history lives in a SQLite file at ~/Library/Messages/chat.db, and sending goes through AppleScript automation of the app. imsg wraps both halves in one Swift binary: read commands open the database in SQLite read-only mode, and send commands ask Messages.app to do the work. The README states the pitch in one line: read directly, stream updates, and ask Messages.app to send.

The audience is narrow and specific. It is people building agents, gateways or shell scripts that need a person's real text threads on a Mac they control. The README's own examples are piped into jq, which tells you the expected consumer is a program, not a human reading a terminal. If you want a chat UI, this is not it. If you want an LLM agent to answer a message that arrived five seconds ago, the watch command exists precisely for that.

How the read, watch and send paths differ

There are three distinct mechanisms under one CLI, and the split matters when you plan permissions.

Read commands such as chats and history open the local Messages database read-only. That is the whole data flow: no network, no private framework, no injection into another process. Watch goes further. According to the README, it follows database and WAL filesystem events, with a polling fallback when macOS drops an event or rotates a sidecar file. The fallback is an admission that filesystem event delivery on macOS is not perfectly reliable, and the polling path is what keeps a long-running watcher from going silent.

Send is a different world. imsg send uses Messages.app's AppleScript surface. That means the send path depends on Automation permission to Messages, and the README notes a real constraint: it cannot force a particular outgoing number when several numbers share one Apple ID. If your Mac has two lines under one Apple ID, you do not get to choose which one sends.

A fourth path exists and is optional. Read receipts, typing indicators, rich sends, message mutation, stickers, polls and chat management use an injected helper inside Messages.app. The README says these require SIP to be disabled and may be blocked by library validation or private-entitlement checks on current macOS releases. The normal commands listed above do not use private frameworks or process injection.

Installing imsg with Homebrew and sending a first message

The README calls Homebrew the smallest path on macOS. The tap is steipete/tap, and imsg requires macOS 14 or newer.

bash
brew install steipete/tap/imsg
imsg --version

Before any read command works you need Full Disk Access for the terminal or the parent process. The README says to grant it in System Settings, Privacy & Security, then reopen the terminal, because imsg needs that permission to read ~/Library/Messages/chat.db.

Start by listing chats and noting an id.

bash
imsg chats --limit 3

Use an id from that output in place of 42 in the next command, which reads the ten most recent messages in that thread.

bash
imsg history --chat-id 42 --limit 10

Sending needs Automation permission to Messages in addition to Full Disk Access. The README's example is a plain text send to an E.164 number.

bash
imsg send --to "+14155551212" --text "on my way"

For machine consumption, add --json. The README states that --json emits one JSON object per line, and that human progress and warnings stay on stderr so stdout remains safe to stream. Pipe finite commands through jq -s when you want a single array.

bash
imsg chats --json | jq -s

For a long-running consumer, imsg rpc starts the stdio JSON-RPC transport the README describes as the interface for agents and gateways. The README also mentions imsg completions llm for model-ready CLI help.

Linux, SMS forwarding and the limits you hit first

The most important limitation is platform. Signed macOS builds and Linux x86_64 read-only builds are published on GitHub Releases, but the Linux build reads a chat.db copied from macOS. It does not connect to iMessage and it does not send messages. Anyone hoping to run imsg as a server-side iMessage gateway on Linux is looking at the wrong artifact: the Linux guide covers reading a copied database, nothing more. The README points readers there explicitly.

Sending has its own gate. For SMS you must enable Text Message Forwarding on the paired iPhone. That is a setting on the phone, not a flag on the command.

Permissions are the second failure surface. Full Disk Access is required for local reads, and the README warns about parent-process grants and stale TCC entries, with a troubleshooting document mapping common failures to their likely gate. A stale TCC entry after a binary update is a realistic first-hour problem, and the documentation treats it as such.

The advanced IMCore surface is where the trade-off is sharpest. Read receipts, typing indicators, rich sends, stickers, polls and chat management need an injected helper, SIP disabled, and may still be blocked by library validation or private-entitlement checks on current macOS releases. That is a large security and stability concession for features that sit outside the core read, watch and send loop. The README frames it as advanced, and the framing is honest: most automation does not need it.

imsg compared with BlueBubbles and with not using Messages at all

The related searches around this project pair it with BlueBubbles, so the comparison is worth making concrete. BlueBubbles is a server that runs on a Mac and exposes Messages over HTTP to clients on other machines, including phones and non-Apple devices. imsg is a local CLI: it reads the database directly and emits NDJSON or JSON-RPC on stdout. If your consumer is a process on the same Mac, imsg removes an HTTP hop and a server process. If your consumer is a phone or a remote host, the architecture of a server like BlueBubbles is the one that matches the problem.

A second alternative is to skip Messages entirely for agent messaging and use a chat platform with a first-class bot API. The related searches include a comparison between iMessage and Telegram, and the difference is not cosmetic. Telegram bots authenticate with a token and work from any host, including Linux containers. imsg gives you the threads a person actually uses, on the Mac where those threads live, with no bot account and no third-party service in the path. That is the reason to accept the macOS and permission constraints. If your users are not on iMessage, none of that matters and the constraints are pure cost.

Maintenance, build and licence

The repository is not archived and the last push was on 2026-08-28, the same date as the v0.14.2 release. The release history shows v0.14.0 on 2026-08-10, v0.14.1 on 2026-08-11 and v0.14.2 on 2026-08-28, so the project is moving in small increments rather than sitting still.

Upgrade cost is mostly operational, not code. The package uses Swift 6 and targets macOS 14 or newer, and the Makefile exposes make lint, make test and make build for anyone building from source. The test target is not a single command: make test runs the docs-site Node tests, then make test-helper, then scripts/generate-version.sh, scripts/patch-deps.sh and swift test. On Linux, make test-helper prints that it is skipping the native bridge tests, which are macOS only. That is a real constraint for contributors without a Mac: the injected helper tests compile Objective-C against AppKit and LinkPresentation and cannot run elsewhere.

The licence is MIT, stated in the README and present as a LICENSE file at the repository root. MIT is permissive, so the usual implications are that you can use, modify and redistribute the code with the licence and copyright notice retained. That is a description of the licence text, not legal advice; check the LICENSE file for the exact terms. The README also states the project is not affiliated with Apple, and that iMessage and SMS are trademarks of their respective owners. If you ship a product built on imsg, that disclaimer is worth carrying forward.

Editorial conclusion

Adopt imsg if you have a Mac that already runs Messages.app, you can grant Full Disk Access to the terminal or agent process, and you want chat history and sends as NDJSON or JSON-RPC rather than through a GUI. Do not adopt it for a Linux server that must send iMessages: the Linux build is read-only and works on a copied chat.db. Before wiring anything to it, verify that the process has Full Disk Access, that Automation to Messages is granted, and that --json output is the shape your parser expects.

Frequently asked questions

Can openclaw/imsg work with iMessage?

Yes. imsg reads the local Messages database at ~/Library/Messages/chat.db and sends through Messages.app automation, and the README describes it as a CLI for reading, watching and sending iMessage and SMS from macOS. Full Disk Access is required for reads, and sending also needs Automation permission for Messages.

Can openclaw/imsg send text Messages?

Yes. The README gives imsg send --to "+14155551212" --text "on my way" as the send example, and send uses Messages.app's AppleScript surface. One documented limit is that it cannot force a particular outgoing number when several numbers share one Apple ID.

Can I use openclaw/imsg on a Linux system?

Only for reading. Signed macOS builds and Linux x86_64 read-only builds are available from GitHub Releases, and the Linux build reads a chat.db copied from macOS. The README states plainly that it does not connect to iMessage or send messages.

Is openclaw/imsg safe?

The normal chats, history, watch, send and read-only RPC workflows do not use private frameworks or process injection, according to the README. The optional advanced IMCore features do inject a helper into Messages.app and require SIP to be disabled, which is a larger concession and is documented separately.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/openclaw-imsg.svg)](https://hysenlabs.com/projects/openclaw-imsg)