v2.8.0: webflow apps, the canonical namespace for Webflow Cloud
v2.8.0: webflow apps, the canonical namespace for Webflow Cloud
v2.8.0 introduces webflow apps, the new canonical command namespace for managing Webflow Cloud apps. It replaces the piecemeal webflow cloud commands with one consistent surface across the whole app lifecycle, designed so a CI job or an AI agent can drive it end-to-end without scraping human-oriented output: structured --json on read commands, --dry-run previews on every write, and predictable exit codes throughout. Reads also retry transient rate limits (429) automatically with bounded backoff, so a busy CI runner doesn’t need its own retry loop.
webflow cloud init and webflow cloud deploy keep working unchanged — they now print a one-time deprecation notice pointing at the apps equivalents.
An app is standalone by default — it gets its own subdomain and isn’t tied to a Webflow site. Attaching to an existing site (mounted at a path, alongside a Designer-built site) is fully supported too; it’s just one additional flag away.
App lifecycle: apps init / apps deploy
Once webflow.json has an app_id, subsequent apps deploy calls need no flags at all — it’s the standalone path that gets simpler over time, since there’s no site or mount path to keep in sync.
apps deploy also takes --dry-run and --json, same as every other write in this namespace:
--dry-run resolves everything from flags, WEBFLOW_APP_ID, and webflow.json — no network calls, no prompts, no changes — and reports which of create / deploy / select the real run would take. --json suppresses the build/upload progress output and emits a single document: {appId, environmentId, deploymentId, deployUrl} on success, an error document on failure, or the dry-run plan when combined with --dry-run.
Attaching to an existing Webflow site instead just adds --site-id and a --mount path at init:
apps init also supports creating an app directly from an existing GitHub repository, either standalone or attached to a site:
The Webflow GitHub App must be installed on the repository and connected to your workspace. --dry-run previews the app that would be created; --branch picks which branch to build (defaults to the repository’s default branch); --skip-clone creates the app from the remote repository without cloning it into a local directory. --idempotency-key is required for non-interactive runs (CI, --no-input) — reuse a retry-stable key unique to the repository and target so a retry replays the original app instead of creating a second one.
Link an existing app: apps link
Points the current directory at an app and environment that already exist by writing the resolved IDs into webflow.json. It only verifies the app — it doesn’t create or deploy anything, so it’s the fastest way to get a checked-out repo working with apps deploy / apps env-vars / apps logs against an app someone else created. A workspace ID is persisted only when --workspace-id is passed explicitly, since it can’t be derived or verified from the app itself. Use --dry-run to preview.
Inspect apps: apps list / apps get / apps domains
list returns every app the token can see — standalone and site-attached alike — and optionally narrows with an exact --site or --name, or a case-insensitive substring --q; combine --site and --name to resolve to at most one app. All three support --fields to project columns and --json for machine-readable output.
Manage apps: apps update / apps delete
Update an app’s name, description, and/or GitHub source (at least one of --name / --description / --github-source is required). --github-source attaches a repository to an app that has none, or repoints one that already has a different repo — it doesn’t deploy on its own, so follow it with apps deployments trigger. apps delete deletes (archives) an app outright; it refuses to run non-interactively without --yes (a safe --dry-run preview is exempt).
Both commands preview with --dry-run before making any change, and both support --json on every path:
update --jsonprints the plan (only the keys actually being changed, plusdryRun: true) on a dry run, and the full updated app object on a real run.delete --jsonprints one document shape on both the dry run and the real run —{ appId, name, action: "archive" | "hard_delete", siteId, siteName, permanent, dryRun, message }— so a caller can parse the same fields either way;messageisnulluntil the delete actually happens.
Environments: apps environments list/create/update/delete
list filters by an exact --branch or a substring --q on branch name. create provisions a new environment bound to a branch and served at a mount path — it starts empty; run apps deployments trigger to build it. update changes an environment’s branch and/or mount (at least one is required) but doesn’t deploy the change itself. delete removes an environment. All three writes support --dry-run, and resolve the app/environment from positional args, WEBFLOW_APP_ID / WEBFLOW_APP_ENVIRONMENT_ID, webflow.json, or an interactive picker.
Deployments: apps deployments list/get/redeploy/trigger
list --status filters on an exact status (success, failed, starting, building, deploying, canceled, unstaged). get --wait polls until the deployment reaches a terminal status and exits 0/1 accordingly — built for CI gating; --interval and --timeout tune the poll (floored at 5s, capped at 30min).
trigger builds a GitHub-connected environment’s current HEAD on demand; redeploy re-runs a past deployment at the same commit, the rollback path. Both require a GitHub-connected app (not eligible for apps deployed from local files via apps deploy) and now also take --wait (with the same --interval/--timeout): since enqueuing a build only returns a 202 with no deployment ID to poll, --wait identifies the new deployment itself and then blocks on it exactly like deployments get --wait — so a CI job can trigger a build and gate on its outcome in one command. All three writes support --dry-run.
Logs: apps logs build / apps logs runtime
Both support --fields, --json, and cursor-based pagination via --cursor.
Environment variables: apps env-vars list/set/delete/import
The headline addition this release: full, non-interactive management of Cloud app environment variables, so secrets no longer require a trip to the dashboard.
--app-id/--environment-iddefault fromwebflow.json(cloud.app_id/cloud.environment_id) when present — as shown above — so most invocations inside a project directory need neither flag. Pass them explicitly (--app-id <id> --environment-id <id>) to target a different app, for example from a shared CI runner.listalso takes an exact--keyor a case-insensitive substring--q, same filtering pattern asapps listandapps environments list.set <key> [value]takes the value three ways, safest first: piped stdin (shown above — works in CI with no TTY), an interactive prompt (masked for secrets) if you omit the value entirely, or a positional argument. A positional secret still works but prints a warning, since it lands in your shell history and process list — stdin or the prompt avoid that.--secretmarks a variable encrypted. Secret values are never echoed back —seton a secret confirms only that it was written, andlistnever returns a secret’s value — it comes back masked. Non-secret values are hidden from the default output too, and shown only if you ask for them with--fields valueor--json.import <file>bulk-loads a.env(or anyKEY=value) file in one call instead of setting variables one by one.--dry-runparses and previews the resulting key set — secret values shown redacted — without making any API calls or writing anything.- Every write command (
set,delete,import) supports--dry-runand--json.
Also in this release
apps init --site-id <id> --no-inputnow correctly attaches the new app to the existing site and runs the DevLink export, instead of silently falling back to a standalone app without one.- The
publicUrlfield on an environment (apps environments list/create/update) replaces the olddeployUrlfield name.