| name | ios_device |
| description | Read iPhone data (contacts, calendar, reminders, location, photos, files, clipboard) and execute device commands (CRUD operations + open apps via URL schemes). Use when user asks about their phone data, wants to schedule events, set reminders, manage contacts, copy to clipboard, or open an app on their phone. NEVER suggest .ics files, email workarounds, or manual steps — always use device.sh.
|
iOS Device
Primary Usage
For all Apple device tasks, use the sub-agent with the user's timezone:
TZ=America/Los_Angeles node /root/workspace/skills/ios-device/apple-agent.js "<natural language request>"
CRITICAL: Always set TZ to the user's timezone (from your memory/config). The VPS runs in UTC — without TZ, all relative times ("in 1 hour", "tomorrow at 3pm") will be wrong. Common values: America/Los_Angeles, America/New_York, America/Chicago, Europe/London.
The sub-agent handles multi-step workflows (fetch, create, verify, web search) autonomously using claude-sonnet-4-5 with tool calling. It can search the web for addresses, track IDs, and business info before acting. Just pass the user's natural language request and relay the result.
Examples:
TZ=America/Los_Angeles node /root/workspace/skills/ios-device/apple-agent.js "remind me to call the dentist tomorrow at 10am"
TZ=America/New_York node /root/workspace/skills/ios-device/apple-agent.js "what's on my calendar today"
TZ=America/Los_Angeles node /root/workspace/skills/ios-device/apple-agent.js "find John Smith's phone number and text him 'running late'"
Only use device.sh directly for simple single-step operations where you already know the exact command.
Use When
- User asks about contacts, calendar, reminders, location, photos, files, or clipboard
- User wants to create/update/delete calendar events, reminders, or contacts
- User says "remind me to...", "schedule...", "what's on my calendar", "where am I"
- User wants to copy text to their phone's clipboard
- User wants to open an app: "get me directions", "play this song", "call John"
- User wants to write a file to iCloud or manage photos
Never Use When
- General knowledge questions unrelated to their device
- Questions about someone else's phone
- NEVER suggest .ics files, email workarounds, or manual steps when device.sh can do it directly
Quick Reference
bash /root/workspace/skills/ios-device/device.sh fetch <topic> [filters_json]
bash /root/workspace/skills/ios-device/device.sh send <action> '<json_params>'
bash /root/workspace/skills/ios-device/device.sh result <command-id>
Fetch Data — Topics
Fetches are real-time — data is read fresh from the device when requested (2-5 second typical, up to 90s with retries). The fetch automatically retries 3 times (~30s each) to handle cases where the phone is waking from background. If still unreachable after ~90s, returns {"error":"device_offline"}.
| Topic | What it returns | Native filters |
|---|
contacts | Contacts with names, phones, emails, org, id | name, email, phone, id |
calendar | Events with title, start, end, location, notes, id | date (YYYY-MM-DD), startDate+endDate |
reminders | Reminders with title, due date, completed flag, id | completed (true/false), list |
location | Current lat, lng, altitude, timestamp | — |
photos | Photo metadata: id, date, dimensions, favorites | favorite (true), startDate, endDate, limit, id |
files | iCloud Drive file listing | — |
clipboard | Current clipboard text | — |
Filter Examples
bash device.sh fetch contacts '{"name":"carlos"}'
bash device.sh fetch calendar '{"date":"2026-02-14"}'
bash device.sh fetch reminders '{"completed":"false","list":"Shopping"}'
bash device.sh fetch photos '{"favorite":"true","limit":"50"}'
bash device.sh fetch contacts
Send Commands — Actions
Calendar
| Action | Required | Optional | Example |
|---|
calendar.create | title, startDate, endDate | location, notes, isAllDay | '{"title":"Standup","startDate":"2026-02-14T09:00:00","endDate":"2026-02-14T09:30:00"}' |
calendar.update | id | title, startDate, endDate, location, notes | '{"id":"E1","title":"Updated"}' |
calendar.delete | id | — | '{"id":"E1"}' |
Reminders
| Action | Required | Optional | Example |
|---|
reminders.create | title | dueDate, notes, priority | '{"title":"Buy milk","dueDate":"2026-02-15T18:00:00"}' |
reminders.update | id | title, dueDate, notes, priority | '{"id":"R1","title":"Buy oat milk"}' |
reminders.complete | id | — | '{"id":"R1"}' |
reminders.delete | id | — | '{"id":"R1"}' |
Contacts
| Action | Required | Optional | Example |
|---|
contacts.create | firstName or lastName | phone, email, organization | '{"firstName":"Jane","lastName":"Doe","phone":"+15551234567"}' |
contacts.update | id | firstName, lastName, phone, email, organization | '{"id":"C1","phone":"+15559999999"}' |
contacts.delete | id | — | '{"id":"C1"}' |
Photos
| Action | Required | Optional | Example |
|---|
photos.createAlbum | title | — | '{"title":"Vacation 2026"}' |
photos.addToAlbum | album_id, asset_ids | — | '{"album_id":"A1","asset_ids":"P1,P2"}' |
photos.favorite | id | favorite (default "true") | '{"id":"P1","favorite":"true"}' |
Files
| Action | Required | Optional | Example |
|---|
files.write | path, content | — | '{"path":"notes/memo.txt","content":"Hello"}' |
files.delete | path | — | '{"path":"notes/old.txt"}' |
Clipboard
| Action | Required | Optional | Example |
|---|
clipboard.set | text | — | '{"text":"copied text"}' |
clipboard.clear | — | — | '{}' |
App Commands — Open Third-Party Apps
Send app.<action> to open apps on the device via URL schemes. The device opens the app directly — no confirmation needed.
| Action | Params | Example |
|---|
app.maps.directions | address, mode (d/w/r) | '{"address":"Golden Gate Bridge","mode":"d"}' |
app.maps.search | query | '{"query":"coffee shops"}' |
app.uber.ride | destination | '{"destination":"SFO Airport"}' |
app.lyft.ride | lat, lng | '{"lat":"37.7749","lng":"-122.4194"}' |
app.spotify.search | query | '{"query":"lofi beats"}' |
app.spotify.play | id (track ID) | '{"id":"4uLU6hMCjMI75M1A2tKUQC"}' |
app.music.search | query | '{"query":"Beatles"}' |
app.youtube.search | query | '{"query":"how to cook pasta"}' |
app.youtube.play | id (video ID) | '{"id":"dQw4w9WgXcQ"}' |
app.whatsapp.send | phone, text | '{"phone":"+15551234567","text":"Hey!"}' |
app.telegram.send | phone, text | '{"phone":"+15551234567","text":"Hello"}' |
app.venmo.pay | recipient, amount, note | '{"recipient":"Jane","amount":"25","note":"Dinner"}' |
app.cashapp.pay | recipient, amount, note | '{"recipient":"$Jane","amount":"25","note":"Lunch"}' |
app.safari.open | query | '{"query":"weather forecast"}' |
app.shortcuts.run | name, input | '{"name":"Morning Routine","input":"start"}' |
app.facetime.call | contact | '{"contact":"john@example.com"}' |
app.facetime.audio | contact | '{"contact":"+15551234567"}' |
app.phone.call | number | '{"number":"+15551234567"}' |
app.sms.send | number, text | '{"number":"+15551234567","text":"On my way"}' |
app.mail.compose | to, subject, body | '{"to":"jane@example.com","subject":"Hi","body":"Hello!"}' |
Worked Examples
1. "Find Carlos in my contacts"
bash /root/workspace/skills/ios-device/device.sh fetch contacts '{"name":"carlos"}'
2. "Remind me to call the dentist tomorrow at 10am"
bash /root/workspace/skills/ios-device/device.sh send reminders.create '{"title":"Call the dentist","dueDate":"2026-02-15T10:00:00"}'
bash /root/workspace/skills/ios-device/device.sh result abc12345-...
3. "What's on my calendar today?"
bash /root/workspace/skills/ios-device/device.sh fetch calendar '{"date":"2026-02-14"}'
4. "Get me directions to the Golden Gate Bridge"
bash /root/workspace/skills/ios-device/device.sh send app.maps.directions '{"address":"Golden Gate Bridge, San Francisco, CA","mode":"d"}'
bash /root/workspace/skills/ios-device/device.sh result def67890-...
Response Format
Fetch returns topic-specific JSON:
{"contacts": [...], "fetched_at": "2026-02-14T..."}
{"events": [...], "fetched_at": "2026-02-14T..."}
Send prints a command ID:
Command sent: <uuid>
Result returns the device's response:
{"status": "created", "event_id": "E123"}
{"status": "opened", "app": "maps.directions", "url": "..."}
{"error": "Calendar access denied"}
Tips
- Always fetch data before modifying (e.g., fetch contacts before updating one)
- Use native filters instead of
jq when possible — they're faster and return less data
- The device must be online and the app running (foreground or background) for fetches to work
- If the device is offline, the fetch retries 3x (~90s total). If it still fails, ask the user to open the app and try again
- IDs from fetch responses are used for update/delete commands
- For
app.* commands: if the app isn't installed, the result will show opened: false
- Date format: ISO 8601 (
2026-02-14T09:00:00), no timezone suffix (device interprets as local time)
- IMPORTANT: The VPS runs in UTC. Always set
TZ=<timezone> when invoking apple-agent.js or device.sh so dates are computed in the user's local time. Never use raw UTC date output for calendar/reminder dates.