Single-Page Apps CLI
The app command group syncs built single-page app bundles between a local apps/ directory and WordPress. Each subdirectory of apps/ is one app: a loopress.app.json plus a built dist/ folder.
These commands are separate from the aggregate lps push / lps pull / lps promote, which do not sync apps: apps have their own build step, so you deploy them explicitly with lps app push.
The local directory
Section titled “The local directory”push and pull operate on one local directory, resolved the same way:
- The
pathargument, if given (pullonly) - The
appsDirkey in the project’sloopress.json, if set ./apps, the default
Typical workflow
Section titled “Typical workflow”# install the app's dependencies, once (Loopress never installs them)npm --prefix apps/search install
# build and ship it (only files whose content changed are uploaded, then one atomic commit)lps app push search
# in a page: [loopress_app name="search"]Commands
Section titled “Commands”Every command below also accepts the common flags: --env, --json, and --yes where it applies.
lps app push
Section titled “lps app push”Build and upload the bundle for one app, or every app in the directory when name is omitted.
When the app directory has a package.json with a build script, the push runs it first (<pm> run build in the app directory), on a --dry-run too so the preview diffs a fresh dist/. The package manager comes from the packageManager field, else from the nearest lockfile up to the repository root (pnpm-lock.yaml, yarn.lock, bun.lock, package-lock.json), else npm. A failing build fails that app with the end of the build output, and nothing is uploaded. Without a build script, dist/ is pushed as is.
The push then builds a manifest of dist/ (sha256 per file), asks the site which files it already has, uploads only the differences, then commits the new build in one step. The front end keeps serving the old build until that commit lands.
lps app push [name]| Argument | Default | Description |
|---|---|---|
name |
every app in appsDir |
Push only this app |
| Flag | Description |
|---|---|
--no-build |
Skip the build script and push dist/ as is, for a CI that already built in an earlier step |
--dry-run / -d |
List what would be uploaded and committed without touching the site |
--yes / -y |
Skip the confirmation prompt shown when the target environment is named production |
--json |
Print the result as JSON ({ pushed: [{ name, buildId, uploaded }], status }) |
Pushing never deletes anything on WordPress. A build that fails to upload or commit leaves the previous build serving.
lps app pull
Section titled “lps app pull”Download every committed app into apps/<name>/dist/, writing a loopress.app.json alongside. When the app already has a loopress.app.json, its files go into its assetsDir and its local-only settings (assetsDir, entry) are kept: only name, mountSelector, routing and crossOrigin are refreshed from the site.
lps app pull [path]| Argument | Default | Description |
|---|---|---|
path |
./apps (or loopress.json’s appsDir) |
Local directory to write into |
| Flag | Description |
|---|---|
--dry-run / -d |
Show what would be written and removed without touching the filesystem |
--yes / -y |
Skip the confirmation asked before removing local app directories |
--json |
Print the result as JSON ({ pulled, orphans, status }) |
Local app directories (a folder with a loopress.app.json) whose app no longer exists on the site are removed on pull, so the directory mirrors what is deployed. In a terminal the list is shown and confirmed first; in scripts and CI they are removed with a warning.
lps app list
Section titled “lps app list”Print the apps currently deployed, with their build id, file count and total size. An app that was uploaded but never committed is flagged.
lps app list| Flag | Description |
|---|---|
--json |
Output the raw apps array instead of formatted text |
Apps (1): search Build: 9f2a1c7b4e10 Files: 22 files, 2.44 MB Deployed: 2026-08-30T12:00:00+00:00lps app remove
Section titled “lps app remove”Delete an app’s bundle from wp-content/loopress/apps/ and unregister its shortcode. Local files are left untouched.
lps app remove <name>| Argument | Default | Description |
|---|---|---|
name |
(required) | The app to remove from WordPress |
| Flag | Description |
|---|---|
--dry-run / -d |
Report what would be deleted without touching the site |
--yes / -y |
Skip the confirmation prompt (and the extra one shown for a production environment) |
--json |
Print the result as JSON ({ name, deleted, status }) |
File format
Section titled “File format”apps/ search/ loopress.app.json dist/ index.html assets/index-9a597e0d.js assets/index-51910369.cssdist/ is your bundler’s output, unchanged. loopress.app.json holds a few optional settings, all documented in the overview. The push derives the entry scripts and styles from dist/index.html; if there is no index.html, add an explicit entry object to loopress.app.json.