Saved queries & login profiles
Saved queries
Section titled “Saved queries”A saved query is a named, replayable extract spec — URL + schema + instruction stored once, run whenever you need fresh data:
sortie query save books --url https://books.toscrape.com --schema @schema.jsonsortie query run books # later, and again, and againsortie query run books --url https://books.toscrape.com/catalogue/page-2.html- Save a spec inline, or promote a past run that worked with
query save <name> --from-run <run-id>. - Replays are real queue runs persisted to SQLite and linked back by name — filter history with
runs list/GET /api/runs?query=<name>; the query trackslastRunAtandrunCount. - One-off overrides (
--url,--instruction) apply to a single replay without touching the saved spec — ideal for running the same schema across many pages. - Available everywhere: CLI, REST (
/api/queries,POST /api/queries/:name/run), the MCPrun_saved_querytool, and the playground’s Queries view (plus “Save as query” on any extract run).
Login profiles
Section titled “Login profiles”Many useful pages live behind a login. A profile is a named, locally stored browser session (Playwright storage state: cookies + localStorage) that any run can start from:
sortie profile login github --url https://github.com/login # log in by hand, press Entersortie extract https://github.com/notifications --profile github --schema @notif.jsonsortie agent https://shop.example --goal "…" --cred SHOP_PASSWORD --save-profile shopCreate one by logging in manually in a headful browser (profile login), or capture the session from a successful agent login (--save-profile). profile list / profile check show a staleness summary (cookie counts, domains, earliest expiry) so you know when to re-login.
Security model
Section titled “Security model”- Profile state lives only on disk at
<dataDir>/profiles/<name>.json(directory0700, file0600). - Never in the database, never in logs or prompts, and never returned by the API.
- Profile names are slug-gated (
a-z0-9_-) as a path-traversal defense. --profileis mutually exclusive with--storage-state, so there’s no silent precedence.
Profiles on a remote/Docker host
Section titled “Profiles on a remote/Docker host”Sessions are created interactively, so bootstrap a headless server from a machine with a display:
# Option A — import over the API (write-only: the server stores the file 0600# and responds with metadata + cookie summary only, never the state itself):sortie profile login shop --url https://shop.example # locallycurl -X POST http://your-host:3470/api/profiles/import \ -H 'content-type: application/json' \ -d "{\"name\":\"shop\",\"state\":$(cat data/profiles/shop.json)}"
# Option B — docker cp fallback (no API call): copy the storage-state file# into the data volume and reference it per-run via "storageStatePath":docker compose cp data/profiles/shop.json sortie:/data/shop-state.jsondocker compose exec sortie chmod 600 /data/shop-state.json# then in run/batch specs: "storageStatePath": "/data/shop-state.json"