Skip to content

iCTRL 1.98.12

Latest

Choose a tag to compare

@wsvn53 wsvn53 released this 15 Oct 04:05
d88bbf0

An AI-friendly iOS/iPadOS automation service. Tell your agent "My iPhone is running iCTRL at :8200 — figure out how to drive it." and it reads the on-device manual and takes it from there. Works with any agent that can make HTTP requests: OpenClaw, Hermes, Minis, Claude Code, Codex and others.

Downloads

Which IPA do I need?

File Needed? What it is
iCTRLUITests-Runner.ipa Required The automation engine. It serves the JSON-RPC API that agents and clients call, and must be running.
iCTRL.ipa Optional A companion app for tasks on the phone itself:
• mount the Developer Disk Image without a Mac, and remount it after a reboot
• start and stop the runner
• choose who can reach the runner (this device only / LAN / LAN + nearby)
• see and revoke authorized clients
• read the runner's log live

Skip iCTRL.ipa if you mount the Developer Disk Image with Xcode or StikDebug, and manage the runner from its notification or a computer. With a free Apple ID you get three sideloaded apps, and SideStore uses one of them. Install StikDebug or the iCTRL app alongside the runner, not both.

Both IPAs are unsigned for distribution (ad-hoc, no provisioning profile). Sign them when you install:

  • Free Apple ID: the latest SideStore signs and installs them. Older SideStore releases skip the nested .xctest, and the runner then crashes on launch.
  • Paid account: Scripts/sign-ipa.sh -i iCTRLUITests-Runner.ipa

The runner also needs the Developer Disk Image mounted (Xcode, StikDebug or the iCTRL app). The README covers the whole setup.

What's new since 1.97.1

Nearby discovery: no address to type

  • Reach the phone without an address. Turn on 📡 Nearby Discovery from the runner's notification or the iCTRL app (it needs Remote Access). Clients can then find the phone:
    • on the LAN, from any OS;
    • from a Mac over Apple peer-to-peer Wi-Fi (AWDL), with no shared network at all. The phone only needs Wi-Fi switched on, not joined to anything.
  • New client commands: python3 ictrl_rpc.py scan lists discovered phones, and --nearby "<name or id>" replaces --host. The first call pairs with the phone (approve once on the phone).
  • Strict exposure:
    • Nothing is announced on the network unless nearby discovery is on.
    • The AWDL listener accepts peer-to-peer connections only, and the main listener refuses them.
    • Nearby discovery can be switched on only from the phone itself (notification, iCTRL app or USB).
  • Self-healing:
    • Advertising follows Wi-Fi off and on, and recovers if the interface is recreated.
    • A failed listener is rebuilt.
    • The notification says why nearby discovery isn't ready yet (turn on Wi-Fi, allow Local Network).

Who can reach the phone, at a glance

  • The status notification's first line shows one of: 🔒 This device only, 🌐 LAN reachable, or 📡 Nearby discoverable.
  • The iCTRL app has a Visibility menu: 🟢 This device only · safe / 🟡 LAN / 🟡 LAN + nearby.
  • LAN addresses are real interfaces only. VPN or proxy tunnel addresses such as 198.18.0.1 are no longer shown as the phone's address.

Pairing and keys

  • Every pairing is approved on the phone. The "trusted for 10 minutes" shortcut is gone.
  • Limits on requests:
    • An unanswered request is refused after 60 s.
    • Only one request waits at a time, with a 15 s cooldown after a refusal.
    • Requests from the phone itself have their own slot, so a remote caller can't lock them out.
  • Check the key. The prompt shows a key fingerprint that the client also prints; allow only if they match.
  • One key per device. Clients store keys per device, so a phone paired once works over USB, the LAN and nearby without pairing again. Keys stored under an address by older clients are picked up automatically.
  • Local Network permission. The runner asks for it at launch and reports it. The iCTRL app warns when it's missing; without it, nearby discovery can't work even though LAN clients may still connect.

iCTRL app

  • Authorized Clients: every key holder, where each last connected from (this device / USB, LAN, nearby, VPN), revoke one or all others.
  • Runner Logs: the runner's log, live, with pause, refresh and filter.
  • Visibility menu (above), and a warning when the runner lacks Local Network access.
  • Share a pairing file to iCTRL from Files, Mail, AirDrop or a chat app when the picker can't reach it. iCTRL confirms when it's stored, or says why it was refused.

Clients

  • Python client:
    • Standard library only. LAN pairing no longer needs pip install cryptography.
    • Never sends iCTRL requests through an http_proxy.
    • If macOS Local Network privacy refuses the process, it relays nearby connections through the system nc.
  • C CLI: gets the same nearby support when built on macOS. The Linux static binary is rebuilt.

Server and API

  • GET /whoami and an X-ICTRL-Device header on every response identify the device.
  • config adds nearby_discovery and device_name, and reports nearby status and LAN addresses. Each client's last address and source appear in its session entry.
  • config now validates every parameter before changing any.
  • A change that restarts the listener replies first instead of returning an empty response.
  • Read-only polling (logs, plain config) no longer fills the log.

Known limitations

  • Nearby discovery over AWDL needs macOS on the client side. A phone whose screen is off may stop being discoverable over AWDL, as with AirDrop.
  • With nearby discovery on, iOS also announces the phone's own host name on the LAN, which often contains its owner's name.
  • Endpoints that need no key (/schema, /skill, /remote, /whoami, /pair) also answer over AWDL, and the screen stream is not encrypted on any channel.

Full details: #3.

SHA-256

d28fcb4775885a7161e8c7aa9f247aeb42fe1af1c7fcfc5ce1bbdb1b07b442f2  iCTRLUITests-Runner.ipa
7d9ceaad8eeb486e67d81a688e661f2278113d4ba4f7d3d73cff2f9973881ac7  iCTRL.ipa