Webflow CLI

This content was generated with the assistance of AI and should be verified against the official Webflow documentation before being relied on in production.

This sub-section’s Webflow bibliography lists the reference material consulted while preparing these pages.

This page describes the Webflow CLI as it was on 2026-10-28, the date on which its facts were checked against the authentication, configuration, command-reference, agent-workflows and migration pages of the CLI documentation on developers.webflow.com. The CLI is a free tool and every command on this page can be run against a Developer workspace site without a paid plan. A few commands act on features that need a particular plan (custom domains for sites publish --domains, Webflow Cloud for the apps family, CMS for the cms family); those are called out where they appear, and plans are named by tier only, never by price. The pinned version is @webflow/webflow-cli 2.15.0, which requires Node.js 22.13.0 or later. The Data API behind the data commands is described in Data API: SDKs, Limits and Errors, and the product map in Developer Platform Overview.

The running example is Fernbrook Gardens, a fictitious botanical garden with the Plants, Garden zones, Events and Journal Collections and two extra locales, Spanish and German. The garden’s developer uses the CLI for four chores: listing and publishing the site from a terminal, creating a few CMS items without writing a script, exporting shared components with DevLink, and deploying a small app from a CI job.

What the CLI is and who uses it

The Webflow CLI is a Node.js program installed globally from npm that exposes one executable, webflow. It is the single command-line entry point to several otherwise separate developer products:

  • the Data API (sites, CMS, assets and forms), as a set of scripting-friendly commands that wrap the REST endpoints

  • DevLink, which exports Webflow components into a React project (see DevLink Export)

  • Designer Extensions, which are scaffolded, bundled and served locally by the CLI (see Designer Extensions and the Designer API)

  • Code components, whose library is configured in webflow.json (see Code Components)

  • Webflow Cloud, whose apps are initialised, deployed and operated with the apps family (see Webflow Cloud)

The users are developers, DevOps engineers and, increasingly, coding agents: the documentation has a dedicated page for agents and CI/CD, and the CLI turns prompts off automatically when it detects a non-interactive environment. Designers and content editors do not need it; everything the data commands do is also possible in the Designer, the Editor and the Dashboard.

flowchart LR DEV["Developer or CI job"] --> CLI["webflow executable"] CLI --> AUTH["auth: login, status, logout"] CLI --> DATA["Data commands: sites, cms, assets, forms"] CLI --> EXT["extension: list, init, bundle, serve"] CLI --> DL["devlink: export, import, bundle"] CLI --> APPS["apps and cloud: init, deploy, operate"] AUTH --> SESSION["Session file auth.json"] DATA --> API["Webflow Data API"] APPS --> CLOUD["Webflow Cloud"] CLI --> MANIFEST["webflow.json in the project"]

Installing and updating

The CLI is distributed as an npm package and installed globally. CLI 2.0 raised the minimum Node.js version to 22.13.0, so check the runtime first.

node --version          # must report v22.13.0 or later
npm install -g @webflow/webflow-cli@2.15.0
webflow --version

The documentation’s own upgrade command installs the latest tag, which is convenient on a developer machine:

npm install -g @webflow/webflow-cli@latest

Two practical rules follow. On a workstation, latest keeps the CLI current. In CI, pin an exact version, as the agent-workflows page itself recommends, because tags such as latest and next move and a pipeline that silently changes tool version is hard to debug.

Release channels: stable and next

The CLI has two npm channels. The stable channel (latest) is what most people install. The pre-release channel is published under the next tag and its builds show a -next. suffix in webflow --version. The channels differ in one important way as of the check date: the webflow apps command family exists only on the next channel, and on a stable install it fails with an unknown-command error. The stable channel covers only webflow cloud init and webflow cloud deploy for Webflow Cloud.

npm install -g @webflow/webflow-cli@next
webflow --version      # a next build carries a -next. suffix

Global options

These options are accepted by every command, according to the command reference.

Option Effect

-v, --version and -h, --help

Print the version or the help text for the command.

--no-input

Disables every interactive prompt, for CI/CD and agents. Missing required values then fail with an error that names the missing flag.

--input

Re-enables prompts unless --no-input is also set. An explicit --no-input always wins.

--manifest <path>

Path to a webflow.json file, or to a directory that contains one, instead of the one in the current directory.

--region

Takes us or eu and selects that stack for this command. Needs CLI 2.9.0 or later.

--skip-update-check

Skips the check for a newer CLI version, which avoids a network call in CI.

--verbose

Prints more detail.

Authentication

The CLI has two authentication modes. The interactive mode uses a browser OAuth flow and stores one workspace-scoped session on the machine, shared by every project directory. The non-interactive mode, for CI/CD and for scripts that target several workspaces, uses a Workspace API token instead. The two are covered in turn; token creation, scopes and OAuth in general are in Data API: Authentication and Scopes.

Browser login

webflow auth login      # opens the browser: pick a workspace, grant access
webflow auth status     # user, region, session file path (and scopes, when recorded)
webflow auth logout     # removes the stored session

auth login accepts -f, --force to authenticate again even when a session exists. auth status prints a Scopes: line only when scopes were recorded with the session. auth logout clears the session but keeps the stored region default, which matters if you work in the EU stack (below). Commands that need a session start the browser login by themselves when none exists; webflow devlink import is the documented example.

The session is stored in a global file: ~/.config/webflow/auth.json on macOS and Linux and %APPDATA%\webflow\auth.json on Windows. It holds the login and the default region, so it is a credential. Keep it out of backups and shared home directories, and never copy it into a container image.

Workspace API tokens for CI/CD

A Workspace API token authenticates without a browser. Only a Workspace Admin can create one, in the workspace settings of the Dashboard, while any workspace user can log in through the browser. One token covers every site in its workspace, so a different site is chosen per project with siteId or --site rather than with a different token. To target several workspaces, create one token per workspace.

# Option 1: pass the token as a flag (visible in the process list)
webflow devlink import --api-token "$WEBFLOW_API_TOKEN" --no-input

# Option 2: let the CLI read the environment variable (preferred in CI)
export WEBFLOW_API_TOKEN="REPLACE_WITH_WORKSPACE_API_TOKEN"
webflow devlink import --no-input

WEBFLOW_API_TOKEN is read only from the process environment or from a .env file; the agent-workflows page states that it is never read from webflow.json. Prefer the environment variable over --api-token, because command-line arguments are visible to other users of the machine through the process list and may be recorded in shell history and CI logs. Never commit a .env file that holds the token: add it to .gitignore and store the value in the CI provider’s secret store. One command, apps init, is the exception to token use: creating an app needs a user token from auth login, not a Workspace API token.

EU and US regions

Webflow runs a US stack and an EU stack. They are separate: separate accounts, separate OAuth apps, and a US login does not carry over to the EU. The region option needs CLI 2.9.0 or later.

webflow --region eu auth login     # log in to the EU stack; EU becomes the stored default
webflow --region eu sites list
webflow --region us auth login     # switch back; US becomes the stored default
webflow --region us sites list

Logging in to a region replaces the stored session and makes that region the default for later commands that do not name one. The default is global, so it applies in every project directory. A command that does not name a region resolves it in this order, highest priority first:

  1. the --region flag

  2. the WEBFLOW_REGION environment variable

  3. region in webflow.json

  4. the region of the last login, stored in auth.json

  5. us

The pitfall is the global default: after a login to the EU stack for one customer, a script run in an unrelated project without --region targets the EU. In CI, set WEBFLOW_REGION explicitly, as in WEBFLOW_REGION=eu webflow sites list.

Selecting the site

Site-scoped commands (sites, cms, assets, forms, DevLink export and Webflow Cloud) need to know which site to act on. The CLI looks for it in these places:

  1. siteId in webflow.json

  2. WEBFLOW_SITE_ID in .env, when siteId is not set

  3. the --site or --site-id flag, a one-off override on commands that support it

  4. an interactive prompt, when nothing is configured and the command can prompt

Because one workspace token covers every site in the workspace, a monorepo with several sites keeps one webflow.json per project directory, each with its own siteId.

Data commands: sites, cms, assets and forms

The data commands wrap Data API endpoints in a form that is convenient for a terminal, a shell script or an agent. All of them accept --json to print machine-readable output. The write commands accept --dry-run, which previews what would happen without calling a mutating endpoint; the command reference describes it per command ("Preview what would be published without building", "Preview the item without creating it"). Use --dry-run first whenever a command was composed by a script or an agent.

Sites

webflow sites list --json
webflow sites get REPLACE_WITH_SITE_ID
webflow sites domains --site REPLACE_WITH_SITE_ID
webflow sites publish --site REPLACE_WITH_SITE_ID --dry-run
webflow sites publish --site REPLACE_WITH_SITE_ID
webflow sites publish --site REPLACE_WITH_SITE_ID --page REPLACE_WITH_PAGE_ID
webflow sites publish --site REPLACE_WITH_SITE_ID --domains DOMAIN_ID_1,DOMAIN_ID_2
Command Options

sites list

--fields, --json

sites get <siteId>

--json

sites domains

--site (required), --json

sites publish

--site (required), --domains (comma-separated custom domain IDs; the default is the Webflow subdomain), --page (publish a single page instead of the whole site), --dry-run, --json

sites publish is the CLI form of the publish endpoint described in Publishing and Scheduling. The same constraints apply: publishing to custom domains needs a Site plan with a custom domain, and the API limits how often a site can be published.

CMS

The cms family manages Collections, fields and items.

webflow cms collections list --site REPLACE_WITH_SITE_ID --json
webflow cms collections get REPLACE_WITH_COLLECTION_ID --json
webflow cms collections create --site REPLACE_WITH_SITE_ID --name "Garden zones" --singular-name "Garden zone" --slug garden-zones --dry-run
webflow cms fields create --collection REPLACE_WITH_COLLECTION_ID --name "Sun exposure" --type PlainText --required
webflow cms items list --collection REPLACE_WITH_COLLECTION_ID --limit 20 --locale REPLACE_WITH_LOCALE_ID --json
webflow cms items get --collection REPLACE_WITH_COLLECTION_ID --item REPLACE_WITH_ITEM_ID --json

The field types accepted by cms fields create --type are PlainText, RichText, Number, DateTime, Link, Image, Video, Color, Bool, Option, ItemRef and ItemRefSet; they correspond to the field types described in Collections and Field Types. Item data is passed as a JSON string to --data, so quoting matters in a shell:

webflow cms items create \
  --collection REPLACE_WITH_COLLECTION_ID \
  --data '{"name":"Japanese maple","slug":"japanese-maple"}' \
  --draft \
  --dry-run

# Remove --dry-run to create the item as a draft, then publish it
webflow cms items create \
  --collection REPLACE_WITH_COLLECTION_ID \
  --data '{"name":"Japanese maple","slug":"japanese-maple"}' \
  --draft --json
webflow cms items publish --collection REPLACE_WITH_COLLECTION_ID --items REPLACE_WITH_ITEM_ID
Command Options

cms collections list

--site, --fields, --sort-by, --order, --json

cms collections get <collectionId>

--json

cms collections create

--name (required), --site, --singular-name, --slug, --dry-run, --json

cms fields create

--collection, --name, --type (all required), --required, --dry-run, --json

cms items list

--collection (required), --fields, --limit, --offset, --locale, --json

cms items get

--collection and --item (required), --locale, --json

cms items create

--collection and --data (required), --draft, --dry-run, --json

cms items update

--collection, --item and --data (required), --dry-run, --json

cms items delete

--collection and --item (required), --dry-run

cms items publish

--collection and --items (comma-separated IDs, required), --dry-run, --json

Two behaviours deserve care. First, --draft is the CLI form of the isDraft flag; whether an item shows on the live site depends on the draft and publish semantics in Data API: CMS. Second, cms items delete removes the item, and the only safety net is --dry-run, so run it first. For bulk work (hundreds of items, idempotent re-runs, backoff on rate limits) write a script with an SDK instead; the CLI performs one operation per invocation and does not batch.

Assets

webflow assets folders list --site REPLACE_WITH_SITE_ID --json
webflow assets folders create "Plants" --site REPLACE_WITH_SITE_ID --parent REPLACE_WITH_FOLDER_ID
webflow assets upload ./photos/japanese-maple.jpg --site REPLACE_WITH_SITE_ID --folder REPLACE_WITH_FOLDER_ID --name "Japanese maple" --dry-run
webflow assets upload ./photos/japanese-maple.jpg --site REPLACE_WITH_SITE_ID --folder REPLACE_WITH_FOLDER_ID --name "Japanese maple"
webflow assets update REPLACE_WITH_ASSET_ID --alt-text "A Japanese maple in autumn colour" --dry-run
webflow assets list --sort-by createdOn --order desc --limit 10 --json

assets upload <file> takes the path to the file and enforces size limits: images up to 4 MB and documents up to 10 MB. --site is optional because the site can come from webflow.json; --name defaults to the file name; --folder selects the destination folder. assets update <assetId> changes --display-name and --alt-text, the latter being an accessibility concern covered in Accessibility. Compare with the lower-level upload (MD5 hash and presigned storage POST) in Data API: Assets, Forms and Custom Code, which the CLI performs for you.

Forms

webflow forms list --site REPLACE_WITH_SITE_ID --json
webflow forms submissions --site REPLACE_WITH_SITE_ID --form REPLACE_WITH_FORM_ID --output submissions.csv

forms submissions writes the submissions to a CSV file with --output, or prints JSON with --json. Submissions hold visitors' personal data (names and email addresses on a newsletter or booking form), so treat the CSV as personal data: store it encrypted, delete it when it has served its purpose, and keep it out of the repository. Form behaviour in general is described in Forms.

Designer Extensions

webflow extension list                              # list available templates
webflow extension init fernbrook-zone-picker react  # project name, then template
webflow extension serve                             # dev server, default port 1337
webflow extension bundle                            # create bundle.zip for upload

The templates are default, react and typescript-alt; omitted arguments are prompted for. extension serve [port] runs the local development server on port 1337 unless another is given, and extension bundle produces the bundle.zip that is uploaded to Webflow. The webflow.json keys that describe an extension are in the manifest section below.

webflow devlink export --site REPLACE_WITH_SITE_ID     # components to a local React bundle
webflow devlink import                                  # bundle and share a library with a Workspace
webflow devlink bundle --public-path /assets/           # bundle locally to ./dist without sharing

devlink export exports a site’s components into a local React project (the CLI-side counterpart of DevLink Export); devlink import bundles a code components library and shares it with a Workspace (see Code Components); devlink bundle bundles locally without sharing and requires --public-path, with --output-path optional. devlink import and devlink bundle also accept -f, --force, --debug-bundler and --dev. The former devlink sync command is deprecated and was removed; use devlink export.

Apps and Webflow Cloud

The apps family initialises, deploys and operates Webflow Cloud apps. It is available on the next channel; on the stable channel the older cloud commands remain. The main commands are listed below.

Command Purpose

apps init

Scaffold an app: --app-name, --framework (astro or nextjs), --mount, --site-id or --new with --workspace-id, or --import <repo-url> to adopt an existing repository. Needs a user token from auth login.

apps deploy

Deploy: --environment, --mount, --app-name, --directory, --description, --skip-mount-path-check, --auto-publish, plus --site-id or --workspace-id, --app-id and --framework.

apps list, apps get, apps domains

Inspect apps and their domains; all accept --json.

apps update, apps delete

Change name, description or GitHub source; delete requires --yes under --no-input or --json.

apps environments (list, create, update, delete)

Manage environments, each tied to a Git branch and a mount path.

apps link

Write the app and environment IDs into webflow.json.

apps deployments (list, get, redeploy, trigger)

List and inspect deployments, wait for one with get --wait, roll back with redeploy, build the branch head with trigger.

apps logs (build, runtime)

Paginated build and runtime logs with --since, --q, --limit and --cursor.

apps env-vars (list, set, delete, import)

Manage environment variables; secrets are always masked in output.

The deprecated cloud aliases are cloud create (deprecated, mounts at /app, default framework nextjs), cloud init (an alias of apps init), cloud deploy (an alias of apps deploy) and cloud list, which lists scaffold templates, not your apps. New scripts should use apps. The environments, deployments and storage that these commands operate are explained in Webflow Cloud: Deployments and Environments.

A secret should never be a command-line argument. apps env-vars set accepts the value on standard input precisely so that it stays out of shell history and the process list:

printf '%s' "$GARDEN_MAP_KEY" | webflow apps env-vars set GARDEN_MAP_KEY --secret \
  --app-id REPLACE_WITH_APP_ID --environment-id REPLACE_WITH_ENVIRONMENT_ID

Webflow Skills

Webflow publishes agent skills and an MCP server for AI clients; these are described in MCP Server and AI Agents. The CLI command reference lists the namespaces assets, auth, cms, devlink, extension, forms, log, sites, apps and the deprecated cloud, and, as of the check date, no separate skills command namespace. The parts of the CLI designed for agents are the non-interactive behaviours described below.

The webflow.json manifest

webflow.json sits in the root of a project. The init commands create it, and you edit it to change how the CLI builds and deploys each product. --manifest <path> points the CLI at another file or directory.

Top-level keys

{
  "siteId": "REPLACE_WITH_SITE_ID",
  "region": "eu"
}

siteId is the site to act on (for DevLink it defaults to the WEBFLOW_SITE_ID environment variable). region is us or eu, optional, default us, and needs CLI 2.9.0 or later. Because webflow.json is usually committed, it must hold identifiers only, never tokens.

Code components

Code components are configured under library:

{
  "library": {
    "name": "Fernbrook components",
    "components": ["./src/**/*.webflow.@(js|jsx|mjs|ts|tsx)"],
    "bundleConfig": "./webpack.webflow.js"
  }
}

name and components (a glob of component files) are required; bundleConfig (a custom webpack configuration) is optional; ssrDefault sets the default server-side rendering behaviour for components that do not set ssr, and defaults to true.

Options go under the devlink-export object, while siteId stays at the top level.

{
  "siteId": "REPLACE_WITH_SITE_ID",
  "devlink-export": {
    "rootDir": "./webflow",
    "components": ".*",
    "componentGroups": ".*",
    "ts": true,
    "cssScopes": true,
    "relativeHrefRoot": "/"
  }
}
Option Default Meaning

rootDir

./webflow

Directory the components are exported into (required).

cssScopes

true

Wraps component styles in CSS @scope.

ts

auto-detected

Generates TypeScript files; detected from tsconfig.json and .ts or .tsx files on the first export.

components

.*

Regular expression of the components to export.

componentGroups

.*

Regular expression of the component groups to export.

relativeHrefRoot

/

How relative href values are rewritten in exported Link and Image components.

Webflow Cloud

{
  "cloud": {
    "app_id": "REPLACE_WITH_APP_ID",
    "framework": "astro"
  }
}

app_id is required and is set automatically by the deploy command; framework is nextjs or astro. Earlier CLI versions wrote project_id; the CLI still reads it as a fallback and new deploys write app_id, but a future major release will drop the legacy field, so rename it when you touch the file. The agent-workflows page adds cloud.environment_id and cloud.workspace_id to the keys that apps init and apps deploy write.

Designer Extensions

{
  "name": "Fernbrook zone picker",
  "apiVersion": "2",
  "publicDir": "dist",
  "appIntents": {
    "image": ["manage"],
    "form": ["manage"]
  },
  "appConnections": ["fernbrookImageConnection", "fernbrookFormConnection"]
}

name, apiVersion (default 2) and publicDir (default dist) are required. appIntents lists the element types that can create connections to the extension, and appConnections lists the connection identifiers.

Environment variables at a glance

Variable Role

WEBFLOW_API_TOKEN

Workspace API token; read only from the environment or .env.

WEBFLOW_SITE_ID

Default site, used when siteId is not set in webflow.json.

WEBFLOW_REGION

Region (us or eu) for commands that do not name one.

WEBFLOW_APP_ID, WEBFLOW_APP_ENVIRONMENT_ID, WEBFLOW_WORKSPACE_ID

Identifiers for the apps commands.

DO_NOT_TRACK

Disables telemetry; overrides every other telemetry setting.

Telemetry

The CLI can send usage telemetry, and webflow auth telemetry controls it. The command reference documents the switches; it does not describe the data collected, so review the privacy information Webflow publishes before enabling it in a regulated environment.

webflow auth telemetry --status
webflow auth telemetry --disable            # global: ~/.config/webflow/telemetry.json
webflow auth telemetry --disable --local    # this project only: written to webflow.json
DO_NOT_TRACK=1 webflow sites list           # environment override

--enable and --disable write to telemetry.json in the same global configuration directory as auth.json, so they apply to every project. --local writes the preference to the webflow.json of the current directory instead. A webflow.json that already contains a telemetry setting is read and takes precedence over the global file regardless of --local, and the DO_NOT_TRACK environment variable overrides both.

Agents and CI/CD

Non-interactive operation

An agent or a CI job cannot answer prompts, so every required value must be a flag or an environment variable. Prompts only appear when a terminal is attached; without one, a missing value fails immediately with an error that names the flag. --no-input is switched on automatically when CI=true, when standard input or output is not a terminal, or when the CLI detects a coding-agent environment. Add it explicitly anyway: it is documented, harmless and survives a change of runner. Deploy prompts depend on whether --mount and --environment are both set, not on --no-input, so always pass both.

An unresolved identifier produces a message of this form:

Missing required appId. Pass --app-id, set WEBFLOW_APP_ID, or add it to webflow.json.

Identifier resolution

For each resource the CLI resolves the identifier from an explicit flag first, then an environment variable, then webflow.json (or the file given by --manifest), and finally an interactive prompt, which is skipped in non-interactive mode. If exactly one candidate exists, it is selected even without a prompt; an ambiguous choice with no identifier produces the missing-flag error.

Resource Flag Environment variable webflow.json key

Site

--site, --site-id

WEBFLOW_SITE_ID

siteId

App

--app-id

WEBFLOW_APP_ID

cloud.app_id, falling back to cloud.project_id

Environment

--environment-id

WEBFLOW_APP_ENVIRONMENT_ID

cloud.environment_id

Workspace

--workspace-id

WEBFLOW_WORKSPACE_ID

cloud.workspace_id

The CLI never writes these environment variables back to .env; only apps init and apps deploy write identifiers into webflow.json. In CI, pass identifiers as flags sourced from secrets instead of relying only on a committed manifest. Site IDs can be discovered with webflow sites list --json (match on displayName). Workspace IDs are not visible in the Dashboard; run webflow apps deploy once interactively and read cloud.workspace_id from the webflow.json it writes.

Exit codes and output

Code Meaning

0

Success, including an empty result list.

1

Operational error: authentication failure, API error, invalid input, an unresolved required value, or a poll timeout under apps deployments get --wait.

Error text is plain text on standard error, even with --json; --json changes only the success output and suppresses informational lines. Base pass or fail decisions on the exit code, not on parsing messages. Note that list commands return an envelope object (deployments and nextCursor for deployments), not a bare array.

Safety features

apps delete refuses to run under --no-input or --json unless --yes is also passed. Write commands (apps update, apps delete, apps env-vars set, delete and import) support --dry-run, which validates the inputs, including authentication, and makes zero API calls. When an agent chose the target identifier, preview first.

First deploy and continuous deployment

There are two deployment types. A site-attached app is served from a mount path such as /app on an existing site and uses --site-id. A project app is standalone and its first deploy provisions a new site; it uses --new at init and --workspace-id at deploy.

# Site-attached app
webflow apps init --no-input --app-name fernbrook-map --framework astro --mount /app --site-id REPLACE_WITH_SITE_ID
webflow apps deploy --no-input --site-id REPLACE_WITH_SITE_ID --mount /app --environment production --skip-mount-path-check

# Project app
webflow apps init --new --no-input --app-name fernbrook-map --framework nextjs --workspace-id REPLACE_WITH_WORKSPACE_ID
webflow apps deploy --no-input --workspace-id REPLACE_WITH_WORKSPACE_ID --app-name fernbrook-map --mount / --environment production

The recommended continuous-deployment route is dashboard-only: push the app to a GitHub repository, connect GitHub under the app’s Settings, Git, select the repository and branch, and the dashboard runs an initial deploy and then deploys on each push. A GitHub Actions workflow is the alternative when the pipeline needs custom build steps, per-environment secrets or deploy gates:

name: Deploy to Webflow Cloud
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      # Pin an exact version in CI; the next tag moves.
      - name: Install Webflow CLI
        run: npm install -g @webflow/webflow-cli@next
      - name: Deploy
        run: |
          webflow apps deploy --no-input \
            --site-id "$WEBFLOW_SITE_ID" \
            --mount /app \
            --environment production \
            --skip-mount-path-check
        env:
          WEBFLOW_API_TOKEN: ${{ secrets.WEBFLOW_API_TOKEN }}
          WEBFLOW_SITE_ID: ${{ secrets.WEBFLOW_SITE_ID }}

In a real pipeline replace @next with an exact pre-release version, as the comment says. To gate later steps on the outcome, wait for the deployment:

DEP_ID=$(webflow apps deployments list --limit 1 --json | jq -r '.deployments[0].id')
webflow apps deployments get "$DEP_ID" --wait --timeout 300

Deployment statuses in progress are starting, building and deploying; terminal statuses are success, failed, canceled and unstaged. With --wait, exit code 0 means success and 1 means any other outcome or a timeout, so read the status to tell a failure from a timeout (--interval has a minimum of 5 seconds and --timeout defaults to 600, maximum 1800). redeploy reruns a deployment at the same commit, which is how to roll back; trigger builds the environment’s configured branch at its current head. Pass --idempotency-key, such as the CI run ID, so retries do not queue duplicate builds. Both need a GitHub-connected app, which apps init --import or apps update --github-source sets up. See Testing, CI and DevOps for the wider pipeline.

Migrating to CLI 2.0

CLI 2.0 changed one requirement and renamed four commands. The Node.js minimum became 22.13.0. The v1 commands still work but emit deprecation warnings and will be removed in a future version, so update scripts and CI.

Version 1 Version 2 What it does

webflow library share

webflow devlink import

Bundles components and shares them with a Workspace.

webflow library bundle

webflow devlink bundle

Bundles a code components library locally without sharing it.

webflow library log

webflow log

Shows the path to the latest log file.

webflow cloud create

webflow cloud init

Initialises a Webflow Cloud app from a template.

Renamed commands take the same options, so a migration is a search and replace in scripts, package.json entries and workflow files, plus raising the Node.js version of CI runners. The sequence is: check node --version, upgrade Node.js if needed, run npm install -g @webflow/webflow-cli@latest, confirm with webflow --version, and replace the old names. Since then the CLI has continued to change: the --region option arrived in 2.9.0, the apps family replaced cloud for new work, and devlink sync was removed in favour of devlink export. See Product Changes and Deprecations for the dated list.

Common errors and pitfalls

  • Unknown command apps. The install is on the stable channel. Install @webflow/webflow-cli@next or use cloud init and cloud deploy.

  • Engine or syntax errors after install. Node.js is older than 22.13.0. Upgrade Node.js; CLI 2.0 and later do not run on older versions.

  • Wrong stack. A previous --region eu login set the global default. Pass --region or set WEBFLOW_REGION in every script.

  • Missing required flag in CI. There is no terminal, so prompts are off. Pass the named flag or set its environment variable.

  • Token in the log. --api-token was used and the shell echoed the command. Use WEBFLOW_API_TOKEN from a secret.

  • Quoting of --data. Use single quotes around the JSON in POSIX shells and escape quotes in PowerShell.

  • Timeout read as failure. deployments get --wait exits 1 for both; read the reported status.