# CLI reference

`alamr` is the public command-line client for Environment, App, and Plugin projects.
Install the exact CLI version shown on the promoted [Start page](/start); after
installation, humans and coding agents use the same stable command surface:

```sh
alamr doctor --json
```

## Commands

- `alamr create environment [directory]` scaffolds an Environment.
- `alamr create environment [directory] --with-backend` additionally wires an
  Environment-owned backend, browser Grant request, server verifier and health
  endpoint.
- `alamr create app [directory]` scaffolds a Compact-first App bundle using the
  embedded App SDK. The desktop AppHost opens the held bundle bytes. Add
  Workspace by declaring it in the manifest and composing from the current
  presentation mode; mode changes preserve the App document and session and
  arrive as `host.presentation.changed`.
- `alamr create plugin [directory]` scaffolds a frontend-only Plugin. Use
  `--kind full-stack --with-backend` for browser plus service, or
  `--kind backend-only --with-backend` for a service-only package with an
  immutable OpenAPI protocol artifact and no browser export.
- `alamr login` authenticates a local human terminal with Authorization Code
  and PKCE S256.
- `alamr login --device --json` creates a structured approval handoff for a
  coding agent; `alamr login --resume <handoffId> --json` completes it after
  the human approves the displayed code.
- `alamr logout` revokes the stored interactive management token before
  deleting it locally. It does not alter `AL_AMR_TOKEN` supplied by CI.
- `alamr auth status` identifies a signed-out shell, a stored CLI session, or a
  process-scoped CI token without printing the credential.
- `alamr auth session list` lists the caller's active CLI management sessions;
  `alamr auth session revoke <sessionId> --yes` revokes one exact session.
- `alamr link [projectId]` links the directory to an existing project, or creates
  the matching Registry project when the ID is omitted. To move a working copy
  to another Registry, run `alamr unlink --yes` first; this removes only the
  local pointer. A new Plugin may keep `publisher.id: "pub_replace_me"` so the
  selected Registry binds it to the signed-in account's Publisher.
- `alamr unlink --yes` removes only the local Project link. It never deletes the
  Registry Project or an immutable snapshot.
- `alamr add <publisher/plugin[@version]>` installs and locks a published Plugin.
  `--integration frontend-adapter --adapter <id>` selects browser code;
  `--integration backend-components` selects the reviewed backend set without a
  browser package.
- `alamr update <publisher/plugin[@version]>` replaces an installed Plugin with
  one exact reviewed release.
- `alamr remove <pluginId|publisher/plugin>` removes the manifest installation,
  lock entry, and unshared package dependency as one local transaction.
- `alamr sync` resolves and reconciles the complete desired Plugin set through
  one digest-bound lockfile-v3 transaction. Legacy v1/v2 locks remain readable
  and normalize to frontend-adapter installations.
- `alamr inspect [publisher/plugin]` inspects a local manifest or catalog entry.
- `alamr validate` validates local manifests and lockfiles.
- `alamr build` runs the project's declared build through its pinned package
  manager and verifies that the standard output directory exists. Run it after
  `alamr link`, because linking may replace a starter's local product ID with
  its Registry identity; only the post-link build may be checked or published.
- `alamr run` starts or reuses the package manager's declared `dev` process and
  returns its readiness, logs, process ID, and opaque stop token.
- `alamr test` creates or reuses the immutable candidate and runs publication
  checks in one operation. For an Environment, pass the built folder with
  `--bundle <dir>` (normally `dist`). For an App, run `alamr build` first and
  then `alamr test`. A Plugin goes directly through `alamr test`.
- `alamr publish` submits the checked candidate for review.
- `alamr status` reads the linked project's current Registry state.
- `alamr doctor --profile <bootstrap|project|runtime|publish>` runs only the
  checks appropriate to that point in the journey.
- `alamr project list|show` reads private Project state. `alamr project member
list|add|change|remove|transfer` manages audited `admin`, `developer`, and `viewer`
  membership within the caller's server-authorized role.
- `alamr token issue|list|revoke` manages scoped, expiring CI credentials.
- `alamr publication list|checks|submit|transition` follows the actions returned
  by the publication resource instead of inferring a workflow from status text.
- `alamr review list|inspect <submissionId>` reads the administrator review
  queue and immutable evidence. `review assignment <submissionId>` reads the
  current owner and version. `review claim|release <submissionId>
--assignment-version <n> --yes` atomically owns or releases a case. `review
decide` requires that returned assignment version and both frozen digests;
  rejection additionally requires `--category`, `--summary`, and
  `--remediation`. `review history|evidence` exposes closed decisions and the
  explicit diff/AI producer status. `review handoff-list|handoff-inspect`
  discovers approved publication work; a second administrator uses
  `handoff-claim`, then `handoff-publish` with the returned handoff version and
  exact digests. Every mutation requires `--yes`.
- `alamr rollback <environment_revision|app_revision|plugin_release> <targetId>`
  activates an eligible immutable target with an audited reason.
- `alamr catalog search <all|environment|app|plugin> [query]` searches only the
  anonymous public catalog.
- `alamr admin users list [--search <query>] [--cursor <cursor>]` and `alamr
admin users show <userId>` read the audited account directory. `alamr admin
roles list|create|update|archive`, `alamr admin roles members <roleId>`, and
  `alamr admin roles assign|unassign <roleId> <userId>` manage platform-managed
  role definitions and assignments. All admin operations require a Registry
  administrator account; `roles create` takes `--key`, `--display-name`,
  optional `--description`, and comma-separated `--environment env_a,env_b`
  (omit for a role that applies to every Environment). `roles update` also
  accepts `--scope-all` (reset to global) and `--expected-updated-at <iso>`
  for optimistic concurrency; `roles assign` accepts `--environment` to
  narrow the assignment to a subset of the role's scope.
- `alamr admin reviewers list` reads active delegated reviewer grants.
  `alamr admin reviewers grant|revoke <userId> --reason <text> --yes` changes
  only review authority, never admin or Project access, and writes an audit
  record containing actor, target, and reason. Mutations support `--dry-run` and
  reject Project tokens.
- `alamr admin apps list` lists the active public App revisions and their
  platform-wide Runtime availability. `alamr admin apps enable|disable
<appId> <revisionId> --reason <text>` changes only that exact published
  revision, requires a Registry administrator, and writes an audit event.
  v0.x availability is global; it is not scoped to an Environment.
- `alamr admin hubs list [hubEnvironmentId] [zoneId]` reads the authored Hub
  slot inventory (`env_hub` / `sunlit-way` by default). `alamr admin hubs set
<hubEnvironmentId> <zoneId> <slotId> <environmentId> --reason <text>` assigns
  or replaces a manual slot, and `alamr admin hubs clear <hubEnvironmentId>
<zoneId> <slotId> --reason <text>` removes its assignment. Mutations require a
  Registry administrator, accept only 3–1000-character reasons, and are
  documented in [Hub placement operations](/docs/publish/hub-placement).
- `alamr workflow get|plan|status|execute|approve|resume <workflowId>` discovers
  and executes a versioned AgentWorkflow v2 DAG.

All commands accept `--json`. Mutating commands require `--yes`; commands with
a safe preflight also accept `--dry-run --json` and must not write local or
Registry state in that mode. The nearest lockfile in the current or an ancestor
directory selects npm, pnpm, Yarn, or Bun, including when a project lives below
a monorepo workspace root. Agents should not infer a package manager from
global installations.

## Local process and readiness profiles

Doctor profiles prevent a fresh scaffold from failing checks for services or
dependencies that do not exist yet. `bootstrap` checks Node and package-manager
selection. `project` additionally checks installed dependencies, the manifest,
and lock. `runtime` adds the Registry and any declared Environment-backend
health endpoint. `publish` checks Registry access and the exact linked Project.

`alamr run` resolves npm, pnpm, or Yarn without constructing a shell command,
starts the declared `dev` script, and safely reuses its durable process record.
Stopping it requires the opaque token returned by the start command:

```sh
alamr doctor --profile bootstrap --json
alamr doctor --profile project --json
alamr run --json
alamr doctor --profile runtime --json
alamr doctor --profile publish --json
alamr run --stop --run-token <runToken> --json
```

## Immutable bundle testing

Environment and App frontends are Registry-held bundles. Their public test
workflow has no publisher-hosted frontend, well-known handshake, or separate
prepare/resume phase. Use the product-specific single-pass command sequence:

```sh
# Environment
alamr build --json
alamr test --bundle dist --json --visibility unlisted --channel preview

# App
alamr build --json
alamr test --yes --json

# Plugin
alamr test --json --visibility unlisted --channel preview
```

For an Environment, `test --bundle dist` validates the manifest, packs the
built folder deterministically, requires `index.html` and the declared cover,
computes SHA-512 integrity, creates or reuses the immutable revision, uploads
the bytes, and runs publication checks. Use `--bundle <dir>` when output is not
`dist`.

For an App, `alamr build` produces `dist`. The following `alamr test`
inventories, packs, uploads, binds, and checks those exact bytes. A changed
build generation receives a fresh immutable revision.

A Plugin goes directly through `alamr test`. A `full_stack` or `backend_only`
Plugin may still declare separately reviewed publisher-hosted HTTPS/WSS backend
deployments in `al-amr.deployments.json`; bundle delivery applies to product
frontend bytes, not those live services.

## Plugin desired-state plans

The Environment manifest is desired state. `add`, `update`, `remove`, and
`sync` first resolve the complete set of exact Registry releases and Managed
Store artifacts. `--plan` saves a short-lived, digest-bound plan without
changing project state; apply that same operation with its returned
`--plan-digest` and `--yes`. A stale, expired, changed, or already attempted
plan fails closed.

```sh
alamr add al-amr/media@<version> --adapter react --config-json '{"directCalls":{"enabled":false}}' --plan --json
alamr add --plan-digest <sha256:plan-digest> --yes --json
alamr sync --plan --json
alamr sync --plan-digest <sha256:plan-digest> --yes --json
```

`--config-json` accepts a JSON object no larger than 64 KiB and becomes the
host-owned immutable Plugin configuration after schema validation. Applying a
changed plan writes a `pending` v3 lock and, for frontend integrations, returns
the exact detected package-manager install command. Run that command explicitly, then run `alamr sync
--yes --json` to verify installed package bytes and move the lock to `applied`.
No partial resolution is authoritative.

## AgentWorkflow v2 execution

The public Developer Portal index exposes structured operations, dependencies,
preconditions, postconditions, mutation scopes, stable result codes, and human
approval boundaries. The CLI validates the exact workflow URL and SHA-256,
exact CLI version, Registry origin, and Platform Release Set before executing
an allowlisted, shell-free adapter.

```sh
alamr workflow get environment.create --json
alamr workflow plan environment.create --json
alamr workflow execute environment.create --idempotency-key <caller-key> --inputs '{"directory":"my-world","package_manager":"pnpm","topology":"standalone"}' --json
alamr workflow status environment.create --resume <resumeToken> --json
alamr workflow approve environment.create --resume <resumeToken> --approval-step <stepId> --yes --json
alamr workflow resume environment.create --resume <resumeToken> --json
```

`execute` requires a caller-owned idempotency key and returns a one-time resume
token. Only hashes of both values are stored under `.al-amr/workflows/`.
Approval records intent for one waiting step but never resumes it; the agent
must invoke `resume` separately. Retrying with the same idempotency key reuses
the durable execution instead of duplicating a mutation.

## Release verification boundary

Without a verification flag, workflow discovery uses the public
`/agent/v2/index.json` and accepts only a `promoted` Release Set. A release gate
may instead deploy an isolated preview for one exact `catalog_verified` set and
invoke the CLI like this:

```sh
alamr workflow execute environment.create \
  --workflow-origin <isolated-preview-origin> \
  --release-verification <releaseSetId> \
  --registry <managed-store-registry-origin> \
  --idempotency-key <caller-key> \
  --inputs '{"directory":"my-world","package_manager":"pnpm","topology":"standalone"}' \
  --json
```

`--release-verification` is a protected release-CI input, not a way for normal
users to select a candidate. It requires an exact Release Set ID and accepts
only an index whose mode is `release_verification`, state is
`catalog_verified`, and ID matches. Every subsequent workflow fetch must use
the same isolated origin, Registry origin, and verification ID. The preview
receives no private publication state; production Portal commands continue to
advertise only the previously promoted set until promotion completes.

## Versioned JSON result

With `--json`, the CLI writes exactly one JSON document to standard output and
does not mix authorization instructions or human prose into standard error.
Every result has this stable version-1 envelope:

```json
{
  "schemaVersion": "1",
  "command": "validate",
  "ok": true,
  "code": "ALAMR_OK",
  "exitCode": 0,
  "message": "Validation passed.",
  "diagnostics": [],
  "nextActions": [],
  "artifacts": [],
  "data": {},
  "meta": {
    "cliVersion": "0.1.0-alpha.1",
    "elapsedMs": 14
  }
}
```

`code` is the stable symbolic automation result. `exitCode` is the numeric
shell category. `diagnostics`, `nextActions`, and `artifacts` are always arrays;
`data` is command-specific and is omitted when the command has no data. New
fields may be added compatibly within schema version `1`; agents must ignore
unknown fields.

## Authentication

Interactive login binds `127.0.0.1` on an operating-system-selected ephemeral
port. It uses the resulting callback URI unchanged for authorization and token
exchange. The registered `http://127.0.0.1/callback` scheme, address, path, and
query remain exact; only the loopback port varies. The CLI rejects non-HTTPS
discovery endpoints outside local development and requires authorization,
token, and revocation endpoints to stay on the Registry issuer's exact origin.
Discovery can never redirect a stored bearer token to another host. The CLI
never stores a runtime Environment token as a management credential. CI should
provide a short-lived, scoped project token in `AL_AMR_TOKEN`.

CLI authentication is independent from browser SSO. Signing out of the Hub or
Developer Portal does not silently revoke CLI or CI credentials, and `alamr
logout` does not sign browser sessions out.

If refresh proves that a stored refresh family is terminally expired or already
invalidated, the CLI removes that exact credential revision before returning the
authentication failure. The next `auth status` or graphical review refresh is
therefore honestly signed out and asks for `alamr login`; it does not retry the
same invalid family forever or expose a raw OAuth error as product UI.

Stored CLI sessions are independently revocable. Inspect them with:

```sh
alamr auth status --json
alamr auth session list --json
alamr auth session revoke <sessionId> --dry-run --json
alamr auth session revoke <sessionId> --yes --json
```

Revoking the current session also removes its local credential. Project tokens
are process credentials rather than managed CLI sessions and never appear in
this list.

### Agent-to-human login handoff

An agent that cannot own a browser session starts a short-lived OAuth Device
Authorization handoff:

```sh
alamr login --device --json
```

JSON output does not select the device flow by itself; agents must pass
`--device` explicitly.

The successful result has symbolic code `ALAMR_LOGIN_APPROVAL_REQUIRED` and
returns `verificationUriComplete`, `userCode`, `expiresAt`, an opaque
`handoffId`, and an exact `resumeCommand`. The human opens the returned URL and
approves only when its code matches the agent's `userCode`. The agent then runs
the returned command, equivalent to:

```sh
alamr login --resume <handoffId> --registry <origin> --json
```

If approval is not complete, the result uses exit code `3`, symbolic code
`ALAMR_LOGIN_APPROVAL_PENDING`, and a bounded `retryAfterSeconds`. After
approval it returns `ALAMR_LOGIN_COMPLETE` and stores the management credential.
The OAuth `device_code` never appears in CLI output; it is kept in a private,
Registry-bound local handoff file and deleted after success, denial, or expiry.
This flow is for a human login boundary, not unattended CI.

## Trusted Plugin preflight

Frontend Plugin packages execute as `trusted_library` code in the Environment's
browser realm; declared permissions are not a JavaScript sandbox. `add` and
`update` therefore require an explicit adapter and approval. Run the exact
operation with `--dry-run --json` first. Its data includes Publisher
verification, trust state, runtime class, declared permissions, browser and
network disclosures, and the files that would change. Re-run with `--yes` only
after reviewing that response.

`add`, `update`, and `remove` keep the Environment manifest, immutable lockfile,
and any real package dependency transaction aligned. A
`backend_components` installation writes no adapter, package, or integrity and
does not invoke the package manager. One `pluginId` has at most one installation;
a full-stack `frontend_adapter` installation also authorizes that same release's
reviewed backend components. `unlink` changes only
`.al-amr/project.json`. None of these commands install dependencies implicitly;
the result returns the detected package manager and exact next install command.

## Management parity and server-directed actions

The graphical Manage surface uses the same endpoints as the commands below:

```sh
alamr project show --json
alamr project member list --json
alamr project member transfer proj_example pmbr_target \
  --previous-owner-role admin --reason "Permanent handoff" --yes --json
alamr token list --json
alamr publication list --json
```

Every publication response contains caller-specific `allowedActions`. An agent
must choose from those actions, preserve the exact immutable target and `from`
state, and supply `--reason` when the action declares it required. A missing
action is an authorization or lifecycle boundary, not a hidden Console-only
button to automate around.

## Stable exit codes

- `0`: success
- `1`: validation or operation failure
- `2`: invalid usage
- `3`: authentication or authorization failure
- `4`: network failure
- `5`: state conflict

Machine consumers must use the exit code and structured `--json` fields rather
than matching human-readable messages. See the [API reference](/reference/api)
for the shared Management API.
