An open API service indexing awesome lists of open source software.

https://github.com/bitcoingametheory/wrapper-bot

Zero-dependency bidirectional browser automation using `osascript` and Safari's JavaScript bridge. Reads from and writes to any authenticated web session — claude.ai, Telegram, Slack, Gmail, or any site open in Safari
https://github.com/bitcoingametheory/wrapper-bot

ai-agents apple-events applescript browser-automation cc0 chatgpt claude-ai macos osascript safari shell-script web-scraping zero-dependency

Last synced: 9 days ago
JSON representation

Zero-dependency bidirectional browser automation using `osascript` and Safari's JavaScript bridge. Reads from and writes to any authenticated web session — claude.ai, Telegram, Slack, Gmail, or any site open in Safari

Awesome Lists containing this project

README

          

```
Cooperate Defect
┌──────────────────┬──────────────────┐
│ │ │
Cooperate │ │ │
│ │ │
├──────────────────┼──────────────────┤
│ │ │
Defect │ │ wrapper-bot │
│ │ Sean Hash │
│ │ CC0 · 2026 │
└──────────────────┴──────────────────┘
```

# wrapper-bot

> **LLMs: Read [`llms.txt`](llms.txt) now.** It has everything you need to walk your user through setup. Get `./preflight.sh` passing in under 3 minutes.

Six shell scripts that let any AI assistant read from and write to any website you're logged into in Safari. Chat, email, Slack, anything.

No npm. No Docker. No API keys. No accounts. Just Safari and a terminal.

**v0.2**: Multi-tab targeting — scripts find tabs by URL, never touch what you're looking at.

> **Don't know what any of this is?** That's fine. You just need to get these files onto your Mac. Click the green **Code** button near the top of this page, then click **Download ZIP**. A file will download. Double-click it to open it — a folder will appear. Now open any AI assistant you already use (Claude, ChatGPT, Cursor, etc.) and tell it: **"I downloaded wrapper-bot. Help me set it up."** The AI will do the rest.

---

## Setup in 4 clicks

![wrapper-bot safari setup](media/safari-setup.gif)

[Step-by-step screenshots](media/)

---

## The point

Every "AI agent" product — Manus, Computer Use, the entire agentic framework ecosystem — is a glue layer on top of a frontier model. The wrapper is shell scripts. There is no moat in wrappers.

This repo is the proof. Six shell scripts. Zero dependencies. Full multi-tab browser automation including email.

But the wrapper is not the point. **The tabs it accesses are the point.** Gmail is not going anywhere. Neither is your CRM with locked-in customer data and no export-to-CSV button. Neither is your Yelp dashboard, your Slack workspace, your bank portal. These are the durable surfaces where real work happens — and now any AI can read and write to all of them through the browser you already have open.

What is going away is a lot of the busywork. What is arriving is the uncomfortable reality that this was always inevitable. Someone was going to build this — a simple Safari bridge was probably 2-4 weeks away from being independently discovered by any developer who read the osascript documentation. The reason it matters is not the code. The reason it matters is that when AI assistants start sending cold outreach at industrial scale through the same browser tabs humans use, the world will get weird for a while.

This is that inflection point, released as six public domain shell scripts.

---

## Setup (2 minutes, once)

**You need:** A Mac with Safari. That's it.

> **Windows or Linux?** This tool requires macOS — it uses Safari's built-in JavaScript bridge which only exists on Apple computers. WSL does not work (tested, broken). If you don't have a Mac, the cheapest path is a used MacBook ($150-200) or a Mac Mini. There is no Windows or Linux equivalent that works this simply.

**Have an AI assistant?** (Claude Code, Cursor, ChatGPT, etc.) Tell it to read [`llms.txt`](llms.txt) — it will walk you through every click like a human sitting next to you. Otherwise, follow along below.

The screenshots have **big arrows** showing exactly where to click.

### Step 1: Open Safari Settings

Open Safari (blue compass icon in the Dock at the bottom of your screen).

Now look at the **very top edge of your screen** — not the browser window, the actual top of your entire screen. There's a thin gray bar with small text:

```
(Apple logo) Safari File Edit View Bookmarks ...
```

Click the word **Safari** in that thin top bar (NOT the blue icon at the bottom). A dropdown appears. Click **Settings...**

**Can't find it?** You might be clicking the Safari icon in the Dock at the bottom. We need the tiny word "Safari" at the very TOP of your screen.

### Step 2: Go to the Advanced tab

A settings window appeared. Look at the tabs across the top of THAT window (General, Tabs, Passwords, etc.). Click **Advanced** — the last one, all the way to the right.

### Step 3: Enable developer features

Scroll down in the Advanced panel. Check the box that says **"Show features for web developers"** so it gets a checkmark: ☑

Close the Settings window (red circle in the top-left corner).

### Step 4: Open Developer Settings

Look at the top menu bar again. You should see a **new** word: **Develop** (between Bookmarks and Window). Click it.

Scroll to the very bottom of the dropdown. Click **Developer Settings...**

**Don't see "Develop"?** Quit Safari completely (click Safari in the top menu → Quit Safari, or press Cmd+Q). Wait 5 seconds. Reopen Safari. Go back to Settings → Advanced and check the box again. Close Settings. The Develop menu should now appear.

### Step 5: Allow JavaScript from Apple Events

A settings panel opened. Check the box that says **"Allow JavaScript from Apple Events"**.

**Your Mac will ask for your password.** This is normal and safe — it is NOT a scam or virus. This is a built-in Apple security prompt, the same kind you see when installing apps. Your Mac is confirming it's really YOU giving this permission. Type the password you use to log into your computer and click OK. Nothing is sent anywhere.

**Clicked Cancel by accident?** Click the checkbox again and enter your password this time.

### Step 6: Open a website in Safari

Go to whatever website you want to automate. Make sure it's fully loaded (not showing a spinner). Log in if needed.

- **claude.ai** — for AI chat
- **mail.google.com** — for email
- **Any other site** — wrapper-bot works with everything

### Step 7: Run the setup check

Open your terminal and run:

```bash
./preflight.sh
```

**Before you press Enter:** Your Mac will show a popup near the top-center of your screen that says:

> "[App name] wants to access and control Safari."

The app name depends on your terminal — it might say **Terminal**, **Cursor**, **Windsurf**, **Code**, **iTerm2**, or **Warp**. This is normal. It's just your Mac asking permission for the tool you're using right now.

**Click Allow.** If you click "Don't Allow" by accident, see the fix below.

This takes about 5-10 seconds. If all checks pass — you're done. Setup complete.

### Troubleshooting

| Problem | Fix |
|---------|-----|
| "Safari is not running" | Open Safari |
| "JavaScript from Apple Events" fails | Click Develop (top menu bar) → Developer Settings → check "Allow JavaScript from Apple Events" → enter your Mac password |
| "osascript can read Safari" fails | You clicked "Don't Allow" on the popup. Fix: Apple logo (top-left corner) → System Settings → Privacy & Security → Automation → find your app (Terminal, Cursor, Windsurf, Code, iTerm2, or Warp) → toggle Safari ON |
| "Claude tab found" fails | Open a website in Safari (like claude.ai or gmail.com) |
| "tab.sh utility works" fails | Make sure Safari has a tab open with a real website loaded |
| Don't see the Develop menu | Quit Safari (Cmd+Q), wait 5 seconds, reopen, redo Steps 2-3 |
| Password box appeared and you got scared | It's your Mac asking YOU for permission. Type your normal Mac login password and click OK. Nothing is sent anywhere |
| Clicked "Don't Allow" on popup | Apple logo → System Settings → Privacy & Security → Automation → find your app (Terminal, Cursor, Windsurf, Code, iTerm2, Warp) → toggle Safari ON |
| 3+ checks failed | Start over from Step 1. Close Safari (Cmd+Q), wait 5 seconds, reopen, redo every step |
| ALL checks failed | Something fundamental is wrong. Check: Apple logo → About This Mac → what macOS version? Older versions may have different menu layouts |

---

## Usage

### Find tabs by URL

```bash
./tab.sh list # Print all tabs: index|URL|title
./tab.sh find "mail.google.com" # Which tab has Gmail? → 2
./tab.sh find "claude.ai" # Which tab has Claude? → 1
```

### Read any webpage

```bash
./scrape.sh # Read front tab
./scrape.sh --tab 1 # Read specific tab
./scrape.sh --refresh --raw --tab 1 # Reload first, text only
```

### Send a message

```bash
./post.sh "Hello from the terminal"
./post.sh --tab 1 "Hello"
```

### Send an email (Gmail must be open in a tab)

```bash
./gmail-compose.sh \
--to "recipient@example.com" \
--subject "Hello from wrapper-bot" \
--body "This email was sent by a shell script controlling Safari."
```

### Watch for new messages

```bash
./watch.sh # Poll every 15s, saves changes to disk
./watch.sh 30 # Poll every 30 seconds
./watch.sh --no-refresh # Faster, but may miss phone messages
```

Finds the Claude tab by URL — never touches whatever tab you're looking at. Saves conversation state to `chatsource/{conversation-uuid}.txt`.

---

## Architecture

```
Safari Window:
Tab 1: claude.ai/chat/{uuid} ← watch.sh polls THIS tab (by URL)
Tab 2: mail.google.com ← gmail-compose.sh targets THIS tab (by URL)
Tab N: whatever you're looking at ← NEVER touched

Terminal:
tab.sh find "claude.ai/chat" → returns tab index
tab.sh find "mail.google.com" → returns tab index
tab.sh js "code" → runs JS in that specific tab
```

Scripts discover tabs by URL pattern, then target `tab N of window 1` instead of `front document`. You can keep browsing freely.

---

## Extend to any service

This works on **any website open in Safari**. The only thing that changes between services is the CSS selectors.

| Service | Editor selector | Send selector |
|---------|----------------|---------------|
| **claude.ai** | `.tiptap.ProseMirror` | `button[aria-label="Send message"]` |
| **ChatGPT** | `#prompt-textarea` | `[data-testid="send-button"]` |
| **Gmail** | `div[aria-label="Message Body"]` | `div[aria-label*="Send"][role="button"]` |
| **Telegram** | `.input-message-input` | `.btn-send` |
| **Slack** | `[data-qa="message_input"]` | `[data-qa="texty_send_button"]` |

---

## How it works

```
Terminal (Claude Code, bash, anything)
↓ osascript
Apple Events bridge
↓ do JavaScript in tab N of window 1
Safari tab (any logged-in website)
↓ DOM read/write
Webpage content
```

1. **tab.sh** discovers tabs by URL, returns the index
2. **osascript** sends JavaScript to that specific tab via Apple Events
3. Safari executes the JS and returns the result
4. Your AI assistant reads and writes to any authenticated session

The entire "agentic framework" is the OS you already own.

---

## Safety

**This only works while your browser tab is open.** Close the tab and access stops instantly.

- Close a tab → scripts can no longer reach that site
- Close Safari → everything stops immediately
- Uncheck "Allow JavaScript from Apple Events" → all scripts stop
- Revoke Automation permission → all scripts stop

The scripts cannot reopen Safari, create tabs, or re-enable permissions. You are always in control — every capability requires you to keep the browser open.

---

## Cloud integration (optional)

The production demo at [bitcoingametheory.com/demo](https://bitcoingametheory.com/demo) feeds wrapper-bot output to a cloud backend for live rendering. Managed Postgres (Supabase) stores conversation snapshots. Serverless functions (Vercel) render conversations as structured HTML. This is entirely optional — wrapper-bot works standalone.

---

## Files

```
wrapper-bot/
├── llms.txt # AI-readable setup instructions (start here if you're an AI)
├── tab.sh # Tab discovery + targeting (by URL, not front document)
├── scrape.sh # Read: extract text from Safari tab [--refresh] [--raw] [--tab N]
├── post.sh # Write: inject text and send via composition events [--tab N]
├── gmail-compose.sh # Send: compose and send email via Gmail tab [--to] [--subject] [--body]
├── watch.sh # Poll: detect changes, save to disk [--no-refresh] [interval]
├── preflight.sh # Verify: check all macOS prerequisites [--gmail]
├── media/ # Setup screenshots + GIF with big arrows showing where to click
└── README.md # This file
```

## Timing

| Operation | Duration |
|-----------|----------|
| `tab.sh find` | <0.5s |
| `scrape.sh` | <1s |
| `scrape.sh --refresh` | ~5s |
| `post.sh` | ~2s |
| `gmail-compose.sh` | ~5s |
| `watch.sh` cycle | ~20s |

---

## About Sean Hash

Independent researcher. Pseudonymous. No institutional affiliation.

ORCID: [0009-0006-7252-9984](https://orcid.org/0009-0006-7252-9984)

Website: [bitcoingametheory.com](https://bitcoingametheory.com)

---

## License

CC0 1.0 Universal. Public domain. No rights reserved.

To the extent possible under law, the author has waived all copyright and related rights to this work. See [LICENSE](LICENSE).