2026-10-26 studio-redo: Napple Studio rebuilt from zero (Liquid Glass), iOS install and IPA export, simulators in the in-game overlay¶
Branch claude/studio-redo-2026-10-26, Mac session (macOS 27.0.1, Xcode 27.1, Swift 6.4). Orchestration orchestrations/studio-redo.md.
The old Studio stays at tag archive/studio-swiftui-2026-10; its sources under studio/Sources/NappleStudio were deleted and rewritten.
What changed¶
Studio (studio/, rewritten)¶
NappleStudio(app):StudioApp(WindowGroup, menu commands, standardSettingsscene),RootView(NavigationSplitView: sidebar, detail, log inspector, whole-window drop, toast, first-run setup sheet, legal sheet),LibraryView(adaptive grid, cover art from the built app's icon, compatibility dot, glass action bar, context menu, search, Delete key),AddGameView(drop zone ->PlanView->BuildingViewwith real stage names + checklist ->DoneView/FailedView;LogInspector),DevicesView(devices +SigningCard+ memory-limit card + command lines),SettingsView(General, Keys & Firmware, Engine),Components(GlassCard, Banner, KeysetForm). Model:AppModel(+Build, +Library, +iOS). Liquid Glass throughglassEffect,GlassEffectContainer,.glass/.glassProminentbuttons,ToolbarSpacer, systemContentUnavailableViewempty states; no custom blur anywhere. Strings go throughLocalizedStringKey/String(localized:). Accessibility identifiers and labels on the main controls; keyboard: ⌘O add, ⌘B build, ⌘. cancel, ⌘1-3 panes, ⌘R refresh devices, ⌥⌘L log, Return = Play in the library.NappleStudioCore(kept and extended):SigningAccount.swift(ProfileDetailsfromsecurity cms -D,XcodeTeamfrom Xcode'sIDEProvisioningTeamByIdentifier,AccountDetector,IOSEntitlementPlan),Provisioner.swift(SigningMode; Automatic mode = stub Xcode project with the bundle id, team and entitlements built withxcodebuild -allowProvisioningUpdates -allowProvisioningDeviceRegistration, thennapple buildsigns with the profile Xcode made;xcodebuild -exportArchivewas tried for real first and refused:certificateType DEVELOPMENT_MANAGED has an invalid value),DeviceService.swift(devicectl+simctldiscovery, install, launch,.ipaunpack, exact command lines),ToolRunner.swift(injectable process runner),BundleIDs(one id per title),BuildTarget.iosSim.- Bundle ids:
<prefix>.<titleid>per game (prefix editable, defaultcom.napple.game) so several games can be installed on one device; a non-wildcard profile pins its id and the UI says so (user request during the session). - Memory limit: paid account ->
com.apple.developer.kernel.increased-memory-limit(+increased-debuggable-memory-limitfor debug builds) in the archive entitlements, capability turned on by automatic signing; free/unknown -> nothing added, plain explanation in the UI. Detection order: Xcode team list, profile grants the capability, profile lifetime (7 d free / >= 60 d paid), "(Personal Team)" name. No JIT, no private API. - Packaging:
build_app.shalso bundlesruntime/build-ios-sim/napple-runtimeasnapple-runtime-ios-sim, registers the NSP/XCI/NSZ/XCZ document types (drop on the Dock icon / File > Open), signs withpackaging/entitlements.plist. - Debug/scripting flags:
--pane,--debug-tour <dir>(every pane -><name>.rectfor an externalscreencapture -R),--debug-tour-build.
Simulators moved to the in-game overlay (user request: "that is per game, not Studio")¶
frontend/src/simulators.m(new): amiibo tab (search, list, Place / Place new copy / Remove, Reload list with cache-first thenNSURLSessionfetch, Import dump…) over the runtime'sAmiiboPicker; Camera tab (authorization status, Allow / Privacy Settings, Mirror) and the webcamIrFrameSource(AVCaptureSession 640x480 BGRA ->irs_adapter_rgb_to_ir), installed at window creation; the permission prompt fires only fromrequest_access(a game starting an IR processor). Runtime symbols are weak references (__attribute__((weak))): the frontend's own test binaries link with-undefined dynamic_lookup.frontend/src/overlay.m: tabsamiiboandCamera(7 segments, small control size);fe_internal.h;frontend/Makefile:-I../runtime/src/services,-fmodules(AVFoundation auto-linked, the runtime link line is untouched), AVFoundation/CoreMedia/UniformTypeIdentifiers for the test binaries.crates/napple-build/src/bundle.rs:NSCameraUsageDescriptionin every Mac game app'sInfo.plist(+ unit test). Amiibo default source changed in the Studio-side loader (now deleted); the runtime'sAMIIBO_DEFAULT_SOURCE(amiiboapi.com, offline since the archive) is noted under "Needs from other areas".- Docs:
docs/guides/studio.md(new),docs/guides/hardware-simulators.md(wiring list -> what was wired), guides README, index.
Parity checklist (old Studio -> new)¶
| Old feature | New |
|---|---|
| Welcome / first-run keys + firmware form, folder scan | Setup sheet on first launch (SetupSheet + KeysetForm, KeyFinder.scan) |
| Key sets: add, replace, delete, select | Settings > Keys & Firmware |
| Drop NSP/XCI/NSZ/XCZ anywhere, folders, picker | Whole-window drop, Dock/File > Open (document types), ⌘O picker, folder expansion with skipped-file note |
| Plan: base, updates, DLC toggles, sizes, warnings, compat note | PlanView |
| Destination: Mac, device, iPhone .ipa, iPad .ipa | DestinationCard + iOS Simulator destination (new) |
| Build with live progress, cancel, quit guard, sleep inhibitor | BuildingView, ⌘., AppDelegate.applicationShouldTerminate, beginActivity |
| Done: play, reveal, copy to Applications, install on device, notes | DoneView |
| Failure with humanised reason | FailedView (+ Show Log) |
| Library: grid, status (present/missing/replaced), locate, trash, remove, adopt output folder, directory watcher | LibraryView + AppModel+Library (same LibraryStore) |
| Compat matrix badge | dot on the card, pill on the plan |
| Engine installer / Move to Applications | Engine setup kept (EngineInstaller), engine status in Settings > Engine; Move-to-Applications prompt dropped (the DMG installer script handles it) |
| iOS signing (identity + profile), unsigned, .ipa, install + launch via devicectl | SigningCard (3 modes), IPAExporter, DeviceService |
| Build log in Application Support/Napple/logs | same, plus the live inspector |
| Settings screen (output folder, legal) | standard Settings scene (⌘,) |
Verified / tested here¶
See the integrator file for the table. Highlights: swift test 56 tests / 17 suites pass; make -C frontend test (settings 36 checks, window 13 checks) pass; runtime
links with the overlay (nm shows fe_amiibo_page, amiibo_service_picker, irs_service_set_source); cargo test -p napple-build --lib bundle 5 pass; Studio built with
build_app.sh; scripted tour screenshots of every pane; LAS built for the Mac through Studio (1 min 2 s, 6.5 GB) and listed in the library with cover art; LAS built
for the iOS Simulator through Studio (51 s) and installed/launched with simctl (simctl listapps booted lists com.napple.game.01006bb00c6f0000, Done screen
captured); the first Simulator run crashed Studio with an AppKit "more Update Constraints in Window passes than there are views" exception, bisected with
--debug-fake-done to the Done screen's ContentUnavailableView followed by a wrapping Banner, now a plain ScrollView; the real iPhone 16 Pro Max is paired but not
connected (shown as "Not connected"), so the devicectl install is exercised through the recorded command lines and the unit tests only; .ipa export needs a team
signed in to Xcode with the -allowProvisioningUpdates path: the code path is unit-tested with a fake tool runner, the real xcodebuild -exportArchive was not run here
(blocker: Xcode has only free Personal Teams on this Mac and no device was connected to register).
Screenshots: docs/archive/changes/img/studio-redo/ (library empty/selected, add, plan, building, done-mac, done-simulator, devices, log, overlay amiibo/camera,
simulator home screen with the installed game).
Decisions¶
- Amiibo and camera are not in Studio at all (user). The Studio-side Swift amiibo library/store and camera panels written earlier in the session were removed again.
- Automatic signing lets Xcode make the profile through a stub project (the only supported way to create App IDs/capabilities/profiles without the portal) and keeps
the signing in
napple build's tested path; the real provisioning run was not executed in this session because it writes to the user's Apple account. - Weak runtime references in the frontend instead of new callbacks in
napple_frontend_callbacks, soruntime/srcstays untouched.
Not done / open¶
- Overlay settings for
NAPPLE_AMIIBO_DB/NAPPLE_AMIIBO_KEY(environment only). - Real-device install and
.ipaexport were not demonstrated on hardware (device not connected, no paid team); exact commands are indocs/guides/studio.md. - Localisation catalogue: strings are
LocalizedStringKey/String(localized:), no.xcstringsfile is generated yet.
Addendum 2026-10-27: overlay rebuilt (user request)¶
Floating glass panel with four tabs (Audio/Video, FPS/Speed, Controls, Game/System), game input kept while it is open, controller navigation, Home/Guide toggle,
render target presets, statistics options and the native Metal HUD, per-player controller profiles (input/: napple_input_*_player_bindings, napple_input_get_pad_state,
tests in test_input), mods/cheats toggles, Mii note. iOS Automatic signing now goes through a stub Xcode project (Provisioner). Screenshots: img/studio-redo/panel-tab0..3.png.
Verified: make -C input test, make -C frontend test (settings 37, window 13), runtime links, panel rendered on a LAS data build. Not verified: controller navigation with a real pad,
Home button toggle, panel drag, the Metal HUD on screen, mods/cheats loading (runtime side missing). LAS flakes at boot (guest Break 0x35f202) in about 1 of 4 runs with or without the panel (known guest-handle flake).