Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .agents/skills/imsg/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ description: "iMessage/SMS: local history, contacts, live watch, and requested s
- Every read command supports `--json` and emits **NDJSON** (one object per line). Pipe to `jq -s` to get an array. Stdout carries only JSON; progress and warnings go to stderr.
- Two capability tiers:
- **Standard** (normal permissions): `chats`, `group`, `history`, `watch`, `search`, `send`, `react`, `nickname --local`, `account --local`, `whois --local`.
- **Bridge** (SIP disabled + `imsg launch` dylib injection): `send-rich`, `send-multipart`, `send-attachment`, `send-sticker`, `tapback`, `poll`, `edit`, `unsend`, `delete-message`, `read`, `typing`, `notify-anyways`, `chat-*`, and default-mode `account`/`whois`/`nickname`.
- **Bridge** (SIP disabled + `imsg launch` dylib injection): `send-rich`, `send-multipart`, `send-attachment`, `send-sticker`, `tapback`, `poll`, `edit`, `unsend`, `delete-message`, `read`, `typing`, `notify-anyways`, `chat-*`, `name-photo`, and default-mode `account`/`whois`/`nickname`.
- Check availability with `imsg status --json` before using bridge commands. Stickers additionally require `send.sticker` in `rpc_methods` and `selectors.stickerSend`; attaching one requires `selectors.stickerAttach`. If the bridge is down, use a standard command only when it preserves the requested semantics; otherwise stop and explain. Never turn a reply/effect/subject into a plain send or a GUID-targeted tapback into `react`, and never suggest disabling SIP unprompted.
- Full command and flag reference: `imsg completions llm`.

Expand Down Expand Up @@ -41,6 +41,7 @@ imsg history --chat-id ID --start 2025-01-01T00:00:00Z --end 2025-02-01T00:00:00
imsg stats --chat-id ID --time-zone UTC --media --json # logical message + media totals
imsg scheduled list --json # future Send Later rows; read-only
imsg chat-background status --chat-id ID --json # inspect local background state; read-only
imsg name-photo status --chat GUID --json # read-only Share Name & Photo eligibility
```

- Chat `id` is the `chat.db` rowid: stable on one machine, the preferred `--chat-id` handle. `identifier` and `guid` are portable across machines.
Expand All @@ -67,10 +68,12 @@ Message `id` doubles as the watch cursor: persist the last-seen id and pass it b
imsg send --to "+15551234567" --text "message" --service auto
imsg send --chat-id ID --text "message" # prefer for groups: no address ambiguity
imsg send --to "+15551234567" --file ~/Desktop/pic.jpg
imsg name-photo share --chat GUID # shares YOUR Name & Photo; explicit request only
```

- `--service auto` prefers iMessage and falls back to SMS for text-only phone sends; `--no-sms-fallback` disables that.
- `imsg react --chat-id ID --reaction like` (AppleScript) only targets the **most recent incoming message** and needs Accessibility permission. To react to a specific message by GUID, use bridge `tapback`.
- `name-photo share` is not a vCard send. It discloses the local Messages Name & Photo to every participant in the selected chat; confirm the destination and explicit user intent before invoking it.

## Bridge extras

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- fix: isolate universal builds per architecture and consume SwiftPM's reported product paths so stale slices cannot silently ship older CLI code.

### Advanced IMCore
- feat: inspect and explicitly share Apple Messages Name & Photo through `imsg name-photo` and compatible contact RPC methods, while fixing bridge nickname lookup to use the current controller and handle APIs (thanks @omarshahine).
- fix: canonicalize securely staged attachment paths when Messages attachments are relocated through a symlink, and find nested threaded-reply items for edit, unsend, delete, and notify operations.

### Native Polls
Expand Down
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ Full docs: **[imsg.sh](https://imsg.sh)**.
- **Attachment-aware.** Filenames, UTIs, byte counts, resolved paths, and
optional CAF→M4A / GIF→PNG conversion for model consumers.
- **Advanced IMCore (opt-in).** Edit, unsend, delete, rich-text formatting,
effects, reply threading, native stickers, group create/rename/photo, member add/remove,
read receipts, typing indicators, and live event streams via the bridge.
effects, reply threading, native stickers, group create/rename/photo,
member add/remove, Name & Photo sharing, read receipts, typing indicators,
and live event streams via the bridge.
- **Linux read-only preview.** Inspect a copied Messages database from a Linux
host. No sending, no Messages.app integration.

Expand Down Expand Up @@ -147,6 +148,7 @@ Advanced IMCore (require `imsg launch` with SIP off — see
`imsg chat-add-member`, `imsg chat-remove-member`, `imsg chat-leave`,
`imsg chat-delete`, `imsg chat-mark`
- `imsg account`, `imsg whois`, `imsg nickname`
- `imsg name-photo status|share --chat <guid>`

`imsg status --json` reports native bridge selector capabilities. Poll creation
requires `selectors.pollPayloadMessage`; poll voting requires
Expand Down Expand Up @@ -384,6 +386,19 @@ imsg nickname --address +15551234567
imsg nickname --address +15551234567 --local
```

Messages Name & Photo:

```bash
imsg name-photo status --chat 'iMessage;-;+15551234567' # read-only offer eligibility
imsg name-photo share --chat 'iMessage;-;+15551234567' # explicitly share with participants
```

`status` reports whether Messages would currently offer its native Share Name
& Photo action; it is advisory, not a durable record of prior sharing. `share`
submits an explicit private-API send request and reports `requested: true`, not
a delivery receipt. Because it discloses your personal profile to every chat
participant, agents must only invoke it after an explicit user request.

Live events (typing indicators surfaced through the dylib):

```bash
Expand Down
4 changes: 3 additions & 1 deletion Sources/IMsgCore/IMsgBridgeProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public enum IMsgBridgeProtocol {
public static func defaultResponseTimeout(for action: BridgeAction) -> TimeInterval {
switch action {
case .sendMessage, .sendRichLink, .sendMultipart, .sendAttachment, .sendSticker, .sendPoll,
.sendPollVote, .sendPollUnvote, .sendReaction, .createChat:
.sendPollVote, .sendPollUnvote, .sendReaction, .createChat, .shareNickname:
return defaultSendResponseTimeout
default:
return defaultResponseTimeout
Expand Down Expand Up @@ -90,6 +90,8 @@ public enum BridgeAction: String, Sendable, CaseIterable {
case searchMessages = "search-messages"
case getAccountInfo = "get-account-info"
case getNicknameInfo = "get-nickname-info"
case shouldOfferNicknameSharing = "should-offer-nickname-sharing"
case shareNickname = "share-nickname"
case checkImessageAvailability = "check-imessage-availability"
case downloadPurgedAttachment = "download-purged-attachment"
}
Expand Down
Loading