Skip to content

Commit 59d37e7

Browse files
committed
docs(targets): real devices close for both platforms, which supersedes the simulator route
ASKED DIRECTLY AND IT IS THE STRONGEST RESULT IN THE SECTION: running on real hardware needs no Apple or Google software on either platform. Android adb push + adb shell Apache-2.0, already packaged iOS pymobiledevice3 GPL-3.0, pure Python 3, no compiled extensions, Linux/Windows/macOS, 2736 stars, pushed 2026-09-10 iOS libimobiledevice LGPL-2.1, the C library it models, 8177 stars, pushed 2026-06-10 pymobiledevice3 requires no Xcode, works with the system usbmuxd, and covers app management plus iOS 17+ tooling over a tunnel; libimobiledevice needs no jailbreak. So the iOS row's execution story is not "needs a device on a Mac": build, bundle, sign, package, deploy and run all close, and the ONLY line that does not is a provisioning profile and signing identity -- a credential, which is category (c) and which no package manager closes. That is the same boundary a developer already lives with under Xcode. It is materially better than the simulator route and the reason is worth stating: the simulator is blocked by a licensed IMAGE that cannot be redistributed, while a real device supplies its own OS and the only thing crossing the boundary is a signature the developer already owns. WHERE A DEVICE SESSION LIVES: the runner program absorbs deployment, so no fourth verb is needed -- "adb push" followed by "adb shell" is one operation from mcpp's side. Both mechanisms are used for what each is: a PLUGIN produces the artefact (dist-ipa, build time), a PACKAGE deploys and runs it (the runner program, run time), and the ENGINE names the runner (the existing "runner" key). The ordering is a real dependency, not a convention: the iOS device runner has nothing to install until dist-ipa has produced a signed file, so R9 precedes R12. THE iOS IMAGE IS A LOCATOR AND NEVER A RE-HOST. An image in a public index is redistribution of Apple's operating system whatever it is labelled, and this differs from the Android decision earlier in this document in a way worth stating precisely: there, Apache-2.0 licence files were verified INSIDE the archives and clause 3.5 genuinely applies; here there is no open-source component to invoke. The legitimate form is the locator tier iphoneos-sdk.lua already documents -- the index carries a path and a probe, not bytes -- and R4 is its engine half. With R12 in place no image is on the critical path at all.
1 parent 47b3c3a commit 59d37e7

1 file changed

Lines changed: 93 additions & 3 deletions

File tree

‎.agents/docs/2026-09-11-platform-targets-design-review.md‎

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ package -- no new mechanism, again.
312312
| R9 | `mcpp pack --format ipa` | a `dist-ipa` member: zip `Payload/<Name>.app/`, after `dist-apple` and `rcodesign` | it needs NO new tool. Every other link is already in the ecosystem or one member away, so iOS PACKAGING closes entirely -- what does not close is the credential and the runtime |
313313
| R10 | `--format dmg` and `--format pkg` | recorded as gaps with a known shape, not attempted | each needs a *creator* as well as a signer (`libdmg-hfsplus`; `xar`), both open source and neither measured here |
314314
| R11 | the macOS rows' runner | Darling recorded as an unmeasured candidate | GPL-3.0, active, and it REIMPLEMENTS Darwin's libraries rather than redistributing them, so unlike the iOS image it carries no licence blocker. A row does not move on a plausible mechanism, so this is a candidate and not a plan |
315+
| R12 | real-device run for both platforms | `xim:android-platform-tools` (have) and a new `xim:pymobiledevice3`, each named by a `runner` program | neither needs Apple or Google software. It supersedes the simulator route rather than complementing it: a device brings its own OS, so the only thing crossing the boundary is a signature the developer already owns |
316+
| R13 | the iOS image | a LOCATOR package, never a re-host, gated on R4 | an image in a public index is redistribution of Apple's OS whatever it is labelled. The locator is the tier `iphoneos-sdk.lua` already documents, and with R12 in place no image is on the critical path at all |
315317

316318
## 7. User-facing experience, which is the test of all of the above
317319

@@ -540,7 +542,95 @@ it is a (b)-category proprietary runtime, and `xcrun simctl spawn` is an argv
540542
prefix -- so §5's model covers it with no new mechanism, on a macOS host, once
541543
R1 gives the simulator a row.
542544

543-
### 10.5 Darling is a candidate for the macOS rows, and is recorded as unmeasured
545+
### 10.5 Real devices close for BOTH platforms, and that is a better answer than an emulator
546+
547+
Asked directly, and it turns out to be the strongest result in this section:
548+
**running on real hardware needs no Apple or Google software on either
549+
platform.**
550+
551+
| platform | what installs and launches | licence | state |
552+
|---|---|---|---|
553+
| Android | `adb push` + `adb shell` | Apache-2.0 | **already packaged** -- `xim:android-platform-tools`, installs on all three hosts |
554+
| iOS | [`pymobiledevice3`](https://github.com/doronz88/pymobiledevice3) | GPL-3.0 | pure Python 3, no compiled extensions, Linux / Windows / macOS; 2736 stars, last push 2026-09-10 |
555+
| iOS | [`libimobiledevice`](https://github.com/libimobiledevice/libimobiledevice) | LGPL-2.1 | the C library it was modelled on; 8177 stars, last push 2026-06-10 |
556+
557+
`pymobiledevice3` describes itself as requiring no Xcode, working with the
558+
system `usbmuxd`, and covering app management plus iOS 17+ developer tooling
559+
over a tunnel. `libimobiledevice` states it needs no jailbreak. Neither
560+
requires a Mac.
561+
562+
So the iOS row's execution story is not "needs a device on a Mac". It is:
563+
564+
build xim:llvm + xim:iphoneos-sdk closed
565+
bundle dist-apple (--format app) closed
566+
sign xim:rcodesign closeable, R7
567+
package dist-ipa (--format ipa) closeable, R9
568+
deploy+run xim:pymobiledevice3 closeable, R12
569+
------------------------------------------------------------------------
570+
entitlement a provisioning profile and a signing identity NOT closeable
571+
572+
**Only the last line does not close, and it is a credential rather than a
573+
tool.** Installing on a non-jailbroken device requires an Apple Developer
574+
provisioning profile; `pymobiledevice3` can install a signed `.ipa` and cannot
575+
conjure the entitlement. That is category (c), and no package manager closes a
576+
credential -- which is the same boundary a developer already lives with when
577+
using Xcode.
578+
579+
That is a materially better position than the simulator route, and it is worth
580+
stating why: the simulator is blocked by a **licensed image** that cannot be
581+
redistributed, while a real device supplies its own OS and the only thing
582+
crossing the boundary is a signature the developer already owns.
583+
584+
### 10.6 Where a device session lives: the runner program absorbs deployment
585+
586+
§5 concluded that a device session is a runner PROGRAM in a `xim:` package,
587+
named by an argv-prefix `runner`. Deployment does not need a fourth verb, and
588+
the reason is that `adb push && adb shell` is one operation from mcpp's side:
589+
590+
mcpp run --target aarch64-linux-android
591+
-> runner = ["mcpp-android-device-run"] a xim package's program
592+
which pushes, executes, collects the exit code and stdout, tears down
593+
594+
mcpp run --target aarch64-ios
595+
-> runner = ["mcpp-ios-device-run"] a xim package's program
596+
which installs the signed .ipa, launches it, streams the log, collects
597+
598+
So both mechanisms are used, each for what it is:
599+
600+
plugin produces the artefact dist-ipa, dist-apple (build time)
601+
package deploys and runs it the runner program (run time)
602+
engine names the runner the `runner` key (already exists)
603+
604+
And the ordering is a real dependency rather than a convention: the iOS device
605+
runner has nothing to install until `dist-ipa` has produced a signed file, so
606+
R9 precedes R12.
607+
608+
### 10.7 The iOS image: a locator, not a re-host
609+
610+
Adding an iOS kernel and root filesystem to a public index would be
611+
redistributing Apple's operating system, and a "temporary, test-only, disabled
612+
later" label does not change that -- anyone resolving the index would install
613+
it. This differs from the Android decision earlier in this document in a way
614+
worth stating precisely: there, Apache-2.0 licence files were verified INSIDE
615+
the archives and clause 3.5 genuinely applies; here there is no
616+
open-source component to invoke.
617+
618+
What serves the same purpose legitimately is the third tier
619+
`pkgs/i/iphoneos-sdk.lua` already documents, and R4's `@system`
620+
generalisation is the engine half of it:
621+
622+
a LOCATOR package records where an image the user already owns lives.
623+
Nothing is re-hosted; the index carries a path and a probe, not bytes.
624+
625+
That is the `msvc@system` shape, and it is why R4 matters beyond iOS: the
626+
engine currently has no spelling for "this row's system is host-located",
627+
so the locator tier is unreachable even though the recipe describes it.
628+
629+
And it is worth noting what the locator would be FOR. With R12 in place, a
630+
simulator or an emulated image is not on the critical path at all -- a real
631+
device is the supported route, and it needs no image from anyone.
632+
633+
### 10.8 Darling is a candidate for the macOS rows, and is recorded as unmeasured
544634

545635
[Darling](https://github.com/darlinghq/darling) is a macOS compatibility layer
546636
for Linux -- GPL-3.0, actively developed (last push 2026-09-06). It reimplements
@@ -558,7 +648,7 @@ not move on a plausible mechanism. What it would be, if it worked, is an
558648
ordinary `runner` argv prefix supplied by a `xim:` package -- the same shape as
559649
`qemu-user-aarch64`.
560650

561-
### 10.6 Genuinely host-bound, and there are exactly three
651+
### 10.9 Genuinely host-bound, and there are exactly three
562652

563653
1. **`/dev/kvm`** -- a kernel facility. No package ships a kernel feature, and
564654
group membership is a machine's configuration. This is why it is the only
@@ -573,7 +663,7 @@ ordinary `runner` argv prefix supplied by a `xim:` package -- the same shape as
573663
is never a package, and `rcodesign` can drive the submission but cannot
574664
supply the account.
575665

576-
### 10.7 The rule that falls out
666+
### 10.10 The rule that falls out
577667

578668
A host dependency is legitimate only when the thing needed is
579669
(a) a kernel facility,

0 commit comments

Comments
 (0)