imsg
The imsg command-line tool enables you to send and read iMessage and SMS messages directly from the terminal, query your Messages database, and watch for incoming messages.
⚠️ Important Privacy & Database Notes
- Database Access:
imsg reads from your local Messages database (~/Library/Messages/chat.db). This is a sensitive file containing your complete message history.
- Permissions: macOS may prompt for permissions when accessing the Messages database. Terminal needs Full Disk Access on newer macOS versions.
- Data Sensitivity: Be cautious when working with message history — it contains private conversations.
- Database Locking: If Messages.app is open, the database may be locked. Close Messages.app if you encounter access issues.
Commands Overview
imsg has four main commands:
chats — List your recent iMessage/SMS conversations
history — Show message history for a specific chat
watch — Stream incoming messages in real-time
send — Send a message (text and/or attachment)
rpc — Run JSON-RPC over stdin/stdout (advanced)
chats — List Conversations
List recent iMessage and SMS conversations from your Messages database.
Usage
imsg chats [options]
Options
--limit <number> — Number of chats to list (e.g., --limit 5)
--json or -j — Output as machine-readable JSON
--db <path> — Custom path to chat.db (defaults to ~/Library/Messages/chat.db)
-v, --verbose — Enable verbose logging
--log-level <level> — Set log level: trace|verbose|debug|info|warning|error|critical
Examples
# List 10 most recent conversations
imsg chats --limit 10
# List conversations as JSON (easier to parse)
imsg chats --limit 5 --json
# List all conversations (no limit)
imsg chats
history — Show Message History
Retrieve message history for a specific conversation. Requires a chat ID (which you get from imsg chats).
Usage
imsg history [options]
Options
--chat-id <id> — Chat ID from imsg chats (required unless using --participants)
--limit <number> — Number of messages to show
--participants <handles> — Filter by participant phone/email (e.g., +15551234567 or [email protected])
--start <ISO8601> — Start date (inclusive), e.g., 2025-01-01T00:00:00Z
--end <ISO8601> — End date (exclusive)
--attachments — Include attachment metadata in results
--json or -j — Output as JSON
--db <path> — Custom path to chat.db
-v, --verbose — Enable verbose logging
--log-level <level> — Set log level
Examples
# Last 20 messages from chat ID 1
imsg history --chat-id 1 --limit 20
# Last 50 messages with attachment info
imsg history --chat-id 1 --limit 50 --attachments
# Messages in date range (as JSON)
imsg history --chat-id 1 --start 2025-01-01T00:00:00Z --end 2025-02-01T00:00:00Z --json
# Messages from specific participant
imsg history --chat-id 1 --participants +15551234567 --limit 10
watch — Stream Incoming Messages
Watch for and stream incoming iMessage/SMS messages in real-time. Useful for monitoring conversations without opening Messages.app.
Usage
imsg watch [options]
Options
--chat-id <id> — Limit to a specific chat (optional)
--since-rowid <id> — Start watching after this message rowid (skip old messages)
--participants <handles> — Filter by participant phone/email
--start <ISO8601> — ISO8601 start time (inclusive)
--end <ISO8601> — ISO8601 end time (exclusive)
--debounce <duration> — Debounce filesystem events (e.g., 250ms) to avoid duplicate notifications
--attachments — Include attachment metadata
--json or -j — Output as JSON (one JSON object per message)
--db <path> — Custom path to chat.db
-v, --verbose — Enable verbose logging
--log-level <level> — Set log level
Examples
# Watch all incoming messages
imsg watch
# Watch specific chat only (with attachments)
imsg watch --chat-id 1 --attachments
# Watch from specific participant
imsg watch --participants +15551234567
# Watch with debouncing (less spam)
imsg watch --chat-id 1 --debounce 500ms --json
send — Send a Message
Send an iMessage or SMS message. You can send text, attachments, or both.
Usage
imsg send [options]
Target Options (choose one method)
--to <handle> — Phone number or email address (e.g., +14155551212 or [email protected])
--chat-id <id> — Send to an existing chat by rowid
--chat-identifier <id> — Send to chat identifier string (e.g., iMessage;+;chat...)
--chat-guid <guid> — Send to chat by GUID
Message Options
--text <message> — Message body (plain text)
--file <path> — Path to attachment file (e.g., ~/Desktop/photo.jpg)
--service <type> — Service: imessage|sms|auto (default: auto)
- auto — Automatically choose iMessage if available, fallback to SMS - imessage — Force iMessage (may fail if recipient not on iMessage) - sms — Force SMS
Other Options
--region <code> — Default region for phone number normalization (e.g., US)
--json or -j — Output result as JSON
--db <path> — Custom path to chat.db
-v, --verbose — Enable verbose logging
--log-level <level> — Set log level
Examples
# Send SMS to a phone number
imsg send --to +14155551212 --text "Hi there!"
# Send iMessage with attachment (auto-falls back to SMS if needed)
imsg send --to [email protected] --text "Check this out" --file ~/Desktop/photo.jpg --service auto
# Send to existing chat
imsg send --chat-id 1 --text "Hello from the terminal!"
# Send with JSON output (useful for scripting)
imsg send --to +14155551212 --text "Hi" --json
Service Selection (auto Fallback)
When using --service auto (recommended):
- If the recipient is on iMessage, the message sends as iMessage (free, full features)
- If iMessage fails, it automatically falls back to SMS (costs may apply, carrier fees)
- This ensures reliable delivery across Apple and non-Apple devices
rpc — JSON-RPC (Advanced)
For advanced use cases, imsg supports JSON-RPC over stdin/stdout. This allows programmatic interaction with the tool. See imsg rpc --help for details.
General Options (All Commands)
--db <path> — Override default chat.db location (defaults to ~/Library/Messages/chat.db)
--log-level <level> — Set verbosity: trace|verbose|debug|info|warning|error|critical
-v, --verbose — Enable verbose output
--json or -j — Output as JSON (available on most commands)
Workflow Examples
1. Find a Conversation and Read Recent Messages
# List recent chats
imsg chats --limit 10
# Read last 20 messages from chat ID 3
imsg history --chat-id 3 --limit 20
2. Send a Message to Someone
# Send SMS or iMessage (auto-selects)
imsg send --to +14155551212 --text "Hello!"
# Or send to an existing chat
imsg chats --limit 5
imsg send --chat-id 2 --text "Hi there!"
3. Monitor a Conversation in Real-Time
# Watch for new messages in chat ID 1
imsg watch --chat-id 1 --debounce 500ms
# Watch with JSON output
imsg watch --chat-id 1 --json
4. Extract Messages for Backup or Analysis
# Get all messages from a chat as JSON
imsg history --chat-id 1 --json > backup.json
# Get messages from a date range
imsg history --chat-id 1 --start 2024-01-01T00:00:00Z --end 2024-12-31T23:59:59Z --json
Tips & Troubleshooting
- Messages.app Lock: If you get database locked errors, close Messages.app first
- Permissions: On newer macOS (Ventura+), Terminal needs Full Disk Access to read the Messages database. Grant it in System Settings > Privacy & Security
- Phone Number Formatting: Use international format (e.g.,
+14155551212 for US numbers)
- JSON Output: Most commands support
--json for scripting and parsing
- Debouncing: When using
watch, set --debounce to avoid spam from rapid file system events
- Private Data: Remember that message history is sensitive — be careful with backups and logs