Find and install the newest App Store version that still works on an older iPhone or iPad.
When an app's current release requires a newer iOS version, a compatible build may still exist in its App Store history. appfit finds that build, verifies that it fits the target device, and can download or install it using the Apple ID that owns the app.
There are two things to decide: whether you want a window or a terminal, and whether the device is plugged in.
| Mac app | Terminal | |
|---|---|---|
| Cable attached | appfit reads the connected device's iOS version, recommends the newest compatible build, then downloads, verifies, and installs it over USB. | The same, driven by appfit install. |
| No cable | Type the iOS version and device family by hand to compare compatible builds, claim the free licence, or download the IPA. | appfit get claims the licence; the device then requests Apple's compatible version itself. |
The Mac app is the shortest path and needs nothing else installed. The terminal suits scripting and repeated runs.
The v0.3.1 disk images bundle outdated Python and CA certificates. Use 0.3.2 or later.
- Download
appfit-<version>-arm64.dmg(Apple silicon) orappfit-<version>-x86_64.dmg(Intel) from GitHub Releases. - Open the disk image and drag appfit to Applications.
- The Mac app is not yet signed with a Developer ID or notarized by Apple, so macOS blocks it the first time it opens. After that first attempt, open System Settings → Privacy & Security, click Open Anyway next to the appfit message, and confirm. The release notes say when a release is unsigned.
That is the whole install. The App Store helper travels inside the app, so Python and Go are not required.
Requires macOS, Python 3.11 or newer, and Go, which builds appfit's App Store helper.
Use a current security-patched Python release, for example 3.12.16 or later in the 3.12 branch, 3.13.18 or later in 3.13, or 3.14.10 or later in 3.14. A wheel uses your environment's Python and certificates; it does not repair old ones.
brew install go
mkdir -p "$HOME/appfit"
cd "$HOME/appfit"
python3 -m venv .venv
source .venv/bin/activateDownload appfit-0.3.2-py3-none-any.whl from
GitHub Releases, then install it.
Include the device extra for USB installation:
pip install "$HOME/Downloads/appfit-0.3.2-py3-none-any.whl[device]"
appfit ipatool installWithout USB installation, install the wheel with no extra. To run the same GUI
from a terminal environment, use the gui extra and the appfit-gui command.
When returning later, reactivate the environment:
cd "$HOME/appfit"
source .venv/bin/activate-
Open appfit.
-
Select the connected device, or switch to a manual iOS version and device family.
-
Search for an app and select the correct result.
-
Choose Find newest compatible version and confirm the Apple ID action.
-
Install over USB, download the IPA, or show the licence-only instructions.
Older compatible builds can be loaded after the recommendation. Apple ID password entry and verification during initial sign-in stay in a separate Terminal window and go directly to ipatool.
Apple sometimes asks for a fresh verification code before it adds an app to your purchases. The Mac app asks for that six-digit code in its own window, forwards it to ipatool over standard input, and resumes the interrupted action. It never stores or logs the code. Terminal commands ask for the code in place.
Sign in, connect and trust the device, then list it:
appfit accounts use you@example.com
appfit devicesPair its UDID with the Apple ID currently used for App Store purchases on that device:
appfit pair <udid> --account you@example.comInstall the newest compatible build:
appfit install <bundle-id> --device <udid>To stop before installation:
appfit resolve <bundle-id> --device <udid>
appfit download <bundle-id> --device <udid>Search first if you do not know the bundle ID:
appfit search "app name"Apple performs the download on the device itself. Sign in, then claim the free app licence for the target iOS version:
appfit accounts use you@example.com
appfit get <bundle-id> --ios 16.7.16 --platform ipadappfit prints the Purchased-tab steps. Apple decides whether an older version is offered on the device.
| Command | Purpose |
|---|---|
appfit search <query> |
Find an App Store app. |
appfit accounts use <email> |
Sign in through ipatool. |
appfit devices |
List connected devices and iOS versions. |
appfit get <app> --ios <version> |
Claim a free licence and show on-device steps. |
appfit resolve <app> --device <udid> |
Find the newest compatible build. |
appfit download <app> --device <udid> |
Download and verify the selected IPA. |
appfit install <app> --device <udid> |
Install the selected IPA over USB. |
appfit cache list |
Show cached resolutions and downloads. |
appfit cache prune |
Preview cleanup of unreferenced IPA files. |
appfit ipatool status |
Show the selected ipatool helper. |
<app> can be a bundle ID, numeric App Store ID, App Store URL, or search term.
Use an exact identifier before any licence-changing action.
- The Apple ID used for App Store purchases on the target device.
- For USB installation: an unlocked, connected, and trusted iPhone or iPad.
- appfit uses intact, encrypted App Store IPAs. It does not decrypt apps or bypass FairPlay.
- Device installation stops if the active Apple ID does not match the account paired to that device.
- Apple controls app availability, licence eligibility, regions, retained historical builds, and its on-device compatible-version offer.
- Apple sometimes declines to serve an app's newest release. appfit reports this and recovers from a build it has already recorded; an app it has not resolved before stays unavailable until Apple serves that release or the app ships another.
- Compatibility checks cover declared iOS and device-family requirements, not every hardware, server-side, or account restriction.
- appfit cannot make third-party IPA downloads safe or account-compatible.
appfit uses Apple's public search API, ipatool, and pymobiledevice3. It is independent and is not affiliated with or endorsed by Apple Inc.
Build metadata and downloaded IPAs are stored under ~/.config/appfit/ and are
reused when possible. Cleanup is dry-run-first:
appfit cache prune
appfit cache prune --yesExported cache metadata contains no password or App Store session, but it can include app bundle IDs and target iOS versions. Review it before sharing.
appfit is not currently published on PyPI.

