How Libretto Read-Only Works
- Use this skill when the browser session must stay strictly read-only.
- Libretto stores read-only vs write-access on the session itself.
- The primary inspection tools are
snapshot and readonly-exec.
readonly-exec reuses Libretto's normal execution pipeline, but it only exposes read-only helpers and denies mutating Playwright methods.
- 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.
Working Rules
- Announce which session you are using and what page you are inspecting.
- Do not use
exec, run, or any direct Playwright action that could change browser or application state.
- Do not click, type, submit forms, navigate, upload files, dispatch DOM events, or send non-GET requests.
- Prefer
snapshot first when the visible page state is unclear.
- Use
readonly-exec for focused inspection: titles, HTML, locator text, counts, visibility checks, and GET requests.
- Keep snippets small and purpose-built. Do not run multiple
readonly-exec commands at the same time.
- Close disposable sessions before your final response once inspection is complete. Open browsers keep consuming local or hosted resources.
- End with diagnosis and handoff guidance, not an attempted in-browser repair.
Commands
connect
- Use
connect to attach to an existing CDP endpoint for a preserved browser session.
- Use
--read-only when creating the Libretto session handle for a preserved browser session.
- Libretto read-only mode is enforced through Libretto commands; direct CDP clients that skip Libretto are outside this boundary.
libretto connect http://127.0.0.1:9222 --read-only --session failed-job-debug
pages
- Use
pages when a popup, new tab, or second page exists.
- If
readonly-exec or snapshot complains about multiple pages, list ids first and then pass --page.
libretto pages --session failed-job-debug
snapshot
- Use
snapshot as the first high-level observation tool.
- Run
snapshot <ref> to inspect a subtree from the latest full snapshot.
readonly-exec
- Use
readonly-exec for narrow inspection code only.
- Denied operations fail with
ReadonlyExecDenied: ....
Helpers
page — a read-only Playwright Page proxy. Standard Playwright read methods work normally (url(), title(), content(), frames(), getByRole(), locator(), textContent(), isVisible(), count(), scrollIntoViewIfNeeded(), etc.). frames() returns read-only Frame proxies, including from childFrames() and parentFrame(). Anything that mutates a page or frame (click, fill, goto, evaluate, keyboard, mouse) is blocked.
state — the current Libretto session state object.
get(url, options?) — HTTP client restricted to GET and HEAD requests. Replaces fetch, which is blocked in readonly mode. Any request with a body or a non-GET/HEAD method throws ReadonlyExecDenied.
scrollBy(deltaX, deltaY) — scroll the viewport by pixel offset. Use this to inspect content below the fold without targeting a specific element.
Standard JS globals console, URL, Buffer, setTimeout, and setInterval are also available.
Examples
libretto readonly-exec "return page.url()" --session failed-job-debug
libretto readonly-exec "return await page.getByRole('heading').first().textContent()" --session failed-job-debug
libretto readonly-exec "return await page.frames()[1]?.getByRole('heading').textContent()" --session failed-job-debug
# HTTP GET inspection
echo "const r = await get('https://api.example.com/status'); return await r.json()" \
| libretto readonly-exec - --session failed-job-debug
# Scroll down to inspect below-the-fold content
libretto readonly-exec "await scrollBy(0, 500)" --session failed-job-debug
close
- Use
close when the inspection session is no longer needed, unless the user explicitly asks to keep the browser open.
libretto close --session failed-job-debug
1---2name: libretto-readonly3description: Read-only Libretto workflow for diagnosing live browser state without clicks, typing, navigation, or mutation requests.4license: MIT5---67## How Libretto Read-Only Works89- Use this skill when the browser session must stay strictly read-only.10- Libretto stores read-only vs write-access on the session itself.11- The primary inspection tools are `snapshot` and `readonly-exec`.12- `readonly-exec` reuses Libretto's normal execution pipeline, but it only exposes read-only helpers and denies mutating Playwright methods.13- 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.1415## Working Rules1617- Announce which session you are using and what page you are inspecting.18- Do not use `exec`, `run`, or any direct Playwright action that could change browser or application state.19- Do not click, type, submit forms, navigate, upload files, dispatch DOM events, or send non-GET requests.20- Prefer `snapshot` first when the visible page state is unclear.21- Use `readonly-exec` for focused inspection: titles, HTML, locator text, counts, visibility checks, and GET requests.22- Keep snippets small and purpose-built. Do not run multiple `readonly-exec` commands at the same time.23- Close disposable sessions before your final response once inspection is complete. Open browsers keep consuming local or hosted resources.24- End with diagnosis and handoff guidance, not an attempted in-browser repair.2526## Commands2728### `connect`2930- Use `connect` to attach to an existing CDP endpoint for a preserved browser session.31- Use `--read-only` when creating the Libretto session handle for a preserved browser session.32- Libretto read-only mode is enforced through Libretto commands; direct CDP clients that skip Libretto are outside this boundary.3334```bash35libretto connect http://127.0.0.1:9222 --read-only --session failed-job-debug36```3738### `pages`3940- Use `pages` when a popup, new tab, or second page exists.41- If `readonly-exec` or `snapshot` complains about multiple pages, list ids first and then pass `--page`.4243```bash44libretto pages --session failed-job-debug45```4647### `snapshot`4849- Use `snapshot` as the first high-level observation tool.50- Run `snapshot <ref>` to inspect a subtree from the latest full snapshot.5152### `readonly-exec`5354- Use `readonly-exec` for narrow inspection code only.55- Denied operations fail with `ReadonlyExecDenied: ...`.5657#### Helpers5859- `page` — a read-only Playwright `Page` proxy. Standard Playwright read methods work normally (`url()`, `title()`, `content()`, `frames()`, `getByRole()`, `locator()`, `textContent()`, `isVisible()`, `count()`, `scrollIntoViewIfNeeded()`, etc.). `frames()` returns read-only `Frame` proxies, including from `childFrames()` and `parentFrame()`. Anything that mutates a page or frame (`click`, `fill`, `goto`, `evaluate`, `keyboard`, `mouse`) is blocked.60- `state` — the current Libretto session state object.61- `get(url, options?)` — HTTP client restricted to **GET and HEAD** requests. Replaces `fetch`, which is blocked in readonly mode. Any request with a body or a non-GET/HEAD method throws `ReadonlyExecDenied`.62- `scrollBy(deltaX, deltaY)` — scroll the viewport by pixel offset. Use this to inspect content below the fold without targeting a specific element.6364Standard JS globals `console`, `URL`, `Buffer`, `setTimeout`, and `setInterval` are also available.6566#### Examples6768```bash69libretto readonly-exec "return page.url()" --session failed-job-debug70libretto readonly-exec "return await page.getByRole('heading').first().textContent()" --session failed-job-debug71libretto readonly-exec "return await page.frames()[1]?.getByRole('heading').textContent()" --session failed-job-debug7273# HTTP GET inspection74echo "const r = await get('https://api.example.com/status'); return await r.json()" \75 | libretto readonly-exec - --session failed-job-debug7677# Scroll down to inspect below-the-fold content78libretto readonly-exec "await scrollBy(0, 500)" --session failed-job-debug79```8081### `close`8283- Use `close` when the inspection session is no longer needed, unless the user explicitly asks to keep the browser open.8485```bash86libretto close --session failed-job-debug87```