@panda-ai/pos
v0.1.4
Published
Official Panda Developer CLI for apps, assets, browser development, and registry workflows.
Readme
Panda Toolchain
Date: 2026-06-04
Author: Codex
CLI integration updated: 2026-10-26 by Codex.
中文说明:开发者命令统一为 pos;Panda SDK 与 App 标识保持原有合同。
apps/toolchain contains the developer-facing Panda SDK app toolchain. It is
TypeScript-first, runs with Bun, and exposes the local CLI package
@panda-ai/pos with the pos binary.
For the first complete app workflow, read
panda-sdk/TUTORIAL.md. The SDK declarations and
namespace reference live under panda-sdk/.
Install
The npm package requires Node.js 22.18 or newer. Bun is needed only when developing or building the toolchain from this repository.
npm install --global @panda-ai/pos
pos --version
pos doctorYou can also run npx @panda-ai/pos --help. The npm package includes its SDK,
schemas and templates; npm installs the platform-specific image dependencies.
The browser simulator is installed separately and selected with pos dev
--runtime <web-root> or PANDA_SIMULATOR_WEB_ROOT.
The current implementation owns the local Panda App Package loop:
- scaffold a Panda SDK app template with
pos new. - validate the manifest and source layout with
pos lint. - run local compile/check reporting with
pos compile. - pack a
.papPanda App Package. - generate developer signing keys for local packages.
- sign, verify, and inspect
.papfiles with a Panda Cloud-rooted developer certificate and per-app profile chain. - install/list/remove packages in a local simulator/device SD target directory.
- load a signed
.papinto a simulator sandbox and launch the bundled simulator. - run Lua-source app directories directly through the same package/sign/install
simulator path with
pos dev-run. - run the current Panda app project in the simulator with
pos simulatororpos sim.
Local catalog commands support signed-catalog-compatible JSON files for search/info/install/update. Registry commands use the Panda Developer service; their returned review state and the service's publication eligibility remain authoritative. A CLI installation does not open public developer publication or developer certificate/profile issuance on a production service.
Panda Developer Commands
pos is the official CLI for the Panda Developer ecosystem. It shares the
existing Panda SDK, Studio, simulator and .pap contracts.
pos --help
pos --version
pos doctor
pos assets icons <input> --output <file.pbm>
pos assets image <input> --output <file.png>
pos pack [directory] [--output file.pap]
pos dev [directory] [--port number] [--no-open] [--no-watch]
pos login|logout|whoami [--registry https-origin]
pos publish [directory|file.pap] [--resume-upload id] [--registry https-origin]
pos search [query] [--category value] [--limit 1..16] [--cursor cursor] [--registry https-origin]
pos view <app-id> [--cursor cursor] [--registry https-origin]
pos unpublish <app-id>@<version> [--registry https-origin]Directory arguments default to the current project. doctor reports required
app-development dependencies separately from optional firmware dependencies;
pos doctor --board <board> requires the selected board definitions and ESP-IDF.
Doctor does not install tools, build firmware or flash a device. Asset conversion
produces 64x64 binary PBM P4 app icons and runtime-compatible PNG images.
dev uses the Panda browser simulator. It opens the browser and watches project
changes by default; --no-open and --no-watch disable those actions separately.
The normal package verification, signing and Runtime admission prerequisites
still apply. Missing runtime artifacts or issuance prerequisites are reported
as errors rather than bypassed. dev-run, simulator and sim retain the
existing headless/Tauri workflows described below.
Registry login is separate from local development: pack, assets and other
local commands remain usable offline. Select a registry using its configured
default or --registry; login, whoami and logout apply to that selected
service. When the registry advertises native Developer login, pos login
uses its existing GitHub identity through browser authorization. Open the printed
URL, approve pos, and return to the terminal. pos login --provider github
requires this path; --provider cloud selects the separate Panda Cloud device
flow. An existing GitHub official operator keeps that same identity and role.
Publication can produce a pending review state. Resume an interrupted
upload with the returned ID and the same final package bytes; do not repack or
re-sign a package while resuming it.
search filters the complete server collection and forwards opaque cursors.
view lists details and version history by the manifest's reverse-domain app
ID. unpublish [email protected] targets exactly that version;
it is not a whole-app removal command. Published version identities remain
immutable. Check the selected service's eligibility and returned state before
announcing an app as available.
Schema v2 catalogs are exact RFC 8785 JCS documents. Their detached P-256
signature covers the canonical catalog document with the signature field
removed; local readers verify it with ReadCatalogOptions.publicKeyPem or the
PANDA_CATALOG_PUBLIC_KEY_PEM environment variable. Archived schema v1
catalogs remain read-only compatible and do not use the v2 trust path.
Local App Loop
Use Bun for local development commands. pnpm is only a fallback when Bun is not available or a package-local Bun issue blocks the same command.
cd apps/toolchain
bun install
bun run pos new hello /tmp/hello-panda
bun run pos lint /tmp/hello-panda
bun run pos compile /tmp/hello-panda --report /tmp/hello-compile-report.jsonpos lint validates manifest.json and the declared entry file. pos
compile also reads the Lua source, writes .panda-build/compile-report.json,
and runs luac -p when luac is installed. If luac is missing, the command
still writes a report with checkerStatus="skipped".
Package Loop
bun run pos pack /tmp/hello-panda --output /tmp/hello.pap
bun run pos keygen --out /tmp/panda-dev-key.json --id dev.local
bun run pos sign /tmp/hello.pap \
--key /tmp/panda-dev-key.json \
--cert /tmp/developer-cert.txt \
--profile /tmp/hello.profile.txt \
--out /tmp/hello.signed.pap
bun run pos verify /tmp/hello.signed.pap
bun run pos inspect /tmp/hello.signed.pap.pap means Panda App Package. New pack/sign/verify/inspect paths require that
extension, and signed outputs should use names such as hello.signed.pap.
Schema v2 authoring emits exactly one canonical manifest.json; it never emits
manifest.txt, profile.json, signature/payload.json, or legacy root
signature.json/signature.bin artifacts. The archived v1 compatibility path
still reads those legacy archives, but does not re-export them as v2. The
toolchain never embeds or silently uses a Panda Cloud root private key. A
normal signing flow must pass externally issued --cert and --profile
artifacts.
For an internally issued Panda Cloud certificate/profile pair, pass the exact artifacts into signing:
bun run pos sign /tmp/hello.pap \
--key /tmp/panda-dev-key.json \
--cert /tmp/developer-cert.txt \
--profile /tmp/hello.profile.txt \
--out /tmp/hello.signed.papThe public Panda Cloud request flow for developer certificates and app profiles is not exposed yet. Until the Panda platform opens, those artifacts are issued by internal Panda Cloud services for allowlisted workflows. Internal tests and controlled tooling may inject a root key through code, but that key is not part of the distributed CLI or source tree.
pos verify checks the full chain before local install, simulator run,
catalog install, or update because the target installer accepts signed packages
only:
- Panda Cloud root signature over the developer certificate.
- Panda Cloud root signature over the app profile.
- Developer key signature over the package payload.
appId,teamId,keyId, and manifest capabilities bound to the profile.
The CLI verifies against the current Panda App production public root by default.
For a separate test registry, set PANDA_TRUST_ROOT_PUBLIC_KEY_PEM to the PEM
contents of its public root; this overrides the default. Never provide a root
private key to the CLI or registry configuration.
Apps may declare a package-owned Hub icon with icon: "assets/icon.pbm" in
manifest.json. The icon file must be a flat assets/*.pbm path and should be
a 64x64 binary PBM P4 1bpp image. The packer includes it in the .pap, the
canonical manifest records its path, and signing covers the icon bytes like
any other package payload file.
Target Install Loop
Use a local directory as an SD-card root when preparing simulator fixtures or copying packages to a mounted device card:
bun run pos push /tmp/hello.signed.pap --target /tmp/panda-sd
bun run pos list --target /tmp/panda-sd
bun run pos remove ai.pandacat.app.hello --target /tmp/panda-sdpos install <file.pap> --target <sd-root> is equivalent to pos push for a
local package file. With a local catalog JSON, pos install <app-id> --catalog
<catalog.json> --target <sd-root> and pos update --catalog <catalog.json>
--target <sd-root> resolve signed local package URLs from the catalog.
Updated 2026-10-08 by Codex: the shared target layout is
/PandaApps/<id>/package.pap plus /PandaApps/<id>/content/, with installed JSON
receipts under /.murphy/panda-apps/installed/. Private storage/state live under
/.murphy/panda-app-data/<id>/. Removal keeps private data by default; use
pos remove <app-id> --target <sd-root> --erase-data to remove it explicitly.
Retained data never retains permissions; reinstall requests them again.
Legacy roots migrate once through journaled target transactions. Preserve unrelated content.
When a mounted target already contains the device-owned /.murphy/apps/consent.bin,
the CLI refuses remove, erase, or retained-data reinstall with
target_permission_owner_unavailable; use the device Manage Apps flow so the OS
permission owner can acknowledge the grant change. The CLI only detects that the
owner state exists: it never parses, resets, or deletes consent.bin.
Schema v2 packages are verified and prepared with a format 2 Runtime receipt. The
target must have a v2-enabled verifier and a matching configured public trust root;
the device revalidates the archive, content and receipt before launch. A successful
CLI install confirms SD preparation, not device execution. Device package limits
include a 2 MiB archive, 16 signed files, 64 KiB per file and a 4 KiB manifest.
HTTP catalog download remains unsupported in this local CLI path; the on-device
Store owns HTTP streaming.
Run the app in the simulator sandbox from a repository checkout:
bun run pos run /tmp/hello.signed.pap --sandbox /tmp/panda-sim-sd --no-launch
bun run pos run /tmp/hello.signed.pap --sandbox /tmp/panda-sim-sdpos run installs the signed package under the sandbox SD root, exports
MOFEI_SIM_SD_ROOT for the simulator process, and launches headless mode by
default. Use --mode tauri for the GUI simulator, --no-launch to only prepare
the sandbox, and -- <simulator-args> to pass extra arguments through. For a
distributed install where pos and the simulator are installed in different
directories, pass --simulator /absolute/path/to/run, set PANDA_SIMULATOR, or
put a panda-simulator launcher next to the pos binary or on PATH.
Build a local installed distribution:
bun run build:binary
./dist/pos new hello /tmp/hello-panda
./dist/pos pack /tmp/hello-panda --output /tmp/hello.papDistribute the complete output directory, including .pos-runtime/ and
pos-distribution.json, alongside pos (pos.exe on Windows). The runtime
contains the package assets and production dependencies needed outside the
checkout, including the host-specific image library. Copying only the executable
is insufficient. bun run test:binary verifies the current host distribution;
other hosts require their own build and qualification.
Run the package validation gate before changing CLI commands, templates, package handling, or simulator launch behavior:
bun run checkMachine-Readable Output
Panda Studio and other IDE shells should call the same pos commands that
developers use manually. Add --json when the caller needs a stable
machine-readable response instead of human console text:
bun run pos run /tmp/hello.signed.pap --sandbox /tmp/panda-sim-sd --no-launch --jsonSuccessful commands print one JSON object to stdout:
{
"schemaVersion": 1,
"command": "run",
"status": "ok"
}Command-specific fields are added to that envelope. For example, run --json
includes the simulator sandbox path, installed app record, and either
launchSkipped or the simulator exitCode.
If a command fails with a toolchain error and --json was present before the
simulator passthrough separator (--), stderr contains:
{
"schemaVersion": 1,
"status": "error",
"error": {
"code": "simulator_mode",
"message": "Simulator mode must be headless or tauri"
}
}Without --json, existing human output remains the default.
Repository examples are packageable app directories:
../examples/hello/../examples/counter/../examples/native-screen/../examples/sdk-tour/
Lua Applet Simulator Dev Loop
For fast local iteration on a Lua-source app directory, use dev-run. It reads
manifest.json, validates the lua-source runtime and entry path, runs the
same Lua compile check as pos compile, packs/signs into .panda-build/, installs into
the simulator SD sandbox, and launches through the same firmware-compatible
pos run simulator contract.
cd apps/toolchain
bun run pos dev-run ../examples/hello --sandbox /tmp/panda-dev-sd --no-launch
bun run pos dev-run ../examples/hello --sandbox /tmp/panda-dev-sd --mode headless -- --duration 15For the Apple-Simulator-style app-directory loop, open a Panda app directory
and run the simulator command directly. It is the discoverable wrapper around
the same dev-run package/sign/install/runtime path:
cd apps/examples/hello
bun ../../toolchain/src/cli.ts simulator --sandbox /tmp/panda-dev-sd --mode tauri
# Short alias, headless test/debug loop.
bun ../../toolchain/src/cli.ts sim --sandbox /tmp/panda-dev-sd --mode headless --duration 15
# Repeatable profiling/debug run with stable artifacts and a debug endpoint.
bun ../../toolchain/src/cli.ts simulator \
--sandbox /tmp/panda-profile-sd \
--mode headless \
--duration 30 \
--artifacts /tmp/panda-profile-artifacts \
--debug-port 47110pos simulator [app-dir] and pos sim [app-dir] accept the same local
development options as dev-run: --grant-storage, --grant-network,
--grant-buzzer, --grant-frontlight, --grant-payment, --cert, --profile, --simulator,
--board, --no-launch, --json, and simulator passthrough arguments after
--. --duration is mapped to the simulator duration environment, while
--artifacts and --debug-port are passed through to the headless simulator
runner.
Local signing still uses the normal Panda signed-package contract. To avoid
repeating long flags on every run, dev-run / simulator discover artifacts in
this order:
--cert <developer-cert>and--profile <app-profile>PANDA_DEVELOPER_CERTandPANDA_APP_PROFILE- app-local
.panda-build/developer-cert.txtand.panda-build/profile.txt
Useful diagnostic checks:
# Invalid manifest / entry-path validation.
bun run pos dev-run /path/to/app-with-bad-manifest --no-launch --json
# Lua syntax errors. The command fails with compile_failed when luac is available.
bun run pos dev-run /path/to/app-with-bad-lua --no-launch --json
# Capability denial: counter requests storage; omit --grant-storage to see denied=storage.
bun run pos dev-run ../examples/counter --sandbox /tmp/panda-dev-sd --no-launch
# Capability grant: use the same installed.json grant fields firmware consumes.
bun run pos dev-run ../examples/counter --sandbox /tmp/panda-dev-sd --grant-storage --no-launchdev-run prints a short [panda-dev-run] diagnostic block before launch:
- manifest entry and runtime version loaded from
manifest.json - Lua syntax-check status
- requested/granted/denied capability summary
- lifecycle contract (
start,resume,render,input,pause,stop) owned by firmwareLuaAppActivity panda.*API contract and simulator log location for Lua lifecycle errors- clean-exit contract via
panda.system.exit()/panda.activity.finish()
The command does not add simulator-only Lua APIs. It prepares a signed package
and installed-app index exactly as the firmware applet launcher expects, so
capability failures and Lua runtime errors remain observable through the same
firmware PANDAAPP / LUAAPP serial logs in simulator runs.
