mirror of https://github.com/garrytan/gstack.git
feat: install gstack from Claude Code marketplace
This allows users to install and update gstack through the native Claude Code plugin system:
```
/plugin marketplace add garrytan/gstack
/plugin install gstack@gstack-marketplace
```
- Add `.claude-plugin/` marketplace and plugin manifests
- Move skills into `skills/` directory for plugin auto-discovery
- Use `${CLAUDE_SKILL_DIR}` for portable paths
- Removes (now unneeded) setup script
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
044c6d568e
commit
1adf401ead
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "gstack-marketplace",
|
||||||
|
"owner": {
|
||||||
|
"name": "Garry Tan",
|
||||||
|
"email": "garry@ycombinator.com"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"description": "Garry's Stack — workflow skills for Claude Code. Plan review, code review, shipping, browser automation, and retrospectives.",
|
||||||
|
"version": "0.0.2"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "gstack",
|
||||||
|
"description": "Complete gstack bundle with all workflow skills: /plan-ceo-review (founder mode), /plan-eng-review (eng manager), /review (paranoid engineer), /ship (release automation), /browse (headless browser QA), /retro (weekly retrospective).",
|
||||||
|
"version": "0.0.2",
|
||||||
|
"homepage": "https://github.com/garrytan/gstack",
|
||||||
|
"license": "MIT",
|
||||||
|
"source": "./"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"name": "gstack",
|
||||||
|
"description": "Complete gstack bundle with all workflow skills: /plan-ceo-review (founder mode), /plan-eng-review (eng manager), /review (paranoid engineer), /ship (release automation), /browse (headless browser QA), /retro (weekly retrospective).",
|
||||||
|
"version": "0.0.2",
|
||||||
|
"author": {
|
||||||
|
"name": "Garry Tan",
|
||||||
|
"email": "garry@ycombinator.com"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/garrytan/gstack",
|
||||||
|
"repository": "https://github.com/garrytan/gstack",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": ["workflow", "planning", "review", "shipping", "browser", "qa", "retrospective"]
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
node_modules/
|
node_modules/
|
||||||
browse/dist/
|
skills/browse/dist/
|
||||||
/tmp/
|
/tmp/
|
||||||
*.log
|
*.log
|
||||||
bun.lock
|
bun.lock
|
||||||
|
|
|
||||||
39
CLAUDE.md
39
CLAUDE.md
|
|
@ -6,33 +6,32 @@
|
||||||
bun install # install dependencies
|
bun install # install dependencies
|
||||||
bun test # run integration tests (browse + snapshot)
|
bun test # run integration tests (browse + snapshot)
|
||||||
bun run dev <cmd> # run CLI in dev mode, e.g. bun run dev goto https://example.com
|
bun run dev <cmd> # run CLI in dev mode, e.g. bun run dev goto https://example.com
|
||||||
bun run build # compile binary to browse/dist/browse
|
bun run build # compile binary to skills/browse/dist/browse
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project structure
|
## Project structure
|
||||||
|
|
||||||
```
|
```
|
||||||
gstack/
|
gstack/
|
||||||
├── browse/ # Headless browser CLI (Playwright)
|
├── .claude-plugin/ # Plugin marketplace config
|
||||||
│ ├── src/ # CLI + server + commands
|
│ ├── plugin.json # Plugin manifest
|
||||||
│ ├── test/ # Integration tests + fixtures
|
│ └── marketplace.json
|
||||||
│ └── dist/ # Compiled binary
|
├── skills/ # All skills (auto-discovered by plugin system)
|
||||||
├── ship/ # Ship workflow skill
|
│ ├── browse/ # Headless browser CLI (Playwright)
|
||||||
├── review/ # PR review skill
|
│ │ ├── src/ # CLI + server + commands
|
||||||
├── plan-ceo-review/ # /plan-ceo-review skill
|
│ │ ├── test/ # Integration tests + fixtures
|
||||||
├── plan-eng-review/ # /plan-eng-review skill
|
│ │ └── dist/ # Compiled binary
|
||||||
├── retro/ # Retrospective skill
|
│ ├── ship/ # Ship workflow skill
|
||||||
├── setup # One-time setup: build binary + symlink skills
|
│ ├── review/ # PR review skill
|
||||||
├── SKILL.md # Browse skill (Claude discovers this)
|
│ ├── plan-ceo-review/ # /plan-ceo-review skill
|
||||||
|
│ ├── plan-eng-review/ # /plan-eng-review skill
|
||||||
|
│ └── retro/ # Retrospective skill
|
||||||
└── package.json # Build scripts for browse
|
└── package.json # Build scripts for browse
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deploying to the active skill
|
## Installation
|
||||||
|
|
||||||
The active skill lives at `~/.claude/skills/gstack/`. After making changes:
|
```
|
||||||
|
/plugin marketplace add garrytan/gstack
|
||||||
1. Push your branch
|
/plugin install gstack@gstack-marketplace
|
||||||
2. Fetch and reset in the skill directory: `cd ~/.claude/skills/gstack && git fetch origin && git reset --hard origin/main`
|
```
|
||||||
3. Rebuild: `cd ~/.claude/skills/gstack && bun run build`
|
|
||||||
|
|
||||||
Or copy the binary directly: `cp browse/dist/browse ~/.claude/skills/gstack/browse/dist/browse`
|
|
||||||
|
|
|
||||||
254
SKILL.md
254
SKILL.md
|
|
@ -1,254 +0,0 @@
|
||||||
---
|
|
||||||
name: gstack
|
|
||||||
version: 1.0.0
|
|
||||||
description: |
|
|
||||||
Fast web browsing for Claude Code via persistent headless Chromium daemon. Navigate to any URL,
|
|
||||||
read page content, click elements, fill forms, run JavaScript, take screenshots,
|
|
||||||
inspect CSS/DOM, capture console/network logs, and more. ~100ms per command after
|
|
||||||
first call. Use when you need to check a website, verify a deployment, read docs,
|
|
||||||
or interact with any web page. No MCP, no Chrome extension — just fast CLI.
|
|
||||||
allowed-tools:
|
|
||||||
- Bash
|
|
||||||
- Read
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# gstack: Persistent Browser for Claude Code
|
|
||||||
|
|
||||||
Persistent headless Chromium daemon. First call auto-starts the server (~3s).
|
|
||||||
Every subsequent call: ~100-200ms. Auto-shuts down after 30 min idle.
|
|
||||||
|
|
||||||
## SETUP (run this check BEFORE any browse command)
|
|
||||||
|
|
||||||
Before using any browse command, find the skill and check if the binary exists:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check project-level first, then user-level
|
|
||||||
if test -x .claude/skills/gstack/browse/dist/browse; then
|
|
||||||
echo "READY_PROJECT"
|
|
||||||
elif test -x ~/.claude/skills/gstack/browse/dist/browse; then
|
|
||||||
echo "READY_USER"
|
|
||||||
else
|
|
||||||
echo "NEEDS_SETUP"
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
Set `B` to whichever path is READY and use it for all commands. Prefer project-level if both exist.
|
|
||||||
|
|
||||||
If `NEEDS_SETUP`:
|
|
||||||
1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait for their response.
|
|
||||||
2. If they approve, determine the skill directory (project-level `.claude/skills/gstack` or user-level `~/.claude/skills/gstack`) and run:
|
|
||||||
```bash
|
|
||||||
cd <SKILL_DIR> && ./setup
|
|
||||||
```
|
|
||||||
3. If `bun` is not installed, tell the user to install it: `curl -fsSL https://bun.sh/install | bash`
|
|
||||||
4. Verify the `.gitignore` in the skill directory contains `browse/dist/` and `node_modules/`. If either line is missing, add it.
|
|
||||||
|
|
||||||
Once setup is done, it never needs to run again (the compiled binary persists).
|
|
||||||
|
|
||||||
## IMPORTANT
|
|
||||||
|
|
||||||
- Use the compiled binary via Bash: `.claude/skills/gstack/browse/dist/browse` (project) or `~/.claude/skills/gstack/browse/dist/browse` (user).
|
|
||||||
- NEVER use `mcp__claude-in-chrome__*` tools. They are slow and unreliable.
|
|
||||||
- The browser persists between calls — cookies, tabs, and state carry over.
|
|
||||||
- The server auto-starts on first command. No setup needed.
|
|
||||||
|
|
||||||
## Quick Reference
|
|
||||||
|
|
||||||
```bash
|
|
||||||
B=~/.claude/skills/gstack/browse/dist/browse
|
|
||||||
|
|
||||||
# Navigate to a page
|
|
||||||
$B goto https://example.com
|
|
||||||
|
|
||||||
# Read cleaned page text
|
|
||||||
$B text
|
|
||||||
|
|
||||||
# Take a screenshot (then Read the image)
|
|
||||||
$B screenshot /tmp/page.png
|
|
||||||
|
|
||||||
# Snapshot: accessibility tree with refs
|
|
||||||
$B snapshot -i
|
|
||||||
|
|
||||||
# Click by ref (after snapshot)
|
|
||||||
$B click @e3
|
|
||||||
|
|
||||||
# Fill by ref
|
|
||||||
$B fill @e4 "test@test.com"
|
|
||||||
|
|
||||||
# Run JavaScript
|
|
||||||
$B js "document.title"
|
|
||||||
|
|
||||||
# Get all links
|
|
||||||
$B links
|
|
||||||
|
|
||||||
# Click by CSS selector
|
|
||||||
$B click "button.submit"
|
|
||||||
|
|
||||||
# Fill a form by CSS selector
|
|
||||||
$B fill "#email" "test@test.com"
|
|
||||||
$B fill "#password" "abc123"
|
|
||||||
$B click "button[type=submit]"
|
|
||||||
|
|
||||||
# Get HTML of an element
|
|
||||||
$B html "main"
|
|
||||||
|
|
||||||
# Get computed CSS
|
|
||||||
$B css "body" "font-family"
|
|
||||||
|
|
||||||
# Get element attributes
|
|
||||||
$B attrs "nav"
|
|
||||||
|
|
||||||
# Wait for element to appear
|
|
||||||
$B wait ".loaded"
|
|
||||||
|
|
||||||
# Accessibility tree
|
|
||||||
$B accessibility
|
|
||||||
|
|
||||||
# Set viewport
|
|
||||||
$B viewport 375x812
|
|
||||||
|
|
||||||
# Set cookies / headers
|
|
||||||
$B cookie "session=abc123"
|
|
||||||
$B header "Authorization:Bearer token123"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Command Reference
|
|
||||||
|
|
||||||
### Navigation
|
|
||||||
```
|
|
||||||
browse goto <url> Navigate current tab
|
|
||||||
browse back Go back
|
|
||||||
browse forward Go forward
|
|
||||||
browse reload Reload page
|
|
||||||
browse url Print current URL
|
|
||||||
```
|
|
||||||
|
|
||||||
### Content extraction
|
|
||||||
```
|
|
||||||
browse text Cleaned page text (no scripts/styles)
|
|
||||||
browse html [selector] innerHTML of element, or full page HTML
|
|
||||||
browse links All links as "text → href"
|
|
||||||
browse forms All forms + fields as JSON
|
|
||||||
browse accessibility Accessibility tree snapshot (ARIA)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Snapshot (ref-based element selection)
|
|
||||||
```
|
|
||||||
browse snapshot Full accessibility tree with @refs
|
|
||||||
browse snapshot -i Interactive elements only (buttons, links, inputs)
|
|
||||||
browse snapshot -c Compact (no empty structural elements)
|
|
||||||
browse snapshot -d <N> Limit depth to N levels
|
|
||||||
browse snapshot -s <sel> Scope to CSS selector
|
|
||||||
```
|
|
||||||
|
|
||||||
After snapshot, use @refs as selectors in any command:
|
|
||||||
```
|
|
||||||
browse click @e3 Click the element assigned ref @e3
|
|
||||||
browse fill @e4 "value" Fill the input assigned ref @e4
|
|
||||||
browse hover @e1 Hover the element assigned ref @e1
|
|
||||||
browse html @e2 Get innerHTML of ref @e2
|
|
||||||
browse css @e5 "color" Get computed CSS of ref @e5
|
|
||||||
browse attrs @e6 Get attributes of ref @e6
|
|
||||||
```
|
|
||||||
|
|
||||||
Refs are invalidated on navigation — run `snapshot` again after `goto`.
|
|
||||||
|
|
||||||
### Interaction
|
|
||||||
```
|
|
||||||
browse click <selector> Click element (CSS selector or @ref)
|
|
||||||
browse fill <selector> <value> Fill input field
|
|
||||||
browse select <selector> <val> Select dropdown value
|
|
||||||
browse hover <selector> Hover over element
|
|
||||||
browse type <text> Type into focused element
|
|
||||||
browse press <key> Press key (Enter, Tab, Escape, etc.)
|
|
||||||
browse scroll [selector] Scroll element into view, or page bottom
|
|
||||||
browse wait <selector> Wait for element to appear (max 10s)
|
|
||||||
browse viewport <WxH> Set viewport size (e.g. 375x812)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Inspection
|
|
||||||
```
|
|
||||||
browse js <expression> Run JS, print result
|
|
||||||
browse eval <js-file> Run JS file against page
|
|
||||||
browse css <selector> <prop> Get computed CSS property
|
|
||||||
browse attrs <selector> Get element attributes as JSON
|
|
||||||
browse console Dump captured console messages
|
|
||||||
browse console --clear Clear console buffer
|
|
||||||
browse network Dump captured network requests
|
|
||||||
browse network --clear Clear network buffer
|
|
||||||
browse cookies Dump all cookies as JSON
|
|
||||||
browse storage localStorage + sessionStorage as JSON
|
|
||||||
browse storage set <key> <val> Set localStorage value
|
|
||||||
browse perf Page load performance timings
|
|
||||||
```
|
|
||||||
|
|
||||||
### Visual
|
|
||||||
```
|
|
||||||
browse screenshot [path] Screenshot (default: /tmp/browse-screenshot.png)
|
|
||||||
browse pdf [path] Save as PDF
|
|
||||||
browse responsive [prefix] Screenshots at mobile/tablet/desktop
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compare
|
|
||||||
```
|
|
||||||
browse diff <url1> <url2> Text diff between two pages
|
|
||||||
```
|
|
||||||
|
|
||||||
### Multi-step (chain)
|
|
||||||
```
|
|
||||||
echo '[["goto","https://example.com"],["snapshot","-i"],["click","@e1"],["screenshot","/tmp/result.png"]]' | browse chain
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tabs
|
|
||||||
```
|
|
||||||
browse tabs List tabs (id, url, title)
|
|
||||||
browse tab <id> Switch to tab
|
|
||||||
browse newtab [url] Open new tab
|
|
||||||
browse closetab [id] Close tab
|
|
||||||
```
|
|
||||||
|
|
||||||
### Server management
|
|
||||||
```
|
|
||||||
browse status Server health, uptime, tab count
|
|
||||||
browse stop Shutdown server
|
|
||||||
browse restart Kill + restart server
|
|
||||||
```
|
|
||||||
|
|
||||||
## Speed Rules
|
|
||||||
|
|
||||||
1. **Navigate once, query many times.** `goto` loads the page; then `text`, `js`, `css`, `screenshot` all run against the loaded page instantly.
|
|
||||||
2. **Use `snapshot -i` for interaction.** Get refs for all interactive elements, then click/fill by ref. No need to guess CSS selectors.
|
|
||||||
3. **Use `js` for precision.** `js "document.querySelector('.price').textContent"` is faster than parsing full page text.
|
|
||||||
4. **Use `links` to survey.** Faster than `text` when you just need navigation structure.
|
|
||||||
5. **Use `chain` for multi-step flows.** Avoids CLI overhead per step.
|
|
||||||
6. **Use `responsive` for layout checks.** One command = 3 viewport screenshots.
|
|
||||||
|
|
||||||
## When to Use What
|
|
||||||
|
|
||||||
| Task | Commands |
|
|
||||||
|------|----------|
|
|
||||||
| Read a page | `goto <url>` then `text` |
|
|
||||||
| Interact with elements | `snapshot -i` then `click @e3` |
|
|
||||||
| Check if element exists | `js "!!document.querySelector('.thing')"` |
|
|
||||||
| Extract specific data | `js "document.querySelector('.price').textContent"` |
|
|
||||||
| Visual check | `screenshot /tmp/x.png` then Read the image |
|
|
||||||
| Fill and submit form | `snapshot -i` → `fill @e4 "val"` → `click @e5` → `screenshot` |
|
|
||||||
| Check CSS | `css "selector" "property"` or `css @e3 "property"` |
|
|
||||||
| Inspect DOM | `html "selector"` or `attrs @e3` |
|
|
||||||
| Debug console errors | `console` |
|
|
||||||
| Check network requests | `network` |
|
|
||||||
| Check local dev | `goto http://127.0.0.1:3000` |
|
|
||||||
| Compare two pages | `diff <url1> <url2>` |
|
|
||||||
| Mobile layout check | `responsive /tmp/prefix` |
|
|
||||||
| Multi-step flow | `echo '[...]' \| browse chain` |
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
- Persistent Chromium daemon on localhost (port 9400-9410)
|
|
||||||
- Bearer token auth per session
|
|
||||||
- State file: `/tmp/browse-server.json`
|
|
||||||
- Console log: `/tmp/browse-console.log`
|
|
||||||
- Network log: `/tmp/browse-network.log`
|
|
||||||
- Auto-shutdown after 30 min idle
|
|
||||||
- Chromium crash → server exits → auto-restarts on next command
|
|
||||||
10
package.json
10
package.json
|
|
@ -5,14 +5,14 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
"browse": "./browse/dist/browse"
|
"browse": "./skills/browse/dist/browse"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "bun build --compile browse/src/cli.ts --outfile browse/dist/browse",
|
"build": "bun build --compile skills/browse/src/cli.ts --outfile skills/browse/dist/browse",
|
||||||
"dev": "bun run browse/src/cli.ts",
|
"dev": "bun run skills/browse/src/cli.ts",
|
||||||
"server": "bun run browse/src/server.ts",
|
"server": "bun run skills/browse/src/server.ts",
|
||||||
"test": "bun test",
|
"test": "bun test",
|
||||||
"start": "bun run browse/src/server.ts"
|
"start": "bun run skills/browse/src/server.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "^1.58.2",
|
"playwright": "^1.58.2",
|
||||||
|
|
|
||||||
62
setup
62
setup
|
|
@ -1,62 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# gstack setup — build browser binary + register all skills with Claude Code
|
|
||||||
set -e
|
|
||||||
|
|
||||||
GSTACK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
||||||
SKILLS_DIR="$(dirname "$GSTACK_DIR")"
|
|
||||||
BROWSE_BIN="$GSTACK_DIR/browse/dist/browse"
|
|
||||||
|
|
||||||
# 1. Build browse binary if needed
|
|
||||||
NEEDS_BUILD=0
|
|
||||||
if [ ! -x "$BROWSE_BIN" ]; then
|
|
||||||
NEEDS_BUILD=1
|
|
||||||
elif [ -n "$(find "$GSTACK_DIR/browse/src" -type f -newer "$BROWSE_BIN" -print -quit 2>/dev/null)" ]; then
|
|
||||||
NEEDS_BUILD=1
|
|
||||||
elif [ "$GSTACK_DIR/package.json" -nt "$BROWSE_BIN" ]; then
|
|
||||||
NEEDS_BUILD=1
|
|
||||||
elif [ -f "$GSTACK_DIR/bun.lock" ] && [ "$GSTACK_DIR/bun.lock" -nt "$BROWSE_BIN" ]; then
|
|
||||||
NEEDS_BUILD=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$NEEDS_BUILD" -eq 1 ]; then
|
|
||||||
echo "Building browse binary..."
|
|
||||||
(
|
|
||||||
cd "$GSTACK_DIR"
|
|
||||||
bun install
|
|
||||||
bun run build
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -x "$BROWSE_BIN" ]; then
|
|
||||||
echo "gstack setup failed: browse binary missing at $BROWSE_BIN" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 2. Only create skill symlinks if we're inside a .claude/skills directory
|
|
||||||
SKILLS_BASENAME="$(basename "$SKILLS_DIR")"
|
|
||||||
if [ "$SKILLS_BASENAME" = "skills" ]; then
|
|
||||||
linked=()
|
|
||||||
for skill_dir in "$GSTACK_DIR"/*/; do
|
|
||||||
if [ -f "$skill_dir/SKILL.md" ]; then
|
|
||||||
skill_name="$(basename "$skill_dir")"
|
|
||||||
# Skip node_modules
|
|
||||||
[ "$skill_name" = "node_modules" ] && continue
|
|
||||||
target="$SKILLS_DIR/$skill_name"
|
|
||||||
# Create or update symlink; skip if a real file/directory exists
|
|
||||||
if [ -L "$target" ] || [ ! -e "$target" ]; then
|
|
||||||
ln -snf "gstack/$skill_name" "$target"
|
|
||||||
linked+=("$skill_name")
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "gstack ready."
|
|
||||||
echo " browse: $BROWSE_BIN"
|
|
||||||
if [ ${#linked[@]} -gt 0 ]; then
|
|
||||||
echo " linked skills: ${linked[*]}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "gstack ready."
|
|
||||||
echo " browse: $BROWSE_BIN"
|
|
||||||
echo " (skipped skill symlinks — not inside .claude/skills/)"
|
|
||||||
fi
|
|
||||||
|
|
@ -20,35 +20,31 @@ Every subsequent call: ~100-200ms. Auto-shuts down after 30 min idle.
|
||||||
|
|
||||||
## SETUP (run this check BEFORE any browse command)
|
## SETUP (run this check BEFORE any browse command)
|
||||||
|
|
||||||
Before using any browse command, find the skill and check if the binary exists:
|
Before using any browse command, check if the binary exists:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Check project-level first, then user-level
|
if test -x "${CLAUDE_SKILL_DIR}/dist/browse"; then
|
||||||
if test -x .claude/skills/gstack/browse/dist/browse; then
|
echo "READY"
|
||||||
echo "READY_PROJECT"
|
|
||||||
elif test -x ~/.claude/skills/gstack/browse/dist/browse; then
|
|
||||||
echo "READY_USER"
|
|
||||||
else
|
else
|
||||||
echo "NEEDS_SETUP"
|
echo "NEEDS_BUILD"
|
||||||
fi
|
fi
|
||||||
```
|
```
|
||||||
|
|
||||||
Set `B` to whichever path is READY and use it for all commands. Prefer project-level if both exist.
|
Set `B` to the binary path: `B="${CLAUDE_SKILL_DIR}/dist/browse"`
|
||||||
|
|
||||||
If `NEEDS_SETUP`:
|
If `NEEDS_BUILD`:
|
||||||
1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait for their response.
|
1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait for their response.
|
||||||
2. If they approve, determine the skill directory (project-level `.claude/skills/gstack` or user-level `~/.claude/skills/gstack`) and run:
|
2. If they approve, run:
|
||||||
```bash
|
```bash
|
||||||
cd <SKILL_DIR> && ./setup
|
cd "${CLAUDE_SKILL_DIR}" && bun install && bun build --compile src/cli.ts --outfile dist/browse
|
||||||
```
|
```
|
||||||
3. If `bun` is not installed, tell the user to install it: `curl -fsSL https://bun.sh/install | bash`
|
3. If `bun` is not installed, tell the user to install it: `curl -fsSL https://bun.sh/install | bash`
|
||||||
4. Verify the `.gitignore` in the skill directory contains `browse/dist/` and `node_modules/`. If either line is missing, add it.
|
|
||||||
|
|
||||||
Once setup is done, it never needs to run again (the compiled binary persists).
|
Once built, the compiled binary persists across sessions.
|
||||||
|
|
||||||
## IMPORTANT
|
## IMPORTANT
|
||||||
|
|
||||||
- Use the compiled binary via Bash: `.claude/skills/gstack/browse/dist/browse` (project) or `~/.claude/skills/gstack/browse/dist/browse` (user).
|
- Use the compiled binary via Bash: `${CLAUDE_SKILL_DIR}/dist/browse`
|
||||||
- NEVER use `mcp__claude-in-chrome__*` tools. They are slow and unreliable.
|
- NEVER use `mcp__claude-in-chrome__*` tools. They are slow and unreliable.
|
||||||
- The browser persists between calls — cookies, tabs, and state carry over.
|
- The browser persists between calls — cookies, tabs, and state carry over.
|
||||||
- The server auto-starts on first command. No setup needed.
|
- The server auto-starts on first command. No setup needed.
|
||||||
|
|
@ -56,7 +52,7 @@ Once setup is done, it never needs to run again (the compiled binary persists).
|
||||||
## Quick Reference
|
## Quick Reference
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
B=~/.claude/skills/gstack/browse/dist/browse
|
B="${CLAUDE_SKILL_DIR}/dist/browse"
|
||||||
|
|
||||||
# Navigate to a page
|
# Navigate to a page
|
||||||
$B goto https://example.com
|
$B goto https://example.com
|
||||||
|
|
@ -30,7 +30,7 @@ You are running the `/review` workflow. Analyze the current branch's diff agains
|
||||||
|
|
||||||
## Step 2: Read the checklist
|
## Step 2: Read the checklist
|
||||||
|
|
||||||
Read `.claude/skills/review/checklist.md`.
|
Read `${CLAUDE_SKILL_DIR}/checklist.md`.
|
||||||
|
|
||||||
**If the file cannot be read, STOP and report the error.** Do not proceed without the checklist.
|
**If the file cannot be read, STOP and report the error.** Do not proceed without the checklist.
|
||||||
|
|
||||||
|
|
@ -145,7 +145,7 @@ If multiple suites need to run, run them sequentially (each needs a test lane).
|
||||||
|
|
||||||
Review the diff for structural issues that tests don't catch.
|
Review the diff for structural issues that tests don't catch.
|
||||||
|
|
||||||
1. Read `.claude/skills/review/checklist.md`. If the file cannot be read, **STOP** and report the error.
|
1. Read `${CLAUDE_SKILL_DIR}/../review/checklist.md`. If the file cannot be read, **STOP** and report the error.
|
||||||
|
|
||||||
2. Run `git diff origin/main` to get the full diff (scoped to feature changes against the freshly-fetched remote main).
|
2. Run `git diff origin/main` to get the full diff (scoped to feature changes against the freshly-fetched remote main).
|
||||||
|
|
||||||
Loading…
Reference in New Issue