name: libretto description: "Browser automation CLI for building, maintaining, and running browser automation workflows by inspecting live pages and prototyping interactions." license: MIT metadata: author: saffron-health version: "0.6.32"
How Libretto Works
- Libretto is a CLI for exploring live websites and building or debugging reusable browser automation scripts.
- Use Libretto commands to inspect the site and open pages, observe state, inspect requests, and prototype interactions.
- Libretto work must end in script changes. Create or edit the workflow file instead of stopping at interactive exploration.
Shipped Source & Documentation
Read references/shipped-source-and-documentation.md for shipped source details, published documentation links, and implementation context beyond what this skill file covers.
Default Integration Approach
- Call the site's fetch/XHR endpoints via browser-context
fetch(). - If
references/site-security-review.md(assess only once per site) rulesfetch()unsafe, passively capture responses withpage.on('response', ...) - Fall back to Playwright UI automation.
Mix strategies freely across steps on a site.
Prefer to enter sites at a user-facing URL (homepage, login, etc.) on the first navigation — deep URLs on a cold session are commonly blocked by edge bot protection.
CAPTCHA Handling
- If a CAPTCHA, Cloudflare challenge, or similar bot check appears in a local Chromium session, try to solve it in the visible browser and continue from the solved state.
- If the same challenge appears while the session is using a hosted browser provider, wait up to 2 minutes for automatic CAPTCHA handling before deciding the workflow is blocked.
- When a CAPTCHA was observed during exploration, generated workflow code should include an explicit timeout wait at that point with a short comment linking to the hosted platform stealth docs. Follow
references/code-generation-rules.mdfor the code shape.
Setup
- Use the package manager convention for the target project. The examples use
npx libretto; pnpm, yarn, and bun projects should use their equivalent package-manager execution form. - Use
npx libretto setupfor first-time workspace onboarding. It installs Chromium and syncs skills. - Use
npx libretto statusto inspect open sessions without triggering setup. - Use
npx libretto updateto upgrade the project-local Libretto package. Usenpx libretto update --dry-runto preview the package-manager command first.
Experiments
- Use
npx libretto experimentsto list internal feature flags andnpx libretto experiments describe <name>for usage notes when an experiment is enabled.
Working Rules
- Announce which session you are using and what page you are on.
- Ask instead of guessing when it is unclear what to click, type, or submit.
- Do not treat visibility as interactivity. If an element will not act, inspect blockers before retrying.
- Defer repo/code review until you begin generating code, unless the user explicitly asks for it earlier.
- Read and follow guidelines in
references/code-generation-rules.mdbefore generating or editing production workflow code. - For authenticated workflows, manual login is discovery only. After the user logs in, read only the sign-in action logs and identify the required credentials; if credentials are unclear, ask before writing code.
- Add missing blank
LIBRETTO_CLOUD_<secret_name>=entries without overwriting populated values. If any required credential is blank, stop and ask the user to fill it; until then, do not inspect logged-in pages, read authenticated network bodies, write workflow code, open validation sessions, or continue discovery. - Authenticated workflows must implement
librettoAuthenticatewith declared credentials before validation. Use a reusable*_totp_secretcredential for authenticator-app MFA, not a one-timeotp_code; text and email verification codes are not supported for fully automated sign-in. - Read
references/website-authentication.mdwhen you needlibrettoAuthenticateexamples or auth-profile details. - Validation requires a successful clean
runon a fresh, unauthenticated session with confirmation of the actual returned output, not just process success. Use the same headed or headless mode that the workflow run is already using. - After validation, always show the user: (1) the output/results from the validation run, and (2) the same command so they can re-run it themselves. Include any
--params,--headed, or--headlessflags the workflow needs. - Treat exploration sessions as disposable unless the user explicitly wants one kept open.
- Close disposable sessions before your final response once exploration, debugging, or validation is complete. Open browsers keep consuming local or hosted resources.
- Get explicit user confirmation before mutating actions or replaying network requests that may have side effects.
- Never run multiple
execcommands at the same time. - If the browser must remain read-only, switch to the
libretto-readonlyskill and usereadonly-execinstead ofexec.
Commands
open
- Open a page before using
execorsnapshot. - Use
openat the start of script authoring when you need live page state to decide how the workflow should work. - Use headed mode when the user needs to log in or watch the workflow.
- Pass
--read-onlywhen you want the session locked for inspection from the moment it is created.
npx libretto open https://example.com
npx libretto open https://example.com --read-only --session readonly-example
npx libretto open https://example.com --session debug-example
connect
- Use
connectto attach to any existing Chrome DevTools Protocol (CDP) endpoint — a browser started with--remote-debugging-port, an Electron app, or any other CDP-compatible target. - After connecting,
exec,snapshot,pages, and the rest of the session commands follow that session's stored mode. - Libretto does not manage the connected process's lifecycle.
closeclears the session but does not terminate the remote process. - Pass
--read-onlyif the connected session must stay inspection-only from the start.
npx libretto connect http://127.0.0.1:9222 --session my-session
npx libretto connect http://127.0.0.1:9222 --read-only --session readonly-session
npx libretto connect http://127.0.0.1:9223 --session another-session
session-mode
- Use
session-modeto inspect whether an existing session iswrite-accessorread-only. - Only a user can change the session mode for an existing session. Never change a session's mode on your own — the user must change it themselves manually.
open,run, andconnectdefault new sessions towrite-accessunless the config setssessionModetoread-only.- Pass
--read-onlyor--write-accessto override the config default for a single command.
npx libretto session-mode --session my-session
snapshot
- Use
snapshotas the primary page observation tool. - Run
snapshotwithout--objectiveor--context; the command prints a screenshot path and compact accessibility tree for the current page. - Run
snapshot <ref>to inspect a subtree from the latest full snapshot. Use ref forms printed in the tree, such asl16; numeric-suffix aliases such ase16also matchl16. - Run an unscoped snapshot before using refs. Subtree snapshots capture a fresh screenshot but reuse the latest cached tree.
- Use it before guessing at selectors, after workflow failures, and whenever the visible page state is unclear.
npx libretto snapshot --session debug-example
npx libretto snapshot <ref> --session debug-example
npx libretto snapshot --session debug-example --page <page-id>
exec
- Use
execfor focused inspection and short-lived interaction experiments. - Use
execto validate selectors, inspect data, or prototype a step before you encode it in the workflow file. - Use
exec -to run multi-line scripts from stdin, especially when the code is too long or complex for a command line argument. - The
execREPL is persistent for each browser session. Define helper functions once and reuse them in laterexeccalls. - Available globals:
page,frame,context,browser,fetch,Buffer. - Let failures throw. Do not hide
execfailures withtry/catchor.catch(). - Do not run multiple
execcommands in parallel. - Do not use
execin read-only diagnosis flows. Usereadonly-execfrom thelibretto-readonlyskill for those sessions. - After successful mutations,
execprints page-change diffs from compact snapshots.
npx libretto exec "await page.url()"
npx libretto exec "await page.locator('button:has-text(\"Continue\")').click()"
echo "async function textOf(selector) { return await page.locator(selector).textContent(); }" | npx libretto exec - --session debug-example
npx libretto exec --session debug-example "await textOf('h1')"
pages
- Use
pageswhen a popup, new tab, or second page appears. - If
execorsnapshotcomplains about multiple pages, list page ids first and then pass--page.
npx libretto pages --session debug-example
npx libretto exec --session debug-example --page <page-id> "await page.url()"
run
- Use
runto verify a workflow file after creating it or editing it. Use the same headed or headless mode for validation that the workflow run is already using. Plainrundefaults to headed mode. - Workflows define their input shape with a Zod schema (see
references/code-generation-rules.md).runvalidates--paramsagainst that schema before calling the handler and prints a clear field-by-field error if the input doesn't match. - Successful runs close the browser by default. Pass
--stay-open-on-successwhen you need to inspect the completed state withpages,snapshot, orexec. - Pass
--read-onlyif the preserved session should come back locked for follow-up terminal inspection after the workflow run. - If the workflow fails, Libretto keeps the browser open. Inspect the failed state with
snapshotandexecbefore editing code. - Insert
await pause(session)statements in the workflow file when you need to stop at specific states for interactive debugging, like breakpoints in the browser flow. - If the workflow pauses, resume it with
npx libretto resume --session <name>. - Re-run the same workflow after each fix to verify the browser behavior end to end.
npx libretto run ./integration.ts --params '{"status":"open"}'
npx libretto run ./integration.ts --read-only
npx libretto run ./integration.ts --stay-open-on-success
resume
- Workflows pause by calling
await pause("session-name")in the workflow file. Importpausefrom"libretto". pause(session)is a no-op whenNODE_ENV === "production".- Use
resumewhen a workflow hit apause()call. - Keep resuming the same session until the workflow completes or pauses again.
npx libretto resume --session debug-example
save
- Use
saveonly when the user explicitly asks to save or reuse authenticated browser state.
npx libretto save app.example.com
close
- Use
closewhen the user is done with the session or an exploration session is no longer helping progress (unless the user asked to keep watching that browser). - Prefer closing sessions promptly after successful validation or diagnosis so unused browsers do not keep consuming resources.
close --allis available for workspace cleanup.
npx libretto close --session debug-example
npx libretto close --all
Session Logs
Session state is stored in .libretto/sessions/<session>/state.json.
Session logs are JSONL files at .libretto/sessions/<session>/:
- CLI logs are in
.libretto/sessions/<session>/logs.jsonl. - Action logs are in
.libretto/sessions/<session>/actions.jsonl. - Network logs are in
.libretto/sessions/<session>/network.jsonland their corresponding raw request/response bodies are in.libretto/sessions/<session>/raw-network/.
Use jq to query jsonl logs directly — for any filtering, slicing, or inspection task.
# Last 20 action entries
tail -n 20 .libretto/sessions/<session>/actions.jsonl | jq .
# POST requests with captured response previews
jq 'select(.method == "POST" and .responseBodyPreview != null) | {id, resourceType, status, contentType, url, requestBodyPreview, responseBodyPreview, responseBodyPath}' .libretto/sessions/<session>/network.jsonl
# Read a saved response sidecar
gunzip -c .libretto/sessions/<session>/raw-network/000001.response.json.gz | jq .
Action log (actions.jsonl)
Key fields: ts (ISO timestamp), source (user or agent), action (click, fill, goto, etc.), selector (locator used by the agent), bestSemanticSelector (canonical selector for user DOM events), success (boolean), url (navigation target), value (typed or submitted value), error (message on failure).
Read references/action-logs.md for full field descriptions and user-vs-agent entry semantics.
Network log (network.jsonl)
Libretto logs useful document, xhr, fetch, and non-noisy mutating requests; obvious static/media/tracking noise is skipped.
Key fields: id (incrementing request id), ts (ISO timestamp), pageId (page target id), method (HTTP method, e.g. GET, POST), url (request URL), resourceType (browser resource type, e.g. document, xhr, fetch), status (HTTP status code, or null for failed requests), statusText (HTTP status text), contentType (response content type), requestHeaders (request headers), responseHeaders (response headers), requestBodyPreview (inline request body preview), requestBodyPath (gzipped full request body sidecar path), requestBodyBytes (request body byte size), requestBodyTruncated (true when the request body exceeded the save limit), requestBodyOmittedReason (why the request body was not captured), responseBodyPreview (inline response body preview), responseBodyPath (gzipped full response body sidecar path), responseBodyBytes (response body byte size), responseBodyTruncated (true when the response body exceeded the save limit), responseBodyOmittedReason (why the response body was not captured), and errorText (request failure or body read error).
Examples
Building new browser automation workflows
Interactive building
<example>
[Context: The user wants to build a new browser workflow and does not yet know the page structure]
Assistant: I'll inspect the real site first if needed, but before I finish I'll create `target-workflow.ts` so the task produces reusable automation code.
Assistant: [Runs `npx libretto open https://target.example.com --headed`]
Assistant: [If sign-in is required, follows the authenticated workflow rules before continuing]
Assistant: [Reads `references/site-security-review.md` before choosing between passive network inspection, direct browser fetch calls, and Playwright-first automation]
Assistant: [Runs `npx libretto snapshot --session <session>`]
Assistant: [Uses `snapshot` and `exec` as needed to understand the site and decide the implementation path]
Assistant: [Reads `references/code-generation-rules.md` before writing production workflow code]
Assistant: I found the working path. I'll now create the workflow file and verify it.
Assistant: [Creates or edits `target-workflow.ts` following `references/code-generation-rules.md`]
Assistant: [Runs `npx libretto run ./target-workflow.ts --params '{"status":"open"}'` on a fresh, unauthenticated session to verify both sign-in and workflow behavior]
Assistant: [If sign-in validation passes and a reusable session is useful, adds an auth profile and reruns validation]
Assistant: Validation passed. Here are the results:
[Shows the output/results from the validation run]
To run it again, use: npx libretto run ./target-workflow.ts --params '{"status":"open"}'
</example>
Debugging existing workflows
<example>
[Context: The user has an existing Libretto workflow that is failing]
Assistant: I'll reproduce the failure first so we can inspect the exact browser state it leaves behind.
Assistant: [Runs `npx libretto run ./integration.ts --session debug-flow`]
Assistant: The workflow failed and Libretto kept the browser open. I'll inspect the page state before changing code.
Assistant: [Runs `npx libretto snapshot --session debug-flow`]
Assistant: [Runs `npx libretto exec --session debug-flow "...focused inspection or prototype..."`]
Assistant: [Reads `references/code-generation-rules.md` before patching the workflow file]
Assistant: I found the issue. I'll patch the workflow code and verify.
Assistant: [Edits `integration.ts` following `references/code-generation-rules.md`]
Assistant: [Runs `npx libretto run ./integration.ts` to validate the fix]
Assistant: Fix verified. Here are the results:
[Shows the output/results from the validation run]
To run it again, use: npx libretto run ./integration.ts
</example>
References
- Read
references/configuration-file-reference.mdwhen you need to inspect or change.libretto/config.jsonfor viewport or session defaults. - Read
references/site-security-review.mdbefore reviewing the site's security posture and deciding whether to lead with network requests, passive interception, or Playwright DOM automation on a new site. - Read
references/code-generation-rules.mdbefore writing or editing production workflow files. - Read
references/website-authentication.mdwhen website sign-in implementation or auth-profile behavior is relevant. - Read
references/pages-and-page-targeting.mdwhen a session has multiple open pages or you need--page. - Read
references/action-logs.mdfor full action log field descriptions and user-vs-agent event semantics. - If the workflow code is deployed to the Libretto Cloud platform and you need to reference its API docs, fetch https://libretto.sh/docs/llms.txt and follow the relevant page links.