Frontend CLI
The acms binary (also antelope-cms), shipped by @antelopejs-private/cms-nuxt, runs the shared dashboard frontend: the dev server, the production build and server, CI typings, and workspace cleanup. For the machine it drives — layers, config, the catch-all renderer — see Frontend layer.
Commands and flags
acms has five commands. They don't all take the same flags — the set varies per command:
-b, --backend-url <url>(envCMS_BACKEND_URL):dev,build,start,prepare,clean.-p, --port <port>(default3001, envPORT):dev,startonly.-f, --force(reinstall deps):dev,build,prepare.--offline(reuse the cached manifest, envCMS_OFFLINE):dev,build,prepare.--bootstrap-secret <secret>(envCMS_BOOTSTRAP_SECRET):dev,build,prepare.-a, --all(clean every workspace):cleanonly.
| Command | Purpose | Backend URL |
|---|---|---|
dev | Dev server with HMR. Reserves the frontend port first and sends it to the backend so it can whitelist the origin for CORS. Copies each layer into the workspace and watches the source to mirror edits. | Auto-discovers (see below) |
prepare | Generate layer typings (nuxi prepare) and symlink .nuxt back into the layer. Meant to run as a layer's postinstall. | Optional — CI-friendly |
build | Production build; downloads the layers as a ZIP from the backend, then nuxi build. | Required |
start | Run the built production server (node .output/server/index.mjs). | Required |
clean | Remove workspace artifacts. -a/--all cleans every workspace. | -b or --all |
prepare exits 0 (with a warning) when no backend URL is set or the backend is unreachable. That's deliberate: a layer's postinstall calling acms prepare must not break a CI install when no backend is running.How dev finds the backend
dev resolves the backend URL in order:
- An explicit
-b/CMS_BACKEND_URL. - Otherwise it walks up from the current directory for a
.antelope/dev.json(written by a runningajs project dev), validates the recordedpidis alive, and reads the API endpoint from it (rewriting a wildcard host like0.0.0.0tolocalhost).
It stops at the first .antelope/dev.json it finds, so it won't accidentally attach to a parent project's backend. build, start, and clean do not auto-discover — give them -b.
Authenticating to the backend
The two routes acms fetches — the manifest and the layers ZIP — carry each layer's private options and full source, so the backend gates them behind nuxt.bootstrapSecret. acms resolves the credential to present in order:
- An explicit
--bootstrap-secret/CMS_BOOTSTRAP_SECRET. Prefer the environment variable — a secret on the command line is visible to every process on the machine. devandpreparethen walk up for the project's.antelope/cms-dev.json, which a development backend publishes for exactly this purpose. So the local loop needs no configuration at all.
A discovered credential is presented only to the backend that published it — acms compares the URL it is about to call against the api endpoint in that project's own .antelope/dev.json. Point -b at a staging or production host from inside a running project and the local credential is withheld rather than sent to it.
build uses only the explicit value: quietly authenticating a production build with a local dev instance's credential would fail far from its cause. start needs no credential — it makes no requests.
A refused credential is fatal for dev and build, and it never falls back to the cached manifest: that cache can still hold private options from a previously-authorized run, and replaying them would defeat the gate. prepare keeps its exit-0 contract and falls back to a workspace-less prepare.
requireBootstrap: "enforce". The default, "warn", answers an unauthenticated caller with a 200 whose private options have been removed — so nothing fails and the build succeeds. acms warns whenever the layers arrive with no private options at all, which is the only client-side signal that this happened.dev fails with a message naming both remedies — it cannot work from a manifest with no layer source paths, which the backend serves only to authenticated callers on the same machine.~/.acms/<hash>/ (each with its own node_modules, manifest cache, and client storage scope). After confusing state, reset with acms clean -b <url> or acms clean --all.