apps/ios/README.md
OpenClaw iOS is the officially released iPhone app. It connects to an OpenClaw Gateway as a role: node for chat, voice, approvals, sharing, and device-aware automation.
pnpmxcodegenpnpm install
pnpm ios:open
OpenClawDebugProduct -> Run)apps/ios/LocalSigning.xcconfig.apps/ios/LocalSigning.xcconfig.example.Generate without opening Xcode:
pnpm ios:gen
Prereqs:
pnpmxcodegenfastlaneFWJYW4S8P8)MATCH_PASSWORD)ai.openclawfoundation.appscripts/ios-app-store-connect-keychain-setup.sh when auto-resolving a build number or uploading to App Store ConnectRelease behavior:
ai.openclawfoundation.app* bundle IDs when the OpenClaw team is available, and unique ai.openclawfoundation.app.test.* bundle IDs only for non-canonical fallback teams.ai.openclawfoundation.app* bundle IDs through a temporary generated xcconfig in apps/ios/build/AppStoreRelease.xcconfig.Apple Distribution signing with profile names pinned in apps/ios/Config/AppStoreSigning.json.match signing sync to the repo/branch pinned in apps/ios/Config/AppStoreSigning.json, and release handling.OpenClawPushMode=appStore, which derives relay transport, official distribution, the canonical production relay, production APNs, production relay profile, appleStrict proof, and the App-Attest-capable entitlement file.pnpm ios:release:upload generates App Store screenshots, uploads release notes, and attaches apps/ios/APP-REVIEW-NOTES.md as a rendered PDF before archiving and uploading the IPA.pnpm ios:release:upload as the only release path. If that command fails, stop and fix the failing screenshot, metadata, archive, validation, or upload step before trying again.pnpm ios:release:archive, asc builds upload, asc release stage, asc publish appstore, direct Fastlane lanes, or App Store Connect mutation commands as fallback upload paths after pnpm ios:release:upload fails.Notes field.apps/ios/.local-signing.xcconfig or apps/ios/LocalSigning.xcconfig.--version.apps/ios/CHANGELOG.md is the iOS-only changelog and release-note source.2026.4.10.CFBundleShortVersionString = 2026.4.10CFBundleVersion = next App Store Connect build number for 2026.4.10package.json; App Store uploads use the explicit --version value.apps/ios/VERSIONING.md for the full workflow.Relay behavior for App Store builds:
https://ios-push-relay.openclaw.ai.Signing setup commands:
pnpm ios:release:signing:plan
pnpm ios:release:signing:check
pnpm ios:release:signing:setup
MATCH_PASSWORD=... pnpm ios:release:signing:sync:push
MATCH_PASSWORD=... pnpm ios:release:signing:sync:pull
Release-owner secrets:
apps/ios/fastlane/.env variables.MATCH_PASSWORD.apps/ios/Config/AppStoreSigning.json to be associated with both the app and share-extension bundle IDs before App Store profiles are regenerated.apps/ios/build/ or Keychain and are gitignored.match assets and pushing a fresh encrypted sync state.Prepare the generated release xcconfig/project without archiving:
pnpm ios:release:prepare -- --version 2026.6.11 --build-number 7
Archive without upload:
pnpm ios:release:archive -- --version 2026.6.11
This command is for local archive validation only. It is not a fallback upload
path after pnpm ios:release:upload fails.
Archive and upload to App Store Connect:
pnpm ios:release:upload -- --version 2026.6.11
If you need to force a specific build number:
pnpm ios:release:upload -- --version 2026.6.11 --build-number 7
Use this when a clone is missing local iOS release setup and you want the shortest path to an App Store Connect upload.
cd apps/ios
fastlane ios auth_check
scripts/ios-app-store-connect-keychain-setup.sh \
--key-path /absolute/path/to/AuthKey_XXXXXXXXXX.p8 \
--issuer-id YOUR_ISSUER_ID \
--write-env
This should create apps/ios/fastlane/.env with non-secret App Store Connect variables while the private key stays in Keychain.
Confirm the App Store Connect app and Apple Developer identifiers/capabilities exist for:
ai.openclawfoundation.appai.openclawfoundation.app.shareai.openclawfoundation.app.activitywidgetai.openclawfoundation.app.watchkitappThe main app and share extension must both be associated with the App Group pinned in apps/ios/Config/AppStoreSigning.json. The main app must also have App Attest enabled.
Use pnpm ios:release:signing:setup for the initial portal setup, then MATCH_PASSWORD=... pnpm ios:release:signing:sync:push to publish encrypted Fastlane match assets to the shared private repo.
If you are starting a brand-new production release train, add or update the matching iOS changelog section and validate the release notes:
pnpm ios:version:check -- --version 2026.6.11
pnpm ios:release:upload -- --version 2026.6.11 --build-number 3
If pnpm ios:release:upload fails, stop at that failure. Do not archive
and upload the IPA through another command. Fix the failing release-lane
step, then rerun pnpm ios:release:upload.
Expected behavior:
--version valueapps/ios/build/AppStoreRelease.xcconfigOpenClawExpected outputs after a successful run:
apps/ios/build/app-store/OpenClaw-<version>.ipaapps/ios/build/app-store/OpenClaw-<version>.app.dSYM.zipUploaded iOS App Store build: version=<version> short=<short> build=<build>If this is a fresh clone on a maintainer machine that already works elsewhere, it is OK to copy the non-secret apps/ios/fastlane/.env from another trusted local clone on the same Mac. The Keychain-backed private key remains machine-local and is not stored in the repo.
--versionpackage.jsonapps/ios/CHANGELOG.mdapps/ios/build/Version.xcconfigapps/ios/SwiftSources.input.xcfilelistapps/ios/CHANGELOG.mdpnpm ios:version
pnpm ios:version:check
pnpm ios:version -- --version 2026.6.11
pnpm ios:filelist:gen
Recommended flow:
2026.6.11.apps/ios/CHANGELOG.md, usually under ## Unreleased while iterating.pnpm ios:version:check -- --version 2026.6.11 after changelog changes.pnpm ios:release:upload -- --version 2026.6.11.package.json.apps/ios/CHANGELOG.md for the new release as needed.pnpm ios:version:check -- --version <release-version>.pnpm ios:release:upload -- --version <release-version>.See apps/ios/VERSIONING.md for the detailed spec.
registerForRemoteNotifications() at launch.apps/ios/Sources/OpenClaw.entitlements derives aps-environment from the active build configuration/signing override.apps/ios/Sources/OpenClawAppAttest.entitlements; local/direct builds do not require App Attest provisioning.push.apns.register).OpenClawPushMode=localSandbox, direct APNs registration, and a development aps-environment entitlement. Local/manual Release builds default to OpenClawPushMode=localProduction and direct production APNs registration.APNs registration failed).OPENCLAW_APNS_TEAM_ID, OPENCLAW_APNS_KEY_ID, and either OPENCLAW_APNS_PRIVATE_KEY_P8 or OPENCLAW_APNS_PRIVATE_KEY_PATH..p8 file is ~/.openclaw/credentials/apns/AuthKey_<KEYID>.p8 with restrictive permissions, then point OPENCLAW_APNS_PRIVATE_KEY_PATH at that file.apps/ios/fastlane/.env only covers App Store Connect / Fastlane auth; it does not provide gateway APNs credentials for local direct-push testing.OpenClawPushMode=localSandbox; Release builds default to production APNs through OpenClawPushMode=localProduction.push.apns.register to the gateway.gateway.identity.get, so another gateway cannot reuse that stored registration.production relay profile, production APNs, App Attest, and a StoreKit app transaction JWS during registration.gateway.push.apns.relay.baseUrl in openclaw.json. OPENCLAW_APNS_RELAY_BASE_URL remains a temporary env override only.iOS -> gateway
gateway.identity.get.iOS -> relay
gateway delegation
gateway -> relay
relay -> APNs
This exists to keep the hosted relay limited to genuine OpenClaw official builds and to ensure a gateway can only send pushes for iOS devices that paired with that gateway.
/pair qr or /pair, then /pair approve in Telegram).node.presence.alive beacons that update gateway last-seen metadata when the app moves between foreground and background, without treating suspended sockets as connected.The iOS app is not a Codex Computer Use backend. Computer Use and cua-driver mcp are macOS desktop-control paths; iOS exposes device capabilities as OpenClaw node commands through the gateway. Agents can drive the iPhone canvas, camera, screen, location, voice, and other node capabilities with node.invoke, subject to iOS foreground/background limits.
Use this for automation signals ("I moved", "I arrived", "I left"), not as a keep-awake mechanism.
Test path to include in QA runs:
Always permissionPass criteria:
canvas.*, camera.*, screen.*, and talk.* are blocked when backgrounded.Always location permission.Automatic wake/reconnect hardening:
xcodegen generate)Settings -> Gateway:
/pair approve from Telegram, then reconnectDiscovery Debug LogsSettings -> Gateway -> Discovery Logsai.openclawfoundation.appGatewayDiagAPNs registration failed