feat: enhance iPhone photo inbox receiver with profile management and clipboard options
This commit is contained in:
@@ -1,123 +1,108 @@
|
||||
# iPhone Photo Inbox
|
||||
|
||||
Local HTTP receiver for sending JPEGs from iPhone Shortcuts into a Mac folder.
|
||||
The transport is intentionally generic: the iPhone uploads a JPEG, and the Mac
|
||||
chooses the destination folder.
|
||||
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.
|
||||
|
||||
Default destination:
|
||||
## Profiles
|
||||
|
||||
```text
|
||||
ai/inbox/photos/
|
||||
```
|
||||
`opencode`
|
||||
|
||||
That default is useful for OpenCode because the images land inside this
|
||||
workspace as raw evidence. For broader use, point the receiver at a neutral
|
||||
folder such as `~/Pictures/iPhone Inbox`.
|
||||
- Saves to `ai/inbox/photos/`
|
||||
- Copies a terminal-safe path to the clipboard
|
||||
- Best for pasting into OpenCode running in a terminal
|
||||
|
||||
`mattermost`
|
||||
|
||||
- Saves to `~/Pictures/iPhone Inbox`
|
||||
- Copies the image data to the clipboard
|
||||
- Best for pasting 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.
|
||||
|
||||
## Start the receiver
|
||||
|
||||
OpenCode/workspace inbox:
|
||||
Recommended:
|
||||
|
||||
```bash
|
||||
IPHONE_PHOTO_TOKEN="choose-a-token" python3 scripts/iphone-photo-inbox/receiver.py
|
||||
```
|
||||
|
||||
General-purpose photo inbox:
|
||||
|
||||
```bash
|
||||
IPHONE_PHOTO_TOKEN="choose-a-token" \
|
||||
IPHONE_PHOTO_OUTPUT_DIR="$HOME/Pictures/iPhone Inbox" \
|
||||
python3 scripts/iphone-photo-inbox/receiver.py
|
||||
```
|
||||
|
||||
Useful receive modes:
|
||||
|
||||
```bash
|
||||
# Show a macOS notification when a photo arrives.
|
||||
IPHONE_PHOTO_NOTIFY=1 IPHONE_PHOTO_TOKEN="choose-a-token" python3 scripts/iphone-photo-inbox/receiver.py
|
||||
|
||||
# Reveal each received photo in Finder.
|
||||
IPHONE_PHOTO_REVEAL=1 IPHONE_PHOTO_TOKEN="choose-a-token" python3 scripts/iphone-photo-inbox/receiver.py
|
||||
|
||||
# Copy each received photo file to the Mac clipboard for pasting into apps.
|
||||
IPHONE_PHOTO_COPY=1 IPHONE_PHOTO_TOKEN="choose-a-token" python3 scripts/iphone-photo-inbox/receiver.py
|
||||
```
|
||||
|
||||
These can be combined:
|
||||
|
||||
```bash
|
||||
IPHONE_PHOTO_NOTIFY=1 \
|
||||
IPHONE_PHOTO_COPY=1 \
|
||||
IPHONE_PHOTO_OUTPUT_DIR="$HOME/Pictures/iPhone Inbox" \
|
||||
IPHONE_PHOTO_TOKEN="choose-a-token" \
|
||||
python3 scripts/iphone-photo-inbox/receiver.py
|
||||
```
|
||||
|
||||
The flags also accept `true`, `yes`, or `on`:
|
||||
|
||||
```bash
|
||||
IPHONE_PHOTO_NOTIFY=true IPHONE_PHOTO_COPY=true ...
|
||||
```
|
||||
|
||||
When these modes are active, the receiver startup log should include:
|
||||
The receiver listens on:
|
||||
|
||||
```text
|
||||
notifications enabled
|
||||
clipboard copy enabled
|
||||
http://MAC_IP:8787/upload
|
||||
```
|
||||
|
||||
After each upload, it should also print:
|
||||
|
||||
```text
|
||||
notification sent
|
||||
copied file to clipboard
|
||||
```
|
||||
|
||||
If those startup lines do not appear, the environment variables were not passed
|
||||
to the running receiver process. If the startup lines appear but the post-upload
|
||||
lines do not, check the printed `macOS action failed:` error and macOS privacy
|
||||
permissions for Terminal/Codex automation and notifications.
|
||||
|
||||
Find the Mac IP address on the current network:
|
||||
|
||||
```bash
|
||||
ipconfig getifaddr en0
|
||||
```
|
||||
|
||||
The iPhone Shortcut should send each JPEG to:
|
||||
If that does not return an IP, use:
|
||||
|
||||
```text
|
||||
http://MAC_IP:8787/upload?token=choose-a-token
|
||||
```bash
|
||||
ifconfig
|
||||
```
|
||||
|
||||
## Shortcut shape
|
||||
## Shortcut config
|
||||
|
||||
### Fastest reliable flow
|
||||
|
||||
Put this Shortcut on the Home Screen, Lock Screen, Action Button, or Back Tap.
|
||||
This is the most reliable "take photo and send immediately" flow because the
|
||||
Shortcut owns the capture and upload sequence.
|
||||
|
||||
Use this when you want the camera itself to be the capture flow:
|
||||
Use a Dictionary near the top of the Shortcut:
|
||||
|
||||
```text
|
||||
mac_ip: 192.168.11.186
|
||||
port: 8787
|
||||
token: choose-a-token
|
||||
profile: opencode
|
||||
```
|
||||
|
||||
Build the URL from the dictionary:
|
||||
|
||||
```text
|
||||
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
|
||||
|
||||
```text
|
||||
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: http://MAC_IP:8787/upload?token=choose-a-token
|
||||
URL: Text
|
||||
Method: POST
|
||||
Request Body: File
|
||||
File: Photo
|
||||
|
||||
Show Notification
|
||||
Sent to Mac photo inbox
|
||||
Sent to [profile]
|
||||
```
|
||||
|
||||
On the tested iPhone flow, `Take Photo` already produces a JPEG, so the
|
||||
conversion step is intentionally omitted for the fastest path.
|
||||
On the tested iPhone flow, `Take Photo` already produces a JPEG, so no
|
||||
conversion step is needed.
|
||||
|
||||
### Existing Photos flow
|
||||
## Existing photos shortcut
|
||||
|
||||
Use this when you want to send existing images from Photos:
|
||||
Use this when sending existing images from Photos:
|
||||
|
||||
```text
|
||||
Receive Images and Media from Share Sheet
|
||||
@@ -126,55 +111,84 @@ Repeat with Each Item in Shortcut Input
|
||||
Image: Repeat Item
|
||||
Format: JPEG
|
||||
Get Contents of URL
|
||||
URL: http://MAC_IP:8787/upload?token=choose-a-token
|
||||
URL: http://[mac_ip]:[port]/upload?token=[token]&profile=[profile]
|
||||
Method: POST
|
||||
Request Body: File
|
||||
File: Converted Image
|
||||
End Repeat
|
||||
Show Notification
|
||||
Sent to Mac photo inbox
|
||||
Sent to [profile]
|
||||
```
|
||||
|
||||
### Semi-automatic Camera.app flow
|
||||
## Overrides
|
||||
|
||||
iOS does not expose a clean "new photo was taken" automation trigger. The
|
||||
closest option is a Personal Automation:
|
||||
Profile folders:
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
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=`:
|
||||
|
||||
```bash
|
||||
IPHONE_PHOTO_PROFILE=mattermost \
|
||||
IPHONE_PHOTO_TOKEN="choose-a-token" \
|
||||
python3 scripts/iphone-photo-inbox/receiver.py
|
||||
```
|
||||
|
||||
Clipboard override for all profiles:
|
||||
|
||||
```bash
|
||||
IPHONE_PHOTO_CLIPBOARD=image
|
||||
IPHONE_PHOTO_CLIPBOARD=terminal-path
|
||||
IPHONE_PHOTO_CLIPBOARD=path
|
||||
IPHONE_PHOTO_CLIPBOARD=file
|
||||
IPHONE_PHOTO_CLIPBOARD=none
|
||||
```
|
||||
|
||||
Other useful options:
|
||||
|
||||
```bash
|
||||
python3 scripts/iphone-photo-inbox/receiver.py --no-notify
|
||||
python3 scripts/iphone-photo-inbox/receiver.py --reveal
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Startup should print each active profile:
|
||||
|
||||
```text
|
||||
When Camera is Closed
|
||||
Get Latest Photos
|
||||
Include Screenshots: Off
|
||||
Limit: 1
|
||||
Convert Image
|
||||
Format: JPEG
|
||||
Get Contents of URL
|
||||
URL: http://MAC_IP:8787/upload?token=choose-a-token
|
||||
Method: POST
|
||||
Request Body: File
|
||||
File: Converted Image
|
||||
profile opencode: dir=... clipboard=terminal-path notify=True reveal=False
|
||||
profile mattermost: dir=... clipboard=image notify=True reveal=False
|
||||
```
|
||||
|
||||
This is convenient, but it can resend the latest photo if you open and close
|
||||
Camera without taking a new one. Prefer the Shortcut-owned camera flow when
|
||||
duplicates would be annoying.
|
||||
After upload, expect:
|
||||
|
||||
## Usage profiles
|
||||
```text
|
||||
notification sent
|
||||
clipboard mode applied: terminal-path
|
||||
saved ... profile=opencode
|
||||
```
|
||||
|
||||
OpenCode analysis:
|
||||
For Mattermost, expect:
|
||||
|
||||
- Use the default `ai/inbox/photos/` destination.
|
||||
- Reference the received file directly from this workspace.
|
||||
- Treat received files as raw evidence until reviewed.
|
||||
```text
|
||||
clipboard mode applied: image
|
||||
```
|
||||
|
||||
Mattermost / Jeff:
|
||||
If files arrive but clipboard/notifications do not behave as expected, check:
|
||||
|
||||
- Use a neutral destination such as `~/Pictures/iPhone Inbox`.
|
||||
- Attach the latest received JPEG from Mattermost on the Mac.
|
||||
- Keep the same Shortcut and URL; only the Mac receiver destination changes.
|
||||
|
||||
General capture:
|
||||
|
||||
- Use the neutral destination when the photo is not specifically workspace
|
||||
evidence.
|
||||
- Keep JPEG validation enabled in the receiver so downstream tools get a
|
||||
predictable format.
|
||||
- The Shortcut URL includes the intended `profile=`.
|
||||
- The receiver log shows the expected profile.
|
||||
- macOS Focus/Do Not Disturb is not hiding notifications.
|
||||
- Terminal/Codex has permission for AppleScript automation if macOS prompts.
|
||||
|
||||
Reference in New Issue
Block a user