What Is AppDrop
AppDrop is a small service that lets you share any app with a single link. Anyone who opens the link can install the app, and each build is signed with the user's Apple ID.
npx appdrop App.ipa
# https://appdrop.app/d/k3m9x2p7qaAll you need is Node.js 18 or later. You can also upload a file by dragging it onto appdrop.app/drop.
Sharing an App with a Link
Run npx appdrop followed by your build file:
npx appdrop build/App.ipaYou can upload an .ipa for iPhone and iPad, an .apk or .aab for Android, and a .app for Mac (or a ZIP file that contains it). An .ipa can be signed or unsigned, because it's re-signed for each person who installs it. Files can be up to 500 MB.
Installing an App on iPhone
Open the link on your iPhone and follow the steps. The first time you install an app, you need to:
- Set up AppDrop on your phone so it can install apps over the air.
- Sign in with your Apple ID to sign apps for this phone.
- Turn on Developer Mode, if your phone asks you to.
After that, you can install other apps with a single tap. Your browser remembers your Apple ID.
Apps signed with a free Apple ID stop opening after seven days. Apps signed with a paid developer account stop opening after about a year. You can see when each app expires in your library at appdrop.app.
Releasing a New Version of an App
Every app has an update link, which ends in /manage#…. Anyone who has it can release new versions, so npx appdrop shows only the share link and saves the update link on the computer you shared from. To see it, run npx appdrop links there:
$ npx appdrop links
My App (com.example.app)
share: https://appdrop.app/d/k3m9x2p7qa
update (keep private): https://appdrop.app/d/k3m9x2p7qa/manage#Xq7…To release a new version, pass the update link to --update with the new build. This works on any computer:
npx appdrop build/App.ipa --update "https://appdrop.app/d/k3m9x2p7qa/manage#Xq7…"On the computer you shared from, the share link works too, because the update link is saved there:
npx appdrop build/App.ipa --update https://appdrop.app/d/k3m9x2p7qaThe link stays the same. People who already installed the app are offered the update the next time they open the link. On iPhone, the installed app updates automatically and keeps its data. You can also open the update link in a browser and upload the new build there.
The new build must use the same bundle identifier and a new build number. To release the same build number again, add --force.
Saving Apps to Your Account
To save the apps you share to your AppDrop account, link the computer you share from. Run this on it:
npx appdrop loginYou'll see a link. Open it on any device that's signed in to appdrop.app and approve it. The command then finishes.
From then on, every app you share from that computer is added to your account, including apps you shared before. You can see and manage them at appdrop.app/account without their update links.
The sign-in lasts a year. It can add and manage apps, and nothing else.
Sharing an Android App
npx appdrop build/App.apk
npx appdrop build/App.aabOpen the link on an Android phone to download and install the app. Android may ask you to allow your browser to install apps.
An .aab is converted into an .apk that Android can install directly. If the app isn't signed, AppDrop signs it with a key saved for this link, so later updates can install over it. If the app is already signed, it keeps its original signature, and later updates must be signed with the same key.
Sharing a Mac App
npx appdrop build/MyApp.appWhile AppDrop can distribute Mac apps, it doesn't sign them, so users will be warned when they open the app. If you want the link for an iPhone app to offer a Mac version too, release the Mac build to that link with --update. After that, Mac users who open the same link get the Mac version.
Sharing an Apple Vision Pro App
The link for an iPhone app can also offer its visionOS version. Release a visionOS .ipa with the same bundle identifier to the link:
npx appdrop build/AppVision.ipa --update https://appdrop.app/d/k3m9x2p7qaAfter that, Apple Vision Pro installs the visionOS version from the link, and other devices still install the iPhone version.
Sharing Multiple Builds of One App
AppDrop treats builds with the same bundle identifier as the same app. Each time you share without --update, you get a new link, so you can share several builds at once, such as one from a feature branch and one from main.
A phone, though, can install only one of these builds at a time, because it can have only one app with a given bundle identifier. Installing another replaces the one already there, so AppDrop asks you first. Only the installed build updates automatically.
If you want two builds on a phone at the same time, give them different bundle identifiers, such as com.example.app and com.example.app.beta. AppDrop then treats them as two different apps.
Each link shows a label to help people tell the builds apart. By default, the label is the git branch you were on when you shared the build. You can also set it yourself:
npx appdrop build/App.ipa --label "onboarding redesign"Using AppDrop with Tailscale
iOS can run only one VPN at a time, so when Tailscale is on, your phone can't use the AppDrop VPN. Instead, run a relay on a computer in the same tailnet, and it stands in for the AppDrop VPN:
npx appdrop relayScan the QR code it shows with your iPhone. Then tap Allow in the browser you used to set up AppDrop. Keep the command running. As long as it runs, apps install and update through that computer, even when the AppDrop VPN is off.
Your approval is saved, so the relay connects right away next time. Each install through the relay is logged in ~/.appdrop/relay-log.jsonl. To set up the relay for a different iPhone, run npx appdrop relay --relink.
Using AppDrop in Scripts and Agents
Standard output contains only the link, so scripts can capture it directly:
url=$(npx appdrop build/App.ipa)Add --json to see the details:
{"url":"https://appdrop.app/d/k3m9x2p7qa","id":"k3m9x2p7qa","name":"My App","bundleId":"com.example.app","version":"42","shortVersion":"1.2.0"}For a new link, the result also includes manageUrl and manageKey. They're shown only once. Save them as secrets so you can release updates from CI. If the upload fails, or the file isn't an app, the command exits with a nonzero code.
If you want an agent to update an app, just give it the update link.
Sharing Every Pull Request from CI
This GitHub Actions workflow builds an .ipa for each pull request, shares it, and posts the link on the pull request. The .ipa doesn't need to be signed, so the runner needs no certificates or provisioning profiles.
name: AppDrop
on: pull_request
jobs:
share:
runs-on: macos-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
# Replace this with your own build. It should leave an .ipa at build/App.ipa.
- run: ./scripts/build-ipa.sh
- name: Share the build
run: |
url=$(npx appdrop build/App.ipa --label "$BRANCH")
gh pr comment "$PR" --body "Install this build on your iPhone: $url"
env:
BRANCH: ${{ github.head_ref }}
PR: ${{ github.event.number }}
GH_TOKEN: ${{ github.token }}Each pull request gets its own link, labeled with its branch. CI checks out a pull request without a branch, so pass --label yourself. Otherwise the label is a commit hash.
To publish every build from main to one link instead, so testers always have the latest, save the app's update link as a repository secret and add --update:
npx appdrop build/App.ipa --update "$APPDROP_UPDATE_LINK" --label mainCommands and Options
| Option | |
|---|---|
--update <link> | Release a new build to an existing link. |
--label <text> | A name that tells this build apart from other builds of the same app. |
--json | Show the result as JSON. |
--force | Release the same build number again. |
--key <key> | The update key, when --update is given a share link. |
-h, --help | Show help. |
| Command | |
|---|---|
npx appdrop links | List the apps shared from the computer. |
npx appdrop login | Link the computer to your account. |
npx appdrop logout | Unlink the computer from your account. |
npx appdrop relay | Install apps while Tailscale is on. |
Caveats
On iPhone, each person's copy of your app gets a new bundle identifier: yours plus a suffix for their Apple ID, such as com.example.app.orbit1a2b3c4d. Anything tied to your own bundle identifier or developer team doesn't work in that copy, including:
- push notifications from your server;
- Sign in with Apple;
- universal links;
- iCloud, and App Groups shared with your other apps;
- in-app purchases.
Widgets, app extensions and Apple Watch apps are removed, unless the person signs with a paid developer account.
