# gstack User Guide

**Garry's Stack** — the all-in-one AI engineering toolkit that gives your coding agent a real browser, a design studio, PDF rendering, and 30+ slash-command skills. Version **1.10.1.0**, MIT licensed, built on Bun.

gstack bridges the gap between AI coding assistants and the real world: it lets agents browse the web, generate UI mockups, render PDFs, and execute structured engineering workflows — all from the command line. Whether you run Claude Code, OpenAI Codex CLI, Cursor, or any of eight other supported hosts, gstack plugs in and immediately expands what your agent can do.

---

## 1. Quick Start

Get gstack running in under two minutes.

**Step 1 — Clone the repository:**

```bash
git clone https://github.com/garrytan/gstack.git
cd gstack
```

**Step 2 — Run setup:**

```bash
./setup
```

This installs gstack skills into your AI host's skill directory (e.g., `~/.claude/skills/gstack/` for Claude Code), compiles the `browse`, `design`, and `make-pdf` binaries, and sets up the state directory at `~/.gstack/`.

**Step 3 — Launch the browser:**

```bash
browse goto https://example.com
```

Expected output:

```
Navigated to https://example.com
Page loaded (200 OK)
```

**Step 4 — Take a snapshot to see the page:**

```bash
browse snapshot
```

Expected output:

```
[snapshot] 47 elements indexed
@e1  <h1> Example Domain
@e2  <p> This domain is for use in illustrative examples...
@e3  <a> More information...
```

**Step 5 — Interact using element references:**

```bash
browse click @e3
```

> [!TIP]
> After running `snapshot`, every interactive element gets an `@ref` handle (like `@e3`). Use these refs with `click`, `fill`, `hover`, `html`, `css`, and `attrs` commands to interact precisely without writing CSS selectors.

---

## 2. Installation

### 2.1 Prerequisites

| Requirement | Minimum Version | Notes |
|---|---|---|
| **Bun** | 1.0.0 | JavaScript/TypeScript runtime — [bun.sh](https://bun.sh) |
| **Git** | Any recent | For cloning the repository |
| **Chromium** | Bundled via Playwright | Installed automatically during setup |

Optional dependencies:

| Tool | Required For |
|---|---|
| **OpenAI API key** | `design` tool (GPT-4o image generation) |
| **ngrok** | Tunnel support for remote `browse` access |
| **pdftotext** | PDF text extraction in `make-pdf` pipeline |

### 2.2 Install from Source

```bash
git clone https://github.com/garrytan/gstack.git
cd gstack
./setup
```

The `setup` script performs the following:

1. Installs Bun dependencies (`bun install`)
2. Builds the three binaries: `browse`, `design`, `make-pdf`
3. Installs Playwright and its bundled Chromium
4. Copies skills to the detected AI host's skill directory
5. Creates `~/.gstack/` for state and configuration

> [!IMPORTANT]
> If you are installing into a specific AI host other than Claude Code, refer to the [Multi-Host Setup](#54-installing-skills-for-other-ai-hosts) section below. The setup script auto-detects your host, but you can override the target.

### 2.3 Building Binaries Manually

If you need to rebuild after pulling updates:

```bash
bun run build
```

This compiles all three entry points:

| Binary | Source | Purpose |
|---|---|---|
| `browse` | `browse/src/cli.ts` | Headless Chromium browser CLI |
| `design` | `design/src/cli.ts` | AI-powered UI design tool |
| `make-pdf` | `make-pdf/src/cli.ts` | PDF rendering pipeline |

### 2.4 Upgrading gstack

gstack includes a built-in upgrade skill with versioned migrations:

```bash
/gstack-upgrade
```

This runs the upgrade system, which applies any necessary migrations between your current version and the latest. You can also pull and rebuild manually:

```bash
cd ~/.claude/skills/gstack   # or wherever gstack is installed
git pull
./setup
```

### 2.5 Verifying Installation

```bash
browse status
```

Expected output when the server is running:

```
Server running on port 34567 (headed mode)
PID: 12345
Uptime: 2m 15s
Tabs: 1
```

If the server is not running, `browse` auto-starts it on the next command (unless `BROWSE_NO_AUTOSTART=1`).

---

## 3. Configuration

gstack is configured entirely through environment variables. There are no YAML, TOML, or INI config files.

### 3.1 Browse Configuration

| Variable | Default | Description |
|---|---|---|
| `BROWSE_PORT` | Random (34567 in headed) | HTTP server listen port |
| `BROWSE_HEADED` | `0` | Set to `1` for headed Chromium (visible window) |
| `BROWSE_IDLE_TIMEOUT` | Auto | Server idle timeout before shutdown |
| `BROWSE_TAB` | None | Pin all commands to a specific tab ID |
| `BROWSE_PARENT_PID` | Auto | Set to `0` to disable parent-process watchdog |
| `BROWSE_NO_AUTOSTART` | `0` | Set to `1` to prevent auto-starting the server |
| `BROWSE_BIN` | Auto-detected | Override the browse binary path |
| `BROWSE_CONTENT_FILTER` | None | Content security filter level |
| `BROWSE_TUNNEL` | Off | Enable ngrok tunnel for remote access |

### 3.2 Chromium and Security

| Variable | Default | Description |
|---|---|---|
| `GSTACK_CHROMIUM_PATH` | Playwright's bundled Chromium | Path to a custom Chromium binary |
| `GSTACK_SECURITY_ENSEMBLE` | Off | Enable ML-based security ensemble classifier |
| `GSTACK_SECURITY_OFF` | `0` | Set to `1` to fully disable security classifier |
| `GSTACK_HAIKU_TIMEOUT_MS` | Auto | Timeout for the Haiku security classifier |

### 3.3 Design Tool

| Variable | Default | Description |
|---|---|---|
| `OPENAI_API_KEY` | None | OpenAI API key for GPT-4o image generation |

Alternatively, store your key in `~/.gstack/openai.json`:

```json
{
  "api_key": "sk-..."
}
```

### 3.4 Other Variables

| Variable | Default | Description |
|---|---|---|
| `GSTACK_SLUG` | Auto | Project slug identifier |
| `GSTACK_SKILL_ROOT` | Auto | Override the root directory for skill discovery |
| `GSTACK_BROWSE_MAX_HTML_BYTES` | Auto | Maximum HTML payload size for `load-html` |
| `NGROK_AUTHTOKEN` | None | ngrok authentication token for tunneling |
| `NGROK_DOMAIN` | None | Custom ngrok domain |
| `SIDEBAR_AGENT_TIMEOUT` | Auto | Timeout for sidebar agent operations |
| `PDFTOTEXT_BIN` | Auto | Override the pdftotext binary path |

> [!NOTE]
> For the complete list of all 84 environment variables and their internal behaviors, see the **Admin Guide**, Section: Environment Variable Reference.

---

## 4. Core Usage

gstack has three primary tools (`browse`, `design`, `make-pdf`) and a library of 30+ slash-command skills.

### 4.1 browse — Headless Chromium Browser

`browse` is a CLI-driven headless browser built on Playwright. It runs a persistent HTTP server that maintains browser state (cookies, tabs, sessions) across commands. AI coding agents use it to navigate websites, fill forms, take screenshots, and extract page content.

#### Navigation

```bash
# Go to a URL
browse goto https://github.com

# Navigate back/forward
browse back
browse forward

# Reload the current page
browse reload

# Print the current URL
browse url
```

#### Reading Page Content

```bash
# Get all visible text
browse text

# Get HTML of the entire page or a specific element
browse html
browse html "#main-content"

# Get all links on the page
browse links

# Get all forms and their fields
browse forms

# Get the accessibility tree
browse accessibility
```

#### Interacting with Elements

```bash
# Click an element (CSS selector or @ref)
browse click "#submit-btn"
browse click @e3

# Fill a form field
browse fill "#email" "[email removed]"
browse fill @e4 "my search query"

# Select a dropdown option
browse select "#country" "United States"

# Hover over an element
browse hover @e1

# Type text (simulates keyboard input)
browse type "Hello, World!"

# Press a specific key
browse press Enter
browse press Tab

# Scroll the page or a specific element
browse scroll
browse scroll "#content-area"

# Upload files
browse upload "#file-input" ./report.pdf ./data.csv

# Wait for conditions
browse wait "#results"              # wait for element
browse wait --networkidle           # wait for network idle
browse wait --load                  # wait for page load
```

#### Viewport and Responsive Testing

```bash
# Set viewport dimensions
browse viewport 1920x1080
browse viewport 375x812

# Generate responsive screenshots at multiple breakpoints
browse responsive my-page
```

Expected output for `responsive`:

```
[responsive] Capturing at 375x812 (mobile)... saved my-page-375x812.png
[responsive] Capturing at 768x1024 (tablet)... saved my-page-768x1024.png
[responsive] Capturing at 1920x1080 (desktop)... saved my-page-1920x1080.png
```

#### Snapshots and Element References

The `snapshot` command is one of the most powerful features — it indexes every interactive element on the page and assigns `@ref` handles:

```bash
browse snapshot
```

Expected output:

```
[snapshot] 128 elements indexed
@e1   <nav>      Main navigation
@e2   <a>        Home
@e3   <a>        Products
@e4   <input>    Search... [text]
@e5   <button>   Sign In
@e6   <a>        Documentation
...
```

Snapshot options:

```bash
# Include invisible elements
browse snapshot -i

# Include cursor-interactive refs (@c1, @c2...)
browse snapshot -C

# Limit depth
browse snapshot -d 3

# Scope to a selector
browse snapshot -s "#sidebar"

# Include detailed attributes
browse snapshot -D

# Include accessibility info
browse snapshot -a

# Save to file
browse snapshot -o page-snapshot.txt
```

After a snapshot, `@ref` selectors work with most commands:

```bash
browse click @e5          # Click "Sign In" button
browse fill @e4 "gstack"  # Fill search input
browse hover @e2           # Hover "Home" link
browse html @e6            # Get HTML of "Documentation" link
browse css @e5 "color"     # Get CSS color of "Sign In"
browse attrs @e3           # Get all attributes of "Products"
```

When using the `-C` flag, cursor-interactive refs (`@c1`, `@c2`) are also available:

```bash
browse click @c1
```

#### Screenshots and PDFs

```bash
# Full-page screenshot
browse screenshot

# Viewport-only screenshot
browse screenshot --viewport

# Screenshot a specific element
browse screenshot @e1

# Clipped region
browse screenshot --clip 0,0,800,600

# Save to a specific path
browse screenshot ./captures/homepage.png

# Render page as PDF
browse pdf ./output/page.pdf
```

#### JavaScript Execution

```bash
# Evaluate a JavaScript expression
browse js "document.title"

# Run a JavaScript file
browse eval ./scripts/extract-data.js
```

#### Inspection

```bash
# Get CSS property value
browse css "#header" "background-color"

# Get element attributes
browse attrs "#logo"

# View console logs
browse console
browse console --errors    # errors only
browse console --clear     # clear and show

# View network requests
browse network
browse network --clear

# Handle dialogs
browse dialog              # show pending dialogs
browse dialog --clear
browse dialog-accept       # accept with optional text
browse dialog-accept "OK"
browse dialog-dismiss

# Check element state
browse is visible "#modal"
browse is hidden "#loading"
browse is enabled "#submit"
browse is checked "#agree-checkbox"
browse is focused "#search"

# Performance metrics
browse perf

# View/set cookies
browse cookies
browse cookie sessionId=abc123

# View/set storage
browse storage
browse storage set mykey myvalue
```

#### Tab Management

```bash
# List all open tabs
browse tabs

# Switch to a tab by ID
browse tab 2

# Open a new tab
browse newtab https://example.com

# Close a tab
browse closetab 2
```

#### Multi-Step Chains

Execute multiple browser actions in a single command by piping JSON from stdin:

```bash
echo '[
  {"action": "goto", "url": "https://example.com"},
  {"action": "snapshot"},
  {"action": "click", "selector": "@e3"},
  {"action": "screenshot", "path": "result.png"}
]' | browse chain
```

#### Page Comparison

```bash
browse diff https://staging.example.com https://production.example.com
```

#### Cookie Management

```bash
# Import cookies from a JSON file
browse cookie-import ./cookies.json

# Import cookies from a local browser
browse cookie-import-browser chrome
browse cookie-import-browser firefox --domain github.com
```

#### Custom Headers and User Agent

```bash
# Set a custom header
browse header "Authorization: Bearer token123"

# Set a custom user agent
browse useragent "MyBot/1.0"
```

#### Headed Mode

Run Chromium with a visible window:

```bash
BROWSE_HEADED=1 browse goto https://example.com
```

Or connect/disconnect from an existing headed session:

```bash
browse connect
browse disconnect
```

#### Remote Pairing

Allow a remote agent to control your browse session:

```bash
browse pair-agent --client remote-agent --domain example.com --control
browse pair-agent --client remote-agent --restrict "navigation,content"
browse pair-agent --client remote-agent --local localhost:8080
```

#### Server Lifecycle

```bash
# Check server status
browse status

# Stop the server
browse stop

# Restart the server
browse restart
```

> [!TIP]
> The browse server persists between commands and maintains state in `.gstack/browse.json` (PID, port, token, server path). If a command finds no running server, it auto-starts one unless `BROWSE_NO_AUTOSTART=1` is set.

### 4.2 design — AI-Powered UI Design

The `design` tool generates UI mockups using OpenAI GPT-4o image generation. It requires an OpenAI API key.

#### Setup

Set your API key via environment variable or config file:

```bash
export OPENAI_API_KEY="sk-..."
```

Or create `~/.gstack/openai.json`:

```json
{
  "api_key": "sk-..."
}
```

#### Generate a Design

```bash
design generate "A modern dashboard for a SaaS analytics platform"
```

#### Iterate on an Existing Design

```bash
design iterate "Make the sidebar darker and add a notification bell icon"
```

#### Evolve a Design

```bash
design evolve "Transition from mobile layout to desktop"
```

#### Quality Check

Runs a vision-based quality gate using GPT-4o to evaluate text readability, layout completeness, and visual coherence:

```bash
design check
```

#### Compare and Diff

```bash
design compare
design diff
```

#### Design Variants

Generate multiple variations of a design concept:

```bash
design variants
```

#### Design Gallery

View and serve your design history:

```bash
design gallery
design serve
```

#### Design to Code

Convert a generated design into HTML/CSS:

```bash
design design-to-code
```

#### Session Management

```bash
design session
design memory
```

### 4.3 make-pdf — PDF Rendering

`make-pdf` renders web pages and HTML content to PDF using Chromium under the hood:

```bash
make-pdf ./my-page.html ./output.pdf
```

It leverages the `browse` infrastructure for Chromium-based page rendering, ensuring pixel-perfect PDF output with full CSS support.

### 4.4 Skills — Slash Commands for AI Hosts

gstack installs 30+ skills as slash commands. In Claude Code, invoke them with `/skill-name`. Each skill has a `SKILL.md` file describing its purpose and usage.

#### Engineering Skills

| Skill | Purpose |
|---|---|
| `/review` | Code review with structured feedback |
| `/qa` | Quality assurance testing |
| `/qa-only` | QA-only pass (no code changes) |
| `/careful` | Extra-careful mode for critical changes |
| `/guard` | Safety guard checks before deployment |
| `/benchmark` | Performance benchmarking |
| `/benchmark-models` | Benchmark across different AI models |
| `/investigate` | Deep investigation of issues or behavior |
| `/learn` | Extract and document learnings |
| `/freeze` | Freeze current state |
| `/unfreeze` | Unfreeze and resume |

#### Design Skills

| Skill | Purpose |
|---|---|
| `/design` | Generate UI designs |
| `/design-consultation` | Design consultation and feedback |
| `/design-html` | Generate HTML from design specs |
| `/design-review` | Review design implementations |
| `/design-shotgun` | Rapid-fire design exploration |

#### Planning and Review Skills

| Skill | Purpose |
|---|---|
| `/autoplan` | Automatic project planning |
| `/plan-ceo-review` | CEO-level strategic plan review |
| `/plan-design-review` | Design-focused plan review |
| `/plan-devex-review` | Developer experience review |
| `/plan-eng-review` | Engineering plan review |
| `/plan-tune` | Fine-tune project plans |
| `/cso` | Chief Strategy Officer analysis |
| `/retro` | Retrospective analysis |

#### Operations Skills

| Skill | Purpose |
|---|---|
| `/ship` | Ship code to production |
| `/land-and-deploy` | Land changes and deploy |
| `/setup-deploy` | Configure deployment pipeline |
| `/canary` | Canary deployment testing |
| `/health` | Health check diagnostics |

#### Productivity Skills

| Skill | Purpose |
|---|---|
| `/context-save` | Save current context for later |
| `/context-restore` | Restore previously saved context |
| `/browse` | Launch browse from within your agent |
| `/open-gstack-browser` | Open gstack browser in headed mode |
| `/setup-browser-cookies` | Import browser cookies for authentication |
| `/make-pdf` | Render content to PDF |
| `/pair-agent` | Set up remote agent pairing |
| `/office-hours` | Structured office hours workflow |
| `/document-release` | Generate release documentation |
| `/devex-review` | Developer experience review |
| `/gstack-upgrade` | Upgrade gstack to the latest version |
| `/codex` | OpenAI Codex integration |

> [!NOTE]
> The full list of skills and their detailed SKILL.md documentation is installed to your host's skill directory. For Claude Code, that is `~/.claude/skills/gstack/`.

---

## 5. Common Tasks

### 5.1 Scraping a Web Page for Your AI Agent

A typical pattern for giving an AI agent web context:

```bash
# Navigate to the page
browse goto https://docs.example.com/api-reference

# Take a snapshot to index interactive elements
browse snapshot

# Extract the text content
browse text
```

For dynamic pages that need interaction first:

```bash
browse goto https://app.example.com/login
browse snapshot
browse fill @e2 "username"
browse fill @e3 "password"
browse click @e4
browse wait --networkidle
browse snapshot
browse text
```

### 5.2 Taking Screenshots for Visual Verification

```bash
# Full page
browse goto https://myapp.localhost:3000
browse screenshot ./screenshots/full-page.png

# Just the viewport
browse screenshot --viewport ./screenshots/viewport.png

# A specific component
browse snapshot
browse screenshot @e7 ./screenshots/nav-component.png

# Multiple responsive breakpoints
browse viewport 375x812
browse screenshot ./screenshots/mobile.png
browse viewport 1920x1080
browse screenshot ./screenshots/desktop.png
```

### 5.3 Filling Out Forms Automatically

```bash
browse goto https://example.com/register
browse snapshot

# Fill form fields using @refs
browse fill @e1 "Jane Doe"
browse fill @e2 "[email removed]"
browse fill @e3 "securepassword123"
browse select @e4 "United States"
browse click @e5   # checkbox: agree to terms
browse click @e6   # submit button

browse wait --networkidle
browse screenshot ./form-submitted.png
```

### 5.4 Installing Skills for Other AI Hosts

gstack supports 10 AI coding hosts. The `./setup` script auto-detects your host, but you can also manually install skills.

| Host | Skill Install Location |
|---|---|
| Claude Code | `~/.claude/skills/gstack/` |
| OpenAI Codex CLI | `~/.codex/skills/gstack/` |
| Cursor | `~/.cursor/skills/gstack/` |
| Factory Droid | `~/.factory/skills/gstack/` |
| Kiro | `~/.kiro/skills/gstack/` |
| OpenCode | `~/.config/opencode/skills/gstack/` |
| Slate | `~/.slate/skills/gstack/` |
| OpenClaw | `~/.openclaw/skills/gstack/` |
| Hermes | `~/.hermes/skills/gstack/` |
| GBrain | `~/.gbrain/skills/gstack/` |

After installation, use the host's CLI to invoke skills:

| Host | CLI Command | Example |
|---|---|---|
| Claude Code | `claude` | `/review` |
| OpenAI Codex CLI | `codex` | `/review` |
| Cursor | `cursor` | `/review` |
| Factory Droid | `droid` | `/review` |
| Kiro | `kiro-cli` | `/review` |
| OpenCode | `opencode` | `/review` |
| Slate | `slate` | `/review` |
| OpenClaw | `openclaw` | `/review` |
| Hermes | `hermes` | `/review` |
| GBrain | `gbrain` | `/review` |

### 5.5 Using the Design Tool for UI Mockups

A complete design workflow:

```bash
# Generate initial mockup
design generate "A settings page with dark mode toggle, notification preferences, and account deletion"

# Iterate on the result
design iterate "Move the delete account section to its own danger zone card at the bottom"

# Run quality check
design check

# Generate code from the approved design
design design-to-code
```

### 5.6 Rendering a Page to PDF

```bash
# Render an HTML file
make-pdf ./report.html ./report.pdf

# Or use browse directly for any URL
browse goto https://example.com/printable-report
browse pdf ./report.pdf
```

### 5.7 Running Code Review with Skills

In Claude Code:

```
/review
```

The review skill examines your current diff, provides structured feedback on code quality, potential bugs, and suggestions. For a more thorough pass:

```
/careful
```

### 5.8 Managing Browser Cookies for Authenticated Sessions

Import cookies from your local browser to access authenticated pages:

```bash
# Import all cookies from Chrome
browse cookie-import-browser chrome

# Import only cookies for a specific domain
browse cookie-import-browser chrome --domain github.com

# Import from a JSON export file
browse cookie-import ./exported-cookies.json
```

Or use the skill:

```
/setup-browser-cookies
```

### 5.9 Using ngrok Tunnels for Remote Access

Expose your local browse server to remote agents:

```bash
export NGROK_AUTHTOKEN="your-ngrok-token"
export BROWSE_TUNNEL=1

browse goto https://localhost:3000
browse status
```

With a custom domain:

```bash
export NGROK_DOMAIN="my-browse.ngrok.io"
```

### 5.10 Saving and Restoring Agent Context

Preserve your working context across sessions:

```
/context-save
```

Later, in a new session:

```
/context-restore
```

> [!TIP]
> Context save/restore is especially useful when switching between tasks. Save before pivoting to a different feature, then restore when you return.

---

## 6. Troubleshooting

### Error: `Chromium not found`

**Cause:** Playwright's bundled Chromium was not installed during setup, or a custom `GSTACK_CHROMIUM_PATH` points to a missing binary.

**Solution:**
1. Run `npx playwright install chromium` from the gstack directory
2. If using a custom path, verify it exists: `ls $GSTACK_CHROMIUM_PATH`
3. Re-run `./setup` to reinstall dependencies

**Prevention:** Always use `./setup` for initial installation rather than manual `bun install`.

### Error: `Server not running` or `Connection refused`

**Cause:** The browse server is not started or crashed.

**Solution:**
1. Check status: `browse status`
2. Check the state file: `cat ~/.gstack/browse.json` or `.gstack/browse.json`
3. If stale, delete the state file and restart: `rm .gstack/browse.json && browse goto https://example.com`
4. Check if the port is in use: `lsof -i :34567` (Unix) or `netstat -ano | findstr 34567` (Windows)

**Prevention:** Let browse auto-manage the server. Avoid killing processes manually.

### Error: `Port already in use`

**Cause:** Another process (or a previous browse instance) is bound to the configured port.

**Solution:**
1. Use a different port: `BROWSE_PORT=34568 browse goto https://example.com`
2. Kill the existing process on the port
3. Delete stale state: `rm .gstack/browse.json`

**Prevention:** Use the default random port assignment (don't set `BROWSE_PORT`) unless you specifically need a fixed port.

### Error: `DESIGN_NOT_AVAILABLE` in Codex workflows

**Cause:** The design tool's fallback paths are broken when running under OpenAI Codex CLI (GitHub issue #1159).

**Solution:**
1. Ensure `OPENAI_API_KEY` is set in your environment
2. Verify the design binary exists: `which design` or check the build output
3. Rebuild: `bun run build`
4. Check that the Codex skill files reference the correct binary path

**Prevention:** After upgrading gstack, always run `bun run build` and verify all three binaries are compiled.

### Error: `Custom OPENAI_BASE_URL not respected`

**Cause:** The design tool does not properly honor custom OpenAI base URLs (GitHub issue #957).

**Solution:**
1. As a workaround, use the standard OpenAI endpoint
2. If you must use a custom endpoint, check the design source for the exact variable handling
3. Monitor issue #957 for an upstream fix

**Prevention:** Use the default OpenAI API endpoint when possible.

### Error: `build exit code 128` during Conductor template creation

**Cause:** Git operations fail during new project scaffolding, typically when the generated repo has an unborn HEAD (GitHub issues #1174, #1176).

**Solution:**
1. Initialize the repo manually: `git init && git add . && git commit -m "init"`
2. Then retry the Conductor template

**Prevention:** Ensure Git is properly configured (`git config user.name` and `git config user.email` are set) before using Conductor templates.

### Error: `setup --prefix` does not work as expected

**Cause:** The `--prefix` flag has a known bug (GitHub issue #620).

**Solution:**
1. Run `./setup` without `--prefix`
2. Manually move the installed files to your preferred location afterward

**Prevention:** Use the default installation path and adjust `GSTACK_SKILL_ROOT` if you need skills in a non-standard location.

### Error: `setup --help` runs installation instead of showing help

**Cause:** The setup script does not support `--help` and interprets it as a normal run (GitHub issue #1133).

**Solution:**
1. Read the setup script source directly: `cat ./setup`
2. Refer to this User Guide for installation instructions

**Prevention:** Do not pass `--help` to the setup script.

### Error: `Snapshot returned 0 elements`

**Cause:** The page content is loaded dynamically (SPA, lazy-loaded frames) and hasn't rendered yet.

**Solution:**
1. Wait for content: `browse wait --networkidle` or `browse wait "#target-element"`
2. Then retry: `browse snapshot`
3. For iframes, try scoping: `browse snapshot -s "iframe"`

**Prevention:** Always add a `wait` step after navigation to dynamic pages before taking a snapshot.

### Error: `@ref not found` or `Invalid element reference`

**Cause:** The `@ref` handle refers to a stale snapshot — the page has changed since the last `snapshot` command.

**Solution:**
1. Run `browse snapshot` again to re-index elements
2. Use the new `@ref` values

**Prevention:** Re-run `snapshot` after any page navigation, form submission, or significant DOM change.

### Error: `Timeout waiting for selector`

**Cause:** The target element doesn't exist, is hidden, or the page is still loading.

**Solution:**
1. Verify the element exists: `browse html` and search for it
2. Wait longer: `browse wait "#my-element"`
3. Check if the element is inside an iframe (iframes need special handling)
4. Try a different selector strategy

**Prevention:** Use `snapshot` to discover actual selectors rather than guessing CSS selectors.

### Error: `Permission denied` when running `./setup`

**Cause:** The setup script doesn't have execute permission.

**Solution:**
1. Add execute permission: `chmod +x ./setup`
2. Or run directly: `bash ./setup`

**Prevention:** After cloning, run `chmod +x ./setup` before first use.

### Error: `bun: command not found`

**Cause:** Bun is not installed or not on the system PATH.

**Solution:**
1. Install Bun: `curl -fsSL https://bun.sh/install | bash`
2. Restart your shell or source the profile: `source ~/.bashrc`
3. Verify: `bun --version` (must be >= 1.0.0)

**Prevention:** Install Bun before running gstack setup.

### Error: `SECURITY: WARN verdict` but no action taken

**Cause:** The security classifier issues WARN-level verdicts but does not take defensive action — it only logs the warning (GitHub issue #1156).

**Solution:**
1. Review the warning manually in the console output
2. If the content is safe, proceed normally
3. If the content is suspicious, avoid interacting with it

**Prevention:** Enable the full security ensemble for stronger classification: `export GSTACK_SECURITY_ENSEMBLE=1`

### Error: `review skill not looking at correct diff`

**Cause:** The review skill may examine the wrong diff when branches are complex (GitHub issue #1152).

**Solution:**
1. Ensure you are on the correct branch
2. Stage the changes you want reviewed: `git add .`
3. Run `/review` again

**Prevention:** Commit or stage your changes before invoking the review skill.

### Error: `Session tracking not gated by telemetry config`

**Cause:** Session tracking and the `OPENCLAW_SESSION` preamble run regardless of telemetry settings (GitHub issue #1150).

**Solution:**
1. This is a known issue — telemetry gating will be fixed upstream
2. The telemetry is anonymous and uses Supabase edge functions

**Prevention:** Monitor the issue tracker for a fix.

### Error: `Codex generated skills still carry Claude defaults`

**Cause:** When skills are generated for Codex, some Claude-specific defaults persist (GitHub issue #1163).

**Solution:**
1. Manually review generated skill files in `~/.codex/skills/gstack/`
2. Update any Claude-specific references to Codex equivalents

**Prevention:** Run `bun run gen:skill-docs` to regenerate skill docs for your specific host after installation.

### Error: `PDF rendering produces blank page`

**Cause:** The page hasn't finished loading before PDF capture, or the page uses print-hostile CSS.

**Solution:**
1. Wait for full load: `browse wait --load`
2. Wait for network idle: `browse wait --networkidle`
3. Then render: `browse pdf ./output.pdf`
4. Try setting a larger viewport: `browse viewport 1920x1080`

**Prevention:** Always ensure the page is fully loaded before PDF rendering.

> [!WARNING]
> If `browse` commands hang indefinitely, the server may be deadlocked. Kill the process (`browse stop`), delete `.gstack/browse.json`, and restart. If the problem persists, check for Chromium zombie processes in your system's process manager.

### Error: `ngrok tunnel failed`

**Cause:** Missing or invalid ngrok authentication.

**Solution:**
1. Set your token: `export NGROK_AUTHTOKEN="your-token"`
2. Verify your ngrok account at [dashboard.ngrok.com](https://dashboard.ngrok.com)
3. Retry: `BROWSE_TUNNEL=1 browse goto https://example.com`

**Prevention:** Ensure `NGROK_AUTHTOKEN` is set before enabling tunnels.

### Error: `dialog: no pending dialog`

**Cause:** The dialog was already handled, auto-dismissed, or never appeared.

**Solution:**
1. Check dialog history: `browse dialog`
2. Trigger the action that produces the dialog again
3. Handle it immediately: `browse dialog-accept` or `browse dialog-dismiss`

**Prevention:** Handle dialogs promptly after the triggering action. Use `browse dialog --clear` to reset state.

---

## 7. FAQ

**Q: What is gstack exactly? Is it a browser, a design tool, or an AI agent?**

gstack is an AI engineering toolkit — a collection of tools and skills that enhance AI coding agents. Its three main tools are `browse` (headless browser), `design` (UI mockup generator), and `make-pdf` (PDF renderer). The 30+ skills are slash commands that add structured workflows (code review, QA, deployment, etc.) to your AI host.

**Q: Which AI coding hosts does gstack support?**

gstack supports 10 hosts: Claude Code, OpenAI Codex CLI, Cursor, Factory Droid, Kiro, OpenCode, Slate, OpenClaw, Hermes, and GBrain. Skills are installed to host-specific directories, and the setup script auto-detects your host.

**Q: Do I need an OpenAI API key to use gstack?**

Only for the `design` tool, which uses GPT-4o for image generation. The `browse` tool, `make-pdf`, and all other skills work without any API key.

**Q: Is Chromium bundled, or do I need to install it separately?**

Playwright installs a bundled Chromium during `./setup`. You don't need to install Chrome or Chromium separately. If you prefer a custom Chromium binary, set `GSTACK_CHROMIUM_PATH`.

**Q: How does the browse server work? Does it start and stop with each command?**

The server is persistent. The first `browse` command starts it, and it stays running across subsequent commands. State (cookies, tabs, sessions) is maintained in `.gstack/browse.json`. The server shuts down on idle timeout or when you run `browse stop`. It auto-starts on the next command unless `BROWSE_NO_AUTOSTART=1`.

**Q: What is headed mode and when should I use it?**

Headed mode (`BROWSE_HEADED=1`) launches Chromium with a visible window so you can watch the browser in real time. It defaults to port 34567. Use it for debugging, demonstrations, or when you need to visually verify what the agent is doing. In headless mode (the default), Chromium runs invisibly with a random port.

**Q: What are @ref selectors and how do they work?**

After running `browse snapshot`, every interactive element on the page gets an `@ref` handle like `@e1`, `@e3`, `@e15`. These are stable shorthand for CSS selectors. Use them with `click`, `fill`, `hover`, `html`, `css`, and `attrs`. Refs become stale after page navigation — run `snapshot` again to refresh them.

**Q: Can I use gstack to scrape websites behind authentication?**

Yes. Import cookies from your local browser with `browse cookie-import-browser chrome --domain example.com`, or set cookies manually with `browse cookie sessionId=abc123`. You can also fill login forms directly with `browse fill` commands.

**Q: How do I use gstack with a remote machine or server?**

Enable ngrok tunneling with `BROWSE_TUNNEL=1` and `NGROK_AUTHTOKEN`. For agent-to-agent collaboration, use `browse pair-agent`. You can also forward a specific port with `BROWSE_PORT`.

**Q: What does the security classifier do?**

gstack includes a content security classifier that evaluates pages for malicious content. It runs automatically during browse operations. You can enable the full ML ensemble with `GSTACK_SECURITY_ENSEMBLE=1` or disable it entirely with `GSTACK_SECURITY_OFF=1`. The classifier issues verdicts (SAFE, WARN, BLOCK) but WARN verdicts currently do not trigger defensive actions.

**Q: How do I update gstack?**

Run the `/gstack-upgrade` skill from your AI host, or manually: `cd` into the gstack directory, `git pull`, and run `./setup` again. The upgrade system includes versioned migrations that handle any necessary state changes.

**Q: What data does gstack's telemetry collect?**

gstack collects anonymous usage analytics via Supabase edge functions. This includes session-level usage data, not personal information. Telemetry gating is being improved (see issue #1150).

**Q: Can I use `browse` without an AI coding host?**

Yes. `browse` is a standalone CLI tool. You can use it directly from any terminal without Claude Code, Codex, or any other AI host. The skills (slash commands) require a host, but the core tools work independently.

**Q: What is the `snapshot -C` flag for?**

The `-C` flag adds cursor-interactive refs (`@c1`, `@c2`, etc.) in addition to the standard `@e` refs. These represent elements that are interactive based on cursor behavior (hover targets, clickable areas) that might not have standard form-element semantics.

> [!CAUTION]
> The `browse` tool can interact with any website your network can reach. Be mindful of terms of service when using it for automated interactions. Do not use it for unauthorized access or aggressive scraping.

**Q: Where does gstack store its state?**

State is stored in two locations: `~/.gstack/` (global — API keys, shared config) and `.gstack/` (project-local — `browse.json` with server PID/port/token). The project-local directory is created in your current working directory.

**Q: How do I check which skills are installed?**

Run `bun run skill:check` from the gstack directory. You can also list the skill directories in your host's skill root (e.g., `ls ~/.claude/skills/gstack/`).

---

_Generated May 2026 from garrytan/gstack at e3d7f49. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
