Add element crop (CSS selector or @ref), region clip (--clip x,y,w,h),
and viewport-only (--viewport) modes to the screenshot command. Uses
Playwright's native locator.screenshot() and page.screenshot({ clip }).
Full page remains the default. Includes 10 new tests covering all modes
and error paths.
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.
If output shows UPGRADE_AVAILABLE <old> <new>: read ~/.claude/skills/gstack/gstack-upgrade/SKILL.md and follow the "Inline upgrade flow" (AskUserQuestion → upgrade if yes, touch ~/.gstack/last-update-check if no). If JUST_UPGRADED <from> <to>: tell user "Running gstack v{to} (just updated!)" and continue.
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).
Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait.
Run: cd <SKILL_DIR> && ./setup
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.)
# 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
$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
# 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
# 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
# Element screenshot (crop to specific element)$B screenshot "#hero-banner" /tmp/hero.png
$B snapshot -i
$B screenshot @e3 /tmp/button.png
# Region crop$B screenshot --clip 0,0,800,600 /tmp/above-fold.png
# Viewport only (no scroll)$B screenshot --viewport /tmp/viewport.png
$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)
# 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)
# 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
# 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.
-i --interactive Interactive elements only (buttons, links, inputs) with @e refs
-c --compact Compact (no empty structural nodes)
-d <N> --depth Limit tree depth (0 = root only, default: unlimited)
-s <sel> --selector Scope to CSS selector
-D --diff Unified diff against previous snapshot (first call stores baseline)
-a --annotate Annotated screenshot with red overlay boxes and ref labels
-o <path> --output Output path for annotated screenshot (default: /tmp/browse-annotated.png)
-C --cursor-interactive Cursor-interactive elements (@c refs — divs with pointer, onclick)
All flags can be combined freely. -o only applies when -a is also used.
Example: $B snapshot -i -a -C -o /tmp/annotated.png
Ref numbering: @e refs are assigned sequentially (@e1, @e2, ...) in tree order.
@c refs from -C are numbered separately (@c1, @c2, ...).
After snapshot, use @refs as selectors in any command:
Accessibility tree with @e refs for element selection. Flags: -i interactive only, -c compact, -d N depth limit, -s sel scope, -D diff vs previous, -a annotated screenshot, -o path output, -C cursor-interactive @c refs
Meta
Command
Description
chain
Run commands from JSON stdin. Format: [["cmd","arg1",...],...]
Tabs
Command
Description
closetab [id]
Close tab
newtab [url]
Open new tab
tab <id>
Switch to tab
tabs
List open tabs
Server
Command
Description
restart
Restart server
status
Health check
stop
Shutdown server
Tips
Navigate once, query many times.goto loads the page; then text, js, screenshot all hit the loaded page instantly.
Use snapshot -i first. See all interactive elements, then click/fill by ref. No CSS selector guessing.
Use snapshot -D to verify. Baseline → action → diff. See exactly what changed.
Use is for assertions.is visible .modal is faster and more reliable than parsing page text.
Use snapshot -a for evidence. Annotated screenshots are great for bug reports.
Use snapshot -C for tricky UIs. Finds clickable divs that the accessibility tree misses.
Check console after actions. Catch JS errors that don't surface visually.
Use chain for long flows. Single command, no per-step CLI overhead.