@webflow/webflow-cli
v2.3.0
Published
The Webflow CLI lets you manage Webflow sites, CMS content, forms, assets, and code components from the command line.
Maintainers
Keywords
Readme
@webflow/webflow-cli
The Webflow CLI lets you manage Webflow sites, CMS content, forms, assets, and code components from the command line.
Installation
npm install -g @webflow/webflow-cliCommands
- Authentication
- Sites
- CMS
- Forms
- Assets
- DevLink Import (Code Components)
- DevLink Export
- Designer Extensions
- Apps (Webflow Cloud)
- Skills (agent skills)
- Global Options
Authentication
Authenticate with Webflow and save credentials locally.
webflow auth login # OAuth login — saves token to .env
webflow auth login --force # Re-authenticate even if credentials existSites
Manage Webflow sites from the CLI.
webflow sites list # List all sites in your workspace
webflow sites get <siteId> # Get details for a specific site
webflow sites domains --site <siteId> # List custom domains for a site
webflow sites publish --site <siteId> # Publish a sitesites list options
| Flag | Description |
| ------------------- | ---------------------------------------------------------------------------------------------------------------- |
| --fields <fields> | Comma-separated columns to display (id, displayName, shortName, timeZone, createdOn, lastUpdated, lastPublished) |
| --json | Output as JSON |
sites publish options
| Flag | Description |
| --------------------- | ---------------------------------------------------------- |
| --site <siteId> | Site ID to publish |
| --domain <domainId> | Publish to a specific custom domain (repeatable) |
| --page <pageId> | Publish a single page instead of the full site |
| --dry-run | Preview what would be published without triggering a build |
CMS
Manage CMS collections and items.
# Collections
webflow cms collections list --site <siteId>
webflow cms collections get --site <siteId> --collection <collectionId>
webflow cms collections create --site <siteId> --name "Blog Posts" --slug "blog-posts"
# Fields
webflow cms fields create --collection <collectionId> --name "Author" --type PlainText
# Items
webflow cms items list --site <siteId> --collection <collectionId>
webflow cms items get --site <siteId> --collection <collectionId> --item <itemId>
webflow cms items create --site <siteId> --collection <collectionId> --data '{"name":"Hello"}'
webflow cms items update --site <siteId> --collection <collectionId> --item <itemId> --data '{"name":"Updated"}'
webflow cms items delete --site <siteId> --collection <collectionId> --item <itemId>
webflow cms items publish --site <siteId> --collection <collectionId> --item <itemId>cms collections list options
| Flag | Description |
| ------------------- | ---------------------------------------------------------------------- |
| --sort-by <field> | Sort by: displayName, slug, lastUpdated (default: displayName) |
| --order <dir> | asc or desc (default: asc) |
| --json | Output as JSON |
Forms
List forms and export submissions from a Webflow site.
webflow forms list --site <siteId> # List all forms on a site
webflow forms submissions --site <siteId> --form <formId> # List submissions in the terminal
webflow forms submissions --site <siteId> --form <formId> --output out.csv # Export submissions to CSVNote: Forms commands require the
forms:readOAuth scope. If you authenticated before upgrading to v1.21.0, runwebflow auth login --forceto pick up the new scope.
forms list options
| Flag | Description |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| --site <siteId> | Site ID (required) |
| --fields <fields> | Comma-separated columns: id, displayName, name, slug, createdOn, lastUpdated (default: id,displayName,slug) |
| --json | Output as JSON |
forms submissions options
| Flag | Description |
| ----------------- | ---------------------------------------------------- |
| --site <siteId> | Site ID (required) |
| --form <formId> | Form ID (required) |
| --output <file> | Save all submissions as CSV to the specified file |
| --json | Output as JSON (ignored when --output is also set) |
Assets
Upload and manage site assets.
webflow assets list --site <siteId> # List assets
webflow assets upload <file> --site <siteId> # Upload a file
webflow assets update <assetId> --display-name "New name" # Update asset metadata
webflow assets folders --site <siteId> # List asset folders
webflow assets folders create --site <siteId> --name "Images"assets list options
| Flag | Description |
| --------------------- | --------------------------------------------------------------------------------------------------------- |
| --folder <folderId> | Filter by folder |
| --sort-by <field> | Sort by: displayName, originalFileName, contentType, size, lastUpdated (default: displayName) |
| --order <dir> | asc or desc (default: asc) |
| --fields <fields> | Comma-separated columns to display |
| --limit <n> | Max assets to return |
| --offset <n> | Skip N assets (for pagination) |
| --json | Output as JSON |
assets upload options
| Flag | Description |
| ---------------------- | ----------------------------------- |
| --name <displayName> | Display name (defaults to filename) |
| --folder <folderId> | Upload into a folder |
| --dry-run | Preview without uploading |
Supported file types: PNG, JPG, JPEG, GIF, SVG, WEBP, AVIF (≤ 4 MB); PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT, CSV, ODT, ODS, ODP, JSON, Lottie (≤ 10 MB)
DevLink Import (Code Components)
Build and import React component libraries to your Webflow workspace.
webflow devlink import # Build and share your component library
webflow devlink bundle # Build locally without sharingAliases: webflow library share, webflow library bundle
Prerequisites
Create a webflow.json in your project root:
{
"library": {
"name": "My Component Library",
"description": "A collection of custom components",
"components": ["src/components/**/*.webflow.tsx"]
}
}devlink import options
| Flag | Description |
| --------------------- | --------------------------------------------------- |
| --api-token <token> | Workspace API token (overrides WEBFLOW_API_TOKEN) |
| --force | Compile even with warnings or type errors |
| --dev | Bundle in development mode |
devlink bundle options
| Flag | Description |
| ---------------------- | ----------------------------------------------------- |
| --public-path <path> | Set the public path for the bundle |
| --output-path <path> | Set the output path for the bundle (default ./dist) |
| --force | Compile even with warnings or type errors |
| --dev | Bundle in development mode |
DevLink Export
Export Webflow Components from your Webflow Site
webflow devlink export # Export Webflow Componentsdevlink export options
| Flag | Description |
| --------------------- | --------------------------------------------------- |
| --api-token <token> | Workspace API token (overrides WEBFLOW_API_TOKEN) |
| --site <siteId> | Site ID to export from |
Designer Extensions
Scaffold and serve Webflow Designer Extensions.
webflow extension init <name> # Create a new extension project
webflow extension serve [port] # Serve locally (default port: 1337)
webflow extension bundle # Build and package for upload (outputs bundle.zip)Apps (Webflow Cloud)
Manage Webflow Cloud app environment variables non-interactively. --app-id and
--environment-id default from webflow.json (cloud.app_id / cloud.environment_id)
when omitted.
webflow apps env-vars list --app-id <appId> --environment-id <envId> # List variables
webflow apps env-vars set <key> <value> --app-id <appId> --environment-id <envId> # Create or update (plaintext; for secrets use stdin/prompt below)
webflow apps env-vars set <key> --secret # Prompt (hidden) for a secret value
printf %s "$VALUE" | webflow apps env-vars set <key> --secret # Read a secret from stdin
webflow apps env-vars delete <key> --app-id <appId> --environment-id <envId> # Delete a variable
webflow apps env-vars import .env --app-id <appId> --environment-id <envId> # Bulk import from a .env file
webflow apps env-vars import .env.secrets --secret # Import every key as a secretSecret values are encrypted server-side and are never displayed: reads return
them masked, and set / import never echo values to stdout, logs, or
telemetry.
For set, the value is optional: omit it to read from piped stdin or to be
prompted with hidden input. Prefer this for secrets — passing a value as a
command-line argument leaves it in your shell history and the process list
(set warns when you do so with --secret).
env-vars list options
| Flag | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------- |
| --app-id <id> | Cloud app ID (default: cloud.app_id in webflow.json) |
| --environment-id <id> | Environment ID (default: cloud.environment_id in webflow.json) |
| --fields <fields> | Comma-separated columns (key, isSecret, value, id, environmentId). value is excluded by default |
| --json | Output as JSON |
env-vars set / delete / import options
| Flag | Description |
| ----------------------- | ------------------------------------------------------------------ |
| --app-id <id> | Cloud app ID (default: cloud.app_id in webflow.json) |
| --environment-id <id> | Environment ID (default: cloud.environment_id in webflow.json) |
| --secret | (set, import) Mark the variable(s) as an encrypted secret |
| --dry-run | Preview without making any API calls |
| --json | Output as JSON |
A plain set on an existing secret preserves its secrecy (it never silently
downgrades a secret to plaintext). import reports a per-key
created/updated/skipped/errors breakdown and exits non-zero if any key fails
(e.g. a reserved or invalid name). The bulk import is capped at 100 variables.
Skills (agent skills)
Install Webflow's first-party agent skills into your coding agents, so an agent working in your repo knows how to use Webflow without being told each time.
These commands write outside the current project. A
--globalinstall writes into your coding agents' skill directories under your home directory. Two rules bound that: nothing is replaced or deleted unless the CLI wrote it and it has not been edited since (anything else needs--force), and--dry-runprints every path before a single byte is written. Run it first if you are unsure.
webflow skills install # Restore from a lockfile, or pick interactively
webflow skills install webflow-cms --dry-run # Preview every path that would be written
webflow skills install webflow-cms --agent claude-code,cursor
webflow skills install --all-skills --all-agents --global
webflow skills list # What is installed, and where
webflow skills update --check # Report what would change; write nothing
webflow skills update
webflow skills remove webflow-cms --dry-run # Preview exactly what is deletedScope: project or global
| Scope | Where skills go | Lockfile |
| ------------------- | ------------------------------------------- | ---------------------------------------- |
| Project (default) | Agent directories under the current project | webflow-skills-lock.json (commit this) |
| Global (--global) | Agent directories under your home directory | skills-lock.json in the CLI config dir |
The project lockfile is meant to be committed: a teammate (or CI) runs
webflow skills install with no arguments and gets the same skills at the same
commit. list shows both scopes by default so a global install is never
invisible.
Each skill's files are written once into a shared canonical store and linked into
every selected agent's directory, so installing for twenty agents costs one copy.
Symlinks are used by default, with an automatic per-target fallback to copying
when the filesystem or platform refuses them; --copy forces copies everywhere.
Safety
install and update refuse to overwrite a skill directory unless the CLI
wrote it and it has not been edited since — anything locally modified, or
anything that exists without a matching lockfile entry, is reported as blocked
and needs --force. --dry-run prints the exact absolute paths that would be
written or deleted and makes no changes, which is the flag to reach for first
when an agent chose the arguments.
skills install options
| Flag | Description |
| --------------------- | ---------------------------------------------------------------------- |
| -a, --agent <ids> | Target agent; repeatable, comma-separated, or all |
| --all-agents | Install for every supported agent |
| --all-skills | Install every skill in the catalog |
| -g, --global | Install into your home directory instead of the current project |
| -p, --project | Install into the current project (the default) |
| --copy | Copy files instead of symlinking from the shared store |
| --ref <branch\|sha> | Pin to a branch or 40-character commit SHA (default: main) |
| --force | Replace destinations that were modified locally or installed elsewhere |
| -y, --yes | Skip the confirmation prompt |
| --dry-run | Print every path that would be written; change nothing |
| --json | Output as JSON |
skills update options
| Flag | Description |
| --------------------- | ------------------------------------------------- |
| --check | Report what would change without writing anything |
| -g, --global | Update the home-directory install |
| -p, --project | Update the current project's install |
| --ref <branch\|sha> | Re-pin to a different branch or commit SHA |
| --force | Overwrite skills that were modified locally |
| -y, --yes | Skip the confirmation prompt |
| --dry-run | Preview without writing |
| --json | Output as JSON |
skills list options
| Flag | Description |
| ------------------- | ----------------------------------------------------------------------------- |
| -g, --global | Only the home-directory install |
| -p, --project | Only the current project's install |
| -a, --agent <ids> | Only skills linked into these agents; repeatable and comma-separated |
| --fields <fields> | Comma-separated columns (name, dir, description, status, mode, agents, scope) |
| --sort-by <field> | Sort by name, dir, status, or scope (default: name) |
| --order <dir> | asc or desc (default: asc) |
| --json | Output as JSON |
status is computed offline by re-hashing what is on disk against what the
lockfile recorded: up-to-date, modified (edited since install), missing
(recorded but gone), or unmanaged (present with no lockfile entry). Checking
for upstream changes needs the network and is skills update --check's job.
skills remove options
| Flag | Description |
| ------------------- | ------------------------------------------------------------- |
| -a, --agent <ids> | Only unlink from these agents; repeatable and comma-separated |
| --all | Remove every installed skill for the scope |
| -g, --global | Remove from the home-directory install |
| -p, --project | Remove from the current project's install |
| --force | Also remove skill directories that have no lockfile entry |
| -y, --yes | Skip the confirmation prompt |
| --dry-run | Print exactly what would be deleted; change nothing |
| --json | Output as JSON |
Removing a skill from one agent unlinks it there and keeps the shared store as long as another agent still references it; the store directory is deleted once nothing does.
remove only deletes what the lockfile records. A skill directory with no
lockfile entry was not installed by this CLI — it may belong to another tool, or
be hand-written — so --all leaves it alone and names it in a warning, and
naming it directly is refused. --force opts in to removing those too.
Global Options
Available on all commands:
| Flag | Description |
| --------------------- | -------------------------------------------------- |
| --no-input | Disable interactive prompts (for CI/CD) |
| --manifest <path> | Path to webflow.json (default: ./webflow.json) |
| --skip-update-check | Skip checking for package updates |
| --verbose | Show detailed output |
License
MIT
