Install
$ agentstack add skill-mthines-agent-skills-aw-setup ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
aw-setup — Aw-Target Scaffolding for aw-tester
Interactive, idempotent setup flow that scaffolds the .claude/aw-targets/ config that aw-tester needs to run specs. Run it once before the first autonomous PR that touches UI. Re-run it when auth drifts, fixtures change, or base URL moves.
> This is the prerequisite for spec-driven UI verification in the > autonomous-workflow. Without an aw-target file, aw-tester cannot run and > the executor's Phase 4 spec verification step skips cleanly.
When to run
- First time: before running any autonomous feature that touches UI.
- Re-run: when
aw-testerreportsauth-refresh-failed, when the base URL
changes, or when seed fixtures are restructured.
- Never auto-triggered by the planner. The planner halts and tells the user
to run /aw-setup. The user runs it explicitly.
Idempotency contract
First run: full guided scaffolding (Phases A–E).
Re-run: detect .claude/aw-targets/local.yml exists, validate each field:
- Auth storage state: does the file exist? Is it fresh (
| The user's command produces.auth/local.json`. |
| (d) None | (skip — no auth) | n/a | | (e) Manual | (skip — aw-tester will skip authed specs) | n/a |
Then for every strategy except (d) / (e):
- Verify
.auth/local.jsonwas written. - Load one fixture URL (base_url +
/) and confirm it renders (HTTP 200 and
the page title is not an error page).
- If the probe fails, report the error and loop back to Phase B.
For strategy (b), the most common probe failure is a locator mismatch — the script's default getByLabel(/email/i) / getByLabel(/password/i) / submit button regex don't match the project's form. The fix is a 3-line edit to the CUSTOMIZE block in scripts/auth-bootstrap-credentials.mjs. aw-setup shows the failing locator and offers to surface the form's actual labels via a one-shot Playwright probe so the user can paste them into the script.
Phase D — Write
Write the aw-target file, the chosen bootstrap script (if applicable), and ensure the auth file is gitignored.
First run:
mkdir -p .claude/aw-targets scripts
# write .claude/aw-targets/local.yml from the template
# if strategy is (a): copy auth-bootstrap-headful.template.mjs → scripts/auth-bootstrap-headful.mjs
# if strategy is (b): copy auth-bootstrap-credentials.template.mjs → scripts/auth-bootstrap-credentials.mjs
Show the complete aw-target YAML AND the bootstrap script to the user for review before writing. For strategy (b), explicitly call out the CUSTOMIZE block in the script and confirm the user has reviewed the locators.
Re-run: show a unified diff:
--- .claude/aw-targets/local.yml (existing)
+++ .claude/aw-targets/local.yml (proposed)
@@ ...
Require user confirmation before writing. If the diff is empty, say "No changes needed — aw-target is up to date."
Gitignore guard:
# Add .auth/ to .gitignore if not already present
grep -q "^\.auth/" .gitignore 2>/dev/null || echo ".auth/" >> .gitignore
Never overwrite .auth/*.json silently. If the file exists and a new one would be produced by the bootstrap command, ask: "Overwrite existing auth state at .auth/local.json?"
Phase E — Smoke-test
Call aw-tester with a one-spec smoke to validate the aw-target end-to-end:
aw-tester:
specs: |
# Specs: Smoke Test
Target: local
## Spec 1: Homepage loads as the identified test user
persist: verify-only
url: /
preconditions:
- User is logged in as {auth.identity.email}
flow:
- WHEN page loads
THEN page title is not "Error" and not "404"
AND page does not contain {text: "Sign in"}
aw-target: local
mode: --bail-on-first-red
| Verdict | Action | |---------|--------| | green | Done. Aw-Target is scaffolded and validated. | | red | Show the diagnostic blob. Loop back to Phase B with the specific failure. | | inconclusive | Auth strategy is manual — expected. Aw-Target is written, authed specs will be skipped. |
Dry-run example
Here is what a first-run session looks like for a Next.js project:
[A] Detecting project configuration...
✓ Base URL: http://localhost:3000 (from .env.local: NEXT_PUBLIC_URL)
✓ Auth: next-auth detected at /api/auth/[...nextauth]
? No test backdoor found. Will ask.
✓ Seed script: pnpm run db:seed:aw (from package.json)
[B] A few questions:
1. Confirm base URL: http://localhost:3000 (detected) [enter to confirm]
2. Auth strategy: I found next-auth. Do you have a bootstrap command that
logs in and captures storage state? (e.g. `pnpm run auth:bootstrap`)
If not, I can set auth.strategy: manual.
3. Test user email + role?
User: [confirmed base URL] [provides: pnpm run auth:bootstrap] [test+aw@example.com, admin]
[C] Probing...
Running: pnpm run auth:bootstrap (timeout: 30s)
✓ .auth/local.json written (12kb)
Loading http://localhost:3000/ ... ✓ HTTP 200, title: "Dashboard"
[D] Writing aw-target:
Creating .claude/aw-targets/local.yml ...
[shows YAML preview]
Adding .auth/ to .gitignore
Confirm? [y/N] y
✓ .claude/aw-targets/local.yml written
[E] Smoke spec...
Running aw-tester smoke spec...
verdict: green
✓ Aw-Target validated. aw-tester is ready.
Re-run example
[Re-run detected] .claude/aw-targets/local.yml exists.
Validating...
✓ base_url: http://localhost:3000 — reachable
✗ auth.storage_state: .auth/local.json — missing (deleted or expired)
✓ fixtures.seed: pnpm run db:seed:aw — script exists
One field needs attention: auth storage state is missing.
[C] Re-running auth bootstrap...
Running: pnpm run auth:bootstrap (timeout: 30s)
✓ .auth/local.json written (12kb)
[D] No changes to aw-target.yml needed.
[E] Smoke spec... verdict: green
✓ Aw-Target re-validated.
Aw-Target file location
| File | Path | Committed? | |------|------|-----------| | Aw-Target definition | .claude/aw-targets/local.yml | Yes | | Bootstrap script (strategy a or b) | scripts/auth-bootstrap-headful.mjs or scripts/auth-bootstrap-credentials.mjs | Yes | | Auth storage state | .auth/local.json | No — gitignored | | Credentials (strategy b) | E2E_EMAIL / E2E_PASSWORD env vars (e.g. .env.local) | No — gitignored |
The aw-target file and bootstrap script are committed so teammates can use the same flow. The auth storage state and credentials are gitignored — they contain secrets.
Auth flow templates
aw-setup ships two ready-to-copy bootstrap scripts under [templates/](./templates/). Both produce the same artifact (a Playwright storageState JSON) but get there differently:
(a) Interactive headful capture — auth-bootstrap-headful.template.mjs
What it does. Launches a headful Chromium pointed at AUTH_LOGIN_URL, prints "log in then close the window" to stderr, and saves storage state when either:
- the page URL matches
AUTH_POST_LOGIN_URL_PATTERN(if provided), or - the user closes the browser window (via a
browser.on('disconnected')
handler — the save is idempotent).
When to pick this. SSO, OAuth, passwordless flows, anything that's hard to script. Also a fine default for first-time setup — log in once, reuse the session for days. To refresh, run the script again.
Env contract. | Var | Required | Purpose | |-----|----------|---------| | AUTH_LOGIN_URL | Yes | The page to open | | AUTH_STORAGE_STATE | Yes | Output path (./.auth/.json) | | AUTH_POST_LOGIN_URL_PATTERN | No | JS regex source; auto-save + close when matched | | AUTH_TIMEOUT_MS | No | Max wait for the pattern (default 10 min) |
Bootstrap command in aw-target.yml:
auth:
strategy: storage-state
storage_state: ./.auth/local.json
refresh:
when: missing-or-expired
command: |
AUTH_LOGIN_URL=http://localhost:3000/login \
AUTH_STORAGE_STATE=./.auth/local.json \
AUTH_POST_LOGIN_URL_PATTERN='/dashboard' \
node scripts/auth-bootstrap-headful.mjs
timeout_seconds: 600 # generous — user-driven step
(b) Automated credentials — auth-bootstrap-credentials.template.mjs
What it does. Headless Chromium logs in by filling a plain HTML form with E2E_EMAIL / E2E_PASSWORD, waits for AUTH_POST_LOGIN_URL_PATTERN, and saves storage state. The locator block at the top of the script is marked >>> CUSTOMIZE .json) | | AUTH_POST_LOGIN_URL_PATTERN | Yes | JS regex source matched after submit | | E2E_EMAIL | Yes | The test user's email/username | | E2E_PASSWORD | Yes | The test user's password (env var, never committed) | | AUTH_TIMEOUT_MS | No | Max wait for the post-login URL (default 30s) |
Bootstrap command in aw-target.yml:
auth:
strategy: storage-state
storage_state: ./.auth/local.json
refresh:
when: missing-or-expired
command: |
AUTH_LOGIN_URL=http://localhost:3000/login \
AUTH_STORAGE_STATE=./.auth/local.json \
AUTH_POST_LOGIN_URL_PATTERN='/dashboard' \
node scripts/auth-bootstrap-credentials.mjs
timeout_seconds: 60
Then declare the credentials env vars in .env.local (gitignored) or your CI secret store:
# .env.local — DO NOT COMMIT
export E2E_EMAIL="test+aw@example.com"
export E2E_PASSWORD=""
Which one wins for your project?
A quick decision aid (the same logic aw-setup uses in Phase B):
Is the login form plain HTML (email + password + submit, no redirects)?
├─ Yes → Can you store the password in a CI secret / .env.local safely?
│ ├─ Yes → (b) Automated credentials
│ └─ No → (a) Interactive headful capture
└─ No (SSO, OAuth, magic link, MFA) → (a) Interactive headful capture
Both flows produce the same .auth/.json — aw-tester does not care which one created it. You can switch later by re-running /aw-setup and picking a different strategy; aw-setup detects the change and offers to rewrite the bootstrap script + the refresh.command line in lockstep.
Compatibility notes
- No dependency on
playwright.config.ts— aw-setup probes vianpx playwright@latest. - No dependency on
aw-testerbeing installed — aw-setup brings its own probe. - If
playwrightis already installed locally, aw-setup uses the local binary;
otherwise it falls back to npx playwright@latest.
- The bootstrap scripts (
scripts/auth-bootstrap-*.mjs)import { chromium } from 'playwright',
so they need Playwright available at runtime. aw-tester's pinned binary resolution covers this transparently (see [templates/aw-tester.agent.md](../templates/aw-tester.agent.md#pinned-playwright-resolution-replaces-npx---yes-playwrightlatest)) — if no project install is found, the cached branch-local install is reused.
Definition of done
- [ ]
.claude/aw-targets/local.ymlwritten and reviewed by the user. - [ ] If strategy (a) or (b): the matching bootstrap script written under
scripts/auth-bootstrap-*.mjs and reviewed by the user (especially the CUSTOMIZE block for strategy b).
- [ ]
.auth/local.jsonexists (orauth.strategy: manualis set). - [ ]
.auth/is in.gitignore. If strategy (b),.env.local(or whichever
file holds E2E_PASSWORD) is also in .gitignore.
- [ ] Smoke spec returned
green(orinconclusiveformanualauth strategy). - [ ] User told what to do next:
- "Run an autonomous task that touches UI — the executor's Phase 4 will
now run aw-tester automatically."
- "Re-run
/aw-setupwhen auth expires or fixtures change." - For strategy (b): "If the login form changes, edit the
CUSTOMIZEblock
in scripts/auth-bootstrap-credentials.mjs. The locator ladder is role/label-based so it tolerates most CSS / DOM changes."
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mthines
- Source: mthines/agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.