Skip to main content

run

The run command executes a named export from a TypeScript workflow file against a live browser. Use it to verify a workflow after creating or editing it.
npx libretto run ./integration.ts main
npx libretto run ./integration.ts main --headless

Syntax

npx libretto run <file> <export> [flags]
  • <file> — path to the TypeScript workflow file
  • <export> — the named export from that file (e.g., main, myWorkflow)

Flags

--headless
boolean
Run the browser in headless mode. Use this for the normal fix-and-verify loop.
--headed
boolean
Run the browser in headed (visible) mode. This is the default when neither flag is passed.
--session
string
Name for this run session. Auto-generated if omitted. Use an explicit name to target the session with exec, snapshot, or resume after a failure or pause.
--params
string
Inline JSON input for the workflow, passed as a quoted string. Example: --params '{"status":"open"}'.
--params-file
string
Path to a JSON file to use as workflow input. Cannot be used together with --params.
--auth-profile
string
Domain of a saved auth profile to load for this run. Example: --auth-profile app.example.com. Profiles are created with npx libretto save <domain>.
--viewport
string
Viewport size in WIDTHxHEIGHT format, for example 1920x1080. Falls back to .libretto/config.json, then 1366x768.
--tsconfig
string
Path to a tsconfig.json file for module resolution during workflow compilation.
--no-visualize
boolean
Disable ghost cursor and element highlight visualization in headed mode.

Behavior on failure

When a workflow fails, Libretto keeps the browser open at the point of failure. You can then use snapshot and exec to inspect the live page state before editing the workflow code.
# Workflow fails — browser stays open
npx libretto run ./integration.ts main --session debug-flow --headed

# Inspect the failure state
npx libretto snapshot \
  --session debug-flow \
  --objective "Find the blocking error or broken selector target" \
  --context "The workflow failed after trying to continue from the review step."

# Prototype a fix
npx libretto exec --session debug-flow "return await page.locator('.error-message').textContent()"

# Re-run after fixing the code
npx libretto run ./integration.ts main --headless

Validation loop

Prefer run --headless for the normal fix-and-verify loop. When the headless run passes, do a final headed run if you or the user wants to watch the finished workflow:
# Fix/verify loop — fast, no visible browser
npx libretto run ./integration.ts main --headless

# Final confirmation run — shows the browser
npx libretto run ./integration.ts main --headed

Examples

# Basic run
npx libretto run ./integration.ts main

# Headless run with inline params
npx libretto run ./integration.ts main --headless --params '{"status":"open"}'

# Run with a params file
npx libretto run ./integration.ts main --params-file ./params.json

# Run with a saved auth profile
npx libretto run ./integration.ts main --auth-profile app.example.com

# Run with explicit session name for post-failure inspection
npx libretto run ./integration.ts main --session debug-flow --headed

resume

The resume command unpauses a workflow that has stopped at an await pause(session) call. Use it repeatedly until the workflow completes or pauses again at the next breakpoint.
npx libretto resume --session debug-example

Flags

--session
string
required
The session name of the paused workflow to resume.

The pause() API

Insert await pause(session) calls in your workflow file to create interactive breakpoints — similar to debugger breakpoints in the browser flow. The workflow stops at each pause() call and waits for resume before continuing.
import { workflow, pause, type LibrettoWorkflowContext } from "libretto";

export const myWorkflow = workflow(async (ctx, input) => {
  const { session, page } = ctx;

  await page.goto("https://app.example.com");

  // Pause here for inspection
  await pause(session);

  await page.locator('#submit').click();

  // Pause again before the final step
  await pause(session);

  return { done: true };
});
pause() is a no-op when NODE_ENV === "production". You can leave pause() calls in your workflow code during development and they will be silently skipped in production.

Complete debugging flow

1

Run the workflow and let it fail (or pause)

npx libretto run ./integration.ts main --session debug-flow --headed
If the workflow hits a pause(), it prints Workflow paused. and returns. The browser stays open.
2

Inspect the paused page state

npx libretto snapshot \
  --session debug-flow \
  --objective "What is on the page and what is the next required action?" \
  --context "The workflow paused before the submit step."

npx libretto exec --session debug-flow "return await page.url()"
3

Resume the workflow

npx libretto resume --session debug-flow
Keep running resume until the workflow prints Integration completed. or fails with an error.
4

Fix the code and re-run

Edit the workflow file to fix any issues found during inspection, then re-run:
npx libretto run ./integration.ts main --headless

snapshot

Inspect page state after a failure or pause.

exec

Prototype fixes against the paused browser before editing code.

Build docs developers (and LLMs) love