ipa-hub uses paired Apple devices reported by Xcode. Physical devices are included by default; simulators are optional.
To pair a device, open Device Hub (installed with Xcode) and choose File → Pair Nearby Device... from the macOS menu bar at the top of the screen. Follow the pairing prompts and enable Developer Mode when requested.
List and inspect devices
ipa-hub device ls
ipa-hub device ls --all
ipa-hub device info --device-name "My iPhone"npx -y ipa-hub device ls
npx -y ipa-hub device ls --all
npx -y ipa-hub device info --device-name "My iPhone"bunx --bun ipa-hub device ls
bunx --bun ipa-hub device ls --all
bunx --bun ipa-hub device info --device-name "My iPhone"device without a subcommand displays help. device ls shows available destinations; --all includes unavailable paired devices. device info shows a concise summary, installed apps, and the source and signature expiry of apps tracked by ipa-hub. Add --json for raw details.
Choose a destination
ipa-hub install gh:owner/repo --device DEVICE_ID
ipa-hub install gh:owner/repo -n "Living Room"
ipa-hub install gh:owner/repo -t iphone -t ipadnpx -y ipa-hub install gh:owner/repo --device DEVICE_ID
npx -y ipa-hub install gh:owner/repo -n "Living Room"
npx -y ipa-hub install gh:owner/repo -t iphone -t ipadbunx --bun ipa-hub install gh:owner/repo --device DEVICE_ID
bunx --bun ipa-hub install gh:owner/repo -n "Living Room"
bunx --bun ipa-hub install gh:owner/repo -t iphone -t ipad--device (-d) accepts a CoreDevice ID, UDID, or exact name. --device-name (-n) matches the full, case-sensitive name. Duplicate matches prompt for a selection.
Repeat --device-type (-t, --type) to consider several types: iphone, ipad, appletv, visionos, and applewatch. All filters are combined; they do not make an incompatible IPA work on another platform. Embedded Watch companions are not supported.
Simulators
ipa-hub device ls -s
ipa-hub install ./Simulator.ipa --simulators-only -n "iPhone 15 Pro Max"npx -y ipa-hub device ls -s
npx -y ipa-hub install ./Simulator.ipa --simulators-only -n "iPhone 15 Pro Max"bunx --bun ipa-hub device ls -s
bunx --bun ipa-hub install ./Simulator.ipa --simulators-only -n "iPhone 15 Pro Max"--include-simulators (-s) adds simulators. --simulators-only excludes physical devices. Simulator IPAs must be compiled for Simulator; re-signing cannot convert a device IPA. Simulator installations do not require a provisioning profile or expire. Discovery requires an Xcode version that reports simulators through CoreDevice.
Signing teams and profiles
ipa-hub teams
ipa-hub teams --all
ipa-hub install gh:owner/repo --team TEAM_ID
ipa-hub install ./App.ipa --select-profile
ipa-hub install ./App.ipa --all-profiles
ipa-hub install ./App.ipa --profile ~/Profiles/App.mobileprovisionnpx -y ipa-hub teams
npx -y ipa-hub teams --all
npx -y ipa-hub install gh:owner/repo --team TEAM_ID
npx -y ipa-hub install ./App.ipa --select-profile
npx -y ipa-hub install ./App.ipa --all-profiles
npx -y ipa-hub install ./App.ipa --profile ~/Profiles/App.mobileprovisionbunx --bun ipa-hub teams
bunx --bun ipa-hub teams --all
bunx --bun ipa-hub install gh:owner/repo --team TEAM_ID
bunx --bun ipa-hub install ./App.ipa --select-profile
bunx --bun ipa-hub install ./App.ipa --all-profiles
bunx --bun ipa-hub install ./App.ipa --profile ~/Profiles/App.mobileprovisionBy default, teams and installation choices show only unrestricted * profiles (TEAM.*). teams --all (-a) also shows profiles scoped to an app or bundle-ID prefix; use install --all-profiles to include compatible specific profiles in the installation picker. --select-profile forces a picker even when only one profile matches, including expired profiles marked for renewal. An explicit --profile PATH remains usable without --all-profiles.
Use teams --json for profile paths and certificate hashes; add --all to include specific profiles in JSON too. --identity SHA1 selects a specific signing identity. The low-level library functions listProfiles() and listTeams() continue returning all discovered profiles; installation options accept allProfiles: true to expand signing choices.
In the manager’s Settings, enable Show specific provisioning profiles to include these profiles. The preference is saved on that browser/device and applies to installations, updates, signature refreshes, and imported apps. It controls profile visibility even when a pasted command contains --all-profiles.
When no suitable profile exists, or the selected profile has expired, ipa-hub builds a disposable app using xcodebuild -allowProvisioningUpdates and your account already signed in to Xcode. It uses the selected team, app identifier, platform, and device. If the team cannot be discovered from local profiles or certificates, pass --team TEAM_ID. Xcode may register the target device and create or update signing assets.
The project, DerivedData, build products, logs, module caches, and temporary build files live together under ~/.ipa-hub/tmp (or the configured data directory). They are removed after success or failure; other projects and their caches are left alone. The renewed profile stays in Xcode’s provisioning-profile library for future installations. Xcode controls which profiles Apple issues: a wildcard is preferred, but an app-specific profile may be returned, with a warning. Before signing, ipa-hub verifies the profile’s team, bundle identifier, platform, expiry, certificate/private key, and device authorization. Required capabilities are checked during signing.
Automatic signature refresh
App Manager enables Automatically refresh app signature for each installed app by default. Open the app’s three-dot menu to turn it off or on. The preference is saved on the Mac and survives app updates and server restarts. Library consumers can use hub.setAutomaticSignatureRefresh(deviceId, bundleId, enabled).
While the server is running, it checks the saved installations on startup and once an hour. It starts trying two days before a seven-day signature expires, or thirty days before a year-long signature expires. Other lifetimes use two sevenths of the installed signature’s duration, capped at thirty days. Signature expiry includes the provisioning profiles for the app and its extensions, and the signing certificate’s expiry.
When the local signing certificate is within seven days of expiry, installations signed before that seven-day cutoff are also eligible. A successful refresh records the new installation date so the same certificate cutoff does not repeatedly trigger it. Xcode manages renewal using the Apple account already signed in on your Mac; if signing needs attention, the server reports the error and tries again on its next hourly check.
The device must be available over USB or the network. ipa-hub checks from the Mac that the app is still installed and that its main process is not running, including in the background. It checks again immediately before installation. Running apps and unavailable devices are skipped until a later check. Automatic refresh never opens the app. If an available device confirms that the app was uninstalled, ipa-hub removes its installation record, retained IPA, and saved download credential.
Each successful installation keeps a private copy of the original IPA under ~/.ipa-hub/devices/<device-id>/apps/<installation-id>/original.ipa, outside the download cache. Automatic refresh uses that copy without downloading the app again or upgrading its version. A successful replacement removes the previous copy; a failed installation keeps it. Apps installed before this retention feature need one manual signature refresh or reinstall to save their original IPA. Simulators do not need signature refreshes.
When signing needs attention
If automatic provisioning fails, check Xcode → Settings → Accounts, accept any pending developer agreements, and ensure the target device is paired and its platform SDK is installed. For a valid, explicitly chosen profile that does not authorize the device, choose another profile or update its device list in Xcode. ipa-hub never asks you to enter Apple credentials.
ipa-hub preserves the bundle identifier when possible. An explicit non-wildcard profile may change it, which can affect app data and Keychain access. App extensions require matching profiles; --strip-extensions removes them explicitly.