sb-mig
Reference

Inspection Commands

Read-only commands for understanding Storyblok state before migration.

Inspection commands

These commands are read-only against Storyblok. They exist to make migration state inspectable before you run write commands.

inspect component-usage

Beta: Needle in a haystack

sb-mig inspect component-usage \
  --from 12345 \
  --all \
  --query flex-group-width-child

inspect component-usage scans selected Storyblok stories with a local query file. Use it when you need to find rare component patterns, such as a specific component with a child component that has a particular field.

The command is read-only against Storyblok. It does not support --dry-run because it never writes to Storyblok. It writes a local JSON report only when --outputPath is passed.

Query files

Query files are normal JavaScript modules. The first implementation supports:

*.sb.query.js
*.sb.query.cjs
*.sb.query.mjs

TypeScript query files are planned, but not supported by this command yet.

The query file must default-export an object with a name and a match function:

export default {
  name: "flex-group-width-child",

  match(node, context) {
    if (node.component !== "flex-group") {
      return null;
    }

    return {
      story: context.story.full_slug,
      path: context.path,
    };
  },
};

match(node, context) is called for every Storyblok component node found under story.content.

Return valueMeaning
null or undefinedNo match.
trueMatch with no extra details.
objectMatch with details stored in the JSON report.

The context object contains:

FieldMeaning
context.storyStory metadata such as id, name, slug, and full_slug.
context.pathComponent path, for example content.body[0].
context.parentParent component object when there is one.
context.ancestorsAncestor component objects.

When --query is a name, sb-mig searches configured local component directories, such as src and storyblok, for a matching query file:

sb-mig inspect component-usage \
  --from 12345 \
  --all \
  --query flex-group-width-child

When --query is a path, sb-mig loads that file directly:

sb-mig inspect component-usage \
  --from 12345 \
  --startsWith landing-pages \
  --query ./queries/flex-group-width-child.sb.query.js

Example: flex group with width child

Create a file such as:

src/storyblok-queries/flex-group-width-child.sb.query.js
const hasValue = (value) =>
  value !== undefined && value !== null && value !== "";

const directArrayChildren = (node) =>
  Object.values(node)
    .filter(Array.isArray)
    .flat()
    .filter((item) => item && typeof item === "object" && item.component);

export default {
  name: "flex-group-width-child",
  description:
    "Find flex groups with vertical or reverse direction and children with width.",

  match(node) {
    if (node.component !== "flex-group") {
      return null;
    }

    if (!["vertical", "reverse"].includes(node.direction)) {
      return null;
    }

    const childrenWithWidth = directArrayChildren(node).filter((child) =>
      hasValue(child.width),
    );

    if (childrenWithWidth.length === 0) {
      return null;
    }

    return {
      childMatches: childrenWithWidth.length,
      matchingChildUids: childrenWithWidth.map((child) => child._uid),
    };
  },
};

Run it by query name:

sb-mig inspect component-usage \
  --from 12345 \
  --all \
  --query flex-group-width-child

Or run it by path and write the full report:

sb-mig inspect component-usage \
  --from 12345 \
  --startsWith landing-pages \
  --query ./src/storyblok-queries/flex-group-width-child.sb.query.js \
  --outputPath sbmig/usage/flex-group-width-child.json

Selectors

Pass exactly one selector:

SelectorTypeEffect
--allbooleanInspect all non-folder stories.
--withSlugrepeatable stringInspect exact story full_slug values.
--startsWithstringInspect stories whose full_slug starts with the prefix.

Options

FlagTypeDefaultEffect
--fromstringconfigured spaceIdSource space ID to inspect. Pass it explicitly for repeatable reports.
--querystringnoneQuery file name or direct path. Required.
--outputPathstringnoneWrite the JSON report to this path.

Output

The command prints a summary:

Component usage inspection
Space: 12345
Query: flex-group-width-child
Stories scanned: 1240
Stories matched: 37
Total matches: 52
Matches by story:
- home: 2
- campaign/summer: 1

When --outputPath is passed, the JSON report includes:

queryName
spaceId
generatedAt
filters
totals.storiesScanned
totals.storiesMatched
totals.matches
matches[]

Each match includes story identifiers, component name, _uid, path, optional parent component metadata, and any details returned from the query.

Invalid combinations

CombinationResult
Missing --queryRejected.
Missing --all, --withSlug, and --startsWithRejected.
More than one selector familyRejected.
--dry-runNot supported. The command is already read-only.

Use this command for inspection and audit work. Do not use it to migrate, publish, update, or delete Storyblok content.

language-publish-state

sb-mig language-publish-state --from 12345

Reads source stories and writes a JSON map of publication state by story and language.

Options

FlagTypeDefaultEffect
--fromstringnoneSource space ID. Required.
--accessTokenstringconfigured access tokenDelivery API token override for translated language checks.
--languagesstringallall, default, or comma-separated language codes such as default,fr,de.
--withSlugrepeatable stringnoneInspect exact story full_slug values.
--startsWithstringnoneInspect stories whose full_slug starts with the prefix.
--fileNamestringderived nameStable output base name under sbmig/language-publish-state.
--outputPathstringdefault folderExplicit output path for the generated JSON file.

Examples

sb-mig language-publish-state \
  --from 12345 \
  --startsWith about/ \
  --languages all \
  --fileName about-prod

sb-mig language-publish-state \
  --from 12345 \
  --accessToken xxx \
  --withSlug about/testimonials \
  --languages default,fr

Default-language state comes from the Management API. Translated language state uses Delivery API published and draft comparisons, so a Delivery API token is required when translated languages are requested and no configured token exists.

published-layer-export

sb-mig published-layer-export --from 12345 --startsWith about/

Exports selected draft/current stories, latest published Story Versions API content, and a comparison summary.

Selectors

Pass one selector family for clarity:

SelectorTypeEffect
--allbooleanExport all non-folder stories.
--storyIdrepeatable stringExport exact story IDs.
--withSlugrepeatable stringExport exact story full_slug values.
--startsWithstringExport non-folder stories under a prefix.

If multiple selector families are passed, implementation priority is --storyId, then --withSlug, then --startsWith, then --all.

Options

FlagTypeDefaultEffect
--fromstringnoneSource space ID. Required.
--fileNamestringderived from selectorStable output base name.
--outputPathstringsbmig/published-layer-exportOutput directory.
--versionsPerPagenumber25Story versions per page.
--maxVersionPagesnumber4Maximum story version pages to inspect per story.

Output files

<name>---draft-current-full.json
<name>---published-layer-full.json
<name>---dual-layer-summary.json

Examples

sb-mig published-layer-export \
  --from 12345 \
  --withSlug about/contact \
  --fileName contact-layer-check

sb-mig published-layer-export \
  --from 12345 \
  --storyId 178888427520390

sb-mig published-layer-export \
  --from 12345 \
  --startsWith about/ \
  --versionsPerPage 50 \
  --maxVersionPages 8

story-versions

sb-mig story-versions --from 12345 --storyId 98765
sb-mig story-versions --from 12345 --withSlug about/contact

Reads Management API story_versions for one story.

Selectors

SelectorTypeEffect
--storyIdstringInspect one story ID. Required unless --withSlug is passed.
--withSlugstringResolve one full_slug to a story ID. Required unless --storyId is passed.

Options

FlagTypeDefaultEffect
--fromstringnoneSource space ID. Required.
--showContentbooleantrueAsk Storyblok to include version content.
--pagenumber1Versions page.
--perPagenumber25Versions per page.
--rawbooleanfalsePrint the raw Storyblok API response instead of compact summary.
--outputPathstringnoneWrite JSON output to this file instead of stdout.

Examples

sb-mig story-versions --from 12345 --storyId 98765

sb-mig story-versions \
  --from 12345 \
  --withSlug tours/europe \
  --raw \
  --outputPath sbmig/story-versions/tours-europe.raw.json

When slug resolution fails, the command searches close Storyblok slugs and prints possible matches.

On this page