Runs UI verification specs in-session through the claude-in-chrome extension — the Chrome sibling of the aw-tester agent. Reads the same specs.md and aw-target.yml, drives Chrome interactively (navigate → read → act → assert, seeing the page between steps), and emits the same compact verdict block. Runs in the current session against an already-logged-in Chrome, so it is faster than the Playwright sub-agent for local runs, but it needs the browser extension and does not work in remote / CI en...
Scanned 9/3/2026
Install to Claude Code
npx -y skills add mthines/agent-skills --skill aw-tester-chrome --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Aw Tester Chrome?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/mthines-aw-tester-chrome)More formats (shields.io, HTML) on the badges page.
---
name: aw-tester-chrome
description: >
Runs UI verification specs in-session through the claude-in-chrome extension —
the Chrome sibling of the aw-tester agent. Reads the same specs.md and
aw-target.yml, drives Chrome interactively (navigate → read → act → assert,
seeing the page between steps), and emits the same compact verdict block. Runs
in the current session against an already-logged-in Chrome, so it is faster
than the Playwright sub-agent for local runs, but it needs the browser
extension and does not work in remote / CI envs. Falls back to aw-tester when
the extension is not connected. Triggers on "run the spec in chrome", "verify
with the chrome driver", "aw-tester-chrome", or a "preview-spec run
--driver chrome" dispatch.
disable-model-invocation: false
argument-hint: '[specs-path] [aw-target] [--all|--bail-on-first-red]'
license: MIT
metadata:
author: mthines
version: '1.0.0'
workflow_type: skill
tags:
- aw-tester
- aw-tester-chrome
- claude-in-chrome
- ui-verification
- spec-run
- autonomous-workflow
---
# aw-tester-chrome — In-Session Spec Runner
You are the **Chrome runner**. Same spec, same verdict as [`aw-tester`](../templates/aw-tester.agent.md) —
different engine. You drive the user's real Chrome through the claude-in-chrome
extension, in this session, seeing the page between every step. That see→act loop
is the point: no throwaway batch script, no blind compile, and the browser is
already logged in, so a local run is fast.
**Read the [spec-run contract](../rules/spec-run-contract.md) first.** It owns the
locator ladder, the auth semantics, the spec-parsing rules, and the verdict
schema. This file owns only how Chrome executes them. Where the two ever disagree,
the contract wins.
> [!NOTE]
> This runner needs the claude-in-chrome browser extension. It is a **local,
> in-session** tool. It cannot run inside a sub-agent (sub-agents have no
> claude-in-chrome tools) and cannot run in a remote / CI environment. Those
> callers use `aw-tester` (Playwright). See § Preflight for the fallback.
---
## Critical First Actions
### 1. Load the browser tools
If the `mcp__claude-in-chrome__*` tools are deferred, load the set you need in
one call:
```text
ToolSearch "select:mcp__claude-in-chrome__tabs_context_mcp,mcp__claude-in-chrome__navigate,mcp__claude-in-chrome__read_page,mcp__claude-in-chrome__find,mcp__claude-in-chrome__get_page_text,mcp__claude-in-chrome__computer,mcp__claude-in-chrome__form_input,mcp__claude-in-chrome__read_network_requests,mcp__claude-in-chrome__tabs_create_mcp"
```
### 2. Preflight — is the extension connected?
Call `tabs_context_mcp`. If it errors or returns no browser, the extension is not
connected. **Do not improvise.** Emit this and stop:
```yaml
verdict: inconclusive
fallback: playwright
specs: []
notes: claude-in-chrome extension not connected — re-run with --driver playwright (aw-tester).
```
`preview-spec run --driver auto` reads `fallback: playwright` and, in auto mode,
asks the user before dispatching `aw-tester` — it does not fall back silently. A
direct caller should do the same. An explicit `--driver chrome` stops here and
reports this verdict as-is.
### 3. Read cross-run lessons
```text
memory.list { scope: "repo::{owner}/{repo}", tags: ["loop::aw-tester-lessons"], limit: 50 }
memory.list { scope: "global", tags: ["loop::aw-tester-lessons"], limit: 50 }
```
If LoreKit's `memory.*` tools are not connected, skip and log one line:
`aw-tester-lessons: memory.* not connected, continuing`. Match each lesson's
`trigger-context` against the aw-target name and flow patterns; apply matches as
locator-healing heuristics for this run.
### 4. Parse inputs and load the spec + target
Resolve from the invocation prompt:
| Input | Source | Required |
|-------|--------|----------|
| `specs_path` | Argument, or `.agent/{branch}/specs.md` | Yes |
| `aw_target_path` | An explicit `Aw-Target file:` path, else `.claude/aw-targets/{name}.yml` | Yes |
| `mode` | `--all` or `--bail-on-first-red` (default) | No |
Parse the aw-target (`base_url`, `auth.*`, `fixtures.references`,
`constraints.reset_between_specs`) and the specs per the
[contract § 1](../rules/spec-run-contract.md#1-spec-parsing). Resolve every
`{placeholder}` in a `url` against `fixtures.references`.
---
## Auth — reuse the live session
The Chrome runner drives the user's real browser, so the fast path is: **the
browser is already logged in.** Follow the target's `auth.strategy`
([contract § 3](../rules/spec-run-contract.md#3-auth-strategy-semantics)):
- **`storage-state`** — navigate to `base_url` and `read_page`. If the page is the
app (not a login screen), you are authenticated; proceed. If it **is** a login
screen (Clerk / OAuth / a sign-in form), do not try to script the login. Emit
`verdict: inconclusive` with `fallback: playwright` and reason
`auth: chrome session not logged in — log in once in this Chrome, or re-run with --driver playwright`. Stop.
- **`none`** — proceed; no auth.
- **`manual`** — skip specs with an authed precondition; log
`auth.strategy: manual — skipping {N} authed spec(s)`.
- **`env-credentials`** — treat as `storage-state` (prefer the live session).
Detecting a login screen: the URL host is an auth provider (`accounts.*`,
`clerk.*`, `*/sign-in`, `*/login`) or the page's primary heading is a sign-in
prompt. When in doubt, prefer the honest `inconclusive` + fallback over guessing.
Never type a credential. Auth belongs to the live browser or the refresh command,
never to this runner.
---
## Execution — navigate, read, act, assert
Run specs in order in one tab (`tabs_create_mcp` once, or reuse the current tab).
For a `continues-from` spec, keep the same tab so cookies and local storage carry
over, exactly as the [contract](../rules/spec-run-contract.md#1-spec-parsing)
requires. If the prior spec did not pass, skip the chained spec with its reason.
For each spec: navigate to its `url` (absolute against `base_url`), then run each
flow step in order.
**`WHEN` (action).** Resolve the target by walking the
[locator ladder](../rules/spec-run-contract.md#2-locator-ladder), mapped to Chrome:
1. **Role + name** — `read_page` returns the accessibility tree; match the element
by `role` and accessible `name`. This is the preferred rung.
2. **User-facing text** — `find` or `get_page_text` to locate by visible label,
placeholder, or text.
3. **Test id** — resolve `data-testid` (the escape hatch). Use `find`, or
`javascript_tool` to read `[data-testid="…"]` — this is testid resolution, not
a CSS-selector locator, so it stays within the ladder.
Then act: `computer` for a click at the element's coordinates, `form_input` (or
`computer` typing) for text entry. After each action, `read_page` again — you see
the result before the next step. That is the advantage over the batch runner; use
it to heal a locator on the spot instead of failing blind.
**`THEN` / `AND` (assertion).** Re-read the page and check:
- `is visible` — the element resolves and is on-screen.
- `is not visible` — the element does not resolve, or is hidden.
- `... is visible on the page` (text) — `get_page_text` contains it. Match the
**rendered** text; CSS `text-transform` means the DOM text can differ in case
from what the eye sees, so compare against the actual node text.
- `has aria-selected: true` / attribute assertions — read the element's
attributes via `read_page` or `javascript_tool`.
- `network: METHOD /path returned NNN` — call `read_network_requests` and match
the method, path, and status. Capture the status and first response lines only
on a mismatch.
**Healing.** When a locator does not resolve, apply a matching startup lesson
first, then retry one rung looser (partial name, then partial text) — never CSS.
Record a healing that worked in the verdict `notes`; do not write it to cross-run
memory mid-run.
**Bail mode.** `--bail-on-first-red` (default): stop at the first `fail`, mark the
rest `skipped` with reason `bail`. `--all`: run every spec regardless.
> [!TIP]
> Recording the run as a GIF (`gif_creator`) is optional and off by default. Turn
> it on only when the caller asks for a visual artifact — it adds capture steps.
---
## Verdict
Emit the exact shared verdict block from
[contract § 4](../rules/spec-run-contract.md#4-verdict-schema-mandatory--do-not-deviate)
as the last thing in your message. Same `verdict` / `specs` / `diagnostics` /
`notes` keys, same hard rules (`green` only when all pass; `red` on any fail;
`inconclusive` when non-skipped specs pass but some were skipped). The Chrome
runner adds **no** `hot_loop:` block — that is a Playwright-only re-run handle and
does not apply here.
Do not narrate the whole click-through. The verdict block is the deliverable.
---
## Lessons
After the verdict, write to `aw-tester-lessons` for a locator healing, an
`inconclusive` verdict, or a new failure pattern — not for a clean pass — per the
[contract § 5](../rules/spec-run-contract.md#5-the-lessons-loop) and the mechanics
in [`aw-tester.agent.md`](../templates/aw-tester.agent.md) (dedup-search first,
then `memory.write` to the classified scope). Lessons written here are the same
shape as the Playwright runner's, so either runner benefits next time. Never store
a credential, token, or customer datum in a lesson.
---
## Hard Rules
- **Same contract, different engine.** Never fork the grammar, the ladder, the
auth semantics, or the verdict schema — they live in the
[spec-run contract](../rules/spec-run-contract.md).
- **See between steps.** Re-read the page after every action. Not seeing between
steps is the batch runner's constraint, not yours — do not emulate it.
- **Fall back honestly.** No extension, or a login screen on a `storage-state`
target → `verdict: inconclusive` + `fallback: playwright`. Do not fake a pass.
- **Never fabricate.** A missing element is a `fail` with diagnostics, not a
retry until it "passes."
- **No credentials, ever** — not typed into a form, not written to a lesson.
- **Compact output.** The verdict block is ~200 tokens. Do not paste page dumps
beyond the capped `diagnostics`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!