Files
gstack/browse/SKILL.md
T
Garry Tan 6cf424fb49 feat: add escalation protocol to preamble — all skills get DONE/BLOCKED/NEEDS_CONTEXT
Every skill now reports completion status (DONE, DONE_WITH_CONCERNS, BLOCKED,
NEEDS_CONTEXT) and has escalation rules: 3 failed attempts → STOP, security
uncertainty → STOP, scope exceeds verification → STOP.

"It is always OK to stop and say 'this is too hard for me.'"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:09:32 -05:00

13 KiB

name, version, description, allowed-tools
name version description allowed-tools
browse 1.1.0 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.
Bash
Read
AskUserQuestion

Preamble (run first)

_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)
[ -n "$_UPD" ] && echo "$_UPD" || true
mkdir -p ~/.gstack/sessions
touch ~/.gstack/sessions/"$PPID"
_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')
find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true
_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)

If output shows UPGRADE_AVAILABLE <old> <new>: read ~/.claude/skills/gstack/gstack-upgrade/SKILL.md and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If JUST_UPGRADED <from> <to>: tell user "Running gstack v{to} (just updated!)" and continue.

AskUserQuestion Format

ALWAYS follow this structure for every AskUserQuestion call:

  1. Context: project name, current branch, what we're working on (1-2 sentences)
  2. The specific question or decision point
  3. RECOMMENDATION: Choose [X] because [one-line reason]
  4. Lettered options: A) ... B) ... C) ...

If _SESSIONS is 3 or more: the user is juggling multiple gstack sessions and context-switching heavily. ELI16 mode — they may not remember what this conversation is about. Every AskUserQuestion MUST re-ground them: state the project, the branch, the current plan/task, then the specific problem, THEN the recommendation and options. Be extra clear and self-contained — assume they haven't looked at this window in 20 minutes.

Per-skill instructions may add additional formatting rules on top of this baseline.

Contributor Mode

If _CONTRIB is true: you are in contributor mode. When you hit friction with gstack itself (not the user's app), file a field report. Think: "hey, I was trying to do X with gstack and it didn't work / was confusing / was annoying. Here's what happened."

gstack issues: browse command fails/wrong output, snapshot missing elements, skill instructions unclear or misleading, binary crash/hang, unhelpful error message, any rough edge or annoyance — even minor stuff. NOT gstack issues: user's app bugs, network errors to user's URL, auth failures on user's site.

To file: write ~/.gstack/contributor-logs/{slug}.md with this structure:

# {Title}

Hey gstack team — ran into this while using /{skill-name}:

**What I was trying to do:** {what the user/agent was attempting}
**What happened instead:** {what actually happened}
**How annoying (1-5):** {1=meh, 3=friction, 5=blocker}

## Steps to reproduce
1. {step}

## Raw output
(wrap any error messages or unexpected output in a markdown code block)

**Date:** {YYYY-MM-DD} | **Version:** {gstack version} | **Skill:** /{skill}

Then run: mkdir -p ~/.gstack/contributor-logs && open ~/.gstack/contributor-logs/{slug}.md

Slug: lowercase, hyphens, max 60 chars (e.g. browse-snapshot-ref-gap). Skip if file already exists. Max 3 reports per session. File inline and continue — don't stop the workflow. Tell user: "Filed gstack field report: {title}"

Completion Status Protocol

When completing a skill workflow, report status using one of:

  • DONE — All steps completed successfully. Evidence provided for each claim.
  • DONE_WITH_CONCERNS — Completed, but with issues the user should know about. List each concern.
  • BLOCKED — Cannot proceed. State what is blocking and what was tried.
  • NEEDS_CONTEXT — Missing information required to continue. State exactly what you need.

Escalation

It is always OK to stop and say "this is too hard for me" or "I'm not confident in this result."

Bad work is worse than no work. You will not be penalized for escalating.

  • If you have attempted a task 3 times without success, STOP and escalate.
  • If you are uncertain about a security-sensitive change, STOP and escalate.
  • If the scope of work exceeds what you can verify, STOP and escalate.

Escalation format:

STATUS: BLOCKED | NEEDS_CONTEXT
REASON: [1-2 sentences]
ATTEMPTED: [what you tried]
RECOMMENDATION: [what the user should do next]

browse: QA Testing & Dogfooding

Persistent headless Chromium. First call auto-starts (~3s), then ~100ms per command. State persists between calls (cookies, tabs, login sessions).

SETUP (run this check BEFORE any browse command)

_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
B=""
[ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/gstack/browse/dist/browse" ] && B="$_ROOT/.claude/skills/gstack/browse/dist/browse"
[ -z "$B" ] && B=~/.claude/skills/gstack/browse/dist/browse
if [ -x "$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

Core QA Patterns

1. Verify a page loads correctly

$B goto https://yourapp.com
$B text                          # content loads?
$B console                       # JS errors?
$B network                       # failed requests?
$B is visible ".main-content"    # key elements present?

2. Test a user flow

$B goto https://app.com/login
$B snapshot -i                   # see all interactive elements
$B fill @e3 "user@test.com"
$B fill @e4 "password"
$B click @e5                     # submit
$B snapshot -D                   # diff: what changed after submit?
$B is visible ".dashboard"       # success state present?

3. Verify an action worked

$B snapshot                      # baseline
$B click @e3                     # do something
$B snapshot -D                   # unified diff shows exactly what changed

4. Visual evidence for bug reports

$B snapshot -i -a -o /tmp/annotated.png   # labeled screenshot
$B screenshot /tmp/bug.png                # plain screenshot
$B console                                # error log

5. Find all clickable elements (including non-ARIA)

$B snapshot -C                   # finds divs with cursor:pointer, onclick, tabindex
$B click @c1                     # interact with them

6. Assert element states

$B is visible ".modal"
$B is enabled "#submit-btn"
$B is disabled "#submit-btn"
$B is checked "#agree-checkbox"
$B is editable "#name-field"
$B is focused "#search-input"
$B js "document.body.textContent.includes('Success')"

7. Test responsive layouts

$B responsive /tmp/layout        # mobile + tablet + desktop screenshots
$B viewport 375x812              # or set specific viewport
$B screenshot /tmp/mobile.png

8. Test file uploads

$B upload "#file-input" /path/to/file.pdf
$B is visible ".upload-success"

9. Test dialogs

$B dialog-accept "yes"           # set up handler
$B click "#delete-button"        # trigger dialog
$B dialog                        # see what appeared
$B snapshot -D                   # verify deletion happened

10. Compare environments

$B diff https://staging.app.com https://prod.app.com

Snapshot Flags

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:

$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)

Output format: indented accessibility tree with @ref IDs, one element per line.

  @e1 [heading] "Welcome" [level=1]
  @e2 [textbox] "Email"
  @e3 [button] "Submit"

Refs are invalidated on navigation — run snapshot again after goto.

Full Command List

Navigation

Command Description
back History back
forward History forward
goto <url> Navigate to URL
reload Reload page
url Print current URL

Reading

Command Description
accessibility Full ARIA tree
forms Form fields as JSON
html [selector] innerHTML of selector (throws if not found), or full page HTML if no selector given
links All links as "text → href"
text Cleaned page text

Interaction

Command Description
click <sel> Click element
cookie <name>=<value> Set cookie on current page domain
cookie-import <json> Import cookies from JSON file
cookie-import-browser [browser] [--domain d] Import cookies from Comet, Chrome, Arc, Brave, or Edge (opens picker, or use --domain for direct import)
dialog-accept [text] Auto-accept next alert/confirm/prompt. Optional text is sent as the prompt response
dialog-dismiss Auto-dismiss next dialog
fill <sel> <val> Fill input
header <name>:<value> Set custom request header (colon-separated, sensitive values auto-redacted)
hover <sel> Hover element
press <key> Press key — Enter, Tab, Escape, ArrowUp/Down/Left/Right, Backspace, Delete, Home, End, PageUp, PageDown, or modifiers like Shift+Enter
scroll [sel] Scroll element into view, or scroll to page bottom if no selector
select <sel> <val> Select dropdown option by value, label, or visible text
type <text> Type into focused element
upload <sel> <file> [file2...] Upload file(s)
useragent <string> Set user agent
viewport <WxH> Set viewport size
`wait <sel --networkidle

Inspection

Command Description
`attrs <sel @ref>`
`console [--clear --errors]`
cookies All cookies as JSON
css <sel> <prop> Computed CSS value
dialog [--clear] Dialog messages
eval <file> Run JavaScript from file and return result as string (path must be under /tmp or cwd)
is <prop> <sel> State check (visible/hidden/enabled/disabled/checked/editable/focused)
js <expr> Run JavaScript expression and return result as string
network [--clear] Network requests
perf Page load timings
storage [set k v] Read all localStorage + sessionStorage as JSON, or set to write localStorage

Visual

Command Description
diff <url1> <url2> Text diff between pages
pdf [path] Save as PDF
responsive [prefix] Screenshots at mobile (375x812), tablet (768x1024), desktop (1280x720). Saves as {prefix}-mobile.png etc.
`screenshot [--viewport] [--clip x,y,w,h] [selector @ref] [path]`

Snapshot

Command Description
snapshot [flags] 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