The official CLI for TestApp.io app distribution
Upload your Android (APK) and iOS (IPA) apps directly from the command line.
Notify your team instantly. Get feedback faster.
Quick Install
curl -Ls https://github.com/testappio/cli/releases/latest/download/install | bash
Works on macOS (Intel & Apple Silicon) and Linux (x86_64, ARM). For Windows, see below.
How to update
Did you land here from a message that says "New version available"? Update like this.
1. Run the installer again
curl -Ls https://github.com/testappio/cli/releases/latest/download/install | bash
It replaces the old version with the latest one. Your settings (~/.ta-cli.json) are not touched.
On Windows, download the newest ta-cli-Windows-x86_64.exe from Releases and replace the old file (see Windows).
2. Check the version
ta-cli version
If you are up to date, it prints You are using the latest version. If not, it prints New version available and the number of the newest version.
What "update necessary due to breaking changes" means
Most updates are optional. The old version keeps working and only shows you the notice.
Sometimes we change something on our servers that an old ta-cli can no longer work with. Then ta-cli stops before uploading anything and prints:
⚠️ Update necessary due to breaking changes ⚠️
Error: update necessary due to breaking changes; install the latest ta-cli (https://help.testapp.io/ta-cli/) and run again
Nothing was uploaded. Run the installer above, then run your command again.
Updating if you use a plugin or CI
| How you use ta-cli | What happens | What you do |
|---|---|---|
| Fastlane plugin | The plugin checks ta-cli version before every upload. With self_update: true (the default) it installs a newer ta-cli by itself. With self_update: false it only warns about a normal update, and stops the lane when the update is required. |
Nothing, unless you set self_update: false. Then update by hand (step 1 above) or set it back to true. You can also set it with TESTAPPIO_SELF_UPDATE. The plugin itself is a separate update: bundle update fastlane-plugin-testappio. |
| GitHub Action | Every run installs the latest ta-cli. | Nothing, if your workflow uses testappio/github-action@v5. Older versions of the action (@v3, @v4) install a fixed old ta-cli. Change them to @v5. |
| Any other CI (GitLab, Jenkins, CircleCI, ...) | Whatever your script does. If it runs the install line before ta-cli publish, it is already updating on every run. |
If you install ta-cli once on the build machine or in an image, run the installer again there. |
| Your own computer | Nothing happens by itself. | Step 1 above. |
What is ta-cli?
ta-cli lets you upload app builds to TestApp.io without leaving your terminal. Perfect for:
- Local development - Quick uploads while coding
- CI/CD pipelines - Automated releases on every build
- Team collaboration - Notify testers instantly with each release
Features:
- Upload Android APK and iOS IPA files
- Automatic app info extraction (version, bundle ID, etc.)
- Git integration for release notes
- Team notifications
- Resumable uploads: if the connection drops, the upload carries on from where it stopped
- Cross-platform support
Installation
macOS & Linux
curl -Ls https://github.com/testappio/cli/releases/latest/download/install | bash
This installs to /usr/local/bin/ta-cli. If that folder needs it, the installer asks for your password.
To install somewhere else, set INSTALL_DIR for the installer:
curl -Ls https://github.com/testappio/cli/releases/latest/download/install | INSTALL_DIR=$HOME/bin bash
Windows
Download from Releases:
| File | Architecture |
|---|---|
ta-cli-Windows-x86_64.exe |
64-bit (recommended) |
ta-cli-Windows-i686.exe |
32-bit |
Rename it ta-cli.exe and add it to your PATH, or run it directly. To update, download the new file and replace the old one.
Verify Installation
ta-cli version
Quick Start
1. Get your credentials
| Credential | Where to find it |
|---|---|
| API Token | portal.testapp.io/profile/tokens |
| App ID | Open your app at portal.testapp.io/apps, then Integrations → Release → TestApp.io CLI → View Setup |
2. Configure (interactive)
ta-cli config
Follow the prompts to enter your credentials.
3. Publish your app
ta-cli publish
That's it! Your app is uploaded, and your team is notified if you turned notifications on.
Commands
ta-cli publish
Upload your app to TestApp.io.
ta-cli publish [flags]
| Flag | Description | Default |
|---|---|---|
--api_token |
Your API token | From config or environment |
--app_id |
Your App ID | From config or environment |
--release |
android, ios, or both |
both |
--apk |
Path to Android APK file | From config or environment |
--ipa |
Path to iOS IPA file | From config or environment |
--release_notes |
Custom release notes (up to 1,200 characters) | None |
--git_release_notes |
Use the latest git commit message as notes | false |
--git_commit_id |
Add the latest git commit ID to the notes | false |
--notify |
Notify team members | false |
--archive_latest_release |
Archive the previous latest release after a successful upload | false |
--upload_timeout |
The longest the upload may take in total, for example 45m or 3h. 0 turns the limit off. |
2h |
--config |
Custom config file path | ~/.ta-cli.json |
With --release both, ta-cli checks both files first and uploads only if both are fine.
ta-cli config
Interactive configuration wizard.
ta-cli config
ta-cli version
Show the version you have, and tell you if a newer one exists.
ta-cli version
ta-cli completion
Generate shell autocompletion scripts.
# Bash
ta-cli completion bash > /etc/bash_completion.d/ta-cli
# Zsh
ta-cli completion zsh > "${fpath[1]}/_ta-cli"
# Fish
ta-cli completion fish > ~/.config/fish/completions/ta-cli.fish
Upload time limit
An upload is allowed to take up to 2 hours in total. After that, ta-cli stops and tells you how much the server had received. Most builds finish in minutes, so you will rarely notice this. If you upload very large files over a slow connection, raise it. If you never want a limit, turn it off.
| Value | Meaning |
|---|---|
45m, 90m, 3h |
Stop after this long |
5400 |
A plain number is read as seconds (5400 seconds = 90 minutes) |
0 |
No limit |
Set it with the flag:
ta-cli publish --apk=./app-release.apk --release=android --upload_timeout=3h
or with the environment variable TESTAPPIO_UPLOAD_TIMEOUT (this is the easy way when you use Fastlane or the GitHub Action):
export TESTAPPIO_UPLOAD_TIMEOUT=3h
You can also put "upload_timeout": "3h" in your config file.
A wrong value (for example soon) or a negative one stops ta-cli before it uploads anything, with a message that says what is wrong.
Fastlane
Nothing to change in the plugin. The plugin starts ta-cli with the environment your lane already has, so set the variable where your lane runs:
export TESTAPPIO_UPLOAD_TIMEOUT=3h
fastlane ios beta
or in your Fastfile, before the upload step:
ENV["TESTAPPIO_UPLOAD_TIMEOUT"] = "3h"
upload_to_testappio(...)
GitHub Action
Nothing to change in the action. Add the variable to the step (or the job) in your workflow:
- name: Upload to TestApp.io
uses: testappio/github-action@v5
env:
TESTAPPIO_UPLOAD_TIMEOUT: 3h
with:
api_token: ${{ secrets.TESTAPPIO_API_TOKEN }}
app_id: ${{ secrets.TESTAPPIO_APP_ID }}
file: ./app-release.apk
Configuration
Config File
Location: ~/.ta-cli.json
{
"api_token": "your_api_token",
"app_id": "your_app_id",
"release": "both",
"apk": "/path/to/app.apk",
"ipa": "/path/to/app.ipa",
"release_notes": "",
"git_release_notes": true,
"git_commit_id": false,
"notify": true,
"archive_latest_release": false,
"upload_timeout": "2h"
}
ta-cli config writes the first nine settings. Add archive_latest_release and upload_timeout by hand if you want them. Note: running ta-cli config again rewrites the file and drops those two lines, so add them again afterwards.
Custom Config Path
ta-cli publish --config=/path/to/custom-config.json
Which setting wins
When the same setting is given in more than one place, the first one in this list wins:
- Command-line flags
- Environment variables
- The file given with
--config .ta-cli.jsonin the current folder~/.ta-cli.json
Environment Variables
Use environment variables instead of config files (ideal for CI/CD):
| Variable | Description |
|---|---|
TESTAPPIO_API_TOKEN |
Your API token |
TESTAPPIO_APP_ID |
Your App ID |
TESTAPPIO_RELEASE |
Release type: android, ios, or both |
TESTAPPIO_ANDROID_PATH |
Path to APK file |
TESTAPPIO_IOS_PATH |
Path to IPA file |
TESTAPPIO_NOTIFY |
Send notifications: true or false |
TESTAPPIO_RELEASE_NOTES |
Custom release notes |
TESTAPPIO_GIT_RELEASE_NOTES |
Use git commit as notes: true or false |
TESTAPPIO_GIT_COMMIT_ID |
Include commit ID: true or false |
TESTAPPIO_ARCHIVE_LATEST_RELEASE |
Archive the previous release: true or false |
TESTAPPIO_UPLOAD_TIMEOUT |
Longest upload time, for example 3h. 0 = no limit. Default 2h. |
Example:
export TESTAPPIO_API_TOKEN="your_token"
export TESTAPPIO_APP_ID="your_app_id"
ta-cli publish --apk=./app.apk --release=android
Older setups may use names without the TESTAPPIO_ start (for example API_TOKEN). They still work, but ta-cli prints a warning. Please rename them.
CI/CD Integrations
ta-cli works with any CI/CD platform that supports bash. Just install and run!
Quick Setup (Any CI/CD)
# 1. Install ta-cli
curl -Ls https://github.com/testappio/cli/releases/latest/download/install | bash
# 2. Upload your app
ta-cli publish \
--api_token=$TESTAPPIO_API_TOKEN \
--app_id=$TESTAPPIO_APP_ID \
--apk=./app-release.apk \
--release=android \
--notify=true
Dedicated Integrations (Recommended)
Our GitHub Action and Fastlane plugin install ta-cli for you and keep it up to date (see How to update).
| Integration | Description | Link |
|---|---|---|
| GitHub Action | Native GitHub Actions integration | testappio/github-action |
| Fastlane Plugin | Native Fastlane plugin | testappio/fastlane-plugin-testappio |
Platform-Specific Guides
We have detailed guides for each CI/CD platform:
| Platform | Documentation |
|---|---|
| GitHub Actions | View Guide |
| Fastlane | View Guide |
| GitLab CI/CD | View Guide |
| Jenkins | View Guide |
| Bitrise | View Guide |
| CircleCI | View Guide |
| Travis CI | View Guide |
| Azure Pipelines | View Guide |
| Codemagic | View Guide |
| Xcode Cloud | View Guide |
Examples
Android Only
ta-cli publish \
--release=android \
--apk=./app-release.apk \
--notify=true
iOS Only
ta-cli publish \
--release=ios \
--ipa=./App.ipa \
--notify=true
Both Platforms
ta-cli publish \
--release=both \
--apk=./app-release.apk \
--ipa=./App.ipa \
--release_notes="Bug fixes and improvements" \
--notify=true
With Git Integration
ta-cli publish \
--git_release_notes=true \
--git_commit_id=true \
--notify=true
Archive Previous Release
ta-cli publish \
--apk=./app-release.apk \
--archive_latest_release=true \
--notify=true
Big file, slow connection
ta-cli publish \
--apk=./app-release.apk \
--upload_timeout=4h
Supported Platforms
Operating Systems
| OS | Architectures | Binary |
|---|---|---|
| macOS | Intel (x86_64), Apple Silicon (arm64), Universal | ta-cli-Darwin-* |
| Linux | x86_64, ARM64 (aarch64), ARMv7, i686 | ta-cli-Linux-* |
| Windows | x86_64 (64-bit), i686 (32-bit) | ta-cli-Windows-*.exe |
Supported File Types
| Platform | File Type | Notes |
|---|---|---|
| Android | .apk |
Debug or release signed APK |
| iOS | .ipa |
Development, Ad-Hoc or Enterprise signed, with a profile that has not expired. Ad-Hoc builds need at least one device in the profile. |
Files up to 4 GB are accepted by ta-cli. Your plan may set a lower limit.
Uninstalling
sudo rm /usr/local/bin/ta-cli
rm ~/.ta-cli.json # Optional: remove config
Troubleshooting
"command not found: ta-cli"
The binary isn't in your PATH:
# Option 1: Restart your terminal
# Option 2: Add to PATH manually
export PATH=$PATH:/usr/local/bin
# Option 3: Use full path
/usr/local/bin/ta-cli version
The upload is slow, drops, or stops
You do not need to do anything for most of these. ta-cli handles them:
- The connection drops. ta-cli asks the server how much it already has and carries on from there. You will see
Upload interrupted (connection lost). Retrying in 5s (attempt 2 of 3).... Bytes the server already has are not sent again. - The connection goes quiet. If nothing is sent for 90 seconds, ta-cli treats the connection as stuck, stops it, and tries again the same way.
- How many tries. ta-cli gives up after 3 tries in a row that make no progress. A try that moves the upload forward starts the count again, so a long upload on a bad connection can still finish.
- The server lost the upload. ta-cli prints a warning and starts that upload again from the beginning, once.
- The 2-hour limit. If the upload takes longer than
--upload_timeout, ta-cli stops and saysthe upload did not finish within 2h0m0s, and how much the server had received. Raise the limit and run again.
If it still fails, the message ends with the name of the release that was created before the upload started. Running again creates a new release, so you may want to archive or delete the empty one in the Portal.
Other things to try: a different network, switching a VPN or proxy off, and making sure the file is not being written to while it uploads.
Errors that stop the upload straight away
Some problems cannot be fixed by trying again. ta-cli stops at once and prints one Error: line that says what is wrong. These are the common ones:
| What the line says | What it means | What to do |
|---|---|---|
unauthorized: not in a team or unauthorized: membership inactive |
The token's user is not an active member of a team. | Ask a team owner to check your membership. |
unauthorized on its own, or the upload server rejected the upload credentials (HTTP 401); check that your API token is valid |
Your API token is wrong, was deleted, or has expired. | Make a new token at portal.testapp.io/profile/tokens and use it in --api_token or TESTAPPIO_API_TOKEN. In CI, update the secret. |
plan limit reached, or your plan's limit was reached (HTTP 402); upgrade your plan or free up space in the Portal |
Your team has used up what its plan allows, such as storage. | Archive or delete old releases in the Portal, or upgrade your plan. |
file too large, or the file is larger than your plan's upload limit (HTTP 413) |
The file is bigger than your plan allows for one upload. | Make the build smaller, or upgrade your plan. |
... exceeds the 4294967296 byte limit |
The file is over 4 GB. This limit is in ta-cli itself. | Make the build smaller. |
APK file missing at ... / IPA path is empty |
The path is wrong or not set. | Check --apk / --ipa (or TESTAPPIO_ANDROID_PATH / TESTAPPIO_IOS_PATH). With CI, the file must exist before the upload step runs. |
--release_notes cannot exceed 1200 characters |
The release notes are too long. | Shorten them. |
update necessary due to breaking changes |
Your ta-cli is too old. | See How to update. |
Lines that start with [Android]: or [iOS]: tell you which build the error is about.
Invalid APK/IPA Error
- APK: Ensure it's a valid Android package with
AndroidManifest.xml, a package name, a version name and a version code. - IPA: Ensure it contains
Info.plistand a valid provisioning profile. App Store builds are not accepted: use Development, Ad-Hoc or Enterprise. An expired profile, or an Ad-Hoc profile with no devices, is rejected before the upload starts.
Config Issues
Reset your configuration:
rm ~/.ta-cli.json
ta-cli config
Windows-Specific Issues
- Run Command Prompt or PowerShell as Administrator if needed
- Use forward slashes or escaped backslashes in paths:
C:/path/to/app.apk
Support
| Resource | Link |
|---|---|
| Help Center | help.testapp.io |
| CLI Documentation | help.testapp.io/ta-cli |
| [email protected] | |
| Issues | GitHub Issues |
Need help? Contact us. We're happy to assist!