mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-21 20:30:47 +02:00
293 lines
11 KiB
Markdown
293 lines
11 KiB
Markdown
<!-- GENERATED by scripts/gstack2/generate-skill-tree.ts; do not edit. -->
|
|
<!-- GSTACK2_PROVENANCE source=pair-agent/SKILL.md.tmpl base=bb57306d98c97011b0919c6132705a15b1579781 blob=75ed42d590f99c46cd0883c37bb1f2f9f499211c baseline_render_sha256=6bb659c03b5df7c36f446fad30aaec4ab6d5e0d25fb8392702573e66923b02fb ported_render_sha256=e75661246495412102632a49d626bc313875ef479d2c570002ec66a2ccd2757a disposition=BUG_FIX -->
|
|
<!-- GSTACK2_ROUTING replacement=$qa --mode Report --module pair-agent visibility=internal depth=standard mutation=configuration web=local-browser -->
|
|
|
|
<!-- GSTACK2_LEGACY_BODY_START source=pair-agent -->
|
|
## Host-neutral runtime bindings
|
|
|
|
These assignments select stable paths only; they do not install anything or grant consent:
|
|
|
|
```bash
|
|
GSTACK_HOME="${GSTACK_HOME:-$HOME/.gstack}"
|
|
GSTACK_ROOT="$GSTACK_HOME"
|
|
GSTACK_STATE_ROOT="$GSTACK_HOME"
|
|
GSTACK_BIN="$GSTACK_HOME/bin"
|
|
BUN_CMD="$GSTACK_BIN/bun"
|
|
B="$GSTACK_BIN/browse"
|
|
D="$GSTACK_BIN/gstack-design"
|
|
P="$GSTACK_BIN/make-pdf"
|
|
```
|
|
## Visible-browser point-of-use gate
|
|
|
|
This workflow may require internal `browser-visible` because it reaches a headed browser, extension, interactive cookie picker, or browser handoff. Do not offer visible Chromium during ordinary headless QA.
|
|
|
|
At the first actual visible-browser step, run the local-only `node references/support/runtime-bootstrap.mjs options --capability browser-visible`, explain that this extension-bearing flow requires managed Chromium because installed Chrome-family builds can block automation extension loading, and ask whether the user wants to check exact official sizes. Disclose that an uncached preview makes one public GitHub signed-manifest request and sends no repository/private data, then STOP. Only after approval run `node references/support/runtime-bootstrap.mjs preview --capability browser-visible --browser managed`. It expands to `core + browser-code + browser-visible` for a first install, but an existing verified headless runtime downloads only missing `browser-visible`; it never requires `browser-headless`. Show the exact missing components and summed incremental compressed bytes, then STOP again for separate install approval. Only after install approval run `node references/support/runtime-bootstrap.mjs install --capability browser-visible --browser managed --yes`, recheck readiness, and resume the interrupted step.
|
|
|
|
# $qa --mode Report --module pair-agent — Share Your Browser With Another AI Agent
|
|
|
|
You're sitting in Claude Code with a browser running. You also have another AI agent
|
|
open (OpenClaw, Hermes, Codex, Cursor, whatever). You want that other agent to be
|
|
able to browse the web using YOUR browser. This skill makes that happen.
|
|
|
|
## How it works
|
|
|
|
Your gstack browser runs a local HTTP server. This skill creates a one-time setup key,
|
|
prints a block of instructions, and you paste those instructions into the other agent.
|
|
The other agent exchanges the key for a session token, creates its own tab, and starts
|
|
browsing. Each agent gets its own tab. They can't mess with each other's tabs.
|
|
|
|
The setup key expires in 5 minutes and can only be used once. If it leaks, it's dead
|
|
before anyone can abuse it. The session token lasts 24 hours.
|
|
|
|
**Same machine:** If the other agent is on the same machine (like OpenClaw running
|
|
locally), you can skip the copy-paste ceremony and write the credentials directly to
|
|
the agent's config directory.
|
|
|
|
**Remote:** If the other agent is on a different machine, you need an ngrok tunnel.
|
|
The skill will tell you if one is needed and how to set it up.
|
|
|
|
## SETUP (run this check BEFORE any browse command)
|
|
|
|
```bash
|
|
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
B=""
|
|
[ -n "$_ROOT" ] && [ -x "$GSTACK_BIN/browse" ] && B="$GSTACK_BIN/browse"
|
|
[ -z "$B" ] && B="${GSTACK_HOME:-$HOME/.gstack}/bin/browse"
|
|
if [ -x "$B" ]; then
|
|
echo "READY: $B"
|
|
else
|
|
echo "NEEDS_SETUP"
|
|
fi
|
|
```
|
|
|
|
If `NEEDS_SETUP`:
|
|
1. Tell the user: "The browser-backed capability is not ready. Do you want to see the local setup options—GStack-managed Chromium or a detected installed Chromium executable—with no network access or changes?" Then STOP and wait.
|
|
2. Read `references/RUNTIME.md` and follow its explicit capability bootstrap. Never assume a standard-installed skill directory contains `./setup`.
|
|
3. The approved managed runtime includes its own pinned Bun at `$GSTACK_BIN/bun`; never download or install another Bun from a skill workflow.
|
|
|
|
## Step 1: Check prerequisites
|
|
|
|
```bash
|
|
$B status 2>/dev/null
|
|
```
|
|
|
|
If the browse server is not running, start it:
|
|
|
|
```bash
|
|
$B goto about:blank
|
|
```
|
|
|
|
This ensures the server is up and healthy before pairing.
|
|
|
|
## Step 2: Ask what they want
|
|
|
|
Use AskUserQuestion:
|
|
|
|
> Which agent do you want to pair with your browser? This determines the
|
|
> instructions format and where credentials get written.
|
|
|
|
Options:
|
|
- A) OpenClaw (local or remote)
|
|
- B) Codex / OpenAI Agents (local)
|
|
- C) Cursor (local)
|
|
- D) Another Claude Code session (local or remote)
|
|
- E) Something else (generic HTTP instructions — use this for Hermes)
|
|
|
|
Based on the answer, set `TARGET_HOST`:
|
|
- A → `openclaw`
|
|
- B → `codex`
|
|
- C → `cursor`
|
|
- D → `claude`
|
|
- E → generic (no host-specific config)
|
|
|
|
## Step 3: Local or remote?
|
|
|
|
Use AskUserQuestion:
|
|
|
|
> Is the other agent running on this same machine, or on a different machine/server?
|
|
>
|
|
> **Same machine** skips the copy-paste ceremony. Credentials are written directly to
|
|
> the agent's config directory. No tunnel needed.
|
|
>
|
|
> **Different machine** generates a setup key and instruction block. If ngrok is
|
|
> installed, the tunnel starts automatically. If not, I'll walk you through setup.
|
|
>
|
|
> RECOMMENDATION: Choose A if the agent is local. It's instant, no copy-paste needed.
|
|
|
|
Options:
|
|
- A) Same machine (write credentials directly)
|
|
- B) Different machine (generate instruction block for copy-paste)
|
|
|
|
## Step 4: Execute pairing
|
|
|
|
### If same machine (option A):
|
|
|
|
Run pair-agent with --local flag:
|
|
|
|
```bash
|
|
$B pair-agent --local TARGET_HOST
|
|
```
|
|
|
|
Replace `TARGET_HOST` with the value from Step 2 (openclaw, codex, cursor, etc.).
|
|
|
|
If it succeeds, tell the user:
|
|
"Done. TARGET_HOST can now use your browser. It will read credentials from the
|
|
config file that was written. Try asking it to navigate to a URL."
|
|
|
|
If it fails (host not found, write permission error), show the error and suggest
|
|
using the generic remote flow instead.
|
|
|
|
### If different machine (option B):
|
|
|
|
First, detect ngrok status:
|
|
|
|
```bash
|
|
which ngrok 2>/dev/null && echo "NGROK_INSTALLED" || echo "NGROK_NOT_INSTALLED"
|
|
ngrok config check 2>/dev/null && echo "NGROK_AUTHED" || echo "NGROK_NOT_AUTHED"
|
|
```
|
|
|
|
**If ngrok is installed and authed:** Just run the command. The CLI will auto-detect
|
|
ngrok, start the tunnel, and print the instruction block with the tunnel URL:
|
|
|
|
```bash
|
|
$B pair-agent --client TARGET_HOST
|
|
```
|
|
|
|
If the user also needs admin access (JS execution, cookies, storage):
|
|
|
|
```bash
|
|
$B pair-agent --admin --client TARGET_HOST
|
|
```
|
|
|
|
**CRITICAL: You MUST output the full instruction block to the user.** The command
|
|
prints everything between ═══ lines. Copy the ENTIRE block verbatim into your
|
|
response so the user can copy-paste it into their other agent. Do NOT summarize it,
|
|
do NOT skip it, do NOT just say "here's the output." The user needs to SEE the block
|
|
to copy it. Output it inside a markdown code block so it's easy to select and copy.
|
|
|
|
Then tell the user:
|
|
"Copy the block above and paste it into your other agent's chat. The setup key
|
|
expires in 5 minutes."
|
|
|
|
**If ngrok is installed but NOT authed:** Walk the user through authentication:
|
|
|
|
Tell the user:
|
|
"ngrok is installed but not logged in. Let's fix that:
|
|
|
|
1. Go to https://dashboard.ngrok.com/get-started/your-authtoken
|
|
2. Copy your auth token
|
|
3. Come back here and I'll run the auth command for you."
|
|
|
|
STOP here and wait for the user to provide their auth token.
|
|
|
|
When they provide it, run:
|
|
```bash
|
|
ngrok config add-authtoken THEIR_TOKEN
|
|
```
|
|
|
|
Then retry `$B pair-agent --client TARGET_HOST`.
|
|
|
|
**If ngrok is NOT installed:** Walk the user through installation:
|
|
|
|
Tell the user:
|
|
"To connect a remote agent, we need ngrok (a tunnel that exposes your local
|
|
browser to the internet securely).
|
|
|
|
1. Go to https://ngrok.com and sign up (free tier works)
|
|
2. Install ngrok:
|
|
- macOS: `brew install ngrok`
|
|
- Linux: `snap install ngrok` or download from ngrok.com/download
|
|
3. Auth it: `ngrok config add-authtoken YOUR_TOKEN`
|
|
(get your token from https://dashboard.ngrok.com/get-started/your-authtoken)
|
|
4. Come back here and run `$qa --mode Report --module pair-agent` again."
|
|
|
|
STOP here. Wait for the user to install ngrok and re-invoke.
|
|
|
|
## Step 5: Verify connection
|
|
|
|
After the user pastes the instructions into the other agent, wait a moment then check:
|
|
|
|
```bash
|
|
$B status
|
|
```
|
|
|
|
Look for the connected agent in the status output. If it appears, tell the user:
|
|
"The remote agent is connected and has its own tab. You'll see its activity in the
|
|
side panel if you have GStack Browser open."
|
|
|
|
## What the remote agent can do
|
|
|
|
With default (read+write) access:
|
|
- Navigate to URLs, click elements, fill forms, take screenshots
|
|
- Read page content (text, HTML, snapshot)
|
|
- Create new tabs (each agent gets its own)
|
|
- Cannot execute arbitrary JavaScript, read cookies, or access storage
|
|
|
|
With admin access (--admin flag):
|
|
- Everything above, plus JS execution, cookie access, storage access
|
|
- Use sparingly. Only for agents you fully trust.
|
|
|
|
## Troubleshooting
|
|
|
|
**"Tab not owned by your agent"** — The remote agent tried to interact with a tab
|
|
it didn't create. Tell it to run `newtab` first to get its own tab.
|
|
|
|
**"Domain not allowed"** — The token has domain restrictions. Re-pair with broader
|
|
domain access or no domain restrictions.
|
|
|
|
**"Rate limit exceeded"** — The agent is sending > 10 requests/second. It should
|
|
wait for the Retry-After header and slow down.
|
|
|
|
**"Token expired"** — The 24-hour session expired. Run `$qa --mode Report --module pair-agent` again to
|
|
generate a new setup key.
|
|
|
|
**Agent can't reach the server** — If remote, check the ngrok tunnel is running
|
|
(`$B status`). If local, check the browse server is running.
|
|
|
|
## Platform-specific notes
|
|
|
|
### OpenClaw / AlphaClaw
|
|
|
|
OpenClaw agents use the `exec` tool instead of `Bash`. The instruction block uses
|
|
`exec curl` syntax which OpenClaw understands natively. When using `--local openclaw`,
|
|
credentials are written to `~/.openclaw/skills/gstack/browse-remote.json`.
|
|
|
|
|
|
### Codex
|
|
|
|
Codex agents can execute shell commands via `codex exec`. The instruction block's
|
|
curl commands work directly. When using `--local codex`, credentials are written
|
|
to `${GSTACK_HOME:-$HOME/.gstack}/browse-remote.json`.
|
|
|
|
### Cursor
|
|
|
|
Cursor's AI can run terminal commands. The instruction block works as-is.
|
|
When using `--local cursor`, credentials are written to
|
|
`~/.cursor/skills/gstack/browse-remote.json`.
|
|
|
|
## Revoking access
|
|
|
|
To disconnect a specific agent:
|
|
|
|
```bash
|
|
$B tunnel revoke AGENT_NAME
|
|
```
|
|
|
|
To disconnect all agents and rotate the root token:
|
|
|
|
```bash
|
|
# This invalidates ALL scoped tokens immediately
|
|
$B tunnel rotate
|
|
```
|
|
<!-- GSTACK2_LEGACY_BODY_END source=pair-agent -->
|
|
|
|
<!-- GSTACK2_BUG_FIX_START pr=679 anchor=GSTACK2_FIX_679_MATCH_USER_LANGUAGE -->
|
|
## Upstream judgment port: PR #679
|
|
|
|
[Match the user language](https://github.com/garrytan/gstack/pull/679)
|
|
|
|
### User-language rule
|
|
|
|
Write questions, progress updates, reports, and artifacts in the language used by the user. Source material, code identifiers, commands, and quotations may remain in their original language when translating them would reduce accuracy.
|
|
<!-- GSTACK2_BUG_FIX_END pr=679 -->
|