en un clic
libretto
// Browser automation CLI for building, maintaining, and running browser automation workflows by inspecting live pages and prototyping interactions.
// Browser automation CLI for building, maintaining, and running browser automation workflows by inspecting live pages and prototyping interactions.
Read-only Libretto workflow for diagnosing live browser state without clicks, typing, navigation, or mutation requests.
Find deepening opportunities in a codebase, informed by the domain language in CONTEXT.md and the decisions in docs/adr/. Use when the user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make a codebase more testable and AI-navigable.
Automate user-installed Electron desktop apps (Slack, Discord, VS Code, Notion, Figma, Spotify, etc.) via CDP using this repo's Libretto CLI. Use when the task is to control a local desktop app on the user's machine, not this repo's own Electron app. Triggers: "desktop Slack app", "connect to Electron app", "remote-debugging-port", "CDP desktop app", "automate VS Code desktop app".
Create a spec sheet for the given feature/fix request in specs/ directory. Use when planning a significant new feature or complex fix.
Stage ALL changes in the repository (not just session changes), commit, and push. Use when you need to commit all pending changes.
Commit and push changes, creating or updating a PR as needed. Use for standard push workflow.
| 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.21"} |
The npm package includes src/ (full TypeScript source) and docs/ for deeper understanding of internals and design decisions. Read these when you need implementation context beyond what this skill file covers. Resolve paths from the package root (e.g. node_modules/libretto/).
Full documentation is published at libretto.sh. Available pages:
fetch().references/site-security-review.md (assess only once per site) rules fetch() unsafe, passively capture responses with page.on('response', ...)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.
references/code-generation-rules.md for the code shape.npx libretto; pnpm, yarn, and bun projects should use their equivalent package-manager execution form.npx libretto setup for first-time workspace onboarding. It installs Chromium and syncs skills.npx libretto status to inspect open sessions without triggering setup.npx libretto experiments to list internal feature flags and npx libretto experiments describe <name> for usage notes when an experiment is enabled.references/code-generation-rules.md before generating or editing production workflow code.run 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.--params, --headed, --headless, or --auth-profile flags the workflow needs.exec commands at the same time.libretto-readonly skill and use readonly-exec instead of exec.openexec or snapshot.open at the start of script authoring when you need live page state to decide how the workflow should work.--read-only when 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
connectconnect to 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.exec, snapshot, pages, and the rest of the session commands follow that session's stored mode.close clears the session but does not terminate the remote process.--read-only if 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-modesession-mode to inspect whether an existing session is write-access or read-only.open, run, and connect default new sessions to write-access unless the config sets sessionMode to read-only.--read-only or --write-access to override the config default for a single command.npx libretto session-mode --session my-session
snapshotsnapshot as the primary page observation tool.snapshot without --objective or --context; the command prints a screenshot path and compact accessibility tree for the current page.snapshot <ref> to inspect a subtree from the latest full snapshot. Use ref forms printed in the tree, such as l16; numeric-suffix aliases such as e16 also match l16.npx libretto snapshot --session debug-example
npx libretto snapshot <ref> --session debug-example
npx libretto snapshot --session debug-example --page <page-id>
execexec for focused inspection and short-lived interaction experiments.exec to validate selectors, inspect data, or prototype a step before you encode it in the workflow file.exec - to run multi-line scripts from stdin, especially when the code is too long or complex for a command line argument.exec REPL is persistent for each browser session. Define helper functions once and reuse them in later exec calls.page, frame, context, browser, fetch, Buffer.exec failures with try/catch or .catch().exec commands in parallel.exec in read-only diagnosis flows. Use readonly-exec from the libretto-readonly skill for those sessions.exec prints 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')"
pagespages when a popup, new tab, or second page appears.exec or snapshot complains 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()"
runrun to 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. Plain run defaults to headed mode.references/code-generation-rules.md). run validates --params against that schema before calling the handler and prints a clear field-by-field error if the input doesn't match.--stay-open-on-success when you need to inspect the completed state with pages, snapshot, or exec.--read-only if the preserved session should come back locked for follow-up terminal inspection after the workflow run.snapshot and exec before editing code.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.npx libretto resume --session <name>.npx libretto run ./integration.ts --params '{"status":"open"}'
npx libretto run ./integration.ts --read-only
npx libretto run ./integration.ts --stay-open-on-success
npx libretto run ./integration.ts --auth-profile app.example.com
resumeawait pause("session-name") in the workflow file. Import pause from "libretto".pause(session) is a no-op when NODE_ENV === "production".resume when a workflow hit a pause() call.npx libretto resume --session debug-example
savesave only when the user explicitly asks to save or reuse authenticated browser state.npx libretto save app.example.com
closeclose when 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).close --all is available for workspace cleanup.npx libretto close --session debug-example
npx libretto close --all
Session state is stored in .libretto/sessions/<session>/state.json.
Session logs are JSONL files at .libretto/sessions/<session>/:
.libretto/sessions/<session>/logs.jsonl..libretto/sessions/<session>/actions.jsonl..libretto/sessions/<session>/network.jsonl and 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 .
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.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).
<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: [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"}'` to validate]
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>
<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/configuration-file-reference.md when you need to inspect or change .libretto/config.json for viewport or session defaults.references/site-security-review.md before reviewing the site's security posture and deciding whether to lead with network requests, passive interception, or Playwright DOM automation on a new site.references/code-generation-rules.md before writing or editing production workflow files.references/auth-profiles.md when auth-profile behavior is relevant.references/pages-and-page-targeting.md when a session has multiple open pages or you need --page.references/action-logs.md for full action log field descriptions and user-vs-agent event semantics.