iMessage has no official API. Apple’s closed ecosystem means most automation attempts rely on AppleScript hacks, GUI automation, or jailbroken device proxies. LINQ CLI sidesteps all of that. It provides a command-line interface to iMessage that agents can call directly. No browser sessions, no screen scraping, no unofficial reverse engineering.
The product page shows a Node.js CLI that wraps LINQ’s messaging API. You install it via npm, authenticate once, and send iMessages from your terminal. The CLI handles chat creation, message sending with effects (confetti, fireworks), tapbacks, group conversations, and attachments.
Authentication Boundary
LINQ CLI does not store your Apple ID credentials locally. Instead, it uses a token-based authentication model:
- You run
linq signuporlinq loginto authenticate once. - The CLI receives an API token tied to your LINQ account.
- LINQ’s backend handles the iMessage connection through their infrastructure.
This means you are not running iMessage on your local machine. You are calling LINQ’s API, which maintains persistent iMessage sessions on their servers. The CLI is a thin client that wraps HTTP calls to LINQ’s messaging API.
Security trade-off: You trust LINQ with message routing. Your iMessage traffic flows through their infrastructure. If you need end-to-end control, this is not the right tool. If you need a stable API without maintaining your own iMessage server, this is the cleanest option available.
Message Delivery and State
The CLI exposes structured output for message operations. The product page shows this example:
$ linq chats create --to +1234567890 --message "Hello!"
LINQ CLI supports:
- Message effects: Confetti, fireworks, and other iMessage animations (documented on product page).
- Tapbacks: Reactions (heart, thumbs up, etc.) as structured commands.
- Group chats: Create and manage multi-participant conversations.
- Attachments: Send images, videos, and files via the
linq attachmentscommand.
The product page does not document delivery confirmation, read receipts, or typing indicators. The CLI appears to return success when LINQ’s backend accepts the message, but detailed delivery telemetry is not exposed in the documented interface.
Rate Limits and Anti-Spam
Apple’s iMessage infrastructure has undocumented rate limits and spam detection heuristics. The product page mentions a sandbox environment with a 20-contact limit for testing, but does not publish specific rate limits for production use.
The typical failure mode with any iMessage automation:
- Sending too many messages to new contacts in a short window triggers Apple’s spam filters.
- Your iMessage session gets flagged or throttled.
- Messages start failing with generic error codes.
Mitigation strategies:
- Use the sandbox environment (
linq signupgives you a shared test number with a 20-contact limit) to validate flows before production. - Warm up new phone numbers by sending low-volume messages over several days.
- Avoid bulk messaging to contacts who have not messaged you first.
LINQ does not expose retry logic or backoff strategies in the CLI. If a message fails, you see an error. Your agent needs to handle retries and exponential backoff.
Bidirectional Communication: Webhooks and Polling
The product page documents webhook support for inbound messages:
$ linq webhooks listen --forward-to http://localhost:3000/webhook
This forwards incoming events (new messages, tapbacks, group chat updates) to your local endpoint. You get a real-time event stream without exposing your local server to the internet.
Event structure: The product page does not show webhook payload examples, but the CLI documentation indicates you receive message content, sender information, chat ID, and timestamp. Your agent parses the payload and decides how to respond.
Polling alternative: If you cannot run a persistent webhook listener, you can poll the API using linq chats list and linq messages list. This is slower and less efficient, but works for batch-style workflows where sub-second latency does not matter.
Architecture: CLI as Agent Tool
Here is how LINQ CLI fits into an agent orchestration flow:
| Component | Role | Failure Mode |
|---|---|---|
| Agent orchestrator | Decides when to send iMessage | Sends message to wrong contact if context window loses track of phone numbers |
| LINQ CLI | Executes linq chats create with parameters | Returns error if rate limit hit or phone number invalid |
| LINQ API backend | Maintains iMessage session, routes message | Session expires if Apple flags account; requires re-authentication |
| Webhook listener | Receives inbound messages, forwards to agent | Misses events if listener crashes; no built-in replay mechanism |
| Agent response logic | Parses webhook payload, decides next action | Infinite loop if agent responds to its own messages |
Example agent tool definition (pseudo-code for subprocess-based integration):
import subprocess
import json
def send_imessage(phone_number: str, message: str) -> dict:
"""Send iMessage via LINQ CLI."""
result = subprocess.run(
["linq", "chats", "create", "--to", phone_number, "--message", message],
capture_output=True,
text=True
)
if result.returncode != 0:
raise Exception(f"LINQ CLI error: {result.stderr}")
try:
return json.loads(result.stdout)
except json.JSONDecodeError as e:
raise Exception(f"Failed to parse LINQ CLI output: {e}")
Your agent calls this function when it needs to send a message. The CLI handles authentication, message formatting, and API calls. The agent gets back structured output it can log or use for follow-up actions.
Observability Gaps
The product page does not document detailed telemetry. Based on the available documentation, you do not get:
- Message delivery timestamps (when Apple’s servers delivered the message to the recipient’s device).
- Read receipts (when the recipient opened the message).
- Typing indicators (when the recipient is composing a reply).
- Retry attempts or backoff state from LINQ’s backend.
If you need these signals, you will need to instrument your own logging around CLI calls and webhook events. Track message IDs, correlate send times with webhook receipt times, and build your own delivery confirmation logic.
Deployment Shape
LINQ CLI is a Node.js package installed via npm. The product page shows installation:
npm install -g @linqapp/cli
It runs on macOS, Linux, and Windows (via WSL). Your deployment options:
- Local development: Install CLI on your laptop, run webhook listener for testing.
- CI/CD pipeline: Use CLI in GitHub Actions or similar to send deployment notifications.
- Agent runtime: Install CLI in the same container or VM as your agent orchestrator, call it as a subprocess.
Token management: The product page shows linq login and linq tokens commands for managing API tokens. If you run agents in ephemeral containers, you need to inject the token via environment variable or mount the config file as a secret.
When to Use LINQ CLI
Good fit:
- You need to send iMessages from agents without maintaining your own iMessage server.
- Your workflow tolerates LINQ’s infrastructure as a dependency.
- You are okay with rate limits and spam detection as external constraints.
- You need bidirectional messaging (send and receive) with webhook support.
Poor fit:
- You need end-to-end encryption guarantees and cannot trust a third-party relay.
- You require sub-second delivery confirmation or read receipts.
- You need to send high-volume messages (hundreds per minute) without rate limit risk.
- You want to self-host the entire iMessage stack.
Technical Verdict
LINQ CLI solves a real problem: iMessage has no official API, and unofficial solutions are fragile. The CLI provides a stable, token-authenticated interface that agents can call without AppleScript or GUI automation.
The trade-off is dependency on LINQ’s infrastructure. You do not control the iMessage session. You do not see detailed delivery telemetry. You accept Apple’s rate limits and spam detection as external constraints.
Use LINQ CLI when you need iMessage integration for agent workflows and are willing to trust a third-party relay. Avoid it if you need full control over message routing or high-volume throughput without rate limit risk.
For local-first agent workflows where iMessage is a notification channel (deployment alerts, status updates, human-in-the-loop confirmations), LINQ CLI is the most production-ready option available.