Developers

Build the iOS app yourself with Xcode

Build the TRS Launcher IPA for iPhone and iPad on a Mac: Xcode project, Rust library, game engine, sideloading and running it with your own Apple ID.

The iOS app is the same Tauri 2 project as the desktop launcher, built for iPhone and iPad. This page is for contributors and for players who want to build the IPA themselves instead of taking ours. If you only want to play, install the official app – see iPhone/iPad: install with AltStore/SideStore.

Before you start:
  • You need a Mac with Xcode. The Xcode project can only be generated on macOS, so it is not in the repository – a script creates it.
  • Playing Minecraft needs the game engine and JIT, exactly like with the official app. The engine is added to the finished app in a separate step (see Build the IPA). An app you start directly from Xcode has no engine: everything else works, but games don't start.
  • Apps signed with a free Apple ID stop opening after 7 days and must be re-signed (refreshed). A free Apple ID can have only 3 sideloaded apps at the same time.
  • Only real devices (arm64) are built – there is no build for the iOS Simulator.

The commands on this page are the ones the CI runs (.github/workflows/ci.yml job launcher-ios, release.yml jobs iOS and iOS engine, .github/workflows/ios-engine.yml). The CI never signs the app – it builds an unsigned IPA, and AltStore/SideStore sign it with the user's Apple ID when installing.

What is where

PathWhat it is
scripts/ios-project.shCreates the Xcode project in src-tauri/gen/apple (tauri ios init) and adds icons and Info.plist keys
scripts/ios-unsigned-ipa.shBuilds the Rust library, then an Xcode archive without code signing, zipped as IPA
scripts/ios/build-engine.shBuilds the game engine (Amethyst-iOS at a pinned commit, CMake, MobileGlues, Java part)
scripts/ios/package-ipa.shPuts the engine into the app and signs it with ldid and the entitlements
src-tauri/tauri.ios.conf.jsoniOS overrides of the Tauri config (iOS 15, no desktop updater)
src-tauri/Info.ios.plistCamera text (QR code of the PC remote) and background fetch for notifications
src-tauri/plugins/tauri-plugin-trs-game/ios/Swift part, engine sources, trs-game.entitlements

Requirements

ToolVersion / note
macOS with Xcodewith the iPhoneOS SDK. The repository doesn't pin an Xcode version; the CI uses the default Xcode of GitHub's macos-latest runner (app) and macos-15 (engine)
Homebrewfor xcodegen (the script installs it if missing), ldid and cmake
Node.js and pnpmNode 22, pnpm as pinned in package.json (corepack enable)
Ruststable via rustup, target aarch64-apple-ios
JDK 8only for the engine (CI: Zulu 8). It must be a JDK 8 – build-engine.sh checks that
git, python3, zipused by the scripts

The app needs iOS 15 (minimumSystemVersion in tauri.ios.conf.json). The CI sets IPHONEOS_DEPLOYMENT_TARGET=15.0 for the app, because the Swift packages of the plugins use APIs from iOS 14 on; the engine itself is built for 14.0.

Build the IPA

Get the code and the tools

git clone https://github.com/theredstonee/TRS-Launcher.git
cd TRS-Launcher
pnpm install
rustup target add aarch64-apple-ios
brew install ldid cmake

Build the frontend

pnpm generate

Create the Xcode project

bash scripts/ios-project.sh

It runs pnpm tauri ios init --ci if src-tauri/gen/apple doesn't exist yet, copies the camera text and the background task from src-tauri/Info.ios.plist into the app's Info.plist and puts the app icons (plus the event icons as alternative icons) into the asset catalog.

Build the app without signing

export IPHONEOS_DEPLOYMENT_TARGET=15.0
bash scripts/ios-unsigned-ipa.sh release build/TRS-Launcher-app.ipa

What happens inside:

  1. cargo build --lib --target aarch64-apple-ios --release --features tauri/custom-protocol with TAURI_CONFIG set to the content of tauri.ios.conf.json. The custom-protocol feature embeds the interface – without it the app looks for a dev server on localhost:3000 and closes again right away.
  2. The library libtrs_launcher_lib.a is copied to src-tauri/gen/apple/Externals/arm64/release/libapp.a.
  3. scripts/ios/disable-rust-phase.py switches off the Xcode build phase "Build Rust Code" (tauri ios xcode-script) – it only works inside a running tauri ios build, and the library is already there.
  4. xcodebuild … archive with CODE_SIGNING_ALLOWED=NO, then the .app is zipped as Payload/ into the IPA.

Use debug instead of release for a debug build (the library then goes to Externals/arm64/debug/). For CurseForge, set CURSEFORGE_API_KEY or put the key into ~/.tauri/curseforge-api-key – it's optional, without it CurseForge is hidden.

Build the game engine

JAVA8_HOME=$(/usr/libexec/java_home -v 1.8) bash scripts/ios/build-engine.sh build/engine-ios

The script fetches Amethyst-iOS at the pinned commit 9212a1894865e7ac0466029e25ddb0d895544c76, checks the vendored files against it, builds the native engine and MobileGlues with CMake and the Java part with the JDK 8. The result is a folder with Frameworks/, libs/, resources/, LICENSES/ and engine.json. The Java runtimes are not part of it – the app downloads them on the first game start.

Put the engine into the app

bash scripts/ios/package-ipa.sh build/TRS-Launcher-app.ipa build/engine-ios build/TRS-Launcher.ipa

This copies the engine into the app, adds the Info.plist keys for the Files app, landscape mode, mouse and game controllers, and signs everything with ldid – the app with the entitlements from src-tauri/plugins/tauri-plugin-trs-game/ios/trs-game.entitlements (get-task-allow for JIT, the increased memory limit and extended virtual addressing). Another file can be passed with TRS_IOS_ENTITLEMENTS.

Install it

Copy build/TRS-Launcher.ipa to your iPhone or iPad and install it in AltStore or SideStore with My Apps → +. They sign it with your Apple ID, like the official app. Other tools that sign an IPA with your Apple ID should work too, but we haven't tested them. Then enable JIT to play.

When AltStore/SideStore re-sign the app with a free Apple ID, the two memory entitlements usually get lost. The app checks at runtime what it really has and picks the Java memory from that – so the game gets less memory than with TrollStore.

Run it from Xcode with your own Apple ID

You can also start the app straight from Xcode on a connected iPhone and sign it with your own team (a free Apple ID works as "Personal Team"). This is handy for working on the interface. Two things to know:

  • The app has no game engine this way – starting an instance reports that the engine is missing. Sign-in, social, wardrobe, modpacks and everything else work.
  • The CI never signs with a team, so we haven't tested this path.

Build the Rust library for Debug

Do the steps up to Create the Xcode project, then:

export IPHONEOS_DEPLOYMENT_TARGET=15.0
bash scripts/ios-unsigned-ipa.sh debug build/TRS-Launcher-debug.ipa

This leaves the library in src-tauri/gen/apple/Externals/arm64/debug/libapp.a and switches off the Rust build phase in the project, so Xcode can build the app on its own.

Open the project

open src-tauri/gen/apple/*.xcodeproj

Choose the scheme that ends in _iOS and your iPhone as the destination.

Set your team and bundle ID

In the app target under Signing & Capabilities, pick your Team and change the Bundle Identifier to one of your own (for example io.github.yourname.trslauncher) – Apple only lets one team use a bundle ID.

Run

Press Run. On iOS 16 and newer, the iPhone asks for Developer Mode first (Settings → Privacy & Security → Developer Mode). With a free Apple ID you may also have to trust your developer profile under Settings → General → VPN & Device Management.

Xcode signing changes live in the generated project. They are gone when you delete src-tauri/gen/apple and create it again.

Make it your own app

  • Bundle ID: AltStore/SideStore sign the IPA with your Apple ID, so you don't have to change anything for that. For Xcode, change the bundle ID there (see above).
  • Don't change identifier in src-tauri/tauri.conf.json. It is shared with Android, where the Kotlin package and the Rust code depend on it – the Android build then stops (see Build the Android app yourself). An iOS-only identifier in tauri.ios.conf.json might work, but we haven't tested it.
  • Keep the background task ID dev.theredstonee.trslauncher.push-poll as it is: it appears both in src-tauri/Info.ios.plist and in the push plugin's Swift code, and iOS only runs tasks listed in the Info.plist.

What still works in your own build, according to the code:

  • Microsoft sign-in uses the device-code sign-in (you type a code on Microsoft's page) – it doesn't depend on the bundle ID.
  • TRS services (friends, chat, capes, TRS API) talk to the same API; there is no check of the app or its signature.
  • Links like trs-launcher://pack/<code> use the same scheme in every build.
  • Updates: your build isn't connected to our AltStore/SideStore source. Update it by building and installing again.

If something breaks in your own build, please report it.

Run the checks

The same checks as the CI:

pnpm generate
cd src-tauri
IPHONEOS_DEPLOYMENT_TARGET=15.0 cargo clippy --workspace --target aarch64-apple-ios -- -D warnings
# game plugin for iOS, Rust and its Swift package (job "iOS engine"):
IPHONEOS_DEPLOYMENT_TARGET=14.0 cargo build -p tauri-plugin-trs-game --target aarch64-apple-ios

Troubleshooting

"Build-Phase tauri ios xcode-script nicht gefunden"

scripts/ios-unsigned-ipa.sh switches off that build phase the first time it runs – a second run doesn't find it any more and stops with this message. The CI always starts with a fresh project. Locally, delete the generated project and create it again:

rm -rf src-tauri/gen/apple
bash scripts/ios-project.sh

Errors about the deployment target or iOS 14 APIs

Set IPHONEOS_DEPLOYMENT_TARGET=15.0 before building the app (14.0 for the engine plugin check) – the Swift packages need at least iOS 14.

The app closes right after opening

If you built the Rust library by hand, you probably left out --features tauri/custom-protocol – then the app waits for a dev server on localhost:3000. Use scripts/ios-unsigned-ipa.sh, which always sets it.

"JDK 8 fehlt (JAVA8_HOME setzen)" or "JAVA8_HOME ist kein JDK 8"

The engine's Java part needs exactly a JDK 8. Install one and point JAVA8_HOME to it.

"ldid fehlt (brew install ldid)"

package-ipa.sh signs with ldid: brew install ldid.

"vendored Datei weicht von Upstream ab"

A file under ios/Engine/vendor/amethyst-ios differs from the pinned Amethyst-iOS commit. Only the patched files listed in that folder's UPSTREAM.md may differ – undo your change or update the list.

The game closes right after starting

Almost always JIT is not on. See Enable JIT. The engine log is in the Files app under On My iPhone → TRS Launcher (trs-engine.log).

Minecraft 26.3 doesn't start

26.3 is not supported on iOS yet (the engine has no SDL3 support there). Use 26.2 or older.

"Unable to verify app" after a week

The 7 days of the free Apple ID are over. Refresh the app in AltStore/SideStore, or run it from Xcode again.

License and name

TRS Launcher is free software under the GNU General Public License v3.0 (LICENSE, copyright notices in NOTICE). You may build, change and share the app. If you share an IPA, the GPL requires that you share it under the same license and make the complete source code of exactly that build available, including your changes. The iOS engine is based on Amethyst-iOS (GPL-3.0) and ships more third-party parts; their license texts are copied into the app (licenses/engine) and listed in NOTICE – keep them.

The repository has no separate trademark rules. Still: if you hand out your own build, give it its own name and bundle ID so nobody mistakes it for the official TRS Launcher, and point people to your source code – not to our support.

Next steps

Build the Android app yourself

The APK with your own signing key – works on Windows and Linux.

iPhone & iPad

Install the official app with AltStore or SideStore.
TRS Launcher – The Redstone Launcher by TheRedstonee

Not an official Minecraft product. Not approved by or associated with Mojang or Microsoft.

© 2026 TheRedstonee · GPL-3.0