mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-06 13:45:35 +02:00
f7b95329c1
* Phase 2: Enhanced browser — dialog handling, upload, state checks, snapshots - CircularBuffer O(1) ring buffer for console/network/dialog (was O(n) array+shift) - Async buffer flush with Bun.write() (was appendFileSync) - Dialog auto-accept/dismiss with buffer + prompt text support - File upload command (upload <sel> <file...>) - Element state checks (is visible/hidden/enabled/disabled/checked/editable/focused) - Annotated screenshots with ref labels overlaid (-a flag) - Snapshot diffing against previous snapshot (-D flag) - Cursor-interactive element scan for non-ARIA clickables (-C flag) - Snapshot scoping depth limit (-d N flag) - Health check with page.evaluate + 2s timeout - Playwright error wrapping — actionable messages for AI agents - Fix useragent — context recreation preserves cookies/storage/URLs - wait --networkidle / --load / --domcontentloaded flags - console --errors filter (error + warning only) - cookie-import <json-file> with auto-fill domain from page URL - 166 integration tests (was ~63) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Phase 2: Rewrite SKILL.md as QA playbook + command reference Reorient SKILL.md files from raw command reference to QA-first playbook with 10 workflow patterns (test user flows, verify deployments, dogfood features, responsive layouts, file upload, forms, dialogs, compare pages). Compact command reference tables at the bottom. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Phase 3: /qa skill — systematic QA testing with health scores New /qa skill for systematic web app QA testing. Three modes: - full: 5-10 documented issues with screenshots and repro steps - quick: 30-second smoke test with health score - regression: compare against saved baseline Includes issue taxonomy (7 categories, 4 severity levels), structured report template, health score rubric (weighted across 7 categories), framework detection guidance (Next.js, Rails, WordPress, SPA). Also adds browse/bin/find-browse (DRY binary discovery using git rev-parse), .gstack/ to .gitignore, and updated TODO roadmap. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Bump to v0.3.0 — Phase 2 + Phase 3 changelog Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: cookie-import-browser — Chromium cookie decryption module + tests Pure logic module for reading and decrypting cookies from macOS Chromium browsers (Comet, Chrome, Arc, Brave, Edge). Supports v10 AES-128-CBC encryption with macOS Keychain access, PBKDF2 key derivation, and per-browser key caching. 18 unit tests with encrypted cookie fixtures. * feat: cookie picker web UI + route handler Two-panel dark-theme picker served from the browse server. Left panel shows source browser domains with search and import buttons. Right panel shows imported domains with trash buttons. No cookie values exposed. 6 API endpoints, importedDomains Set tracking, inline clearCookies. * feat: wire cookie-import-browser into browse server Add cookie-picker route dispatch (no auth, localhost-only), add cookie-import-browser to WRITE_COMMANDS and CHAIN_WRITE, add serverPort property to BrowserManager, add write command with two modes (picker UI vs --domain direct import), update CLI help text. * chore: /setup-browser-cookies skill + docs (Phase 3.5) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: bump version and changelog (v0.3.1) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * security: redact sensitive values from command output (PR #21) type no longer echoes text (reports character count), cookie redacts value with ****, header redacts Authorization/Cookie/X-API-Key/X-Auth-Token, storage set drops value, forms redacts password fields. Prevents secrets from persisting in LLM transcripts. 7 new tests. Credit: fredluz (PR #21) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * security: path traversal prevention for screenshot/pdf/eval (PR #26) Add validateOutputPath() for screenshot/pdf/responsive (restricts to /tmp and cwd) and validateReadPath() for eval (blocks .. sequences and absolute paths outside safe dirs). 7 new tests. Credit: Jah-yee (PR #26) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: auto-install Playwright Chromium in setup (PR #22) Setup now verifies Playwright can launch Chromium, and auto-installs it via `bunx playwright install chromium` if missing. Exits non-zero if build or Chromium launch fails. Credit: AkbarDevop (PR #22) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * security: fix path validation bypass, CORS restriction, cookie-import path check - startsWith('/tmp') matched '/tmpevil' — now requires trailing slash - CORS Access-Control-Allow-Origin changed from * to http://127.0.0.1:<port> - cookie-import now validates file paths (was missing validateReadPath) - 3 new tests for prefix collision and cookie-import path traversal Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address review informational issues + add regression tests - Add cookie-import to CHAIN_WRITE set for chain command routing - Add path validation to snapshot -a -o output path - Fix package.json version to match 0.3.1 - Use crypto.randomUUID() for temp DB paths (unpredictable filenames) - Add regression tests for chain cookie-import and snapshot path validation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add /qa, /setup-browser-cookies to README + update BROWSER.md - Add /qa and /setup-browser-cookies to skills table, install/update/uninstall blurbs - Add dedicated README sections for both new skills with usage examples - Update demo workflow to show cookie import → QA → browse flow - Update BROWSER.md: cookie import commands, new source files, test count (203) - Update skill count from 6 to 8 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: team-aware /retro v2.0 — per-person praise and growth opportunities - Identify current user via git config, orient narrative as "you" vs teammates - Add per-author metrics: commits, LOC, focus areas, commit type mix, sessions - New "Your Week" section with personal deep-dive for whoever runs the command - New "Team Breakdown" with per-person praise and growth opportunities - Track AI-assisted commits via Co-Authored-By trailers - Personal + team shipping streaks - Tone: praise like a 1:1, growth like investment advice, never compare negatively Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add Conductor parallel sessions section to README Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
341 lines
9.9 KiB
Markdown
341 lines
9.9 KiB
Markdown
---
|
|
name: gstack
|
|
version: 1.1.0
|
|
description: |
|
|
Fast headless browser for QA testing and site dogfooding. Navigate any URL, interact with
|
|
elements, verify page state, diff before/after actions, take annotated screenshots, check
|
|
responsive layouts, test forms and uploads, handle dialogs, and assert element states.
|
|
~100ms per command. Use when you need to test a feature, verify a deployment, dogfood a
|
|
user flow, or file a bug with evidence.
|
|
allowed-tools:
|
|
- Bash
|
|
- Read
|
|
|
|
---
|
|
|
|
# gstack browse: QA Testing & Dogfooding
|
|
|
|
Persistent headless Chromium. First call auto-starts (~3s), then ~100-200ms per command.
|
|
Auto-shuts down after 30 min idle. State persists between calls (cookies, tabs, sessions).
|
|
|
|
## SETUP (run this check BEFORE any browse command)
|
|
|
|
```bash
|
|
B=$(browse/bin/find-browse 2>/dev/null || ~/.claude/skills/gstack/browse/bin/find-browse 2>/dev/null)
|
|
if [ -n "$B" ]; then
|
|
echo "READY: $B"
|
|
else
|
|
echo "NEEDS_SETUP"
|
|
fi
|
|
```
|
|
|
|
If `NEEDS_SETUP`:
|
|
1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait.
|
|
2. Run: `cd <SKILL_DIR> && ./setup`
|
|
3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash`
|
|
|
|
## IMPORTANT
|
|
|
|
- Use the compiled binary via Bash: `$B <command>`
|
|
- NEVER use `mcp__claude-in-chrome__*` tools. They are slow and unreliable.
|
|
- Browser persists between calls — cookies, login sessions, and tabs carry over.
|
|
- Dialogs (alert/confirm/prompt) are auto-accepted by default — no browser lockup.
|
|
|
|
## QA Workflows
|
|
|
|
### Test a user flow (login, signup, checkout, etc.)
|
|
|
|
```bash
|
|
B=~/.claude/skills/gstack/browse/dist/browse
|
|
|
|
# 1. Go to the page
|
|
$B goto https://app.example.com/login
|
|
|
|
# 2. See what's interactive
|
|
$B snapshot -i
|
|
|
|
# 3. Fill the form using refs
|
|
$B fill @e3 "test@example.com"
|
|
$B fill @e4 "password123"
|
|
$B click @e5
|
|
|
|
# 4. Verify it worked
|
|
$B snapshot -D # diff shows what changed after clicking
|
|
$B is visible ".dashboard" # assert the dashboard appeared
|
|
$B screenshot /tmp/after-login.png
|
|
```
|
|
|
|
### Verify a deployment / check prod
|
|
|
|
```bash
|
|
$B goto https://yourapp.com
|
|
$B text # read the page — does it load?
|
|
$B console # any JS errors?
|
|
$B network # any failed requests?
|
|
$B js "document.title" # correct title?
|
|
$B is visible ".hero-section" # key elements present?
|
|
$B screenshot /tmp/prod-check.png
|
|
```
|
|
|
|
### Dogfood a feature end-to-end
|
|
|
|
```bash
|
|
# Navigate to the feature
|
|
$B goto https://app.example.com/new-feature
|
|
|
|
# Take annotated screenshot — shows every interactive element with labels
|
|
$B snapshot -i -a -o /tmp/feature-annotated.png
|
|
|
|
# Find ALL clickable things (including divs with cursor:pointer)
|
|
$B snapshot -C
|
|
|
|
# Walk through the flow
|
|
$B snapshot -i # baseline
|
|
$B click @e3 # interact
|
|
$B snapshot -D # what changed? (unified diff)
|
|
|
|
# Check element states
|
|
$B is visible ".success-toast"
|
|
$B is enabled "#next-step-btn"
|
|
$B is checked "#agree-checkbox"
|
|
|
|
# Check console for errors after interactions
|
|
$B console
|
|
```
|
|
|
|
### Test responsive layouts
|
|
|
|
```bash
|
|
# Quick: 3 screenshots at mobile/tablet/desktop
|
|
$B goto https://yourapp.com
|
|
$B responsive /tmp/layout
|
|
|
|
# Manual: specific viewport
|
|
$B viewport 375x812 # iPhone
|
|
$B screenshot /tmp/mobile.png
|
|
$B viewport 1440x900 # Desktop
|
|
$B screenshot /tmp/desktop.png
|
|
```
|
|
|
|
### Test file upload
|
|
|
|
```bash
|
|
$B goto https://app.example.com/upload
|
|
$B snapshot -i
|
|
$B upload @e3 /path/to/test-file.pdf
|
|
$B is visible ".upload-success"
|
|
$B screenshot /tmp/upload-result.png
|
|
```
|
|
|
|
### Test forms with validation
|
|
|
|
```bash
|
|
$B goto https://app.example.com/form
|
|
$B snapshot -i
|
|
|
|
# Submit empty — check validation errors appear
|
|
$B click @e10 # submit button
|
|
$B snapshot -D # diff shows error messages appeared
|
|
$B is visible ".error-message"
|
|
|
|
# Fill and resubmit
|
|
$B fill @e3 "valid input"
|
|
$B click @e10
|
|
$B snapshot -D # diff shows errors gone, success state
|
|
```
|
|
|
|
### Test dialogs (delete confirmations, prompts)
|
|
|
|
```bash
|
|
# Set up dialog handling BEFORE triggering
|
|
$B dialog-accept # will auto-accept next alert/confirm
|
|
$B click "#delete-button" # triggers confirmation dialog
|
|
$B dialog # see what dialog appeared
|
|
$B snapshot -D # verify the item was deleted
|
|
|
|
# For prompts that need input
|
|
$B dialog-accept "my answer" # accept with text
|
|
$B click "#rename-button" # triggers prompt
|
|
```
|
|
|
|
### Test authenticated pages (import real browser cookies)
|
|
|
|
```bash
|
|
# Import cookies from your real browser (opens interactive picker)
|
|
$B cookie-import-browser
|
|
|
|
# Or import a specific domain directly
|
|
$B cookie-import-browser comet --domain .github.com
|
|
|
|
# Now test authenticated pages
|
|
$B goto https://github.com/settings/profile
|
|
$B snapshot -i
|
|
$B screenshot /tmp/github-profile.png
|
|
```
|
|
|
|
### Compare two pages / environments
|
|
|
|
```bash
|
|
$B diff https://staging.app.com https://prod.app.com
|
|
```
|
|
|
|
### Multi-step chain (efficient for long flows)
|
|
|
|
```bash
|
|
echo '[
|
|
["goto","https://app.example.com"],
|
|
["snapshot","-i"],
|
|
["fill","@e3","test@test.com"],
|
|
["fill","@e4","password"],
|
|
["click","@e5"],
|
|
["snapshot","-D"],
|
|
["screenshot","/tmp/result.png"]
|
|
]' | $B chain
|
|
```
|
|
|
|
## Quick Assertion Patterns
|
|
|
|
```bash
|
|
# Element exists and is visible
|
|
$B is visible ".modal"
|
|
|
|
# Button is enabled/disabled
|
|
$B is enabled "#submit-btn"
|
|
$B is disabled "#submit-btn"
|
|
|
|
# Checkbox state
|
|
$B is checked "#agree"
|
|
|
|
# Input is editable
|
|
$B is editable "#name-field"
|
|
|
|
# Element has focus
|
|
$B is focused "#search-input"
|
|
|
|
# Page contains text
|
|
$B js "document.body.textContent.includes('Success')"
|
|
|
|
# Element count
|
|
$B js "document.querySelectorAll('.list-item').length"
|
|
|
|
# Specific attribute value
|
|
$B attrs "#logo" # returns all attributes as JSON
|
|
|
|
# CSS property
|
|
$B css ".button" "background-color"
|
|
```
|
|
|
|
## Snapshot System
|
|
|
|
The snapshot is your primary tool for understanding and interacting with pages.
|
|
|
|
```bash
|
|
$B snapshot -i # Interactive elements only (buttons, links, inputs) with @e refs
|
|
$B snapshot -c # Compact (no empty structural elements)
|
|
$B snapshot -d 3 # Limit depth to 3 levels
|
|
$B snapshot -s "main" # Scope to CSS selector
|
|
$B snapshot -D # Diff against previous snapshot (what changed?)
|
|
$B snapshot -a # Annotated screenshot with ref labels
|
|
$B snapshot -o /tmp/x.png # Output path for annotated screenshot
|
|
$B snapshot -C # Cursor-interactive elements (@c refs — divs with pointer, onclick)
|
|
```
|
|
|
|
Combine flags: `$B snapshot -i -a -C -o /tmp/annotated.png`
|
|
|
|
After snapshot, use @refs everywhere:
|
|
```bash
|
|
$B click @e3 $B fill @e4 "value" $B hover @e1
|
|
$B html @e2 $B css @e5 "color" $B attrs @e6
|
|
$B click @c1 # cursor-interactive ref (from -C)
|
|
```
|
|
|
|
Refs are invalidated on navigation — run `snapshot` again after `goto`.
|
|
|
|
## Command Reference
|
|
|
|
### Navigation
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `goto <url>` | Navigate to URL |
|
|
| `back` / `forward` | History navigation |
|
|
| `reload` | Reload page |
|
|
| `url` | Print current URL |
|
|
|
|
### Reading
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `text` | Cleaned page text |
|
|
| `html [selector]` | innerHTML |
|
|
| `links` | All links as "text -> href" |
|
|
| `forms` | Forms + fields as JSON |
|
|
| `accessibility` | Full ARIA tree |
|
|
|
|
### Interaction
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `click <sel>` | Click element |
|
|
| `fill <sel> <val>` | Fill input |
|
|
| `select <sel> <val>` | Select dropdown |
|
|
| `hover <sel>` | Hover element |
|
|
| `type <text>` | Type into focused element |
|
|
| `press <key>` | Press key (Enter, Tab, Escape) |
|
|
| `scroll [sel]` | Scroll element into view |
|
|
| `wait <sel>` | Wait for element (max 10s) |
|
|
| `wait --networkidle` | Wait for network to be idle |
|
|
| `wait --load` | Wait for page load event |
|
|
| `upload <sel> <file...>` | Upload file(s) |
|
|
| `cookie-import <json>` | Import cookies from JSON file |
|
|
| `cookie-import-browser [browser] [--domain <d>]` | Import cookies from real browser (opens picker UI, or direct import with --domain) |
|
|
| `dialog-accept [text]` | Auto-accept dialogs |
|
|
| `dialog-dismiss` | Auto-dismiss dialogs |
|
|
| `viewport <WxH>` | Set viewport size |
|
|
|
|
### Inspection
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `js <expr>` | Run JavaScript |
|
|
| `eval <file>` | Run JS file |
|
|
| `css <sel> <prop>` | Computed CSS |
|
|
| `attrs <sel>` | Element attributes |
|
|
| `is <prop> <sel>` | State check (visible/hidden/enabled/disabled/checked/editable/focused) |
|
|
| `console [--clear\|--errors]` | Console messages (--errors filters to error/warning) |
|
|
| `network [--clear]` | Network requests |
|
|
| `dialog [--clear]` | Dialog messages |
|
|
| `cookies` | All cookies |
|
|
| `storage` | localStorage + sessionStorage |
|
|
| `perf` | Page load timings |
|
|
|
|
### Visual
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `screenshot [path]` | Screenshot |
|
|
| `pdf [path]` | Save as PDF |
|
|
| `responsive [prefix]` | Mobile/tablet/desktop screenshots |
|
|
| `diff <url1> <url2>` | Text diff between pages |
|
|
|
|
### Tabs
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `tabs` | List tabs |
|
|
| `tab <id>` | Switch tab |
|
|
| `newtab [url]` | Open tab |
|
|
| `closetab [id]` | Close tab |
|
|
|
|
### Server
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `status` | Health check |
|
|
| `stop` | Shutdown |
|
|
| `restart` | Restart |
|
|
|
|
## Tips
|
|
|
|
1. **Navigate once, query many times.** `goto` loads the page; then `text`, `js`, `screenshot` all hit the loaded page instantly.
|
|
2. **Use `snapshot -i` first.** See all interactive elements, then click/fill by ref. No CSS selector guessing.
|
|
3. **Use `snapshot -D` to verify.** Baseline → action → diff. See exactly what changed.
|
|
4. **Use `is` for assertions.** `is visible .modal` is faster and more reliable than parsing page text.
|
|
5. **Use `snapshot -a` for evidence.** Annotated screenshots are great for bug reports.
|
|
6. **Use `snapshot -C` for tricky UIs.** Finds clickable divs that the accessibility tree misses.
|
|
7. **Check `console` after actions.** Catch JS errors that don't surface visually.
|
|
8. **Use `chain` for long flows.** Single command, no per-step CLI overhead.
|