A full-featured iMessage SDK for reading, sending, and automating iMessage conversations on macOS. Perfect for building AI agents, automation tools, and chat-first applications.
Features
| Feature | Method | Example |
|---|---|---|
| Send Messages | sdk.send() |
01-send-text.ts |
| Send Images | sdk.send() |
02-send-image.ts |
| Send Files | sdk.sendFile() |
03-send-file.ts |
| Send to Groups | sdk.send() |
04-send-group.ts |
| Query Messages | sdk.getMessages() |
05-query-messages.ts |
| List Chats | sdk.listChats() |
06-list-chats.ts |
| Real-time Watching | sdk.startWatching() |
07-watch-messages.ts |
| Auto Reply | sdk.message() |
08-auto-reply.ts |
| Batch Send | sdk.sendBatch() |
09-batch-send.ts |
| Get Sent Message | sdk.send() |
10-get-sent-message.ts |
| Plugin System | sdk.use() |
11-plugin.ts |
| Error Handling | SendError |
12-error-handling.ts |
| Watch Own Messages | sdk.startWatching() |
13-watch-own-messages.ts |
| Scheduled Messages | MessageScheduler |
14-scheduled-messages.ts |
| Smart Reminders | Reminders |
15-smart-reminders.ts |
Quick Start
Installation
# For Bun (zero dependencies) bun add @photon-ai/imessage-kit # For Node.js (requires better-sqlite3) npm install @photon-ai/imessage-kit better-sqlite3
Basic Usage
import { IMessageSDK } from '@photon-ai/imessage-kit' const sdk = new IMessageSDK() // Send a message await sdk.send('+1234567890', 'Hello from iMessage Kit!') // Clean up await sdk.close()
Configuration
interface IMessageConfig { debug?: boolean // Enable debug logging maxConcurrent?: number // Max concurrent sends (default: 5) scriptTimeout?: number // AppleScript timeout in ms databasePath?: string // Custom database path plugins?: Plugin[] // Plugins watcher?: { pollInterval?: number // Polling interval (default: 2000) unreadOnly?: boolean // Only watch unread (default: false) excludeOwnMessages?: boolean // Exclude own messages (default: true) } webhook?: { url: string headers?: Record<string, string> } }
Granting Permission
IMessageKit requires Full Disk Access to read your chat history and perform automation tasks.
- Open System Settings → Privacy & Security → Full Disk Access
- Click "+" and add your IDE or terminal (e.g., Cursor, VS Code, Terminal, Warp)
Messages
Examples: 01-send-text.ts | 02-send-image.ts | 03-send-file.ts | 05-query-messages.ts
Send Messages
// Send text await sdk.send('+1234567890', 'Hello World!') // Send to email await sdk.send('user@example.com', 'Hello!')
Send Images
// Send local images await sdk.send('+1234567890', { images: ['image1.jpg', 'image2.png'] }) // Send network images (auto-download) await sdk.send('+1234567890', { images: ['https://example.com/image.jpg'] }) // Text with images await sdk.send('+1234567890', { text: 'Check this out!', images: ['photo.jpg'] })
Send Files
// Send files (PDF, CSV, VCF, etc.) await sdk.send('+1234567890', { files: ['document.pdf', 'data.csv', 'contact.vcf'] }) // Convenience methods await sdk.sendFile('+1234567890', '/path/to/document.pdf') await sdk.sendFiles('+1234567890', ['file1.pdf', 'file2.csv'], 'Multiple files')
Query Messages
// Get messages with filters const result = await sdk.getMessages({ sender: '+1234567890', unreadOnly: true, limit: 20, since: new Date('2025-01-01'), search: 'meeting' }) // Get unread messages grouped by sender const unread = await sdk.getUnreadMessages() console.log(`${unread.total} unread from ${unread.senderCount} senders`)
Chats
Examples: 04-send-group.ts | 06-list-chats.ts
List Chats
// Get all chats const all = await sdk.listChats() // Filter chats const groups = await sdk.listChats({ type: 'group', hasUnread: true, sortBy: 'recent', search: 'Project', limit: 20 }) // Each chat includes for (const chat of groups) { console.log({ chatId: chat.chatId, name: chat.displayName, isGroup: chat.isGroup, unread: chat.unreadCount }) }
Send to Groups
// Get group chatId from listChats() const groups = await sdk.listChats({ type: 'group' }) const chatId = groups[0].chatId // e.g., 'chat45e2b868...' // Send to group await sdk.send(chatId, 'Hello group!') await sdk.send(chatId, { text: 'Check these files', files: ['report.pdf'] })
Real-time Events
Examples: 07-watch-messages.ts | 08-auto-reply.ts | 13-watch-own-messages.ts
Real-time Watching
await sdk.startWatching({ // All messages onMessage: (msg) => { console.log(`New: ${msg.text}`) }, // DMs only onDirectMessage: (msg) => { console.log(`DM from ${msg.sender}`) }, // Groups only onGroupMessage: (msg) => { console.log(`Group: ${msg.chatId}`) }, onError: (error) => { console.error(error) } }) // Stop watching sdk.stopWatching()
Auto Reply
await sdk.startWatching({ onDirectMessage: async (msg) => { await sdk.message(msg) .ifFromOthers() .matchText(/hello/i) .replyText('Hi there!') .execute() } })
Message Chain API
await sdk.message(msg) .ifUnread() .ifNotReaction() // Skip tapback reactions .ifGroupChat() .when(m => m.sender.startsWith('+1')) .matchText(/photo/i) .replyImage(['photo.jpg']) .execute()
Attachments
Examples: 02-send-image.ts | 03-send-file.ts
Attachment Helpers
import { attachmentExists, downloadAttachment, getAttachmentSize, isImageAttachment, isVideoAttachment, isAudioAttachment } from '@photon-ai/imessage-kit' const msg = await sdk.getMessages({ hasAttachments: true, limit: 1 }) const attachment = msg.messages[0].attachments[0] if (await attachmentExists(attachment)) { const size = await getAttachmentSize(attachment) if (isImageAttachment(attachment)) { await downloadAttachment(attachment, '/path/to/save.jpg') } }
Supported File Types
- Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT, RTF
- Images: JPG, PNG, GIF, HEIC, WEBP, AVIF
- Contact Cards: VCF (vCard)
- Data Files: CSV, JSON, XML
- Archives: ZIP, RAR, 7Z
- Media: MP4, MOV, MP3, M4A
Scheduling
Examples: 14-scheduled-messages.ts | 15-smart-reminders.ts
Scheduled Messages
import { IMessageSDK, MessageScheduler } from '@photon-ai/imessage-kit' const sdk = new IMessageSDK() const scheduler = new MessageScheduler(sdk, { debug: true }, { onSent: (msg, result) => console.log(`✅ Sent: ${msg.id}`), onError: (msg, error) => console.error(`❌ Failed: ${error.message}`), onComplete: (msg) => console.log(`🏁 Completed: ${msg.id}`) }) // One-time message const id = scheduler.schedule({ to: '+1234567890', content: 'Reminder!', sendAt: new Date(Date.now() + 5 * 60 * 1000) // 5 minutes }) // Recurring daily scheduler.scheduleRecurring({ to: '+1234567890', content: 'Good morning! ☀️', startAt: new Date('2025-01-01T08:00:00'), interval: 'daily', // 'hourly' | 'daily' | 'weekly' | 'monthly' | number endAt: new Date('2025-12-31') }) // Manage scheduler.reschedule(id, newDate) scheduler.cancel(id) scheduler.getPending() // Persistence const data = scheduler.export() scheduler.import(data) // Cleanup scheduler.destroy()
Smart Reminders
A human-friendly wrapper for scheduling with natural language:
import { IMessageSDK, Reminders } from '@photon-ai/imessage-kit' const sdk = new IMessageSDK() const reminders = new Reminders(sdk) // Relative time reminders.in('5 minutes', '+1234567890', 'Take a break!') reminders.in('2 hours', '+1234567890', 'Call the client') reminders.in('1 day', '+1234567890', 'Follow up') // Specific time reminders.at('5pm', '+1234567890', 'End of day review') reminders.at('tomorrow 9am', '+1234567890', 'Morning standup') reminders.at('friday 2pm', '+1234567890', 'Weekly sync') // Exact date reminders.exact(new Date('2025-12-25T10:00:00'), '+1234567890', 'Merry Christmas!') // Manage reminders.list() // List pending reminders.count() // Count pending reminders.cancel(id) reminders.destroy()
Supported formats:
- Duration:
"5 minutes","2 hours","1 day","30 seconds","1 week" - Time:
"5pm","5:30pm","17:30" - Day + Time:
"tomorrow 9am","friday 2pm"
Plugin System
Example: 11-plugin.ts
import { loggerPlugin } from '@photon-ai/imessage-kit' // Built-in logger sdk.use(loggerPlugin({ level: 'info', colored: true })) // Custom plugin sdk.use({ name: 'my-plugin', onInit: async () => console.log('Initialized'), onBeforeSend: async (to, content) => { console.log('Sending to:', to) return { to, content } }, onAfterSend: async (result) => { console.log('Sent:', result) }, onDestroy: async () => console.log('Destroyed') })
Error Handling
Example: 12-error-handling.ts
import { SendError, DatabaseError, PlatformError } from '@photon-ai/imessage-kit' try { await sdk.send('+1234567890', 'Hello') } catch (error) { if (error instanceof SendError) { console.error('Send failed:', error.message) } else if (error instanceof DatabaseError) { console.error('Database error:', error.message) } else if (error instanceof PlatformError) { console.error('Platform error:', error.message) } }
Examples
Run any example with Bun:
bun run examples/<filename>.ts
Getting Started
- 01-send-text.ts - Basic text message
- 02-send-image.ts - Send images
- 03-send-file.ts - Send files
Message Operations
- 05-query-messages.ts - Query messages
- 09-batch-send.ts - Batch sending
- 10-get-sent-message.ts - Get sent message
Chats & Groups
- 04-send-group.ts - Send to group
- 06-list-chats.ts - List chats
Real-time & Automation
- 07-watch-messages.ts - Watch messages
- 08-auto-reply.ts - Auto-reply bot
- 13-watch-own-messages.ts - Watch own messages
Scheduling
- 14-scheduled-messages.ts - Scheduled messages
- 15-smart-reminders.ts - Smart reminders
Advanced
- 11-plugin.ts - Custom plugin
- 12-error-handling.ts - Error handling
API Reference
Core Methods
| Method | Description |
|---|---|
getMessages(filter?) |
Query messages with filters |
getUnreadMessages() |
Get unread messages grouped by sender |
listChats(options?) |
List chats with filtering/sorting |
send(to, content) |
Send text, images, and/or files |
sendFile(to, path, text?) |
Send a single file |
sendFiles(to, paths, text?) |
Send multiple files |
sendBatch(messages) |
Send multiple messages concurrently |
message(msg) |
Create message processing chain |
startWatching(events?) |
Start monitoring new messages |
stopWatching() |
Stop monitoring |
use(plugin) |
Register plugin |
close() |
Close SDK and release resources |
Types
interface Message { id: string guid: string text: string | null sender: string senderName: string | null chatId: string isGroupChat: boolean isFromMe: boolean isRead: boolean service: 'iMessage' | 'SMS' | 'RCS' attachments: Attachment[] date: Date // Reaction fields isReaction: boolean reactionType: 'love' | 'like' | 'dislike' | 'laugh' | 'emphasize' | 'question' | null isReactionRemoval: boolean associatedMessageGuid: string | null } interface SendResult { sentAt: Date message?: Message // Available if watcher is running }
Requirements
- OS: macOS only
- Runtime: Node.js >= 18.0.0 or Bun >= 1.0.0
- Permissions: Full Disk Access
LLMs
Download llms.txt for language model context:
Context7 MCP
Add Context7 MCP to your IDE, then use:
use context7: photon-hq/imessage-kit
License
Note: This SDK is for educational and development purposes. Always respect user privacy and follow Apple's terms of service.
