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.
Note
✨ Looking for advanced features like threaded replies, tapbacks, message editing, unsending, live typing indicators? Check out Advanced iMessage Kit and contact us at [email protected].
| 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 |
# For Bun (zero dependencies)
bun add @photon-ai/imessage-kit
# For Node.js (requires better-sqlite3)
npm install @photon-ai/imessage-kit better-sqlite3import { 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()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>
}
}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)
Examples: 01-send-text.ts | 02-send-image.ts | 03-send-file.ts | 05-query-messages.ts
// Send text
await sdk.send('+1234567890', 'Hello World!')
// Send to email
await sdk.send('[email protected]', 'Hello!')// 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 (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')// 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`)Examples: 04-send-group.ts | 06-list-chats.ts
// 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
})
}// 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']
})Examples: 07-watch-messages.ts | 08-auto-reply.ts | 13-watch-own-messages.ts
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()await sdk.startWatching({
onDirectMessage: async (msg) => {
await sdk.message(msg)
.ifFromOthers()
.matchText(/hello/i)
.replyText('Hi there!')
.execute()
}
})await sdk.message(msg)
.ifUnread()
.ifGroupChat()
.when(m => m.sender.startsWith('+1'))
.matchText(/photo/i)
.replyImage(['photo.jpg'])
.execute()Examples: 02-send-image.ts | 03-send-file.ts
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')
}
}- 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
Examples: 14-scheduled-messages.ts | 15-smart-reminders.ts
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()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"
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')
})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)
}
}Run any example with Bun:
bun run examples/<filename>.ts- 01-send-text.ts - Basic text message
- 02-send-image.ts - Send images
- 03-send-file.ts - Send files
- 05-query-messages.ts - Query messages
- 09-batch-send.ts - Batch sending
- 10-get-sent-message.ts - Get sent message
- 04-send-group.ts - Send to group
- 06-list-chats.ts - List chats
- 07-watch-messages.ts - Watch messages
- 08-auto-reply.ts - Auto-reply bot
- 13-watch-own-messages.ts - Watch own messages
- 14-scheduled-messages.ts - Scheduled messages
- 15-smart-reminders.ts - Smart reminders
- 11-plugin.ts - Custom plugin
- 12-error-handling.ts - Error handling
| 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 |
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
}
interface SendResult {
sentAt: Date
message?: Message // Available if watcher is running
}- OS: macOS only
- Runtime: Node.js >= 18.0.0 or Bun >= 1.0.0
- Permissions: Full Disk Access
Download llms.txt for language model context:
Add Context7 MCP to your IDE, then use:
use context7: photon-hq/imessage-kit
Note: This SDK is for educational and development purposes. Always respect user privacy and follow Apple's terms of service.
