Initial import from garrytan/gstack@026751e (main snapshot via local relay)
Some checks failed
Workflow Lint / actionlint (push) Has been cancelled
Build CI Image / build (push) Has been cancelled
Skill Docs Freshness / check-freshness (push) Has been cancelled
Periodic Evals / build-image (push) Has been cancelled
Periodic Evals / evals (map[file:test/codex-e2e.test.ts name:e2e-codex]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/gemini-e2e.test.ts name:e2e-gemini]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-design.test.ts name:e2e-design]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-plan.test.ts name:e2e-plan]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-qa-bugs.test.ts name:e2e-qa-bugs]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-qa-workflow.test.ts name:e2e-qa-workflow]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-review.test.ts name:e2e-review]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-workflow.test.ts name:e2e-workflow]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-routing-e2e.test.ts name:e2e-routing]) (push) Has been cancelled
Some checks failed
Workflow Lint / actionlint (push) Has been cancelled
Build CI Image / build (push) Has been cancelled
Skill Docs Freshness / check-freshness (push) Has been cancelled
Periodic Evals / build-image (push) Has been cancelled
Periodic Evals / evals (map[file:test/codex-e2e.test.ts name:e2e-codex]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/gemini-e2e.test.ts name:e2e-gemini]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-design.test.ts name:e2e-design]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-plan.test.ts name:e2e-plan]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-qa-bugs.test.ts name:e2e-qa-bugs]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-qa-workflow.test.ts name:e2e-qa-workflow]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-review.test.ts name:e2e-review]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-e2e-workflow.test.ts name:e2e-workflow]) (push) Has been cancelled
Periodic Evals / evals (map[file:test/skill-routing-e2e.test.ts name:e2e-routing]) (push) Has been cancelled
Source: https://github.com/garrytan/gstack/commit/026751e
This commit is contained in:
267
pair-agent/SKILL.md.tmpl
Normal file
267
pair-agent/SKILL.md.tmpl
Normal file
@@ -0,0 +1,267 @@
|
||||
---
|
||||
name: pair-agent
|
||||
version: 0.1.0
|
||||
description: |
|
||||
Pair a remote AI agent with your browser. One command generates a setup key and
|
||||
prints instructions the other agent can follow to connect. Works with OpenClaw,
|
||||
Hermes, Codex, Cursor, or any agent that can make HTTP requests. The remote agent
|
||||
gets its own tab with scoped access (read+write by default, admin on request).
|
||||
Use when asked to "pair agent", "connect agent", "share browser", "remote browser",
|
||||
"let another agent use my browser", or "give browser access". (gstack)
|
||||
voice-triggers:
|
||||
- "pair agent"
|
||||
- "connect agent"
|
||||
- "share my browser"
|
||||
- "remote browser access"
|
||||
triggers:
|
||||
- pair with agent
|
||||
- connect remote agent
|
||||
- share my browser
|
||||
allowed-tools:
|
||||
- Bash
|
||||
- Read
|
||||
- AskUserQuestion
|
||||
|
||||
---
|
||||
|
||||
{{PREAMBLE}}
|
||||
|
||||
# /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.
|
||||
|
||||
{{BROWSE_SETUP}}
|
||||
|
||||
## 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 `/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 `/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 `~/.codex/skills/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
|
||||
```
|
||||
Reference in New Issue
Block a user