LLM USAGE GUIDE:
  Write small, focused scripts. Each script should do ONE thing: navigate, click, fill, or check.
  End each script by logging the state you need for the next decision.
  Use descriptive page names like "login", "checkout", or "results" instead of "page1".
  Named pages from browser.getPage("name") persist between script runs, so you usually do not need to re-navigate.
  Inside page.evaluate(...), write plain JavaScript only - no TypeScript syntax in the browser context.
  On Windows/PowerShell, use here-strings to pipe multiline scripts:
    @"
    const page = await browser.getPage("main");
    console.log(await page.title());
    "@ | dev-browser --connect

  Quick inspection:
    dev-browser --connect <<'EOF'
    const tabs = await browser.listPages();
    console.log(JSON.stringify(tabs, null, 2));
    EOF

    dev-browser --connect <<'EOF'
    const page = await browser.getPage("TARGET_ID_HERE");
    console.log(JSON.stringify({
      url: page.url(),
      title: await page.title(),
    }, null, 2));
    EOF

  AI snapshots for element discovery:
    dev-browser <<'EOF'
    const page = await browser.getPage("main");
    const result = await page.snapshotForAI();
    console.log(result.full);
    // Returns { full: string, incremental?: string }.
    // Optional args: { track?: string, depth?: number, timeout?: number }.
    // Read result.full to identify the right element.
    // Then interact with it using Playwright:
    // await page.getByRole("button", { name: "Continue" }).click();
    // Re-run page.snapshotForAI({ track: "main" }) after the page changes.
    EOF

  Choosing your approach:
    Unknown pages: use page.snapshotForAI() first to discover the page, then interact based on what you find.
    Known pages/selectors: skip the snapshot and use direct Playwright selectors like page.click(), page.fill(), or page.locator() for faster, more reliable automation.
    Prefer locators/snapshotForAI first; switch to page.domCua node ids when a unique stable locator can't be built or after 2 failed locator attempts on the same target; switch to page.cua coordinates when the visual structure is clearer than the DOM.
    After acting, collect the cheapest state check; don't take both a snapshot and a screenshot by default.

  Vision workflow (page.cua):
    Coordinate-based control across two scripts on a named page.
    Script 1 - look: take a screenshot, then read the saved image to pick coordinates.
    dev-browser <<'EOF'
    const page = await browser.getPage("checkout");
    const shot = await page.cua.screenshot();
    console.log(JSON.stringify(shot));
    // {"path":"/Users/you/.dev-browser/tmp/cua-page_abc123.jpeg","width":1280,"height":720}
    EOF
    Script 2 - act: click at the coordinates measured on the image.
    dev-browser <<'EOF'
    const page = await browser.getPage("checkout");
    await page.cua.click({ x: 412, y: 233 });
    console.log(page.url());
    EOF
    Pixel coordinates measured on the saved image map 1:1 onto page.cua coordinates (any display, any DPR).
    Always use a named page so coordinates stay valid between scripts.
    This holds for viewport and clip screenshots only — never derive click coordinates from a fullPage capture; scroll, then re-screenshot.
    Also available: cua.doubleClick({x, y}), cua.drag({path: [{x, y}, ...]}), cua.move({x, y}),
    cua.scroll({x, y, scrollX, scrollY}) (positive scrollY scrolls content down),
    cua.keypress({keys: ["ctrl", "a"]}), cua.type({text}).
    cua.click and domCua.click wait ~1s for a click-triggered navigation (then up to 10s for the load);
    pass waitForNavigation: false to skip that grace wait in tight loops.

  DOM-id workflow (page.domCua):
    Snapshot the visible interactive elements, then act on them by node id.
    dev-browser <<'EOF'
    const page = await browser.getPage("checkout");
    console.log(await page.domCua.getVisibleDom());
    // <input node_id=1 type="text" placeholder="name here" />
    // <button node_id=2>Submit</button>
    // <a node_id=3 href="https://example.com">Example link</a>
    EOF
    dev-browser <<'EOF'
    const page = await browser.getPage("checkout");
    await page.domCua.click({ nodeId: 2 });
    console.log(page.url());
    EOF
    Ids are only valid against the latest snapshot of the current document.
    A "DOM node N is stale or missing — re-run getVisibleDom()" error means the id predates the latest snapshot or the document changed; re-run getVisibleDom() and use the fresh ids.
    Re-snapshot after every navigation - ids from the old document never act on the new one.
    The snapshot only includes elements visible in the viewport; scroll and re-snapshot to see more.
    A truncation marker line appears when the snapshot budget is hit.
    Also available: domCua.doubleClick({nodeId}), domCua.scroll({scrollX, scrollY, nodeId?}),
    domCua.type({text}) and domCua.keypress({keys}) (both act on the focused element - click first).

  Screenshots for visual state:
    dev-browser <<'EOF'
    const page = await browser.getPage("main");
    const buf = await page.screenshot();
    const path = await saveScreenshot(buf, "debug.png");
    console.log(path);
    EOF

  Waiting patterns:
    dev-browser <<'EOF'
    const page = await browser.getPage("search-results");
    await page.waitForSelector(".results");
    await page.waitForURL("**/success");
    console.log(JSON.stringify({
      url: page.url(),
      title: await page.title(),
    }, null, 2));
    EOF

  Dev server navigation:
    For local dev servers (Next.js, Vite, etc.), prefer:
      await page.goto(url, { waitUntil: "domcontentloaded" });
    The default "load" wait can hang on HMR, streaming, or other long-lived dev-server connections.
    Use "load" only when you specifically need every subresource to finish loading.

  Error recovery:
    If a script fails, the page usually stays where it stopped.
    Reconnect to the same page name, take a screenshot, and log the URL/title:
    dev-browser <<'EOF'
    const page = await browser.getPage("checkout");
    const path = await saveScreenshot(await page.screenshot(), "debug.png");
    console.log(JSON.stringify({
      screenshot: path,
      url: page.url(),
      title: await page.title(),
    }, null, 2));
    EOF

  Common Playwright Page methods:
    page.goto(url, { waitUntil: "domcontentloaded" })
                                           Navigate to a URL; prefer this on dev servers
    page.title()                           Get the current page title
    page.url()                             Get the current URL
    page.snapshotForAI(options)            Get an AI-optimized snapshot; returns { full, incremental? }
                                           Options: { track?: string, depth?: number, timeout?: number }
    page.getByRole(role, { name })         Target elements discovered from the snapshot
    page.textContent(selector)             Get the text content of an element
    page.innerHTML(selector)               Get the inner HTML of an element
    page.fill(selector, value)             Fill an input field
    page.click(selector)                   Click an element
    page.type(selector, text)              Type text character by character
    page.press(selector, key)              Press a key such as Enter or Tab
    page.waitForSelector(selector)         Wait for an element to appear
    page.waitForURL(url)                   Wait for navigation to a URL
    page.screenshot()                      Capture a screenshot buffer; save it with saveScreenshot(...)
    page.cua.screenshot(options)           Save a JPEG for the vision workflow; returns { path, width, height }
                                           Options: { name?: string, fullPage?: boolean, clip? }
    page.cua.click({ x, y })               Click at viewport coordinates measured on a cua screenshot
    page.domCua.getVisibleDom()            Snapshot visible interactive elements as node_id=N lines
    page.domCua.click({ nodeId })          Click an element by node id from the latest snapshot
    page.$$eval(selector, fn)              Run a function on all matching elements
    page.$eval(selector, fn)               Run a function on the first matching element
    page.evaluate(fn)                      Run JavaScript in the page context (plain JS only)
    page.locator(selector)                 Create a locator for chained actions

  Connecting to a running Chrome instance:
    Auto-discover Chrome with debugging enabled:
      dev-browser --connect <<'EOF'
        const page = await browser.getPage("main");
        console.log(await page.title());
      EOF

    Connect to a specific CDP endpoint:
      dev-browser --connect http://localhost:9222 <<'EOF'
        const page = await browser.getPage("main");
        console.log(await page.title());
      EOF

    To launch Chrome with debugging enabled:
      chrome.exe --remote-debugging-port=9222
      google-chrome --remote-debugging-port=9222

    Or visit chrome://inspect/#remote-debugging to configure.

  Tips:
    - Use console.log(JSON.stringify(...)) for structured output.
    - Prefer page.snapshotForAI() for structure; use screenshots when visual layout or styling matters.
    - Keep page names stable across scripts so you can resume work after failures.
    - Each --browser name maps to a separate daemon-managed browser instance.
    - Use --connect to attach to an existing browser; omit the URL to auto-discover Chrome with debugging enabled.
    - Use short timeouts (--timeout 10) so scripts fail fast instead of hanging on missing elements.
    - Add --headless for unattended automation; omit it when you want to watch the browser window.
