Skip to content

Check your files without a browser

A shoot stops at the first document it cannot read, so fixing a shot list becomes a matter of running it, reading one complaint, fixing it, and running it again. This guide checks everything at once instead, without Playwright and without your site running.

Requires shotlist 0.4.0 or later.

Check everything

npx shotlist --lint

This parses the configuration and every recipe, macro and data file it names, reports what is wrong with all of them, and stops. Nothing is opened, nothing is captured, and no image is written.

nothing wrong in 9 files

When something is wrong, the report is grouped by file:

screenshots/recipes/order-row.yaml
  ✗ clip: unknown key "marching" — did you mean "matching"?
screenshots/macros/sign-in.yaml
  ✗ steps.1: unrecognized step "fil"

2 errors in 9 files

It exits non-zero when any file has an error, so it works as a pre-commit hook or a CI step without any extra plumbing.

npx shotlist --lint --warnings
screenshots/recipes/dashboard.yaml
  ! mark "status" is never used by a callout
  ! install: "handbook" is not a destination the config names

0 errors, 2 warnings in 9 files

Warnings are marked ! rather than ✗, and cover:

  • a mark no callout points at
  • a callout pointing at a mark nothing defines
  • an install: naming a destination the configuration does not have
  • a session: naming a session the configuration does not have

--warnings never changes the exit code. A file with warnings and no errors still exits 0, so you can turn this on in CI without it failing builds on style.

Run it in CI

Put it before the job that takes screenshots. It needs no browser, so it finishes in about a second and catches the failures that would otherwise appear several minutes into a shoot:

.github/workflows/screenshots.yml
- run: npx shotlist --lint --warnings

A job that only lints needs neither Playwright nor a running site, so it can skip both installs entirely. See Run shotlist in CI.

What it cannot tell you

Linting is about the files, not the site. A recipe that parses can still fail when it runs, because a query only resolves against a real page. --lint catches a misspelled key; only a shoot catches a button that was renamed.