Migrate from Contentstack CLI V1 to V2

View as Markdown
Intermediate37 min readLast updated November 6, 2026

Overview

This guide applies if you are upgrading Contentstack CLI from version 1.x.x to 2.x.x.

V2 requires Node.js 22+, routes all publish operations through Nested Reference Publishing (NRP), removes several flags and command aliases with no runtime warning, and changes the on-disk format of exports (per-UID files replace aggregate JSON files like schema.json and globalfields.json).

You get a flag-by-flag mapping for every removed command, the export and import file-format changes to check in your tooling, a pre-upgrade checklist, and the failure modes in this upgrade that produce no error output. The fixes for those failure modes are in the CLI troubleshooting FAQs.

This guide covers CLI-only changes. It does not cover Contentstack platform or API changes.

Quick Decision Guide

Find the rows that match how you use the CLI, then read only those sections.

If youImpactRead
Run csdx by hand, with no scriptsLowPrerequisites, Command Aliases Removed
Script export or importHighcm:stacks:export, cm:stacks:import, Compatibility of V1 Artifacts with V2
Export more than one branchHighcm:stacks:export. V2 exports only main by default and writes flat output, so exporting two branches to one directory overwrites the first.
Parse stdout in CIHighDefault Output: Progress Bars Replace Console Logs
Publish or unpublish in bulkHighcm:stacks:bulk-entries, cm:stacks:bulk-assets, All Publish Operations Now Use NRP
Authenticate with --auth-token or an aliasMediumAuthentication Changes
Use launch:* or cm:entries:migrate-html-rteMediumPlugin Changes. Both are separate installs in V2.
Use cm:bootstrapMediumcm:bootstrap. V2 removes 13 app configs.
Import the composable-studio moduleMediumAuthentication Changes. Basic Auth is the only supported path.
Maintain a custom CLI plugin or import configMediumRemoved Import Config Keys (Custom Plugins and Config Files), Node.js 22+
Use tsgen or content-type:*LowType Mapping Reference. Flag renames only.

Commands not listed above need no changes beyond the flag renames in Type Mapping Reference.

Before you upgrade, work through the Pre-Upgrade Checklist. If a command reports success but produces no data, read the CLI troubleshooting FAQs first. Several failure modes in this upgrade produce no error output.

Compatibility of V1 Artifacts with V2

Use this table if you already upgraded and need to know whether an existing export, config, or token still works.

V1 artifactWorks with V2?What to do
V1 export, content typesYesNothing. V1 writes per-UID files (along with schema.json), which V2 continues to read.
V1 export, global fieldsNo, skipped. The pre-import audit then offers to remove Global field fieldsRe-export with V2 before importing. See Global Fields Silently Skipped on Import.
V1 multi-branch exportNo, imports nothingPoint --data-dir at the branch subfolder. See V1 Multi-Branch Export Produces an Empty Import.
V1 export, audited with V2No, reports a false cleanRe-export with V2 before auditing. See cm:stacks:audit Reports Zero Global-Field Issues on a V1 Export (False Clean).
V1 show-console-logs configNo, silently ignoredRe-run csdx config:set:log --show-console-logs. See V1 Console Log Config Silently Ignored After Upgrade.
Saved management tokensYesNothing. Tokens carry over with no re-authentication.
branches.json, export-info.json, schema.json, globalfields.jsonNot written by V2Remove any pipeline step that reads them. See cm:stacks:export.

Prerequisites

Node.js 22+

V2 requires Node.js >=22.0.0.

If you need to upgrade, run:

nvm install 22
nvm alias default 22   # makes 22 the permanent default, not just for this shell session
nvm use 22

Warning On Node 18 or 20, the npm install -g @contentstack/cli completes with EBADENGINE warnings and appears to succeed, but the CLI fails at runtime. Upgrade Node first, then install.

Install V2

npm install -g @contentstack/cli@2

Using yarn or pnpm:

yarn global add @contentstack/cli@2
pnpm add -g @contentstack/cli@2

Verify the upgrade succeeded:

csdx --version

The output shows a 2.x version, such as 2.0.2.

Warning npm install -g replaces the csdx binary in place. A roughly 30-second window exists during installation where csdx is unavailable. For continuous integration (CI) pipelines, run the install and the CLI commands in the same pipeline step. Do not rely on a pre-installed binary from a prior step.

On a 2.x beta, upgrade directly to the latest 2.x release with npm install -g @contentstack/cli@2.

Note: Verify Node 22 in Every Environment

Run this check on every environment where the CLI runs, including CI and continuous delivery (CD) pipelines, not only your local machine:

  • Dev machines
  • CI/CD runners
  • Docker base images (pin to the Node 22 LTS tag)

Type Mapping Reference

The table below lists every flag rename and removed short character across every command. Rows that repeat the same V1 and V2 flag name had only their short character removed. Rows marked "use OAuth" mean you authenticate with Open Authorization (OAuth) login (csdx auth:login --oauth) instead of the removed flag.

CommandV1 FlagV1 ShortV2 FlagV2 Short
cm:stacks:export--stack-uid-s--stack-api-key-k
--dataNone--data-dir-d
--management-token-aliasNone--alias-a
--auth-token-A(removed, use OAuth + --alias)None
--module-m--moduleNone
--content-types-t--content-typesNone
--branch-B--branchNone
cm:stacks:import--stack-uid-s--stack-api-key-k
--dataNone--data-dir-d
--management-token-aliasNone--alias-a
--auth-token-A(removed, use OAuth + --alias)None
--module-m--moduleNone
--backup-dir-b--backup-dirNone
--branch-B--branchNone
--skip-app-recreationNone(removed, no replacement)None
cm:stacks:import-setup--branch-B--branchNone
cm:stacks:bulk-entries--api-versionNone(removed)None
cm:stacks:bulk-taxonomies--api-versionNone(removed)None
cm:stacks:seed--stack-s--stack-api-key-k
--repo-r--repoNone
--org-o--orgNone
--fetch-limit-l(removed)None
cm:stacks:migration--branch-B--branchNone
--authtoken-A(removed, use OAuth + --alias)None
--filePath-n--file-pathNone
--config-fileNone(removed, use --config)None
--api-key-k--stack-api-key-k
--management-token-aliasNone--alias-a
--multiNone--multipleNone
cm:stacks:validate-regex--contentType-c--contentTypeNone
--filePath-f--filePathNone
--globalField-g--globalFieldNone
cm:bootstrap--appName-a--app-nameNone
--directory-d--project-dirNone
--app-typeNone(removed)None
--appType-s(removed)None
auth:tokens:add--delivery-d--deliveryNone
--management-m--managementNone
--token-t--tokenNone
--api-keyNone--stack-api-key-k
--branchNone(removed)None
--force-f--yes-y
auth:tokens:remove--ignore-i(removed)None
auth:logout--force-f--yes-y
config:set:region--cda-d--cdaNone
--cma-m--cmaNone
--name-n--nameNone
tsgen--token-alias-a--alias-a
--output-o--outputNone
--prefix-p--prefixNone
--doc-d--docNone
app:create--name-n--nameNone
migrate:convert--output-o--outputNone
--master-locale-m--master-localeNone
--affix-a--affixNone
migrate:export--output-o--outputNone
content-type:audit--stack-s--stack-api-key-k
--token-alias-a--alias-a
--content-type-c--content-typeNone
content-type:compare--stack-s--stack-api-key-k
--token-alias-a--alias-a
--content-type-c--content-typeNone
--left-l--leftNone
--right-r--rightNone
content-type:compare-remote--origin-stack-o--origin-stackNone
--remote-stack-r--remote-stackNone
--content-type-c--content-typeNone
content-type:details--stack-s--stack-api-key-k
--token-alias-a--alias-a
--content-type-c--content-typeNone
--path-p--pathNone
content-type:diagram--stack-s--stack-api-key-k
--token-alias-a--alias-a
--output-o--outputNone
--direction-d--directionNone
--type-t--typeNone
content-type:list--stack-s--stack-api-key-k
--token-alias-a--alias-a
--order-o--orderNone
cm:stacks:audit--reference-onlyNone(removed)None
cm:stacks:audit:fix--reference-onlyNone(removed)None

Behavior Change: cm:stacks:migration configuration flags In V1, --config took inline configuration and --config-file took a file path. In V2, --config takes the file path, inline configuration moved to the new --inline-config flag, and --config-file is removed. This is the one flag in the CLI that kept its name and changed its meaning, so a V1 script passing inline values to --config is read as a file path rather than failing outright.

Global CLI Behavior Changes

Authentication Changes

V2 removes the token-passing flags. You authenticate once, then reference a stored alias.

V1V2
--auth-token / -A on export and importRemoved. Run csdx auth:login, then pass --alias.
--authtoken / -A on cm:stacks:migrationRemoved. Run csdx auth:login, then pass --alias.
--management-token-alias on export and import--alias
--token-alias on tsgen and content-type:*--alias
--api-key on auth:tokens:addRemoved. Use --stack-api-key (-k).
--branch on auth:tokens:addRemoved with no replacement.

Saved tokens carry over. Management tokens added with csdx auth:tokens:add under V1 are available immediately after upgrading. You do not need to re-authenticate. See Tokens and Config Carry Over Automatically.

The composable-studio import module requires Basic Auth. V2 skips this module when you authenticate with a management token or with OAuth. V2 prints a skip message rather than an error:

Skipping Studio project import when using management token
Skipping Studio project import when using OAuth authentication

Authenticate with username and password instead. Basic Auth is the only supported path for this module:

csdx auth:login -u <EMAIL> -p <PASSWORD>

Default Output: Progress Bars Replace Console Logs

BehaviorV1V2
Output formatText printed line-by-line to stdout as operations runVisual progress bars render in the terminal
Console log outputPrinted live to stdout, parseable by scripts and CISuppressed by default
End-of-run outputAccumulated text output, no separate summaryShows only a summary and a log file path

Effect: Any script or CI pipeline that parses stdout for success or failure signals receives different output. V2 does not exit non-zero or throw because of this. Whether a log line still reaches the console depends on its level:

Log levelReaches the console when progress bars are active
error, warnYes, always
info, success, debugNo, suppressed

A script that parses stdout for a suppressed line finds nothing, not an error.

CI environments: By default, V2 shows progress bars and hides info and success log lines for export, import, audit, import-setup, clone and bulk operations. If your CI pipeline reads those lines, turn console logs on:

csdx config:set:log --show-console-logs

See config:set:log for the full flag reference.

Log file location: V2 writes logs to a logs/ directory in whichever folder you ran the CLI from (for example, ./logs/). Set the CS_CLI_LOG_PATH environment variable or run csdx config:set:log --path <dir> to redirect logs.

Deprecated Flags Removed

V2 raises no runtime warning when a deprecated flag stops working, unlike V1. Audit your scripts before upgrading.

Before (V1):

csdx cm:stacks:export --stack-uid blt123

This prints a deprecation warning, then runs.

After (V2):

csdx cm:stacks:export --stack-uid blt123
ERROR: Nonexistent flag: --stack-uid

The same applies to every other deprecated flag (--data, -s, -B, and similar).

Short Flags Cleaned Up

V2 systematically removes single-character short flags that conflicted with global CLI flags or were ambiguous across commands. In every case the long form still works. See each command section for the specific characters removed.

All Publish Operations Now Use NRP

In V2, all publish operations, including entry, asset, and taxonomy publishes triggered during import and all bulk publish and unpublish commands, go through the Nested Reference Publishing (NRP) API. V1 did not use NRP for import. For bulk publish, V1 cm:stacks:bulk-entries and cm:stacks:bulk-taxonomies accepted an --api-version flag.

What changed:

CommandV1V2
cm:stacks:import (auto-publish)Did not use NRPUses NRP for all entry, asset, and taxonomy publishes
cm:stacks:bulk-entriesAccepted --api-version (default 3.2)Always uses NRP, --api-version flag removed
cm:stacks:bulk-assetsNo --api-version flagAlways uses NRP
cm:stacks:bulk-taxonomiesAccepted --api-version (default 3.2)Always uses NRP, --api-version flag removed

Impact: Your stack must have NRP enabled. V2 has no flag to run publish operations without NRP.

Note Passing --api-version to cm:stacks:bulk-entries or cm:stacks:bulk-taxonomies in V2 causes an immediate error: ERROR: Nonexistent flag: --api-version.

Command Aliases Removed

V2 removes several short-form aliases that V1 used:

Removed AliasV2 Replacement
csdx cm:exportcsdx cm:stacks:export
csdx cm:importcsdx cm:stacks:import
csdx cm:import-setupcsdx cm:stacks:import-setup
csdx tokenscsdx auth:tokens:list
csdx cm:seedcsdx cm:stacks:seed
csdx auditcsdx cm:stacks:audit
csdx audit:fixcsdx cm:stacks:audit:fix
csdx cm:migrationcsdx cm:stacks:migration

Plugin Changes

launch Plugin: Now Opt-In

V2 no longer bundles launch:* commands in the CLI. When you run any launch:* command, V2 prints a guided error with the install instruction and exits with code 127.

Affected commands: launch, launch:deployments, launch:environments, launch:functions, launch:logs, launch:open, launch:rollback

No prior equivalent required: these commands existed bundled in V1. V2 keeps the same commands available as an installable plugin.

Before: the launch plugin ships bundled with the CLI in V1. You need no install step.

After:

csdx plugins:install @contentstack/cli-launch

migrate-rte Plugin: Now Opt-In

V2 no longer bundles cm:entries:migrate-html-rte in the CLI. As with launch, when you run it V2 prints a guided error with the install instruction and exits with code 127.

Affected commands: cm:entries:migrate-html-rte

Before: the migrate-rte plugin ships bundled with the CLI in V1. You need no install step.

After:

csdx plugins:install @contentstack/cli-cm-migrate-rte

Docs: Migrate content from HTML RTE to JSON RTE

Post-Upgrade Behavior

Tokens and Config Carry Over Automatically

V2 carries over your existing saved tokens (management tokens added with csdx auth:tokens:add) automatically. You do not need to re-authenticate after upgrading.

V2 also carries over other stored config (proxy settings, region config) unchanged.

Exception: the console log setting. V2 uses a different internal key and silently ignores the V1 setting (see V1 Console Log Config Silently Ignored After Upgrade). If you ran this in V1, re-run it after upgrading:

csdx config:set:log --show-console-logs

Gradual Migration

npm global install allows only one active version per Node environment. If you need V1 available during testing, install it under a different nvm Node version. For example:

nvm install 22 && nvm use 22 && npm install -g @contentstack/[email protected]
nvm install 24 && nvm use 24 && npm install -g @contentstack/cli@2

What this does not do: nvm switches which install is active, it does not isolate CLI state. Both versions read the same saved tokens and the same region and proxy config described above, so signing out or reconfiguring in one affects the other. Only the console log setting is not shared, per the exception above.

Command Reference

cm:stacks:export

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference. Authentication flags are covered in Authentication Changes.

Before:

csdx cm:stacks:export -s blt123 --data ./export -m content-types -t blog article -B main

After:

csdx cm:stacks:export --stack-api-key blt123 --data-dir ./export --module content-types --content-types blog article --branch main

Behavior Change: Branch Export Writes Flat Output

V1: When you omit --branch, V1 exports all branches. V1 nests the output under exportDir/<branch-uid>/... for each branch.

V2: Two independent changes apply:

  1. Default branch: When you omit --branch, V2 exports only the branch named main. If no main branch exists, the command errors.
  2. No branch subfolder, always: Even when you specify --branch, V2 writes output flat to exportDir/... with no <branch-uid>/ subfolder. This applies regardless of how you select the branch.

Impact for multi-branch stacks: You must export each branch to a separate --data-dir. If you export two branches to the same directory, the second export overwrites every file with a matching path and leaves the rest, so the folder holds a mix of both branches. V2 prints only a warning, The export directory is not empty. Existing files in this folder may be overwritten., and continues.

Use a separate --data-dir per branch:

csdx cm:stacks:export --branch main       --data-dir ./export-main    --stack-api-key bltXXX
csdx cm:stacks:export --branch feature-x  --data-dir ./export-feature --stack-api-key bltXXX
csdx cm:stacks:export --branch-alias prod --data-dir ./export-prod     --stack-api-key bltXXX

branches.json removed:

  • V1 wrote a branches.json file to the export root listing all branches at export time.
  • V2 does not write this file, and raises no error. If your import pipeline or post-export tooling reads branches.json, remove that step.

export-info.json No Longer Written

V1 wrote export-info.json to the export directory containing { "contentVersion": 2, "logsPath": "..." }. V2 does not write this file. If your pipeline checks for this file or reads contentVersion from it, remove that step.

content_types/schema.json Removed

Warning A pipeline or script that reads export/content_types/schema.json fails on a V2 export with no error message, because the file does not exist in a V2 export.

V1 wrote a combined content_types/schema.json with all content type schemas in one array. V2 only writes individual content_types/<uid>.json files. V2 drops the aggregate file entirely.

Before:

cat export/content_types/schema.json

After:

ls export/content_types/*.json

Global Fields Format Changed (Per-File)

Warning If any pipeline or script reads export/global_fields/globalfields.json, it fails on a V2 export. The file does not exist.

Before: V1 stores all global fields in one file.

export/global_fields/globalfields.json

After: V2 stores one file per global field UID.

export/global_fields/my_header.json
export/global_fields/my_footer.json
export/global_fields/shared_banner.json

Update any tooling that reads globalfields.json to iterate per-UID files instead.

Behavior Change: Module Flag Now Validated, studio Renamed

Module validation:

  • V1: an invalid --module value is not checked upfront. The command fails partway through the operation, after work has already started.
  • V2: the CLI validates --module against an explicit allowed-values list before any operation starts, and fails immediately with a clear error.

V2 renames V1's --module studio value to --module composable-studio. The old value fails:

Error: Expected --module=studio to be one of: stack, assets, locales, ...composable-studio

Before:

csdx cm:stacks:export --module studio

After:

csdx cm:stacks:export --module composable-studio

V2 also adds two export targets that V1 does not have: publishing-rules, personalize. Both are also supported on import (see cm:stacks:import).

cm:stacks:import

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference. Authentication flags are covered in Authentication Changes. One removed flag has no replacement at all:

RemovedV2 Replacement
--skip-app-recreationRemoved with no replacement

Before:

csdx cm:stacks:import -s blt123 --data ./export -b ./backup -B main

After:

csdx cm:stacks:import --stack-api-key blt123 --data-dir ./export --backup-dir ./backup --branch main

Warning: V2 removes --skip-app-recreation completely, with no replacement. Remove it from all import scripts.

--skip-taxonomy-publish is a new, unrelated flag (see Taxonomy Publishing). It does not replace --skip-app-recreation.

The following flags exist in both V1 and V2 and require no migration:

  • --branch-alias
  • --skip-audit
  • --exclude-global-modules
  • --replace-existing
  • --skip-existing
  • --import-webhook-status
  • --personalize-project-name
  • --skip-assets-publish
  • --skip-entries-publish

Of these, --skip-assets-publish and --skip-entries-publish interact with a real behavior change: when unset, the publish that runs now goes through NRP (see All Publish Operations Now Use NRP). The flag's own skip or no-skip behavior is unchanged.

Behavior Change: Module Flag Validates Against a Strict List

Same as export: V2 validates --module on import before any operation begins. --module studio fails. Use --module composable-studio instead. V2 adds --module variant-entries as a new valid value that V1 does not have.

Behavior Change: Importing a V1 Export Silently Skips Global Fields

V2's importers use per-UID file readers that explicitly ignore aggregate files. The impact differs between modules because V1 export behavior differs:

ModuleV1 export writesV2 importer readsImpact on V1 export
Content typesIndividual <uid>.json files and schema.jsonPer-UID files only (ignores schema.json)No impact, per-UID files exist, content types import correctly
Global fieldsglobalfields.json only (no individual files)Per-UID files only (ignores globalfields.json)Silently skipped, no per-UID files exist in a V1 export

Impact: Running V2 import on a V1 export skips all global fields. The screen shows no error, because the CLI writes No global fields found in directory to the log file only. Before it imports, the CLI runs an audit fix that treats every Global field field in your content types as a broken reference, and asks whether to remove them. Answer No, and do not pass --yes, when you import a V1 export.

Resolution: Re-export your stack with V2 before importing. If the source stack no longer exists, write each object in global_fields/globalfields.json to its own global_fields/<uid>.json file, then import. No released CLI tool performs this split.

See Global Fields Missing After Importing a CLI V1 Export with CLI V2 in the CLI troubleshooting FAQs. Symptom: the import command reports success, and zero global fields exist in the target stack afterward.

Behavior Change: V1 Multi-Branch Export Auto Detection Removed

V1 import auto-detected the branch by reading branches.json at the export root and navigating to the correct <branch-uid>/ subfolder. V2 removes this selectBranchFromDirectory logic.

Before:

csdx cm:stacks:import --data-dir ./my-export

V1 reads branches.json and auto-navigates to ./my-export/main/.

After:

csdx cm:stacks:import --data-dir ./my-export/main

When importing a V1 multi-branch export, V2 requires you to specify the branch subfolder explicitly (V2's own exports write flat, with no subfolder at all, see cm:stacks:export).

If you point V2 import at a V1 multi-branch export root, it attempts to read content files directly from the root (where only branches.json lives), finds nothing, and silently produces an empty import. See Import with CLI V2 Finds No Content in a CLI V1 Branch Export in the CLI troubleshooting FAQs. Symptom: the command completes and reports success, and no content imports.

Behavior Change: composable-studio Module Requires Basic Auth

Same requirement as export. See Authentication Changes for the skip conditions, skip messages, and login command.

Removed Import Config Keys (Custom Plugins and Config Files)

If you maintain a custom plugin or tool that reads the import config object, V2 removes these keys:

Removed KeyWas Set To
importConfig.branchDira redundant alias for contentDir. V2 uses contentDir directly.
importConfig.contentVersiona JS/TS module routing number used for internal module routing

Use importConfig.contentDir directly in V2.

Rename: modules["asset-management"] is now modules["cs-assets"]. If your external config JSON still uses the old key, V2 renames it internally and logs a deprecation warning.

Fix: Update your config files to use "cs-assets" directly to suppress the warning.

cm:stacks:import-setup

Removed Flags

The cm:import-setup alias is removed, so use the full command name (see Command Aliases Removed). The removed short character is listed in Type Mapping Reference.

Before:

csdx cm:import-setup --stack-api-key blt123 -B main

After:

csdx cm:stacks:import-setup --stack-api-key blt123 --branch main

cm:stacks:bulk-entries

Replaces (all removed in V2): cm:entries:publish, cm:entries:publish-modified, cm:entries:publish-only-unpublished, cm:entries:publish-non-localized-fields, cm:entries:unpublish, cm:entries:update-and-publish, cm:stacks:publish (entries), cm:stacks:unpublish (entries), cm:stacks:publish-revert

V2 replaces all 15 commands in the @contentstack/cli-cm-bulk-publish plugin (across cm:entries:*, cm:stacks:*, cm:bulk-publish:*, and cm:assets:*) with 3 commands in @contentstack/cli-bulk-operations, each driven by an --operation flag instead of a dedicated command per action. Rewrite every bulk publish script against the new flag-based interface.

V1 to V2 Command Mapping

V1 Command (REMOVED)V2 Replacement
csdx cm:entries:publishcsdx cm:stacks:bulk-entries --operation publish
csdx cm:entries:publish-modifiedcsdx cm:stacks:bulk-entries --operation publish --filter modified
csdx cm:entries:publish-only-unpublishedcsdx cm:stacks:bulk-entries --operation publish --filter unpublished
csdx cm:entries:publish-non-localized-fieldscsdx cm:stacks:bulk-entries --operation publish --filter non-localized
csdx cm:entries:unpublishcsdx cm:stacks:bulk-entries --operation unpublish
csdx cm:entries:update-and-publishcsdx cm:stacks:bulk-entries --operation publish
csdx cm:stacks:publish (for entries)csdx cm:stacks:bulk-entries --operation publish
csdx cm:stacks:unpublish (for entries)csdx cm:stacks:bulk-entries --operation unpublish
csdx cm:bulk-publish:cross-publishcsdx cm:stacks:bulk-entries --operation publish --source-alias <alias>
csdx cm:stacks:publish-revert --log-file ./log.jsoncsdx cm:stacks:bulk-entries --revert ./log.json
csdx cm:stacks:publish-configureNO EQUIVALENT, REMOVED
csdx cm:stacks:publish-clear-logsNO EQUIVALENT, REMOVED

--filter valid values: draft, modified, unpublished, non-localized. Passing any other value causes an immediate error.

csdx cm:stacks:bulk-entries --operation publish \
  --content-types blog article \
  --environments prod \
  --locales en-us \
  --stack-api-key bltXXX \
  --alias myalias

csdx cm:stacks:bulk-entries --operation unpublish \
  --content-types blog \
  --environments prod \
  --locales en-us \
  --stack-api-key bltXXX \
  --alias myalias

csdx cm:stacks:bulk-entries --revert ./log.json \
  --stack-api-key bltXXX \
  --alias myalias

Cross-Publish Migration (cm:bulk-publish:cross-publish to --source-alias)

Before: V1 accepts an inline --delivery-token flag.

After: V2 requires a stored delivery token alias. Complete this one-time setup:

  1. Store the delivery token as an alias.
  2. Use the alias in cm:stacks:bulk-entries.
csdx auth:tokens:add \
  -a staging-delivery \
  --delivery \
  --token bltABC \
  --stack-api-key blt123 \
  --environment staging

csdx cm:stacks:bulk-entries \
  --operation publish \
  --source-env staging \
  --source-alias staging-delivery \
  --content-types blog article \
  --environments prod \
  --locales en-us \
  -k blt123

--api-version Flag Removed

V2 hardcodes api_version: '3.2' on every publish and unpublish call. V2 removes the --api-version flag. Passing it fails immediately:

ERROR: Nonexistent flag: --api-version

Fix: Remove --api-version from all bulk publish scripts.

cm:stacks:bulk-assets

Replaces (all removed in V2): cm:assets:publish, cm:assets:unpublish, cm:stacks:publish (assets), cm:stacks:unpublish (assets)

V1 to V2 Command Mapping

V1 Command (REMOVED)V2 Replacement
csdx cm:assets:publishcsdx cm:stacks:bulk-assets --operation publish
csdx cm:assets:unpublishcsdx cm:stacks:bulk-assets --operation unpublish
csdx cm:stacks:bulk-assets --operation publish \
  --environments prod \
  --locales en-us \
  --stack-api-key bltXXX \
  --alias myalias

New: CS Assets Bulk Delete and Move

No prior equivalent in V1. V2 adds two new operation types to cm:stacks:bulk-assets that target the CS Assets API, separate from the CMS publish pipeline:

OperationWhat it does
--operation deleteBulk delete assets from a CS Assets space (async job)
--operation moveBulk move assets to a target folder in a CS Assets space

CS Assets bulk delete:

csdx cm:stacks:bulk-assets \
  --operation delete \
  --space-uid am123 \
  --org-uid bltOrg \
  --locale en-us \
  --asset-uids-file ./assets.json

assets.json contains { "uids": ["uid1", "uid2"] }.

CS Assets bulk move:

csdx cm:stacks:bulk-assets \
  --operation move \
  --space-uid am123 \
  --org-uid bltOrg \
  --target-folder-uid amFolder \
  --asset-uids-file ./assets.json

Requirements:

  • Configure csAssetsUrl in region settings first:

    csdx config:set:region --cs-assets <url>
  • Do not combine CMS flags (--stack-api-key, --alias, --environments, --locales, --branch) with CS Assets flags.

Operation--locale
deleteRequired
moveNot accepted

Where to find --space-uid and --org-uid:

  1. In the Contentstack UI, go to Organization > Contentstack Assets > Settings.
  2. Note the Space UID and Organization UID shown there.

V2 hardcodes api_version: '3.2' on all calls (same as bulk-entries). V1 never had an --api-version flag on this command.

cm:stacks:bulk-taxonomies

V1 already has cm:stacks:bulk-taxonomies for bulk publishing or unpublishing taxonomy terms, with an --api-version flag. V2 removes --api-version and hardcodes api_version: '3.2' on all calls.

FlagShort FlagTypeRequiredDefaultDescription
--operation-stringNo. Prompted if omitted-publish or unpublish
--stack-api-key-kstringNo. Prompted if --alias is not used-Stack API key
--alias-astringNo. Prompted if --stack-api-key is not used-Management token alias
--environments-string[]No. Prompted if omitted-Target environments (multiple allowed)
--locales-string[]No. Prompted if omitted-Target locales (multiple allowed)
--taxonomies-stringNo. Acts on every taxonomy in the stack if omitted-Comma-separated taxonomy UIDs. Omit to target all taxonomies.
--branch-stringNomainBranch (defaults to main)
--yes-ybooleanNofalseSkip confirmation prompt

Publish specific taxonomies:

csdx cm:stacks:bulk-taxonomies \
  --operation publish \
  --environments staging prod \
  --locales en-us fr-fr \
  --taxonomies products_tax,brands_tax \
  --stack-api-key bltXXX \
  --alias myalias

Publish all taxonomies:

csdx cm:stacks:bulk-taxonomies \
  --operation publish \
  --environments prod \
  --locales en-us \
  --stack-api-key bltXXX \
  --alias myalias

cm:stacks:seed

Removed Flags

The cm:seed alias is removed, so use the full command name (see Command Aliases Removed). Every flag rename and removed short character for this command is listed in Type Mapping Reference.

Before:

csdx cm:seed -s blt123 -r contentstack/kickstart-stack-seed -o orgUid

After:

csdx cm:stacks:seed --stack-api-key blt123 --repo contentstack/kickstart-stack-seed

Behavior Change: Curated List Replaces GitHub API in Interactive Mode

Before: running csdx cm:stacks:seed without --repo in V1 queries the GitHub API for all Contentstack repos.

After: V2 shows a fixed curated list of 3 repos:

  1. Kickstart stack seed (contentstack/kickstart-stack-seed)
  2. Kickstart Veda (contentstack/kickstart-veda-seed)
  3. Compass starter stack (contentstack/compass-starter-stack)

Note V2 removes contentstack/stack-starter-app from the curated list. If you need it, pass it directly with --repo contentstack/stack-starter-app.

If you need a repo that is not on this list, use --repo owner/repo directly.

cm:bootstrap

Removed Flags

--appName and --directory are renamed, and both renames are listed in Type Mapping Reference. One further flag is removed outright:

RemovedV2 Replacement
--appType / -s(removed, no replacement needed, V2 hardcodes app type internally)

Note V1 has a short flag collision, both --appName and --alias claim -a. V2 resolves this: --app-name has no short character, and -a exclusively means --alias. Any script that used -a for app name must switch to --app-name (long form only).

Before:

csdx cm:bootstrap --appName reactjs --directory ./myapp --appType sampleapp

After:

csdx cm:bootstrap --app-name compass-app --project-dir ./myapp

13 App Configs Removed

V2 no longer accepts the following --app-name values. Passing any of them throws CLI_BOOTSTRAP_INVALID_APP_NAME.

Removed sample apps (4), were in the sampleApps interactive list:

--app-nameGitHub SourceStack Seed
reactjscontentstack/contentstack-reactjs-universal-sample-appcontentstack/stack-contentstack-reactjs-universal-sample-app
nextjscontentstack/contentstack-nextjs-react-universal-democontentstack/stack-contentstack-nextjs-react-universal-demo
gatsbycontentstack/gatsby-starter-contentstackcontentstack/stack-gatsby-starter-contentstack
angularcontentstack/contentstack-angular-modularblock-examplecontentstack/stack-contentstack-angular-modularblock-example

Removed starter apps (8), were in the starterApps interactive list:

--app-nameGitHub SourceStack Seed
reactjs-startercontentstack/contentstack-react-starter-appcontentstack/stack-starter-app
nextjs-startercontentstack/contentstack-nextjs-starter-appcontentstack/stack-starter-app
gatsby-startercontentstack/contentstack-gatsby-starter-appcontentstack/stack-starter-app
angular-startercontentstack/contentstack-angular-startercontentstack/stack-starter-app
nuxt-startercontentstack/contentstack-nuxtjs-starter-appcontentstack/stack-starter-app
vue-startercontentstack/contentstack-vuejs-starter-appcontentstack/stack-starter-app
stencil-startercontentstack/contentstack-stencil-starter-appcontentstack/stack-starter-app
nuxt3-startercontentstack/contentstack-nuxt3-starter-appcontentstack/stack-starter-app

Removed hidden config entry (1), never shown interactively, passable through --app-name:

--app-nameGitHub Source
nuxtjs-disabledcontentstack/contentstack-nuxtjs-vue-universal-demo

Valid App Names in V2 (8)

These apps existed in V1's starterApps list and carry over to V2 unchanged. Display names ending in SSR or SSG name the app's rendering strategy, server-side rendering (SSR) or static site generation (SSG):

--app-nameDisplay NameGitHub SourceStack Seed
compass-appCompass Appcontentstack/compass-starter-appcontentstack/compass-starter-stack
kickstart-nextKickstart Next.jscontentstack/kickstart-nextcontentstack/kickstart-stack-seed
kickstart-next-ssrKickstart Next.js SSRcontentstack/kickstart-next-ssrcontentstack/kickstart-stack-seed
kickstart-next-ssgKickstart Next.js SSGcontentstack/kickstart-next-ssgcontentstack/kickstart-stack-seed
kickstart-next-graphqlKickstart Next.js GraphQLcontentstack/kickstart-next-graphqlcontentstack/kickstart-stack-seed
kickstart-next-middlewareKickstart Next.js Middlewarecontentstack/kickstart-next-middlewarecontentstack/kickstart-stack-seed
kickstart-nuxtKickstart NuxtJScontentstack/kickstart-nuxtcontentstack/kickstart-stack-seed
kickstart-nuxt-ssrKickstart NuxtJS SSRcontentstack/kickstart-nuxt-ssrcontentstack/kickstart-stack-seed

cm:stacks:audit

Removed Flags

V2 strips the short aliases from both commands. See Command Aliases Removed for the full alias list.

Before:

csdx audit
csdx audit:fix

After:

csdx cm:stacks:audit
csdx cm:stacks:audit:fix

Behavior Change: Audit Reads Per-UID Files, So V1 Exports Produce Empty Results

cm:stacks:audit now uses readContentTypeSchemas and readGlobalFieldSchemas (the same utilities V2 import uses) to load content type and global field schemas from the --report-path directory. These utilities read individual <uid>.json files and explicitly ignore schema.json and globalfields.json.

Running audit against a V1 export directory has the same per-module impact as V2 import:

ModuleV1 export writesImpact on audit
Content typesIndividual <uid>.json filesNo impact, content types load correctly
Global fieldsglobalfields.json only (no individual files)False clean, audit returns zero results

Migration: Re-export global fields with V2 before auditing. Do not run cm:stacks:audit:fix on a V1 export, because it removes Global field fields from your content types. If you cannot re-export, audit the V1 export with CLI V1.

See Audit with CLI V2 Reports No Global Field Issues in a CLI V1 Export in the CLI troubleshooting FAQs. Symptom: audit reports zero global-field issues even when the export contains actual issues.

cm:stacks:migration

Removed Flags

RemovedV2 Replacement
-B--branch
-A--alias
-n--file-path
--api-key--stack-api-key
--authtoken(removed, use csdx auth:login then --alias)
--management-token-alias--alias
--filePath--file-path
--multi--multiple

Before:

csdx cm:migration -B feature-branch -n ./migrate.js

After:

csdx cm:stacks:migration --branch feature-branch --file-path ./migrate.js

Taxonomy Migration Script Removed

V2 deprecates taxonomy migration through cm:stacks:migration and does not include the sample import-taxonomies.js script. The Taxonomy Migration steps work with V1 only. In V2, use cm:stacks:export and cm:stacks:import to migrate taxonomies between stacks.

cm:stacks:validate-regex

Removed Flags

Every removed short character for this command is listed in Type Mapping Reference. The long-form flag names are unchanged.

Before:

csdx cm:stacks:validate-regex -c -g -f ./output

After:

csdx cm:stacks:validate-regex --contentType --globalField --filePath ./output

Output Format

The results table and results.csv file use the same column order in both V1 and V2: Module, Title, UID, Invalid Regex Count. If you parse CSV output by header name, you need no changes.

auth:tokens

In V2, auth:tokens no longer lists tokens directly. It becomes a help dispatcher for its sub-commands.

Before: csdx auth:tokens lists your tokens in V1.

csdx auth:tokens

After: V2 displays sub-command help instead. Use csdx auth:tokens:list to list tokens.

csdx auth:tokens:list

Silent failure risk:

  • V1: csdx auth:tokens prints a token table to stdout.
  • V2: csdx auth:tokens prints help text to stdout instead, with no error code. A script that parses this output for a token table silently receives help text instead.

Short alias removed:

  • V1: csdx tokens is a short alias for csdx auth:tokens.
  • V2: removes the alias. csdx tokens fails with "command not found".

auth:tokens:add

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference. Three of them were hidden flags in V1: --api-key is replaced by --stack-api-key, -f / --force becomes -y / --yes, and --branch is removed entirely with no replacement.

Before:

csdx auth:tokens:add -a myalias -d -t bltABC -k blt123

After:

csdx auth:tokens:add -a myalias --delivery --token bltABC --stack-api-key blt123

auth:tokens:remove

Removed Flags

-i / --ignore is removed, as listed in Type Mapping Reference.

Before: in V1, -i / --ignore makes the command succeed silently even if the alias does not exist.

csdx auth:tokens:remove -a myalias -i

After: V2 removes the flag entirely.

  • V1 (without -i): if the alias does not exist, the command exits non-zero.
  • V1 (with -i): the command always exits 0, even if the alias does not exist.
  • V2: always behaves like V1's -i case. If the alias does not exist, it prints a yellow warning and exits 0, regardless of any flag.
csdx auth:tokens:remove -a myalias

V2 prints No token found with alias 'myalias'. (yellow) and exits 0. Scripts that relied on a non-zero exit when the alias was missing (V1's no-flag default) must account for this change.

auth:logout

Removed Flags

-f / --force (a hidden flag in V1) is removed, as listed in Type Mapping Reference.

Before:

csdx auth:logout -f
csdx auth:logout --force

After: V2 returns an "Unexpected argument" error for both forms above. Use:

csdx auth:logout -y
csdx auth:logout --yes

config:set:region

Removed Flags

Every removed short character for this command is listed in Type Mapping Reference. The long-form flag names are unchanged.

Before:

csdx config:set:region -d https://cdn.example.com -m https://api.example.com --ui-host https://app.example.com -n MyRegion

After:

csdx config:set:region --cda https://cdn.example.com --cma https://api.example.com --ui-host https://app.example.com --name MyRegion

New: --cs-assets Flag

No prior equivalent in V1. V2 adds a --cs-assets flag for specifying the Contentstack Assets API URL when you configure a custom region:

csdx config:set:region \
  --cma https://custom.cma.example.com \
  --cda https://custom.cda.example.com \
  --ui-host https://custom.ui.example.com \
  --name MyRegion \
  --cs-assets https://custom.am-api.example.com

When you omit --cs-assets, V2 derives the CS Assets URL from the Content Management API (CMA) URL automatically.

config:get:region now also shows Contentstack Assets URL in its output.

config:set:log

V2 stores the console log preference under a different config key, so your V1 setting does not carry over. V1 stores it as log["show-console-logs"] (hyphenated). V2 stores it as log["showConsoleLogs"] (camelCase). The two formats are not compatible.

After you upgrade, V2 silently ignores your V1 console log configuration. Progress bars are the default. If your CI needs console log output, re-run:

csdx config:set:log --show-console-logs

To explicitly switch back to progress bars (the V2 default):

csdx config:set:log --no-show-console-logs

See Console Log Setting from CLI V1 Has No Effect After Upgrading to CLI V2 in the CLI troubleshooting FAQs. Symptom: info and success log lines no longer appear in the console, even though you configured console logs under V1.

config:set:early-access-header

Documentation fix, no behavioral change.

V1 has the --header and --header-alias descriptions swapped:

FlagV1 description (incorrect)V2 description (correct)
--header-alias"Provide the Early Access header value""Provide a name (alias) for this Early Access header"
--header"Provide the Early Access header alias name""Provide the Early Access header value"

The actual behavior was always: --header-alias sets the alias name, --header sets the header value. If you followed V1's incorrect help text and passed values in the wrong order, correct your scripts:

csdx config:set:early-access-header --header-alias myheader --header x-header-value

tsgen

tsgen generates TypeScript interfaces from your stack's content type schemas, authenticated with a delivery token alias. Use the generated types to annotate content model access in a TypeScript client, whether that client uses the Contentstack Delivery SDK or a plain HTTP request. See the tsgen plugin docs for full usage.

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference.

-a (short for alias) is kept, on the renamed --alias flag.

Before:

csdx tsgen --token-alias myalias -o ./types -p CS_ -d

After:

csdx tsgen --alias myalias --output ./types --prefix CS_ --doc

Or use -a for alias:

csdx tsgen -a myalias --output ./types --prefix CS_ --doc

app:create

Removed Flags

-n is removed. Use --name (long form only). See Type Mapping Reference.

Before:

csdx app:create -n my-app

After:

csdx app:create --name my-app

migrate:convert

Removed Flags

Every removed short character for this command is listed in Type Mapping Reference. The long-form flag names are unchanged.

Before:

csdx migrate:convert -o ./output -m en-us -a v2_

After:

csdx migrate:convert --output ./output --master-locale en-us --affix v2_

migrate:export

Removed Flags

-o is removed. Use --output (long form only). See Type Mapping Reference.

Before:

csdx migrate:export -o ./output

After:

csdx migrate:export --output ./output

content-type:audit

Note the content-type:* commands belong to a separate plugin (contentstack-cli-content-type) that inspects and compares content type schemas. They differ from cm:stacks:* commands: they do not export or import content, they analyze schema structure. The flag changes below apply to every command in this namespace.

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference.

Before:

csdx content-type:audit --stack blt123 --token-alias myalias -c blog

After:

csdx content-type:audit --alias myalias --content-type blog

content-type:compare

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference.

Before:

csdx content-type:compare --stack blt123 --token-alias myalias -c blog -l v1 -r v2

After:

csdx content-type:compare --alias myalias --content-type blog --left v1 --right v2

content-type:compare-remote

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference.

Note: content-type:compare-remote never has --stack / --token-alias flags in V1.

Before:

csdx content-type:compare-remote -o bltOrigin -r bltRemote -c blog

After:

csdx content-type:compare-remote --origin-stack bltOrigin --remote-stack bltRemote --content-type blog

content-type:details

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference.

Before:

csdx content-type:details --stack blt123 --token-alias myalias -c blog -p

After:

csdx content-type:details --alias myalias --content-type blog --path

content-type:diagram

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference.

Before:

csdx content-type:diagram --stack blt123 --token-alias myalias -o ./diagram.svg -d landscape -t svg

After:

csdx content-type:diagram --alias myalias --output ./diagram.svg --direction landscape --type svg

content-type:list

Removed Flags

Every flag rename and removed short character for this command is listed in Type Mapping Reference.

Before:

csdx content-type:list --stack blt123 --token-alias myalias -o title

After:

csdx content-type:list --alias myalias --order title

CS Assets (Asset Management 2.0)

No prior equivalent in V1. V2 adds support for Contentstack's CS Assets system (Asset Management 2.0, or AM 2.0) in export, import, and import-setup, each of which detects and handles CS Assets automatically if your stack has linked workspaces.

Bulk operations support: delete and move only. CS Assets has no bulk publish or unpublish support.

Export: if your stack has linked workspaces configured in Contentstack Assets settings, export writes CS Assets data to a spaces/ directory alongside the standard assets/ directory. If your stack has no linked workspaces, export falls back to standard asset export automatically:

export/
  assets/         (CMS assets, unchanged)
  spaces/         (new: CS Assets)
    <space-id>/workspaces/
    <space-id>/asset_types/
    <space-id>/assets/
    <space-id>/folders/

Import: V2 detects the spaces/ directory and imports CS Assets automatically.

Import-setup: V2 detects CS Assets exports and generates identity UID and URL mapper files.

New bulk operations: cm:stacks:bulk-assets --operation delete and --operation move handle CS Assets (see the new flags --space-uid, --org-uid, --workspace, --asset-uids-file, --target-folder-uid in cm:stacks:bulk-assets).

Taxonomy Publishing

V2 adds taxonomy publishing support across export, import, and bulk operations.

Before: V1 export does not capture taxonomy publish details. V1 import does not re-publish taxonomies.

After:

  • Export captures publish_details per locale for each taxonomy.
  • Import re-publishes taxonomies after import by default. To skip publishing (for example, if you want to review taxonomies before publishing):
    csdx cm:stacks:import --skip-taxonomy-publish -d ./export -k bltXXX
  • cm:stacks:bulk-taxonomies handles bulk taxonomy publish operations (see cm:stacks:bulk-taxonomies).

Pre-Upgrade Checklist

This checklist orders items by risk. Complete top sections before lower ones.

Critical: Do These First

  1. Test the entire upgrade in a non-production environment before touching production.
  2. Your saved tokens carry over automatically. Management tokens stored with csdx auth:tokens:add are available immediately after upgrading. You need no re-authentication. (Tokens and Config Carry Over Automatically)

High-Risk Script Changes

  1. Add an explicit --branch flag to all cm:stacks:export calls for non-main branches. V2 only exports main when you omit --branch. (cm:stacks:export, Branch Export Silently Overwrites Another Branch's Data)
  2. Use a separate --data-dir per branch. V2 output is always flat (no <branch-uid>/ subfolder), so exporting two branches to the same directory overwrites the first, with only a warning. (Branch Export Silently Overwrites Another Branch's Data)
  3. Rewrite all cm:entries:publish*, cm:assets:publish*, cm:bulk-publish:*, cm:stacks:publish, cm:stacks:unpublish calls to cm:stacks:bulk-entries / cm:stacks:bulk-assets commands. (cm:stacks:bulk-entries, cm:stacks:bulk-assets)
  4. Verify publish behavior in a staging stack. All bulk publish and unpublish calls now use api_version: '3.2', and V2 removes the --api-version flag. (All Publish Operations Now Use NRP)
  5. Remove checks for export-info.json or content_types/schema.json in post-export tooling. V2 does not write these files. (cm:stacks:export)
  6. Update tooling that reads global_fields/globalfields.json to iterate per-UID JSON files instead. (Global Fields Format Changed (Per-File))
  7. Replace any cm:stacks:migration call that runs the sample import-taxonomies.js script. V2 does not include the script. (cm:stacks:migration)

CI and Pipeline Audit

  1. Verify your CI does not parse stdout for success signals. The output format changed to progress bars by default. (Default Output: Progress Bars Replace Console Logs)
  2. Run csdx config:set:log --show-console-logs after upgrading if your CI parses console output. V2 silently drops the V1 log setting. (V1 Console Log Config Silently Ignored After Upgrade)

Script Audit: Command Renames

  1. Replace csdx cm:export with csdx cm:stacks:export. (Command Aliases Removed)
  2. Replace csdx cm:import with csdx cm:stacks:import. (Command Aliases Removed)
  3. Replace csdx cm:import-setup with csdx cm:stacks:import-setup. (Command Aliases Removed)
  4. Replace csdx cm:seed with csdx cm:stacks:seed. (Command Aliases Removed)
  5. Replace csdx tokens with csdx auth:tokens:list. (Command Aliases Removed)
  6. Replace csdx auth:tokens (when used to list tokens) with csdx auth:tokens:list. (auth:tokens)
  7. Replace csdx audit with csdx cm:stacks:audit. (Command Aliases Removed)

Script Audit: Flag Changes

  1. Remove --stack-uid / -s everywhere and use --stack-api-key instead. (Type Mapping Reference)
  2. Remove --data and use --data-dir instead. (Type Mapping Reference)
  3. Remove --management-token-alias and use --alias instead. (Type Mapping Reference)
  4. Remove --auth-token / -A and use csdx auth:login then --alias instead. (Type Mapping Reference)
  5. Remove --skip-app-recreation from all import scripts. V2 has no replacement. (cm:stacks:import)
  6. Remove --token-alias on tsgen and use --alias instead. (tsgen)
  7. Audit scripts for removed short flags on export and import commands: -m / -t / -B / -b / -A (switch to long form only). (cm:stacks:export, cm:stacks:import)
  8. Update cm:bootstrap flags: --appName to --app-name, --directory to --project-dir. (cm:bootstrap)
  9. Remove bootstrap app names that no longer exist: reactjs, nextjs, gatsby, angular, and the *-starter variants. (cm:bootstrap)
  10. Update content-type:* commands: remove --stack / -s, --token-alias / -a, and every listed short character. (content-type:audit)
  11. Replace csdx auth:logout -f / --force with csdx auth:logout -y / --yes. (auth:logout)

Plugin Management

  1. Install the launch plugin separately if you use launch:* commands: csdx plugins:install @contentstack/cli-launch. (launch Plugin: Now Opt-In)
  2. Install the migrate-rte plugin separately if you use cm:entries:migrate-html-rte: csdx plugins:install @contentstack/cli-cm-migrate-rte. (migrate-rte Plugin: Now Opt-In)
  3. If you use CS Assets, verify your stack has linked workspaces configured in Contentstack Assets settings. Otherwise export falls back to standard asset export. (CS Assets (Asset Management 2.0))

Custom Plugins (Plugin Authors Only)

  1. Update engines.node to >=22.0.0 in your plugin's package.json. (Node.js 22+)
  2. Update @oclif/core from ^3.0.0 to ^4.11.14.
  3. Add @contentstack/cli-command and @contentstack/cli-utilities at ~2.0.0 to your dependencies. Import Command from @contentstack/cli-command, and flags and Args from @contentstack/cli-utilities, so your plugin needs no direct dependency on @oclif/core.
  4. Point oclif.commands at ./lib/commands, the compiled JavaScript output, rather than ./src/commands. A build step is now required before linking or installing, and pointing at TypeScript source makes command discovery fail.
  5. Rewrite your tests if you use @oclif/test. Version 4 removed the chained test.stdout().command().it() API entirely and now exports only runCommand, captureOutput and runHook. The old API throws TypeError: Cannot read properties of undefined.

For the full authoring workflow, see Create Custom CLI Plugins for Contentstack.

Test Run

  1. Run a full export and import cycle on a non-production stack before cutting over.
  2. Verify branch exports capture the correct branches explicitly.
  3. If you use CS Assets, verify your stack has linked workspaces configured. Otherwise export falls back to standard asset export automatically, with no error.
  4. If you use bulk publish or unpublish, run a test publish in staging. All calls now use api_version: '3.2'.

Next Steps