iOS Agent
TL;DR
The CMDOP iOS agent turns your iPhone or iPad into a remote endpoint. Install the app from the App Store, grant permissions, then control files, photos, and device telemetry via CLI or Python SDK. Shell access is not available due to iOS restrictions. Use push wake to maintain background connectivity.
The CMDOP iOS app turns your iPhone or iPad into a remote-controllable endpoint.
What does the iOS agent do?
What capabilities does the iOS agent have?
| Feature | Available | Notes |
|---|---|---|
| File access | β | Sandboxed to app documents |
| Photo access | β | With permission |
| Telemetry | β | Battery, storage, device info |
| Push wake | β | Wake device for operations |
| Shell | β | iOS doesnβt allow |
| Browser | β | iOS restrictions |
How do I install the CMDOP iOS app?
- Download CMDOP from App Store
- Open app and sign in
- Grant permissions (files, photos, notifications)
- Device appears in your workspace
How do I connect to an iOS device from the CLI?
# List all registered devices in your CMDOP workspace
cmdop machines
# Output:
# HOSTNAME TYPE STATUS
# macbook-pro desktop connected
# prod-server server connected
# marks-iphone ios connected
# Open a terminal session to the iPhone device
cmdop terminal marks-iphone
# Note: No shell, but file operations workHow do I connect to an iOS device from the SDK?
from cmdop import AsyncCMDOPClient
# Initialize a remote client session with your API key
async with AsyncCMDOPClient.remote(api_key="cmd_xxx") as client:
# Switch the terminal context to the iPhone device
await client.terminal.set_machine("marks-iphone")
# List all files at the root of the iPhone sandbox
files = await client.files.list("marks-iphone", "/")
print(./files)
# Retrieve device telemetry: battery level, free storage, etc.
info = await client.system.info("marks-iphone")
print(f"Battery: {info.battery_percent}%")
print(f"Storage: {info.storage_free_gb} GB free")How do I get device info from an iOS device?
from pydantic import BaseModel
# Pydantic model describing the fields returned by system.info()
class DeviceInfo(BaseModel):
device_name: str
model: str
os_version: str
battery_percent: int
battery_charging: bool
storage_total_gb: float
storage_free_gb: float
wifi_connected: bool
cellular_connected: bool
# Fetch real-time device info from the connected iPhone
info = await client.system.info("marks-iphone")
# DeviceInfo(
# device_name="Mark's iPhone",
# model="iPhone 15 Pro",
# os_version="17.4",
# battery_percent=78,
# battery_charging=False,
# storage_total_gb=256.0,
# storage_free_gb=45.2,
# ...
# )What does the iOS file system look like?
iOS apps have sandboxed file access:
marks-iphone:/
βββ Documents/ # App documents (read/write)
βββ Library/ # App library (read/write)
βββ tmp/ # Temporary files (read/write)
βββ Photos/ # Photo library (read only, with permission)How do I access files on an iOS device?
# List all files in the Documents directory
files = await client.files.list("marks-iphone", "/Documents")
# Read the contents of a text file from the device
content = await client.files.read("marks-iphone", "/Documents/notes.txt")
# Write a JSON configuration file to the device
await client.files.write(
"marks-iphone",
"/Documents/config.json",
'{"setting": "value"}'
)
# Download a database file from the device to the local machine
await client.files.download(
"marks-iphone",
"/Documents/data.sqlite",
"./data.sqlite"
)
# Upload a local PDF to the device's Documents folder
await client.files.upload(
"./report.pdf",
"marks-iphone",
"/Documents/report.pdf"
)How do I access photos on an iOS device?
# List all photos in the photo library (requires user-granted permission)
photos = await client.files.list("marks-iphone", "/Photos")
# Download a specific photo by filename to the local machine
await client.files.download(
"marks-iphone",
"/Photos/IMG_1234.jpg",
"./photo.jpg"
)What are the iOS agent limitations?
Why is there no shell access on iOS?
iOS doesnβt allow shell execution:
# Attempting shell execution on iOS will raise an error
output, code = await client.terminal.execute("ls -la")
# Error: Shell not available on iOS devicesWhy can I only access sandboxed storage?
Only access files within app sandbox:
# Accessing sandbox paths works normally
files = await client.files.list("marks-iphone", "/Documents")
# Accessing paths outside the sandbox is denied by iOS
files = await client.files.list("marks-iphone", "/var/mobile")
# Error: Access deniedWhat are the background execution limitations?
iOS suspends apps in background:
# Long operations may be interrupted when the app is suspended
# Use push wake for reliability (see Push Wake guide)What are some common iOS agent use cases?
How do I backup photos from my iPhone?
async def backup_photos():
# List every photo in the device's photo library
photos = await client.files.list("marks-iphone", "/Photos")
# Download each photo to a local backup directory
for photo in photos:
await client.files.download(
"marks-iphone",
photo.path,
f"./backup/{photo.name}"
)
print(f"Backed up: {photo.name}")
await backup_photos()How do I sync documents to my iPhone?
async def sync_documents():
# Get the list of local and remote document filenames
local_docs = os.listdir("./docs")
remote_docs = await client.files.list("marks-iphone", "/Documents")
# Upload any local file that doesn't already exist on the device
for doc in local_docs:
if doc not in [r.name for r in remote_docs]:
await client.files.upload(
f"./docs/{doc}",
"marks-iphone",
f"/Documents/{doc}"
)
print(f"Synced: {doc}")
await sync_documents()How do I monitor my iPhone battery remotely?
async def monitor_battery():
while True:
# Poll device info to read current battery level
info = await client.system.info("marks-iphone")
# Alert when battery drops below 20% and is not charging
if info.battery_percent < 20 and not info.battery_charging:
send_notification("iPhone battery low!")
await asyncio.sleep(300) # Check every 5 minutesHow do I take a remote screenshot of my iPhone?
# Request a screenshot (the CMDOP app must be in the foreground)
screenshot = await client.system.screenshot("marks-iphone")
# Save the screenshot bytes to a local PNG file
with open("screenshot.png", "wb") as f:
f.write(screenshot)What are the iOS app connection states?
| State | Connection | Operations |
|---|---|---|
| Foreground | Active | All operations |
| Background | Maintained (briefly) | Limited time |
| Suspended | None | Push wake needed |
| Terminated | None | Push wake needed |
Next
- Push Wake β Wake device for operations
- File Access β Detailed file operations
Last updated on