Phone Control
The Phone Control extension manages temporary access to high-risk commands on iOS phone nodes. It uses an arm/disarm model with timed expiry to grant and revoke camera, screen recording, and write access through the gateway.
Command groups
Commands are organized into three groups, plus an all shortcut:
| Group | Commands | Description |
|---|---|---|
camera | camera.snap, camera.clip | Take photos and short video clips |
screen | screen.record | Screen recording |
writes | calendar.add, contacts.add, reminders.add | Create calendar events, contacts, reminders |
all | All of the above | Arm everything at once |
Arm/disarm model
Arming
When you arm a group, the extension:
- Adds the group's commands to the gateway
allowCommandslist - Removes them from the
denyCommandslist (if present) - Writes the armed state to disk for crash recovery
- Starts an expiry timer
bash/phone arm camera 10m # Allow camera commands for 10 minutes /phone arm all 30s # Allow everything for 30 seconds /phone arm writes 2h # Allow write commands for 2 hours
Duration format
| Unit | Example | Description |
|---|---|---|
s | 30s | Seconds |
m | 10m | Minutes (default: 10m) |
h | 2h | Hours |
d | 1d | Days |
If no duration is specified, the default is 10 minutes.
Disarming
Disarming reverses the config changes:
- Removes commands that were added to
allowCommands - Restores commands to
denyCommandsthat were removed during arming - Deletes the state file
bash/phone disarm # Immediately revoke all armed commands
Auto-disarm
A background service checks the expiry timer every 15 seconds. When the armed duration expires, it automatically disarms by restoring the original gateway configuration.
The expiry check also runs on service startup, so if Mayros was restarted while armed, the state is recovered and expired states are cleaned up.
State persistence
Armed state is persisted to {stateDir}/plugins/phone-control/armed.json:
typescript{ version: 2, armedAtMs: number, // When the arm was activated expiresAtMs: number | null, // null = manual disarm only group: "camera" | "screen" | "writes" | "all", armedCommands: string[], // Commands in the armed group addedToAllow: string[], // Commands added to allowCommands removedFromDeny: string[] // Commands removed from denyCommands }
The state file tracks exactly which config changes were made so disarming can precisely reverse them, even if the config was modified by other means in the interim.
Gateway integration
The extension modifies the gateway node configuration at config.gateway.nodes:
allowCommands: commands the gateway can invoke on phone nodesdenyCommands: commands the gateway must not invoke
Arming moves commands from deny to allow. Disarming moves them back. The extension writes the config file after each change, which triggers the config_change hook.
Slash command
The /phone slash command provides the full interface:
bash/phone help # Show usage and available groups /phone status # Show current arm state and expiry /phone arm <group> [dur] # Arm a command group with optional duration /phone disarm # Immediately disarm
Status output
Phone control: armed (expires in 8m).
Temporarily allowed: camera.snap, camera.clip
Or when disarmed:
Phone control: disarmed.
Related
- Architecture — extension and plugin system
- IoT Bridge — fleet management for edge nodes