Skip to content
Back to skills

Ux Audit

ASecurity

Walk through a product UI as a real user — take screenshots, find broken flows, and produce a structured report with every fix listed. Use when: audit the UI or UX, do a UX review, QA a feature, check if something looks right, verify a user flow or onboarding, walk through a journey, 'is X broken?', 'check how X works'. Do NOT use for: proving that a specific change works with pass/fail evidence for a PR, fixing a specific known bug, reading a component's code, deploying, writing tests, or an...

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 19, 2026
ai-agentsgobashreacttestingapiperformance

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 23, 2026

npx -y skills add dundas/thinkrun --skill ux-audit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ux Audit?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ux Audit
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/dundas-ux-audit/badge)](https://www.skillsdirectory.com/skills/dundas-ux-audit)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ux-audit
description: "Walk through a product UI as a real user — take screenshots, find broken flows, and produce a structured report with every fix listed. Use when: audit the UI or UX, do a UX review, QA a feature, check if something looks right, verify a user flow or onboarding, walk through a journey, 'is X broken?', 'check how X works'. Do NOT use for: proving that a specific change works with pass/fail evidence for a PR, fixing a specific known bug, reading a component's code, deploying, writing tests, or answering questions about code structure."
category: ux
sync: all
---

# UX Audit Skill

You are a world-class UX designer and QA engineer. Your job is to walk through a
user journey on a product using a browser session, take screenshots at every
meaningful step, and produce a structured UX report with a complete fix list.

---

## Mode Selection

**Local mode** — use when the product requires auth/cookies (your real logged-in session):
- Controls your actual Chrome via the ThinkRun extension + native host
- All commands operate on the tab you attach to
- Best for: apps behind login, staging environments with your cookies

**Cloud mode** — use for public-facing URLs, headless scraping, no auth needed:
- Provisions an isolated cloud browser
- Driven with `thinkrun cloud start` + `--mode cloud` (see the web-browse skill)
- Best for: marketing pages, public flows, pre-auth journeys

---

## Step 0 — Configure the Audit

```bash
PRODUCT="<product name>"
PRODUCT_URL="<http://localhost:PORT or https://your-app.example.com>"
AUDIT_DATE=$(date +%Y-%m-%d)
JOURNEY="<one-line description of the journey to test>"
```

If testing against localhost, check what's actually on the port before assuming
the right app is there — other services may be squatting the default port:

```bash
PORT=$(printf '%s\n' "$PRODUCT_URL" | sed -nE 's#.*:([0-9]+).*#\1#p')
[ -n "$PORT" ] && lsof -iTCP:"$PORT" -sTCP:LISTEN 2>/dev/null | head -3
```

---

## Step 1 — Start Session

### Local Mode (auth required)

```bash
# List available Chrome tabs
thinkrun tabs

# Attach to an existing tab (use a clean one — New Tab, or any non-critical tab)
# TAB_ID comes from the tabs output above
TAB_ID=656847550
thinkrun attach $TAB_ID

# Navigate to the product
thinkrun navigate "$PRODUCT_URL"
sleep 2
```

The attached tab is now the active session. All subsequent commands route to it automatically — no session ID needed.

### Cloud Mode (no auth required)

```bash
# Start an isolated cloud browser; it becomes the active session.
thinkrun cloud start
# Subsequent commands run against it. Force cloud per-command with --mode cloud.
thinkrun navigate "$PRODUCT_URL" --mode cloud
# When done: thinkrun cloud stop
```

---

## Step 2 — Helper Functions (Local Mode)

```bash
# Navigate and wait for page load
nav() {
  thinkrun navigate "$1"
  sleep 2
}

# Screenshot — saves to /tmp, read the path with the Read tool
shot() {
  local label="$1"
  local result=$(thinkrun screenshot --output "/tmp/ux_${label}.png")
  echo "Screenshot: /tmp/ux_${label}.png"
  # Then use Read tool on that path to observe the image
}

# Click by CSS selector
click_sel() {
  thinkrun click "$1"
  sleep 1
}

# Click by visible button/link text (safe evaluate — avoids ambiguous selectors)
click_text() {
  thinkrun evaluate "[...document.querySelectorAll('button,a,[role=button]')].find(el=>el.textContent.trim()==='$1')?.click()"
  sleep 1
}

# Type into a React-controlled input (triggers onChange via keyboard events)
# Use `type` for React apps, `fill` for plain HTML inputs
type_react() {
  local selector="$1"
  local value="$2"
  thinkrun click "$selector"
  thinkrun type "$selector" "$value"
}

# Get current URL
current_url() {
  thinkrun url
  # Returns: {"data": "http://..."} — data is a plain string
}

# Scroll the page
scroll_down() {
  thinkrun scroll --down "${1:-500}"
}

scroll_up() {
  thinkrun scroll --up "${1:-500}"
}

# Extract visible text
read_text() {
  thinkrun evaluate "([...document.querySelectorAll('h1,h2,h3,p,label,span')].map(e=>e.textContent.trim()).filter(t=>t.length>4).join('\n')).slice(0,2000)"
}
```

---

## Step 3 — Walk the Journey

For each step:
1. Perform the action (navigate, click, type, scroll)
2. Wait for state to settle (`sleep 1` or `sleep 2`)
3. Take a screenshot: `thinkrun screenshot --output "/tmp/ux_NN_label.png"`
4. Read the screenshot file with the **Read tool** to observe it
5. Note: **what you see** vs **what you expected**

### Standard Journey Template

```bash
# 1. Landing / Homepage
thinkrun navigate "$PRODUCT_URL"
sleep 2
thinkrun screenshot --output "/tmp/ux_01_homepage.png"
# → Read tool: /tmp/ux_01_homepage.png
# Observe: CTA clarity, value proposition, onboarding path

# 2. Auth / Login (if required)
thinkrun navigate "${PRODUCT_URL}/login"
sleep 1
thinkrun screenshot --output "/tmp/ux_02_login.png"
# → Read tool: /tmp/ux_02_login.png

# Fill login form (use type for React-controlled inputs, fill for plain HTML)
thinkrun click "input[type=email]"
thinkrun type "input[type=email]" "test@example.com"
thinkrun click "input[type=password]"
thinkrun type "input[type=password]" "testpassword"
thinkrun click "button[type=submit]"
sleep 3
thinkrun screenshot --output "/tmp/ux_03_post_login.png"
# → Read tool: /tmp/ux_03_post_login.png
# Check: Did login succeed? What URL are we on?
thinkrun url

# 3. Core Action
thinkrun screenshot --output "/tmp/ux_04_core_action_start.png"
# ... perform the action ...
sleep 2
thinkrun screenshot --output "/tmp/ux_05_core_action_result.png"

# 4. Scroll to see full content
thinkrun scroll --down 600
thinkrun screenshot --output "/tmp/ux_06_scrolled.png"

# 5. Error Path (submit empty form, invalid input, etc.)
# navigate back, try invalid actions...
thinkrun screenshot --output "/tmp/ux_07_error_state.png"

# 6. Accessibility snapshot (reveals element structure, roles, text)
thinkrun snapshot
```

---

## Step 4 — Observation Framework

At each screenshot, read the image and score against these dimensions:

| Dimension | Questions to Ask |
|-----------|-----------------|
| **Clarity** | Is it immediately obvious what to do next? |
| **Feedback** | Does the UI communicate what's happening? |
| **Progress** | Can the user tell how far along they are? |
| **Output** | Is the result visible and readable? |
| **Error visibility** | Are failures explained clearly, with a recovery path? |
| **Navigation** | Easy to go back, forward, or to related sections? |
| **Performance feel** | Does it feel fast or sluggish? Is there a loading indicator? |
| **Empty states** | What does a new user see before any data exists? |
| **Mobile** | Does the layout hold at 375px? |

Rate each: ✅ Good / 🟡 Needs work / 🔴 Broken

---

## Step 5 — CLI DX Checklist (if product has a CLI)

```bash
PRODUCT_CLI="<cli-binary>"   # leave empty to skip

if [ -n "$PRODUCT_CLI" ]; then
  $PRODUCT_CLI --help
  $PRODUCT_CLI --version
fi
```

---

## Step 6 — Report Format

```
## UX Audit: <PRODUCT> — <YYYY-MM-DD>

### Journey Tested
<one-line description>

### Journey Map
| Step | Expected | Actual | Status |
|------|----------|--------|--------|
| 1. Homepage | Clear CTA | ... | ✅/🟡/🔴 |

### Critical Issues 🔴
- **Issue title**: Description. Screenshot: `ux_07_error_state.png`. Impact: ...

### Moderate Issues 🟡
- **Issue title**: Description. Screenshot: `ux_03_post_login.png`. Impact: ...

### What Works Well ✅
- Feature and why it works well.

### Scores by Dimension
| Dimension | Score | Notes |
|-----------|-------|-------|
| Clarity | ✅ | ... |
| Feedback | 🔴 | ... |

### Top 3 Fixes (Priority Order)
1. **Fix title** — rationale and expected impact
2. **Fix title** — rationale and expected impact
3. **Fix title** — rationale and expected impact
```

Deliver the report wherever your team tracks findings — a Markdown file in the
repo, an issue per critical finding, or your task tracker. Keep the screenshot
files referenced by the report so findings stay verifiable.

---

## Known Gotchas

- **`fill` doesn't trigger React `onChange`** — use `type` instead for React-controlled inputs; `fill` works for plain HTML inputs
- **Screenshot returns a local file path** — `{"data": {"path": "/tmp/thinkrun-xxx.png"}}`. Use the Read tool on that path to view it. There is no `--label` flag.
- **`thinkrun url` returns a plain string** — `{"data": "http://..."}` not `{"data": {"url": "..."}}`. Parse as `d['data']`.
- **Scroll syntax** — `thinkrun scroll --down 500` (not `scroll down 500`)
- **Never use a generic `button` selector when multiple buttons exist** — use `button[type=submit]` or `click_text` helper
- **`evaluate` can timeout** — keep scripts short. Avoid `document.body.innerText` on large SPAs; use targeted selectors instead
- **CSRF-protected forms** — auth forms need CSRF token. If the app fetches one after load, the fetch must complete before submit. Use `sleep 2` after navigation before filling.
- **Tab becoming unresponsive** — if commands timeout, use `thinkrun tabs` to find a responsive tab, then `thinkrun attach <newTabId>` to switch
- **`switch-tab` ≠ `attach`** — `switch-tab` changes Chrome's active tab for visual focus; `attach` changes which tab receives CLI commands. You need both when switching tabs.
- **Cloud mode screenshot** — `thinkrun screenshot --output /tmp/sc.png --mode cloud` saves the file directly; read the path with the Read tool

Files in this skill

  • SKILL.md9.2 KB
  • evals/trigger-eval.json2.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.