/libretto-readonly
Read-only Libretto workflow for diagnosing live browser state without clicks, typing, navigation, or mutation requests.
$ npx -y skills add saffron-health/libretto --skill libretto-readonly --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/libretto-readonly
Context preview
The summary Claude sees to decide when to auto-load this skill.
Read-only Libretto workflow for diagnosing live browser state without clicks, typing, navigation, or mutation requests.
SKILL.md
libretto-readonly.SKILL.mdname: libretto-readonly
description: "Read-only Libretto workflow for diagnosing live browser state without clicks, typing, navigation, or mutation requests."
license: MIT
metadata:
author: saffron-health
version: "0.6.41"
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
Read more
name: libretto-readonly description: "Read-only Libretto workflow for diagnosing live browser state without clicks, typing, navigation, or mutation requests." license: MIT metadata: author: saffron-health version: "0.6.41"
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
Libretto is a toolkit for building robust web integrations. It gives your coding agent a live browser and a token-efficient CLI to: Inspect live pages with minimal context overhead Capture network traffic to reverse-engineer site APIs Record user actions and
Repo: saffron-health/libretto
Other skills on libretto.
- /libretto
Browser automation CLI for building, maintaining, and running browser automation workflows by inspecting live pages and prototyping interactions.
Open skill - /dev-browser
Browser automation with persistent page state. Use when users ask to navigate websites, fill forms, take screenshots, extract web data, test web apps, or automate browser workflows. Trigger phrases include "go to [url]", "click on", "fill out the form", "take a screenshot",
Open skill - /libretto
Browser automation CLI for building, maintaining, and running browser automation workflows by inspecting live pages and prototyping interactions.
Open skill

