Files
fidelity-ai-workspace/scripts/iphone-photo-inbox

iPhone Photo Inbox

Local HTTP receiver for sending JPEGs from iPhone Shortcuts into Mac inboxes. The Shortcut sends a profile, and the Mac decides the destination folder and clipboard behavior.

Profiles

opencode

  • Saves to ai/inbox/photos/
  • Copies terminal-safe paths to the clipboard
  • Best for pasting into OpenCode running in a terminal

mattermost

  • Saves to ~/Pictures/iPhone Inbox
  • Copies native macOS file URLs to the clipboard
  • Best effort for pasting one or more files directly into Mattermost

general

  • Saves to ~/Pictures/iPhone Inbox
  • Does not modify the clipboard
  • Useful for plain capture

All profiles show a macOS notification by default.

Batch debounce

Uploads are grouped by profile. Every new photo extends the active profile batch by 10 seconds and immediately refreshes the clipboard with the full batch.

Example for opencode:

photo 1 arrives -> clipboard has photo 1 path
photo 2 arrives within 10s -> clipboard has photo 1 + photo 2 paths
photo 3 arrives within 10s -> clipboard has photo 1 + photo 2 + photo 3 paths
10s pass with no new photo -> notification says the batch is ready

This keeps the Shortcut simple while still making the clipboard usable before the final notification appears.

For mattermost, each upload rewrites the clipboard with the full batch using a small Swift helper and NSPasteboard.writeObjects. This is closer to Finder's file-copy behavior than the older AppleScript alias approach. If the native helper fails, the receiver falls back to AppleScript and logs the fallback.

Start the receiver

Recommended:

IPHONE_PHOTO_TOKEN="choose-a-token" python3 scripts/iphone-photo-inbox/receiver.py

The receiver listens on:

http://MAC_IP:8787/upload

Find the Mac IP address on the current network:

ipconfig getifaddr en0

If that does not return an IP, use:

ifconfig

Shortcut config

Use a Dictionary near the top of the Shortcut:

mac_ip: 192.168.11.186
port: 8787
token: choose-a-token
profile: opencode

Build the URL from the dictionary:

http://[mac_ip]:[port]/upload?token=[token]&profile=[profile]

Use profile: opencode when the next paste target is OpenCode. Use profile: mattermost when the next paste target is Mattermost.

Camera shortcut

Dictionary
    mac_ip: 192.168.11.186
    port: 8787
    token: choose-a-token
    profile: opencode

Text
    http://[mac_ip]:[port]/upload?token=[token]&profile=[profile]

Take Photo
    Show Camera Preview: On

Get Contents of URL
    URL: Text
    Method: POST
    Request Body: File
    File: Photo

Show Notification
    Sent to [profile]

On the tested iPhone flow, Take Photo already produces a JPEG, so no conversion step is needed.

Existing photos shortcut

Use this when sending existing images from Photos:

Receive Images and Media from Share Sheet
Repeat with Each Item in Shortcut Input
    Convert Image
        Image: Repeat Item
        Format: JPEG
    Get Contents of URL
        URL: http://[mac_ip]:[port]/upload?token=[token]&profile=[profile]
        Method: POST
        Request Body: File
        File: Converted Image
End Repeat
Show Notification
    Sent to [profile]

Overrides

Profile folders:

IPHONE_PHOTO_OPENCODE_DIR="/path/to/opencode/photos"
IPHONE_PHOTO_MATTERMOST_DIR="$HOME/Pictures/iPhone Inbox"
IPHONE_PHOTO_GENERAL_DIR="$HOME/Pictures/iPhone Inbox"

Global folder override for all profiles:

IPHONE_PHOTO_OUTPUT_DIR="$HOME/Pictures/iPhone Inbox" \
IPHONE_PHOTO_TOKEN="choose-a-token" \
python3 scripts/iphone-photo-inbox/receiver.py

Default profile when the URL does not include profile=:

IPHONE_PHOTO_PROFILE=mattermost \
IPHONE_PHOTO_TOKEN="choose-a-token" \
python3 scripts/iphone-photo-inbox/receiver.py

Clipboard override for all profiles:

IPHONE_PHOTO_CLIPBOARD=image
IPHONE_PHOTO_CLIPBOARD=files
IPHONE_PHOTO_CLIPBOARD=terminal-path
IPHONE_PHOTO_CLIPBOARD=path
IPHONE_PHOTO_CLIPBOARD=file
IPHONE_PHOTO_CLIPBOARD=none

Debounce override:

IPHONE_PHOTO_DEBOUNCE_SECONDS=5

Other useful options:

python3 scripts/iphone-photo-inbox/receiver.py --no-notify
python3 scripts/iphone-photo-inbox/receiver.py --reveal
IPHONE_PHOTO_DEBUG=1 python3 scripts/iphone-photo-inbox/receiver.py

Troubleshooting

Startup should print each active profile:

profile opencode: dir=... clipboard=terminal-path notify=True reveal=False
profile mattermost: dir=... clipboard=files notify=True reveal=False

After each upload, expect:

clipboard mode applied: terminal-path profile=opencode count=2
saved ... profile=opencode batch_count=2

After the debounce window closes, expect:

batch notification sent profile=opencode count=2
batch finalized profile=opencode count=2 dir=...

The native file clipboard helper lives at:

scripts/iphone-photo-inbox/copy_files_to_clipboard.swift

For faster multi-file clipboard updates during debounce, compile it once:

swiftc scripts/iphone-photo-inbox/copy_files_to_clipboard.swift \
  -o scripts/iphone-photo-inbox/copy_files_to_clipboard

The compiled binary is ignored by git. If it is not present, the receiver can run the Swift script directly, but that is slower on first use.

If files arrive but clipboard/notifications do not behave as expected, check:

  • The Shortcut URL includes the intended profile=.
  • The receiver log shows the expected profile.
  • With IPHONE_PHOTO_DEBUG=1, the Mattermost profile should report pasteboard files=2 items=2 after the second photo in a two-photo batch.
  • macOS Focus/Do Not Disturb is not hiding notifications.
  • Terminal/Codex has permission for AppleScript automation if macOS prompts.