The ploa command is the other way into Ploa: from a terminal, in CI, or with no agent at all. It builds on your computer, checks the project, ships what you built, puts a web version up, and runs the MCP server your agent uses. Anything that needs your approval waits for it here too. Run ploa --help for this list in the terminal.
Install and update
curl -fsSL https://ploa.dev/install.sh | sh # macOS and Linux; or: npm install -g @ploa/cli
irm https://ploa.dev/install.ps1 | iex # Windows, in PowerShell
ploa update # the newest version (--check only says whether there is one)
ploa --version # or: ploa version, ploa -v
Needs Node 24 or newer. Installed from npm, ploa update says to use npm install -g @ploa/cli@latest instead; npx -y @ploa/cli <command> runs any command without installing. More: Install the CLI.
Options for every project command
Option
What it does
--dir <path>
The app's folder. Without it, the folder you're in; project commands also work from the app's parent folder (a repository with the app in mobile/, say).
--json
Output for scripts, on status, icon, preflight, privacy, files and files push.
--no-wait
On builds and requests: start and return, and follow it on the dashboard.
-h, help
The list of commands.
Account
Command
What it does
ploa login [--no-browser] [--server <url>]
Signs in with a code you confirm in the browser, where you choose the level (Access and approvals). --no-browser prints the link instead of opening it; --server for a Ploa server other than ploa.dev.
ploa logout
Signs out and revokes this computer's token on the server.
ploa whoami
Who you're signed in as: email, role, workspace, level and server.
ploa update [--check]
Installs the newest ploa. --check only says whether there is one.
ploa doctor
Whether this computer is ready to build and ship: Node, ploa, git, Xcode, CocoaPods, Java, the Android SDK, Flutter, disk space, the sign-in and whether the folder is linked, each with its fix.
Project
Command
What it does
ploa init [--apple <name>] [--google <name>]
Links this app to Ploa and writes ploa.json: finds the app in Ploa by its bundle ID or package name, or adds it. --apple / --google name the store connection when the workspace has several. An agent does the same with ploa_link, so you don't need it when you work with one.
ploa init --aab <file> --ipa <file>
Links an app built another way (Unity, .NET MAUI…), with its IDs read from what it built. One of the two is enough.
ploa status
What the stores have for this app now.
ploa icon
Sends the app's icon to Ploa now (status, preflight and releases do it by themselves when it changed).
ploa preflight [--github] [--changed]
What the stores would reject, before you build. --github: in GitHub Actions, sign in as the run and mark the pull request's lines. --changed: check each app linked to the repository that the pull request changes.
ploa privacy
What the code says about the data it collects, for App Privacy and Data safety.
ploa files
The files a build on GitHub reads that git doesn't have, and where each is.
ploa files push [<path>…]
Sends them from here (google-services.json, .env…) for you to approve on ploa.dev; files you don't approve within 24 hours are dropped.
Release: Android
# Build here, sign with the upload key Ploa keeps, straight to internal testing
ploa release android [--version-code <n|auto>]
# Ship a bundle built any way, with the version it says
ploa release android --aab app.aab
# Build and check here, keep the bundle, send nothing (before Google Play has the app, too)
ploa release android --no-upload
# Also ask for a rollout, and wait for your approval
ploa release android --promote production --rollout 10
# Promote something already uploaded
ploa release android --release <id> --promote production --rollout 10
# Build in your own Google Cloud, from what's pushed
ploa release android --gcp [--sha <commit>]
Option
What it does
--version-code <n|auto>
The version code: a number, or auto for the next free one. Without it, the project's own.
--aab <file>
Ships a bundle built any way (Unity, .NET MAUI, your own Gradle setup), with the version it says.
--promote production|beta|alpha
Asks for your approval to move it to that track, and waits for your answer (--no-wait returns at once).
--rollout <percent>
The share of users for a staged rollout, 1 to 100. Everyone by default.
--release <id>
Works on a release already uploaded instead of building (with --promote).
--gcp [--sha <commit>]
Builds in your own Google Cloud project with Cloud Build, from what's pushed; Google bills the minutes to that project (set up in Settings › Builds). Ploa signs the bundle as always: no key goes to Google.
--force
Builds even when preflight finds problems.
The bundle goes from this computer straight to Google Play: Ploa signs only its signature file and opens the upload with Google, so neither the upload key nor Ploa's access to Google Play reaches this computer. If the direct upload doesn't go through, the bundle goes through Ploa instead. More: Builds and signing.
Release: iOS
# Build on this Mac, signed with Ploa's key, then TestFlight
ploa release ios [--build-number <n|auto>]
# Ship an .ipa, .app or .xcarchive built any way
ploa release ios --ipa App.ipa
# Build and sign here without sending: a check of the build
ploa release ios --no-upload
# Apple builds and signs it in Xcode Cloud
ploa release ios --xcode-cloud [--workflow "Release"] [--branch main]
# Ask for your approval of each next step
ploa release ios --release <id> --submit [--replace]
ploa release ios --release <id> --withdraw
ploa release ios --release <id> --app-store
ploa release ios --release <id> --phased pause|resume|complete
Option
What it does
--build-number <n|auto>
The build number; the next free one with auto.
--ipa <file>
Ships an app built any way, with the version it says. One not signed for the App Store (development, ad hoc, unsigned) is signed here, on any computer, the same way.
--resign
Signs an --ipa again even when it's already signed for the App Store.
--submit
Once it's on TestFlight, also asks for your approval to submit it for App Review.
--no-upload
Builds and signs without sending it to Apple.
--sign keychain
Puts the key in a throwaway keychain on this Mac while Xcode signs. By default the key stays on Ploa, and this Mac sends Ploa only what it signs.
Apple builds and signs it in Xcode Cloud from what's pushed (main unless --branch), and Ploa follows it to TestFlight; the key stays with Apple.
--release <id> --submit [--replace]
Asks for your approval to submit a TestFlight build for App Review. --replace takes out the version's build that's with App Review now and submits this one in its place.
--release <id> --withdraw
Asks for your approval to take the version out of App Review.
--release <id> --app-store
Asks for your approval to release the version App Review approved on the App Store.
--release <id> --phased pause|resume|complete
Asks for your approval to pause, resume or finish the version's phased release.
--force
Builds even when preflight finds problems.
iOS builds run on your Mac, on GitHub or in Xcode Cloud. ploa xcode-cloud gets the repository ready for Xcode Cloud (an Expo app's ios/ made after Xcode Cloud clones it) and says what's left to set up in Xcode. More: Setting up Xcode Cloud.
Websites and web apps
An app's web, hosted on Ploa at a free <name>.ploa.app address or a domain you own. More: Web: site and web app.
Builds the site with its own framework (Expo, Vite, Next static export, Astro, SvelteKit, Nuxt, Angular, Gatsby, Hugo, Flutter and more) and sends the built folder as a new version. Ploa numbers it (from app.json or package.json unless --version), checks it and puts it at its own testing address. --no-build sends what's built already; --create <address> makes the site first when the workspace has none. ploa web deploy is the same.
ploa web release [<build>] [--site <address>] [--at <date and time>]
Puts a tested version live, the newest one waiting or the build named, now or at a time (like 2026-11-06T09:00). You approve it on ploa.dev, unless the token is autonomous.
ploa web status [--site <address>]
The sites, their addresses and their versions.
ploa web rollback [--site <address>] [--version <build>]
Goes back at once to the version live before, or the one named.
ploa web domain [<domain>] [--site <address>]
Connects a domain you own and prints the DNS records to add (Ploa sells no domains). Without a domain, checks the site's domains.
The app's server
The web app's server side: its own API, scheduled jobs and Postgres, in Ploa's cloud or in your own Google Cloud.
Command
What it does
ploa server
Where the app's server stands: its address, version and database.
ploa server create --ploa | --own <project> [--region <region>]
Makes it in Ploa's cloud (on Pro and Team, with the room the plan gives each app) or in your own Google Cloud project, which Google bills you for (any plan).
ploa server retry
Tries again: making it after a failure, or deleting it.
ploa server deploy [--folder <dir>] [--github [--sha <commit>]] [--no-wait]
Sends the server's folder (its Dockerfile, or Node, Python, Go, Java, Ruby, PHP or .NET as it is) as a new version, or has Ploa take it from the app's GitHub repository.
ploa server env [NAME=value…] [--secret] [--remove <NAME>]
The server's environment variables; setting them restarts the live version with them. --secret keeps the values hidden.
ploa server logs [--text <words>] [--since <time>] [--job <name>]
The server's logs, filtered by words, time or job.
ploa server run "<command>"
Runs a command once with the live version (no SSH: the output is in the logs).
ploa server jobs [--name <n> --schedule "<cron>" --command "<cmd>"] [--remove <n>]
Lists the scheduled jobs, adds or changes one, or removes one.
ploa server sql "<query>" [--write]
Queries the database as the server's own role; read-only unless --write, which needs the Production level.
This Mac as a GitHub runner
For iOS builds on GitHub, from a repository's own workflow, on your Mac.
Command
What it does
ploa runner add [--repo <owner/name>]
Downloads GitHub's runner, registers it for the repository and runs it as a service. Paste the token from GitHub's "New self-hosted runner" page when asked, or pipe it in (pbpaste | ploa runner add), never on the command line.
ploa runner status
The runners on this Mac, and whether each is running.
ploa runner remove [--repo <owner/name>]
Stops one, takes it off GitHub and deletes it.
Agents
Command
What it does
ploa mcp
Ploa's MCP server over stdio. Agents start it themselves, in the app's folder or with --dir.
Adds Ploa to the agents' MCP settings (the ones found on this computer by default). See Connect your agent.
In GitHub Actions and on Ploa's servers
These run inside builds; you don't type them yourself.
ploa release android|ios --github --app=<id> --queued=<id> --nonce=<n>: the build Ploa started on GitHub. The workflow Ploa writes runs it, on GitHub's machines, or for iOS on your own Mac as a runner or GitHub's Macs where an owner allowed them. See Builds on GitHub Actions.
ploa preflight --github: the check on each pull request.
ploa web-host runs on Ploa's own hosting machines.
Environment
Variable
What it does
PLOA_TOKEN
A token from Settings › Tokens, in place of the saved sign-in (for CI and servers).
PLOA_SERVER
A Ploa server other than the saved one.
PLOA_APP
The app's ID, for ploa preflight and builds in GitHub Actions where there's no ploa.json. Other commands, and the MCP server, need the folder linked.
PLOA_CONFIG
Where the sign-in is kept, in place of ~/.config/ploa/config.json.
ploa.json
Written in the app's folder by ploa init, or by your agent with ploa_link: the app's ID in Ploa and the server. No secrets; commit it so your team, your agents and CI work on the same app. The same file can hold the site's own rules (Site rules), which are kept when it's written again.