Skip to content

CLI ​

The lightningpanda command ships in the npm package @povio/lightning-panda (its bin). It has two halves: the native browser binary (version, eval, serve, fetch) and two test runners written in TypeScript that need Bun (test, e2e).

sh
bunx lightningpanda <command> [options]
# or, installed in a project
bun add -d @povio/lightning-panda
./node_modules/.bin/lightningpanda <command> [options]
CommandWhat it doesRuns on
versionPrints the version and engine capabilitiesnative binary
evalRuns JavaScript in an about:blank page until idlenative binary
serveCDP server over WebSocketnative binary
fetchLoads a URL (scripts run) and prints the DOM after loadnative binary
testPlaywright-style test runner (playwright test replacement)Bun
e2eOne-process runner for @povio/lightning-panda/e2e specsBun
help, --help, -h, no commandPrints the usage summarynative binary

How the npm lightningpanda command dispatches ​

The npm bin is a small Node/Bun script (dist/cli.js):

  • test and e2e run in-process when the script runs under Bun. Under Node it re-launches itself with bun on PATH; with no Bun it prints lightningpanda test: needs Bun (https://bun.sh) on PATH and exits 1.
  • Every other command is forwarded, arguments unchanged, to the native binary. SIGINT, SIGTERM and SIGHUP are forwarded to it, and its exit code (or signal) becomes the wrapper's.

The native binary is chosen in this order:

  1. $LIGHTNINGPANDA_BIN (env).
  2. A lightningpanda file next to the package directory (the layout of a release archive).
  3. The bundled binary native/<platform>-<arch>/lightningpanda (darwin-arm64, darwin-x64, linux-arm64, linux-x64).

On any other platform it fails with: Lightningpanda has no bundled browser for <platform>-<arch>. The browser supports macOS 14+ and Linux (glibc 2.39+) on arm64 and x64. See Platforms and limits.

Exit codes ​

Native commands:

CodeMeaning
0Success (help too)
1Runtime failure: engine or page creation failed; eval: an uncaught exception or unhandled promise rejection; fetch: the navigation failed; serve: could not bind or start (a --fork template that fails to start)
2Usage error: unknown command, unknown or malformed option, unreadable eval file; serve --fork on a build without fork support
124eval / fetch: the --timeout-ms deadline passed

test and e2e exit 0 when every test passed, 1 on any failure, and 2 on a usage error. e2e interrupted by a signal exits 128 + signal (130 for SIGINT).

version ​

sh
lightningpanda version      # or: lightningpanda --version

Prints the version and what the linked JavaScriptCore supports:

text
lightningpanda 0.0.33
engine: JavaScriptCore; capabilities: Capabilities { weak_refs: true, modules: true, import_maps: true, typed_modules: true, unhandled_rejections: true, termination: true, hidden_properties: true, proxy_targets: true, object_global_context: true, fork: true, global_constants: true }

fork: true means the binary supports serve --fork; the e2e runner checks this line before it adds --fork.

eval ​

text
lightningpanda eval [--timeout-ms N] (-e CODE | FILE | -)

Runs JavaScript in a fresh about:blank page, then keeps the event loop running until the page is idle (timers, promises and tasks done) or the deadline passes. No network is set up: use fetch or serve to load pages.

OptionTypeDefaultDescription
--timeout-ms Ninteger (ms)30000Deadline for the evaluation and everything it schedules. Covers the first evaluation too: a watchdog terminates running JavaScript (loops included). Exceeding it exits 124.
-e CODEstringThe source to run (reported as eval.js).
FILEpathRead the source from a file (reported under its path).
-Read the source from standard input (reported as stdin.js).

Exactly one source is needed; if several are given the last wins. Any other argument is taken as a file path (so eval --help reports --help: No such file or directory).

Output: console.log/info/debug go to stdout; console.error, warn and assert go to stderr. Strings print as-is and objects as JSON. An uncaught exception prints Uncaught <message> and its stack to stderr; an unhandled rejection prints Unhandled promise rejection: <message>. Either makes the exit code 1, but the run still continues until idle.

sh
lightningpanda eval -e 'console.log(1 + 1, { a: 1 }); setTimeout(() => console.log("later"), 10)'
# 2 {"a":1}
# later

echo 'console.log(navigator.userAgent)' | lightningpanda eval -
# Mozilla/5.0 (compatible; lightningpanda/0.0.33)

lightningpanda eval --timeout-ms 100 -e 'setInterval(() => {}, 10)'
# lightningpanda: timed out after 100 ms   (exit 124)

serve ​

text
lightningpanda serve [OPTIONS]

Starts the CDP server: Chrome DevTools Protocol over WebSocket on ws://HOST:PORT/ (default ws://127.0.0.1:9222/), with GET /json/version and GET /json/list. This is what Lightningpanda.launch(), the Playwright drop-in, Puppeteer and raw CDP clients connect to. It runs until killed (or until --parent-pid exits).

sh
lightningpanda serve --port 9222
lightningpanda serve --fork --static http://app.test=./dist --prepare http://app.test/

Every option, with types, defaults and environment equivalents, is in serve options. lightningpanda serve --help prints the same list for the installed version.

On start it logs to stderr (unless --log-level is above info):

text
lightningpanda: CDP server listening on ws://127.0.0.1:9222/
lightningpanda: CDP server listening on ws://127.0.0.1:9222/ (fork mode)

fetch ​

text
lightningpanda fetch [--dump html|none] [--wait-ms N] [--timeout-ms N] URL

Loads URL with the network enabled, runs its scripts, waits for the load event, and prints the serialized DOM to stdout.

OptionTypeDefaultDescription
URLURLrequiredhttp:, https:, data: or file: (exactly one; an argument starting with - is an option).
--dump html|noneenumhtmlhtml: print <!DOCTYPE html> (when the document has a doctype) and the outerHTML of the root element. none: print nothing (exit code only).
--wait-ms Ninteger (ms)0After load, keep running the page until it is idle or N ms pass (for content rendered after load). Bounded by --timeout-ms.
--timeout-ms Ninteger (ms)30000Overall deadline. If load has not fired by then, or the wait runs past it, the command exits 124.

Console output of the page goes to stdout/stderr as for eval. A failed navigation prints lightningpanda: <url>: <error> (for example net::ERR_CONNECTION_REFUSED) and exits 1. fetch has no --help (it is a usage error).

sh
lightningpanda fetch https://example.com > page.html
lightningpanda fetch --wait-ms 2000 https://spa.example.com/
lightningpanda fetch --dump none https://example.com && echo reachable

See One-off fetches for recipes.

test ​

text
lightningpanda test [options] [test-filter...]

Runs tests written against @povio/lightning-panda/playwright the way playwright test does: it reads the config, finds each project's test files (testDir, testMatch, testIgnore), starts webServers and runs globalSetup once, then runs the files with bun test in worker processes, one browser per worker. Needs Bun. Guide: Config and the test runner.

OptionValueDefaultDescription
-c, --config <file>pathlightningpanda.config.{ts,mts,mjs,js}, else playwright.config.* in the working directoryConfig file. Sets LP_CONFIG for the workers.
--project <name>stringall projectsOnly this project (repeatable). An unknown name exits 1.
-j, --workers <n|n%>count or percentage of CPUsthe config's workers, else half the CPUsWorker processes.
-g, --grep <regex>regexOnly tests whose title path matches.
--grep-invert <regex>regexSkip tests whose title path matches.
--retries <n>integerconfig's retriesRetries of a failing test (sets LP_RETRIES).
--timeout <ms>integerconfig's timeout (30000)Test timeout (sets LP_TIMEOUT).
-u, --update-snapshots [mode]changed | all | missing | nonechanged when the flag is givenRewrite snapshots and screenshot baselines (sets LP_UPDATE_SNAPSHOTS to the mode).
--fully-parallelflagconfig's fullyParallelRun every file's tests in parallel across workers.
-xflagStop after the first failure (as --max-failures=1).
--max-failures <n>integerStop after n failures (workers get SIGTERM).
--reporter <name>list | line | dotlistConsole reporter.
--listflagList the tests without running them (one worker, no web servers or global setup).
-q, --quietflagDo not print the tests' own output.
--headed, --debug, --uiflagAccepted; print has no effect (lightningpanda is headless).
-h, --helpflagPrint the usage and exit 0.

Options also take the --name=value form. test-filter arguments are regular expressions; a file runs when its absolute or relative path matches any of them. With no files found the command prints lightningpanda test: no tests found and exits 1.

The browser is $LIGHTNINGPANDA_WS when set (an already running serve), else each worker launches its own. Test output lines are prefixed [wN]; colors are off when stdout is not a TTY or NO_COLOR is set.

sh
lightningpanda test                        # every project
lightningpanda test -j 8 --project chromium login
lightningpanda test -u all e2e/visual      # rewrite all baselines of matching files

e2e ​

text
lightningpanda e2e [options] [path | dir | glob | filter ...]

Runs spec files written against @povio/lightning-panda/e2e in one Bun process: tests of every file share one queue (up to --concurrency at a time, so cases of different files interleave) and one fork-mode browser, launched on first use and always closed. Needs Bun. Guide: Suite runner.

Without paths it runs every *.test.* / *.spec.* file (also _test/_spec; extensions js, jsx, ts, tsx, mjs, cjs, mts, cts) under the working directory, skipping node_modules and dot-directories. An argument that is a file, a directory or a glob (contains *, ?, [ or {) selects files; any other argument filters the spec paths by substring, as with bun test.

OptionValueDefaultDescription
-j, --concurrency <n>integer ≥ 1the CPU countTests at a time across all files.
--max-concurrency <n>integer ≥ 1unlimitedTests of one file at a time (as bun test's).
--timeout <ms>integer5000Default timeout of tests and hooks without their own.
-t, --test-name-pattern <re>regexOnly tests whose name (describes and test joined by spaces) matches.
--onlyflagOnly tests and describes marked .only.
--shard <i>/<n>i/n, 1 ≤ i ≤ nRun shard i of n. Files are split by --timings (longest first onto the least-loaded shard; files without a timing count as the average).
--timings <file>pathPer-file durations, {"version":1,"files":{"<path>":ms}}. Without --shard, files start longest first.
--update-timingsflagWrite this run's per-file durations to --timings (needs it; skipped with -t, --only or a stopped run).
--setup <module>pathModule exporting setup(), browser(result), teardown(result) (or a default export with them). See Setup.
--preload <module>pathLoaded before the specs; its top-level hooks apply to every test (repeatable).
--browser-arg <arg>stringExtra lightningpanda serve argument (repeatable), for example --browser-arg=--static --browser-arg=http://app.test=./dist.
--reporter junitjunit | consoleconsoleAlso write a JUnit report (needs --reporter-outfile).
--reporter-outfile <file>pathWhere the JUnit report goes.
--junit <file>path--reporter junit --reporter-outfile <file> in one.
-u, --update-snapshotsflagWrite screenshot baselines instead of comparing (sets LP_UPDATE_SNAPSHOTS=1).
--bail [n]integer1 when givenStop after n failures.
-h, --helpflagPrint the usage and exit 0.

Options also take the --name=value form.

The browser it launches is lightningpanda serve --fork --cdp-max-connections <max(64, 4 × concurrency + 8)> plus the setup module's browser().args and every --browser-arg (a --cdp-max-connections of yours replaces the computed one). If the binary's version does not report fork: true it warns has no fork mode; every page boots its profile and launches without --fork.

Exit code: 1 when no spec files are found, no tests match, or any test, hook or file load failed (or a test did not run); else 0. An empty shard exits 0. On SIGINT/SIGTERM/SIGHUP it stops starting tests, closes the browser, runs teardown, and exits 128 + signal; a second signal exits at once. NODE_ENV defaults to test.

sh
lightningpanda e2e                                    # every spec under the cwd
lightningpanda e2e e2e/positions -t 'closes'          # one directory, matching names
lightningpanda e2e --shard 2/4 --timings e2e/timings.json --junit reports/e2e.xml
lightningpanda e2e --setup e2e/setup.ts --browser-arg=--static --browser-arg=http://app.test=./dist

AGPL-3.0-only. A derivative of Lightpanda. Built by Povio.