CLI — Client
The client CLI talks to a running StoryShelf server over /api/v1 and carries no Playwright or server dependencies. Run it with your package manager’s runner:
npx storyshelf --helppnpx storyshelf --helpyarn dlx storyshelf --helpPackage reference: For install and programmatic use see @storyshelf/cli.
storyshelf init
Section titled “storyshelf init”Initialize the current Storybook with .storybook/storyshelf.json (client config). Fails if .storybook/main.* is not found.
storyshelf init --url http://localhost:3000 --slug my-design-system --build-dir storybook-static# or with prompts:storyshelf init# ? Server URL? http://localhost:3000 (detected React-Vite • 1 addons)# ? Project slug? my-design-system# also: --build-dir, --build-command, --build-script-name, --skip, -c/--configWrites .storybook/storyshelf.json: { "slug": "...", "url": "...", "buildDir": "...", "skip": "..." } (no token, see Configuration). Token stays in STORYSHELF_TOKEN env / --token.
storyshelf create
Section titled “storyshelf create”Create a project on the server (requires site-admin token) and write .storybook/storyshelf.json.
storyshelf create --url http://localhost:3000 --name "My Design System" --token $STORYSHELF_ADMIN_TOKEN# also reads STORYSHELF_ADMIN_TOKEN / ADMIN_TOKEN env if --token omittedPrints Project slug: ... and CI token: ....
storyshelf build
Section titled “storyshelf build”Build the Storybook output without uploading — same buildDir/buildCommand resolution as upload, but no server contact.
storyshelf buildstoryshelf build --force-buildstoryshelf build --build-dir dist-storybook --build-command "nx run app:build-storybook"Prints Build ready: <dir> and fails fast when the output lacks index.json.
storyshelf upload
Section titled “storyshelf upload”Build (optionally), zip, and upload a Storybook build for capture.
# explicit flagsstoryshelf upload \ --url http://localhost:3000 \ --slug my-design-system \ --token shelf_xxx \ --sha "$GITHUB_SHA" \ --branch "$GITHUB_REF_NAME"
# with .storybook/storyshelf.json present (no args defaults to upload)storyshelfstoryshelf upload --token shelf_xxx --sha $GITHUB_SHA --branch main| Flag | Description |
|---|---|
--url | Server URL (or file / STORYSHELF_URL) |
--slug | Project slug (or file / STORYSHELF_SLUG) |
--token | Project API token (Authorization: Bearer, or STORYSHELF_TOKEN) |
--sha | Revision SHA (flag, CI env, local git HEAD, or synthesized local-*) |
--branch | Baseline namespace (flag, CI env, local git branch, or local) |
--build-dir / -d | Built Storybook directory (default storybook-static) |
--config / -c | Config file path (default .storybook/storyshelf.json) |
--build-command | Custom build command (mutually exclusive with --build-script-name) |
--build-script-name / -b | npm script to build (default build-storybook) |
--force-build | Force rebuild even if buildDir exists |
--skip | Glob to skip upload (e.g. "main") |
--message | Build message |
--author-name, --author-email | Author attribution |
--label key=value | Attach a build label (repeatable) |
--full | Disable affected capture for this upload (render every story) |
--untraced <glob> | Exclude matching files from affected tracing (repeatable, e.g. "**/*.generated.ts"; unions with untraced in config) |
--stats-file <path> | Bundler stats file (default <buildDir>/preview-stats.json) |
--dry-run | Validate/build but send no requests |
Affected capture is on by default: the CLI traces git diff baseline..HEAD through the build’s dependency graph, posts the affected set, and prints a summary (Affected capture: rendering 3 stories (baseline abc1234)). Anything it cannot prove unchanged renders anyway — see Affected capture. STORYSHELF_FULL=1 and "affectedOnly": false opt out the same way as --full.
Servers without testing. An instance that hosts Storybooks only reports testing: false when the build is created. storyshelf upload then skips the affected-capture computation, uploads as usual, and ends with Testing is off on this server: the Storybook is published, but no captures or visual checks will run.
Large Storybooks on hosts without a job consumer. A zip over the server’s maxInlineUnzipSize is normally published by a background job. A serverless host runs no consumer, so it answers 413 with a message pointing to the file-by-file route (/dedup, /content, /manifest). storyshelf upload handles that by itself: it prints Zip is over the server's inline publish limit; uploading file by file instead, hashes the build directory, uploads only the files the server lacks, and posts the manifest, which completes publishing. A 413 for maxUploadBytes is not retried this way; raise the limit instead.
storyshelf doctor / whoami
Section titled “storyshelf doctor / whoami”storyshelf doctor# ✓ Storybook setup found# ✓ Config loaded (slug "my-design-system")# ✓ Connection: http://localhost:3000 / my-design-system (token present)# ✓ Server reachable# ! Build output missing — upload would run: npm run build-storybook -- --output-dir storybook-static# ✓ Affected capture ready (history and stats available)
storyshelf whoami# Server: http://localhost:3000# Project: My Design System (my-design-system)storyshelf retry / purge
Section titled “storyshelf retry / purge”storyshelf retry --url http://localhost:3000 --slug my-design-system --build-id <id> [--token $STORYSHELF_TOKEN]storyshelf purge --url http://localhost:3000 --token $STORYSHELF_ADMIN_TOKENretry re-runs capture without a new revision. purge triggers retention GC (normally scheduled).
storyshelf protect
Section titled “storyshelf protect”Print, validate and (only with --apply) write the branch rule that makes StoryShelf gate merges. It talks to GitHub or GitLab directly with an admin token; it does not contact your StoryShelf server.
storyshelf protect --provider github --repo acme/widgets [--branch main] [--prefix storyshelf] [--gate testing|review] [--token $GITHUB_TOKEN] [--apply]storyshelf protect --provider gitlab --repo group/project [--host https://gitlab.example.com] [--token $GITLAB_TOKEN] [--apply]It always prints the required check names (<prefix>/testing, or <prefix>/review with --gate review) and the manual steps. With a token (--token, or GITHUB_TOKEN / GITLAB_TOKEN) it also compares them with the branch’s rule: the exit code is 1 when something is missing and nothing was written (dry run, the default). --apply adds only the missing part. See Let StoryShelf set the rule for what each host supports.
See Configuration for file/env precedence and Labels for persistent tagging.