Give your agent a goal and a URL, and get back a complete browser automation script.
1Use the Libretto skill. Go on https://sfbay.craigslist.org and scrape the first 10 "free stuff" listings for title, location, and link.
12# What the agent runs behind the scenes npx libretto open https://sfbay.craigslist.org --headless --session one-shot-flow
--headless. You can mention "I need to log in first" in your prompt to be explicit.npx libretto snapshot and npx libretto exec in your terminal.The listings are in the main content area, not the sidebar.
workflow(). Here's roughly what to expect:1234567891011121314151617181920212223242526272829303132333435import { workflow } from "libretto"; import { z } from "zod"; const outputSchema = z.object({ listings: z.array(z.object({ title: z.string(), location: z.string(), link: z.string().url(), })), }); export default workflow( "freeStuff", { input: z.object({}), output: outputSchema, startUrl: "https://sfbay.craigslist.org/search/zip", }, async (ctx) => { const { page } = ctx; await page.waitForSelector(".result-row"); const rows = await page.locator(".result-row").all(); const listings = []; for (const row of rows.slice(0, 10)) { const title = await row.locator(".result-title").textContent(); const link = await row.locator("a").getAttribute("href"); // ... extract location } return { listings }; }, );
startUrl is set to the workflow's entry page12# What the agent runs npx libretto run ./free-stuff.ts --headless
The location is always empty. It looks like it's reading the wrong element.
npx libretto save.
Future runs can restore your login state so you don't have to authenticate
every time.npm create libretto@latest or npx libretto setup in your project root
if you haven't already.