Install and manage Apps
Ordinary Apps are complete source releases in a .pocketapp container. HTTP and UART are only ingress paths: both stop at the same on-product review screen and hand the package to the same AppSupervisor lifecycle.
Package a first install
# App without credentials
cargo xtask package app counter
# App whose manifest declares credentials
cargo xtask package app exa path/to/exa-credentials.jsonOutput is written to target/pocketapps/<id>.pocketapp with file mode 0600 on Unix. For a credentialed first install, credentials.json must contain exactly the credential ids declared by app.json, with no missing or extra keys.
Upload over the local network
Open http://<device-ip>/ from a computer or phone and choose the package, or upload directly:
curl --fail-with-body \
--data-binary @target/pocketapps/exa.pocketapp \
http://DEVICE_IP/installUpload over USB UART
python3 tools/uart-install.py "$DEVICE_PORT" \
target/pocketapps/exa.pocketappUART upload does not provision a model, overwrite Wi-Fi, reset the board or bypass review. It transfers the same complete package to the same Installer. Set DEVICE_PORTusing the discovery step on the P4 or S3 target page first.
Review on the product
The runtime validates the archive before showing review: identity, size, source files, Framework API, capabilities, native service policy, resources and credential declarations. A person then sees the App name, version, Tool count, schedules, network/credential needs and whether this is a fresh install or update. Activation starts only after confirmation.
Package an update
# Update packages omit credentials
cargo xtask package app exaAn update keeps the same App id and native permissions. PocketPi preserves App SQLite data and already stored credentials, rehearses the candidate source and any migrations on a copied database, then swaps the single active source release. Updates that carry credentials, change native permissions, downgrade the schema or skip a migration are rejected.
Let Pi Agent iterate an installed App
- Ask Pi Agent to call
app.checkoutwith the installed ordinary App id. - The Tool returns
apps/<id>/checkoutplus the latest.system/app-events/<id>.jsonoutcome file. - The Agent reads the previous outcome, edits only the checkout with normal file Tools and advances
app.jsonversion. - For a SQLite shape change, it also advances
schemaVersionand adds every requiredmigrations/N.sqlstep. - The Agent calls
app.submitwith the exact checkout path. - PocketPi validates and stages the candidate, then opens the same review screen used by HTTP and UART. Nothing changes until a person confirms.
app.checkout({ "id": "exa" })
# edit apps/exa/checkout/app.json
# edit apps/exa/checkout/actions.js or view.js
app.submit({ "path": "apps/exa/checkout" })Checkout copies source once and reopens existing Agent work on later calls. It does not copydata/, tmp/ or credentials. Submit moves the candidate into the existing installer staging area instead of creating a parallel update mechanism.
Uninstall
Open Apps, choose UNINSTALL APP, then tap the App's X. Uninstall removes:
- the App source release and complete private data root;
- SQLite databases, files and schedule state;
- public Tool routes and cached View/Action Guests;
- native credentials and native MCP session state.
Uninstall is destructive and there is no rollback. The resident Pi Agent System App cannot be installed, updated or uninstalled through the ordinary App lifecycle.
Common install failures
| Message or symptom | Meaning | Fix |
|---|---|---|
credentials.json ids do not match app.json | First-install secret keys differ from manifest bindings | Supply exactly the declared ids; omit credentials for an update |
unsupported Framework API | App targets a different System Framework contract | Set frameworkApi to the supported value or update runtime intentionally |
another install is pending | A review already owns the install slot | Confirm or dismiss it on the product |
| Update rejected before mutation | Permission/schema/migration contract failed | Correct the candidate; installed source/data remain active |