Sitelooper

io.github.restspace由 GitHub 账号 restspace 发布v0.7.0更新于 Oct 29, 2026

Record a browser flow once with a model, then compile it to a Playwright spec that needs no model.

已验证STDIO仅桌面浏览器自动化开发者工具

概览

AI 生成的概览

用模型驱动的代理录制浏览器流程,再编译成无需模型的纯 Playwright 测试。

可以做什么
  • 打开浏览器会话、设置变量,并用一条可验证的指令或断言逐步操作页面
  • 查看当前页面的网址、标题与无障碍快照,或截取 PNG 截图
  • 把录制会话保存为命名流程、列出流程并导出流程包
  • 把流程编译成 Playwright 流程与测试,并以后台任务运行就绪检查、轮询任务状态
  • 针对漂移的步骤提出并应用修复,或单独重录某一步
  • 列出与停止浏览器会话,并检查浏览器、Node 及所用模型提供方等环境
适用场景
适合希望用自然语言编写端到端浏览器测试、再在 CI 中以普通 Playwright 运行的情况,也适合应用变更后修复已生成的测试。编写测试时让助手操作真实浏览器并核验结果同样适用。
运行要求
通过 npx 以 stdio 在本地运行,需要 Node 20+、可用的 Chromium 浏览器,编译后的测试还需要 @playwright/test。编写、修复与重录需要模型 API 密钥,默认是 OPENROUTER_API_KEY,也可使用其他提供方的密钥变量;doctor 会显示实际使用哪一个。需要能访问模型提供方与目标应用。
安装前请注意
模型密钥是付费凭据:编写、构建收敛、修复与重录都会调用模型并产生费用,而编译后的回放不产生费用。代理会操作真实浏览器,可能在目标应用中创建、修改或删除数据,应指向测试环境。凭据应以环境变量标记传入而非写入配置文件,TOTP 种子只应属于测试账号。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Sitelooper,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

sitelooper

Write browser tests in plain English. Run them in CI as plain Playwright. Repair them automatically when the app changes.

sitelooper is a CLI with a small LLM agent inside. You give it one instruction at a time, such as "sign in as [email protected], create a ticket titled 'k7 Bench' and report its id". It works the live browser and returns one verified result. Every step it gets right is compiled into a procedure that replays with no model, no tokens and no cost, and can be exported as a standalone @playwright/test spec.

[Three instructions recorded with the agent, then the same flow replayed with the model asleep]

Recorded once against the in-repo repair-desk app (24s, 28s and 42s with the agent driving). The app is reset, the same flow replays in 16s with zero model calls, and then the app's own state is queried.

How it works

  1. Record. A cheap model follows your instructions. As it works, sitelooper records durable locators, where each value came from, and what each step changed on the page.
  2. Replay. The recording replays deterministically. If the app has changed under a step, only that step goes back to the model, and a recovery that validates is pinned into the flow, so the flow heals itself over runs.
  3. Compile. sitelooper build emits a Playwright spec with effect checks on every step. It runs in CI with no sitelooper daemon and no model.

Results

Ten self-hosted apps, each job done once to record it, then twice more with no model, then as a compiled Playwright spec. The comparator is agent-browser driven by an LLM, which redoes the job on every run. Every run was scored against the app's own database or API, never against the tool's own report. September 2026:

appsitelooper, first runsitelooper replay ×2compiled specagent-browser, GPT-6 Lunaagent-browser, GPT-6.1 Sol
repair-desk6/6 · $0.02 · 187s6/6 · $0 · 52s6/66/6 · $0.016/6 · $0.29
Odoo6/6 · $0.07 · 589s6/6 · $0 · 193s6/63/6 · $0.026/6 · $0.37
Grafana6/6 · $0.09 · 615s6/6 · $0 · 145spass5/6, then 6/6 · $0.044/6 · $0.33
Kanboard6/6 · $0.05 · 357s6/6 · $0 · 56s4/4 + 2 report-only6/6, duplicate comment · $0.0056/6 · $0.23
OpenProject7/7 · $0.05 · 377s7/7 · $0 · 93-132s5/5 + 2 report-only7/7, duplicate comment · $0.027/7 · $0.38
Gitea7/7 · $0.04 · 324s7/7 · $0 · 76s5/5 + 2 report-only6/7 · $0.097/7 · $0.25
Vikunja7/7 · $0.04 · 270s7/7 · $0 · 76s5/5 + 2 report-only7/7, duplicate comment · $0.017/7 · $0.28
EspoCRM7/7 · $0.06 · 454s7/7 · $0 · 165srefused to compile1/7 · $0.027/7 · $0.23
Snipe-IT7/7 · $0.04 · 298s7/7 · $0 · 78s5/5 + 2 report-only1/7 · $0.027/7 · $0.25
Ghost7/7 · $0.02 · 142s7/7 · $0 · 46s5/5 + 2 report-only7/7 · $0.0057/7 · $0.10
  • sitelooper verified every objective in all 30 runs, with GPT-6 Luna writing the instructions and DeepSeek V4.1 Flash driving the browser. Every replay ran with zero model calls. Nine of the ten compiled specs pass; EspoCRM's refuses to compile rather than guess.
  • agent-browser on the same model was clean on 3 of 11 runs. It failed outright on Odoo, EspoCRM and Snipe-IT, posted duplicate comments on three apps, and twice reported work as done that the app had not saved.
  • On GPT-6.1 Sol, about 20× the per-token price, agent-browser was clean on 9 of 10. It still pays that price on every run, and on Grafana it again reported unsaved settings as verified.

Report-only objectives ask a run to state a value in its final report, which a compiled spec does not write.

Quick start

You need Node 20+ and an OpenRouter API key for authoring. The compiled tests need only @playwright/test.

sh
npm install -g siteloopernpm install -D @playwright/test && npx playwright install chromiumexport OPENROUTER_API_KEY=sk-or-...sitelooper doctor        # shows the provider and models it will use, and whysitelooper init          # writes sitelooper.config.json

Record one logical outcome per instruction. Use {{env:NAME}} for credentials, and declare values that should change between runs with var. Here, demo becomes a {{runid}} slot:

sh
sitelooper --session ticket --learn open http://localhost:3000sitelooper --session ticket var runid=demositelooper --session ticket do "Sign in as {{env:TEST_USER}} using {{env:TEST_PASSWORD}} and verify the dashboard opens"sitelooper --session ticket do "Create a ticket titled 'demo Test'; verify it appears and report its id"sitelooper --session ticket assert "the ticket list shows 'demo Test' with status Open"sitelooper --session ticket stop --save-flow ticketsitelooper flow export ticket --out .sitelooper/procedures.json

Build the test and run it:

sh
sitelooper build ticket --var runid=test-{n} --reset-cmd "npm run reset:e2e"# or, if your Playwright fixtures already prepare fresh data:# sitelooper build ticket --var runid=test-{n} --fixture-isolation# with a reset command, build converges by default (2 rounds): it re-records the steps a refusal or# a failing spec names (the model works those steps only). Tune or opt out:# sitelooper build ticket --var runid=test-{n} --reset-cmd "npm run reset:e2e" --converge 3 [--rerecord-runs 2] [--json]# sitelooper build ticket --var runid=test-{n} --reset-cmd "npm run reset:e2e" --no-convergenpx playwright test tests/sitelooper/ticket.spec.ts

ticket.flow.ts is generated: it holds the procedures, a typed input/output API, named steps and effect checks. ticket.spec.ts belongs to you. Add business assertions and fixtures there, and recompiling will never overwrite it.

Why an agent's own script doesn't rerun

Asking the agent to write a script from what it did fails for structural reasons:

  • The run's values are baked in. The script quotes today's record id, so tomorrow it opens yesterday's record, or works the wrong one to completion and reports success.
  • The selectors name positions, not things. tr:nth-of-type(3), generated class names, a textbox named after the current minute.
  • The waits are gone. Each of the agent's observation turns was a pause the app needed.
  • Nobody checks the effect. A click can "succeed" on the wrong element, and a save can be refused by a dialog the script never saw.

sitelooper treats the recording as evidence to compile, not text to replay:

  • Locator chains, including role and name, label, test id and a structural path. Candidates are retired by measuring which ones resolve on each replay.
  • Parameters, not literals. Typed values become slots, and declared values become {{runid}}. A value that one step read and a later step used is threaded between them live. An id the app minted is re-read on each run, and anything with no source is left for recovery instead of being guessed.
  • Effect gates. A step that ran but did not produce its recorded effect stops the replay before the next step acts on the wrong state.
  • A recovery ladder. Each step first replays with zero model calls. If that fails, a cheap model recovers it; if that is blocked, a stronger model tries; if that fails too, the run halts and reports per-step state.
  • Nothing app-specific in the tool. App knowledge goes in an optional per-session briefing, so a fix for one app never becomes a hack for it.

Using it in a project

Readiness means running the emitted code

build <flow-or-bundle> compiles the flow and runs the readiness gate. check <name.flow.ts> --ready runs the same gate on an existing artifact. Plain compile works offline, and plain check runs the spec once.

build also converges by default when a reset command is available (--reset-cmd or resetCommand in the project config): it runs the compiled spec once and, if the compile is refused, the spec fails, or it passes only through a blocking locator fallback (below), re-records the step it names (2 rounds; --converge N sets the count), then runs the readiness gate on the spec that passed. Without a reset command it cannot check against a clean app, so it compiles and runs readiness exactly as before and prints one line (and, with --json, a convergence: { skipped: true, why } field) saying convergence was skipped. Re-recording calls the model: with no API key configured, build compiles and checks once and stops with status unavailable if a re-record is needed. --no-converge restores compile plus readiness only.

Convergence also redoes work the recording did that the flow left out. An instruction that changed the app but did not report success is not a flow step (omitted in the flow file, an omitted-work warning at compile); when nothing later in the flow entered its values again, build puts the instruction back as a step where it was recorded (04b-… after 04-…, so no existing step id moves), re-records it with the model, and drops the omission once the step is pinned. Without convergence build stops before readiness and says which instruction is missing: a spec that passes without that work does not show the task was done. Plain compile still only warns.

The gate requires three clean executions with retries disabled. Each run starts from state prepared by the reset command or by declared fixtures, and it uses at least two distinct datasets ({n} becomes 1, 2, 3). No step may be skipped or unresolved, and no locator fallback may decide what a run acts on or uses: a fallback on an action, or on a read whose value a later step or assertion uses, blocks. A fallback on a read that only feeds the final report is listed under warnings in the evidence and does not block. Convergence applies the same rule, so a spec it calls converged is not refused by readiness for the same fallback. The gate uses your Playwright config and project (--config, --project). Evidence goes to <name>.readiness.json, or to --report <file.json>. Three clean runs are an execution gate, not a statistical guarantee against flakiness.

--negative-spec <file> adds an authored fault-injection test that must fail its outcome assertion, and it reports failureDetection: verified. See project fixtures and negative checks.

Assertions: conditions that must hold on every run

do records what the agent did. assert records something you want to be true, and it makes that check impossible to skip. It takes a sentence and never acts on the page:

sh
sitelooper --session ticket assert "the order total is 370.00"sitelooper --session ticket assert "no error banner is showing"

The sentence is checked against the page now. Exit 0 means it held, 1 means it did not, and 2 means the check could not run. In a --learn session a passing assert is also recorded as its own step of the saved flow. A model finds the element once, at record time. After that the step replays and compiles with no model.

An assert can record seven conditions: an element is visible, an element is hidden, its text equals a value, its text contains a value, a count of matching elements, a form field's value, and the page url contains a value.

The expected value must be written in the sentence. It can be a literal, the value of a declared var, or a value an earlier step reported. A value the agent only read off the page does not count: "the total is correct" would turn into "the total equals whatever it shows", and the page would agree with itself on every run. If the sentence states no value to compare with, the assert fails and says so.

A recorded assert is strict. If it does not hold, or its element cannot be found, there is no recovery ladder, no model call and no re-pin, and nothing may skip it as already done:

  • In sitelooper run the step's status is assert-failed and the flow halts.
  • In the compiled spec the test fails with assertion failed: <your sentence> — <detail>, or assertion could not be checked: <your sentence> — <detail> when no recorded locator found the element.

assert is for conditions a sentence can state. For anything else, such as a computed comparison or a check against the app's own API, write an expect call in your .spec.ts. That file is yours, and recompiling never overwrites it. See choosing between the two.

Project configuration

sitelooper init creates sitelooper.config.json. The nearest ancestor config supplies defaults, and CLI flags override them. Never put credentials in this file.

json
{  "targetUrl": "http://localhost:3000",  "vars": { "runid": "test-{n}" },  "requiredVars": ["runid"],  "resetCommand": "npm run reset:e2e",  "playwright": { "config": "playwright.config.ts", "project": "chromium" },  "verificationRuns": 3,  "outputDir": "tests/sitelooper",  "snapshotFile": ".sitelooper/procedures.json",  "style": "runtime"}

targetUrl may be relative to Playwright's baseURL. A runtime-style spec still expects the origin it was recorded on: SITELOOPER_TARGET_URL moves only its first page load, and its URL checks compare the origin exactly. So record on the origin your CI serves, or use --style readable, whose URLs are relative. fixtureIsolation: true replaces the reset command. flow export bundles a flow with its pinned procedures so that another machine can compile it. Commit the bundle, the config and the generated files.

One-time codes

Put a test account's TOTP seed (base32, or the whole otpauth:// URI) in an environment variable and write {{totp:NAME}} where the code goes. The code is generated when it is typed. Recordings and compiled specs keep only the marker, never the seed or a code.

sh
export TEST_TOTP=JBSWY3DPEHPK3PXP   # a test user's seed, never a real person'ssitelooper --session ticket do "Enter the authentication code {{totp:TEST_TOTP}} and verify the dashboard opens"

Repair once, review, apply

sh
sitelooper repair tests/sitelooper/ticket.flow.ts --propose ticket-repair.json \  --var runid=repair-{n} --reset-cmd "npm run reset:e2e"sitelooper repair apply ticket-repair.json

A proposal does a live triage run and convergence runs, and then checks a staged candidate under plain Playwright next to your original spec. Review it before you apply it. apply writes exactly the source that was checked, and it refuses if anything has changed since then. Your .spec.ts is never rewritten. When a diagnostic points at a bad recording, run rerecord <flow> <step> to re-record just that step in isolation.

Override flags are kept separate: --allow-demoted accepts a diagnosed demoted procedure, and --overwrite-spec replaces the user scaffold.

Readable specs

By default compile writes the runtime style: a .flow.ts that carries the recording and the code that replays it, with fallback locators and drift reporting. It works, but it is large and nobody reviews it by reading it. --style readable writes plain Playwright code instead, one function per step and one locator per action, the kind of file you would write by hand:

sh
sitelooper compile .sitelooper/procedures.json --style readablesitelooper build ticket --var runid=test-{n} --reset-cmd "npm run reset:e2e" --style readable

Use it for code that will be contributed to another project or reviewed by people. The readable file gives up two things on purpose: there is no locator fallback at run time, and no drift lines. When the app changes, the test fails at the step that broke, like any hand-written test. Its URLs are relative, so it runs on whatever origin Playwright's baseURL names, not only the one it was recorded on.

The recording stays in the bundle (flow export, or the project's snapshotFile). The readable file names it on a // @sitelooper-source line, and it is still generated: it is rewritten on every compile, rerecord and repair, so edit the bundle (by re-recording) rather than the file. Your .spec.ts is unchanged and works with either style.

  • A file keeps its style. A recompile writes the style the existing file has, unless you pass --style. "style": "readable" in sitelooper.config.json sets the style of new files; the default is still runtime.
  • compile, build, rerecord and repair accept the readable <name>.flow.ts itself and find the bundle from it (then the project snapshot, then your user store).
  • rerecord <name.flow.ts> <step> re-records the step into the bundle and recompiles the file.
  • repair <name.flow.ts> on a readable file runs the spec once, re-records the step it fails at, recompiles and checks again (--converge N rounds). It needs a model key. --propose, --dry-run and --out are not supported for readable files yet; use rerecord and then compile --style readable, and review the diff.
  • check and readiness work the same way on both styles. A readable file whose bundle has changed since it was compiled is reported as stale (a warning) until you recompile it.
  • --json result documents include style.

To hand the file over for good, as code that is yours (or another project's) to maintain, add --standalone:

sh
sitelooper compile .sitelooper/procedures.json --style readable --standalone

The file then has no regenerate header and no @sitelooper-source link, and nothing in it depends on sitelooper. It also leaves out what only sitelooper reads: the @step markers, the step log lines, the metadata exports, the run record, and values no later step uses. The .spec.ts written beside it is a plain test with no run record; if a .spec.ts written for a generated file is already there (it uses createFlowRun), compile stops, so pass --overwrite-spec to replace it. Edit both like any other test. sitelooper won't regenerate them: a later compile refuses to overwrite a .flow.ts it did not generate, so move the file or pass --out <dir>.

Calling from another agent

--json returns versioned results (schemaVersion, stage, outcome, nextActions as argument arrays). --report <file.json> writes the same document to a fixed path. Progress goes to stderr. For multiline instructions, use do --instruction-file <file> or do --stdin.

do returns {report: {status, summary, details?, evidence?}, turns, usage, model}. On a turn or time cap it also returns actions, the tool calls that ran, so a caller can check state before resuming. Snapshots, retries and tool chatter stay inside the daemon.

Exit codes: 0 success, 1 agent/recording failure, 2 invalid input, 3 replay convergence failure, 4 compiled-spec/readiness failure.

Claude Code plugin

The sitelooper plugin teaches Claude to write browser tests, repair them and drive the browser with this CLI. It has three skills (write-browser-test, fix-browser-test, sitelooper) and no hooks or servers:

/plugin marketplace add restspace/sitelooper/plugin install sitelooper@sitelooper

The skills are in plugin/skills/, and they also ship in the npm package. To use them without the plugin, copy each folder to ~/.claude/skills/. See plugin/README.md for what the plugin runs and sends.

MCP server

sitelooper mcp is a stdio MCP server. It gives an MCP client tools to open a page, run do and assert, build and check a flow, and repair or re-record a step. It runs the CLI underneath, so sessions are shared with your terminal. Set your model key (for example OPENROUTER_API_KEY) in your own environment. Prefer inheriting it or a prompted input to writing it into a JSON file.

Claude Code:

claude mcp add --transport stdio sitelooper -- npx -y [email protected] mcp

Add --scope project to share it through .mcp.json, or --scope user for all projects. The key is inherited from the shell that starts Claude Code. On native Windows, use -- cmd /c npx -y [email protected] mcp.

Cursor (.cursor/mcp.json, or ~/.cursor/mcp.json for all projects), Claude Desktop (claude_desktop_config.json) and Windsurf (mcp_config.json) use the same shape:

json
{  "mcpServers": {    "sitelooper": {      "command": "npx",      "args": ["-y", "[email protected]", "mcp"],      "env": { "OPENROUTER_API_KEY": "${env:OPENROUTER_API_KEY}" }    }  }}

${env:NAME} reads the variable from your environment in Cursor and Windsurf. In Claude Desktop, leave env out and set the key as a user environment variable before you start the app.

VS Code (.vscode/mcp.json) uses servers and can prompt for the key without storing it:

json
{  "inputs": [    { "type": "promptString", "id": "sl-key", "description": "Model API key", "password": true }  ],  "servers": {    "sitelooper": {      "type": "stdio",      "command": "npx",      "args": ["-y", "[email protected]", "mcp"],      "env": { "OPENROUTER_API_KEY": "${input:sl-key}" }    }  }}

Tools: open, do, assert, set_var, peek, screenshot, save_flow, list_flows, build_start, check, repair_propose, repair_apply, rerecord, job_status, sessions, stop, doctor. Builds and other long runs return a job_id to poll with job_status. The tools have no style option: they compile in the style the project config or the existing file sets, so set "style": "readable" in sitelooper.config.json to get readable files. See docs/mcp.md for inputs, safety rules and troubleshooting.

Reference

Providers

The LLM layer is an OpenAI-compatible adapter with presets.

PresetBase URLDefault modelEscalation modelKey env var
openrouter (default)https://openrouter.ai/api/v1deepseek/deepseek-v4.1-flash (DeepSeek backend)z-ai/glm-5.3OPENROUTER_API_KEY
zhipuhttps://api.z.ai/api/paas/v4glm-5.2—GLM_API_KEY / ZHIPU_API_KEY
novitahttps://api.novita.ai/openaideepseek/deepseek-v4-flashzai-org/glm-5.3NOVITA_API_KEY
openaihttps://api.openai.com/v1gpt-5-mini—OPENAI_API_KEY
anthropichttps://api.anthropic.com (native Messages API)claude-sonnet-5—ANTHROPIC_API_KEY

Every field resolves in the order flag > env > config file > preset: --provider, --model, --base-url, --fallback-model; SITELOOPER_PROVIDER, SITELOOPER_MODEL, SITELOOPER_FALLBACK_MODEL, SITELOOPER_BASE_URL, SITELOOPER_API_KEY; and sitelooper config set <key> <value>, which writes ~/.sitelooper/config.json. Prefer env for the key.

  • No provider named. A Z.ai key keeps zhipu. Otherwise OPENROUTER_API_KEY selects openrouter, a generic SITELOOPER_API_KEY goes to zhipu, and with no key at all the default is openrouter. sitelooper doctor prints the choice and the reason.
  • Routing pin. With its default model, the openrouter preset sends {"provider":{"only":["DeepSeek"]}}, which is the backend the benchmark prices assume. SITELOOPER_EXTRA_BODY replaces it, and '{}' turns it off. SITELOOPER_FALLBACK_EXTRA_BODY sets the same for the escalation model.
  • Escalation. An instruction reported blocked is retried once on the escalation model, in the same browser, which is told to re-check state before it repeats anything. A verified failure is not retried. --no-escalate turns this off.

Configuration

Env / flagDefault
SITELOOPER_CHANNELchrome → msedge → bundledbrowser channel
SITELOOPER_EXECUTABLE—explicit browser binary
SITELOOPER_HEADED=1, --headedheadlessvisible window (first call of a session)
SITELOOPER_HOME~/.siteloopersessions, skills, flows, config
SITELOOPER_SKILLS=1, --learnofflearning mode; SITELOOPER_SKILLS_DIR relocates the store
SITELOOPER_FLOWS_DIR~/.sitelooper/flowsflow files
SITELOOPER_RECORD=1, --recordoffwebm per tab; paths printed by stop
SITELOOPER_SCRIPT=1, --scriptoffrecord every action as a raw Playwright step (exploratory)
--max-turns30agent turn cap per instruction
--timeout300wall-clock seconds per instruction
--turn-timeout90seconds for one LLM call before it is aborted and nudged

Run sitelooper --help for the full command reference.

What it will not do

  • Canvas-rendered content has no DOM to read or verify. The agent reports blocked.
  • Anti-bot evasion, CAPTCHA solving and crawling are out of scope. sitelooper is for apps you operate or are authorised to test.
  • Vision. The agent is text-only and reads the accessibility tree and the DOM.
  • Guessing credentials. A missing or rejected credential is reported as blocked immediately, never retried.

Development

sh
npm run build                         # tsc -> dist/npm test                              # unit testsBP_BROWSER_TESTS=1 npx vitest run     # + browser-backed replay tests (needs Chrome/Edge)

test/rebuild.test.ts recompiles real published recordings and pins what they compile to. It runs the built engine, so build before you test. The benchmark procedure and targets are under bench/.

sitelooper was previously published on npm as sleep-walker. Env-var prefixes and home directories from its earlier names still work as aliases; the old command names do not.

来源:README.md,提交 7b4b596

工具

17

open

Navigate a browser session to a URL (no model involved); starts the session if it is not running. learn and headed apply only when this call starts the session: learn=true records every later do/assert as a reusable flow step (needed before save_flow). Typical authoring: open (learn) → set_var → do/assert per outcome → save_flow → build_start.

输入参数cwdurl必填learnheadedsession

do

Have the agent perform ONE verifiable outcome in the session's browser and verify it, e.g. "create a customer named {{runid}} and confirm it appears in the list". One verifiable outcome per do: split multi-part tasks into several calls. State expected values in the sentence. Credentials: write each secret as one {{env:NAME}} marker ({{totp:NAME}} for a one-time code), exactly as written: the marker alone, never the value and never $NAME. NAME must be set in the environment the MCP server was started with. Never ask the user for a secret value. Needs a model API key in the server environment. Returns the report (status, summary, evidence values). Exit 1 = the agent could not complete it.

输入参数cwdsessionmax_turnstimeout_sinstruction必填

assert

Check a condition on the current page now; never acts. State the expected text in the sentence, e.g. "the order list shows a row with total 42.00". In a learn session a passing assert becomes a flow step that fails the run when it does not hold. Credentials: write each secret as one {{env:NAME}} marker ({{totp:NAME}} for a one-time code), exactly as written: the marker alone, never the value and never $NAME. NAME must be set in the environment the MCP server was started with. Never ask the user for a secret value. isError with exit 1 = the condition did not hold; exit 2 = could not be checked.

输入参数cwdsessioncondition必填timeout_s

set_var

Set a session variable that later instructions reference as {{name}}; in a learn session it becomes a flow variable that build/check bind with vars. Not for secrets (use {{env:NAME}} markers).

输入参数cwdname必填value必填session

peek

Return the session page's URL, title and an accessibility snapshot (no model, no actions).

输入参数cwdsessionselectorinteractive

screenshot

Capture the session page as a PNG; returns the image and the file path it was saved to.

输入参数cwdsessionfull_page

save_flow

Stop a learn session, save what it recorded as a named flow, then export the flow with its pinned procedures to a bundle file (default .sitelooper/procedures.json in cwd). Closes the session's browser. Then call build_start with the flow name.

输入参数cwdname必填bundlesession

list_flows

List saved flows with their step counts, variables and origin.

输入参数cwd

build_start

Start a background job that compiles a saved flow (or bundle) into a Playwright .flow.ts/.spec.ts and verifies it (readiness: clean runs). With a reset command (sitelooper.config.json resetCommand) it first converges, re-recording failing steps with the model. Readiness needs a reset command or fixture_isolation. Returns a job_id at once: poll job_status until done/failed (minutes).

输入参数cwdflow必填varsconvergefixture_isolation

check

Run a compiled <name>.flow.ts once under plain Playwright (no model) and report pass/fail (exit 4 = failed, 2 = could not run). With ready=true it runs the readiness gate (several clean runs) as a background job: the call returns a job_id; poll job_status.

输入参数cwdrunsvarsreadyflow_file必填fixture_isolation

repair_propose

Start a background job that replays a compiled .flow.ts against the app, repairs drifted steps and stages a checked candidate as a proposal file for review (repair --propose); never rewrites the spec. Returns a job_id: poll job_status. Apply a good proposal with repair_apply.

输入参数cwdvarsflow_file必填proposal_file必填

repair_apply

Apply a proposal staged by repair_propose to its flow file exactly as checked (no browser run).

输入参数cwdproposal_file必填

rerecord

Start a background job that re-records one step of a flow with the agent (optionally with a new instruction), then verifies it over several runs and re-pins it. Needs a model API key. Credentials: write each secret as one {{env:NAME}} marker ({{totp:NAME}} for a one-time code), exactly as written: the marker alone, never the value and never $NAME. NAME must be set in the environment the MCP server was started with. Never ask the user for a secret value. Returns a job_id: poll job_status.

输入参数cwdflow必填runsvarsstep_id必填instruction

job_status

Report a background job started by build_start, check (ready), repair_propose or rerecord: status running|done|failed, the last progress lines, and the final JSON result and exit code when finished. Waits up to wait_s seconds for the job to finish before answering.

输入参数job_id必填wait_s

sessions

List browser sessions and whether each is running.

输入参数cwd

stop

Stop a browser session (closes its browser and daemon) without saving a flow. Use save_flow instead to keep a learn session's recording.

输入参数cwdsession

doctor

Inspect the setup: browser, Node, and which model provider/API key is in use and why (never shows the key).

输入参数cwd

版本历史

1
  1. v0.7.0最新Oct 22, 2026

评分

已满足适用检查项的 90%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分
  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分