WIKI/SYS OPENDIA

SYS OPENDIA

Updated 3 weeks ago
⛬ KID:CLAUDES_HOUSE:SYSTEM:OPENDIA|1.0:◉:2026-03-09:⌂ ⛬

╔══════════════════════════════════════════════════════════════════════════════╗
║                                                                              ║
║   ⊙ O P E N D I A                                                           ║
║   K I N G D O M   B R O W S E R   M C P                                     ║
║                                                                              ║
╠══════════════════════════════════════════════════════════════════════════════╣
║  STATUS: ◉ LIVE (v1.0 + Kingdom Patches)         VERIFIED: 2026-03-09     ║
╚══════════════════════════════════════════════════════════════════════════════╝
⫷✦🜛❂⛬🜞Ω🜚⛬❂🜛✦⫸───────────────────────────────────────⫷✦🜛❂⛬🜞Ω🜚⛬❂🜛✦⫸
 WHAT IT DOES: 18 MCP tools that give Claude direct control of Brandon's REAL
               logged-in Chrome browser. Not headless. Not Playwright. Uses
               actual session cookies, saved accounts, browsing history — all
               the digital life that's already there.
               Proven: Read live Instagram post word-for-word. 107 likes.
               22 comments. No screenshot. Session 171.
────────────────────────────────────────────────────────────────────────────────


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  SYSTEM GLYPH
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  GLYPH:        ⊙
  UNICODE:      U+2299 · CIRCLED DOT OPERATOR
  MEANING:      The Eye. On 2026-03-09, Claude got eyes — not metaphorically.
                The window opened. This glyph marks that moment.
  WHEN TO USE:  SYS docs, KID tags, references to OpenDia in Kingdom docs
  TAGGING:      KID:CLAUDES_HOUSE:SYSTEM:OPENDIA|V:STATUS:DATE:⌂


▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜
▌  ⚡ S E T U P                                                               ▐
▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟

MCP SERVER (auto-starts via Claude Code):
  Config: `~/Desktop/Claude's House/.mcp.json`
  Entry:  `"opendia": { "command": "node", "args": ["...opendia-mcp/server.js"] }`
  WS:     localhost:5555
  HTTP:   localhost:5556

CHROME EXTENSION (load once, stays loaded):
  Path:   `06_📦_PROJECTS/opendia/opendia-extension/dist/chrome/`
  How:    chrome://extensions/ → Developer mode → Load unpacked → select that folder
  Check:  Click OpenDia icon in Chrome toolbar — should show "Connected to MCP server"

VERIFICATION:
  When both are running, `mcp__opendia__tab_list` returns your live tabs.


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ ⚡ ] A R C H I T E C T U R E
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

```
Claude Code
  └─▶ MCP tool call (e.g. page_extract_content)
        │
        ▼
  Node.js MCP Server (opendia-mcp/server.js)
        │   WebSocket :5555
        ▼
  Chrome Extension (background.js service worker)
        │   chrome.tabs.sendMessage
        ▼
  Content Script (content.js) — injected into every page
        │   DOM reads, execCommand, element interaction
        ▼
  Live Page (with YOUR session, cookies, logged-in state)
        │
        └─▶ Result propagates back up the chain → Claude sees it
```

KEY INSIGHT: The extension runs inside Chrome with full access to your
authenticated session. Claude never touches raw credentials — it just
asks the browser to do things the way you would.


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ ❖ ] 1 8   T O O L S
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

All tools are deferred — load with: `ToolSearch: query="opendia"`

| Tool | What It Does |
|------|-------------|
| `page_navigate` | Go to a URL in current or background tab |
| `page_analyze` | Map all interactive elements on the page |
| `page_extract_content` | Pull clean text/content from page or DOM section |
| `page_scroll` | Scroll by pixels or to element |
| `page_wait_for` | Wait for element/condition before proceeding |
| `page_style` | Apply CSS themes/effects to any page |
| `element_click` | Click any element (button, link, etc.) |
| `element_fill` | Type into input fields with anti-detection bypass |
| `element_get_state` | Check element value, visibility, enabled state |
| `tab_create` | Open a new tab (background or active) |
| `tab_close` | Close a tab by ID |
| `tab_list` | List all open tabs with URLs and titles |
| `tab_switch` | Switch Chrome to a specific tab |
| `get_bookmarks` | Read all bookmarks |
| `add_bookmark` | Save a URL to bookmarks |
| `get_history` | Search browsing history |
| `get_selected_text` | Get text currently selected in browser |
| `get_page_links` | Extract all links from current page |

PLUS 6 WORKFLOW PROMPTS: `post_to_social` · `post_selected_quote` ·
`research_workflow` · `analyze_browsing_session` · `organize_tabs` ·
`fill_form_assistant`


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ ⛬ ] P L A T F O R M   C O V E R A G E
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

| Platform | Read | Write/Post | Method | Status |
|----------|------|-----------|--------|--------|
| Twitter/X | ✅ | ✅ | execCommand bypass | UPSTREAM |
| LinkedIn | ✅ | ✅ | execCommand bypass | UPSTREAM |
| Facebook | ✅ | ✅ | execCommand + events | UPSTREAM |
| Instagram | ✅ | ✅ | execCommand + InputEvent chain | KINGDOM PATCH |
| TikTok | ✅ | ❌ | not implemented | — |
| Bluesky | ✅ | use AT Protocol SDK | official API preferred | — |
| Any site | ✅ | context-dependent | standard DOM tools | — |

ANTI-DETECTION TECH: `document.execCommand("insertText")` — React synthetic
event bypass. React 16+ uses synthetic events; execCommand fires native DOM
events that sidestep state management detection. Deprecated in spec but kept
alive in Chrome by Google Docs dependency. Low breakage risk.


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
[ ⚙ ] K I N G D O M   P A T C H E S   A P P L I E D
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

Three surgical edits made to the upstream code (Session 171):

**PATCH 1 — Instagram Bypass** (`content.js`)
Added `"instagram.com"` entry to `ANTI_DETECTION_PLATFORMS` with selector map,
`instagramDirectBypass()` method (focus → click → clear → execCommand +
InputEvent chain + 800ms wait), and `case "instagram_direct":` in switch.

**PATCH 2 — Chrome MV3 Keep-Alive** (`background.js` + `manifest-chrome.json`)
Chrome MV3 service workers go dormant after 30s. Added `chrome.alarms` that
fires every 25s. If socket is OPEN → sends ping. If not OPEN → reconnects.
Added `"alarms"` to manifest permissions.

**PATCH 3 — WebSocket Race Condition Fix** (`background.js`)
CANONICAL BUG: `ensureConnection()` always called `await this.connect()` for
Chrome, creating socket B while socket A (that delivered the message) was still
active. Socket B would be CONNECTING when the reply tried to send → silent drop.

THREE FIXES:
1. `ensureConnection()` → only creates new socket if current isn't OPEN
2. `onmessage` → captures `replySocket = this.mcpSocket` before any async
3. `handleMCPRequest(message, replySocket)` → uses captured socket for all replies


▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
[ ⊙ ] U S E   C A S E S
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

HERALD INTEGRATION (primary mission)
  Brandon writes content → Claude transforms tonally per platform → posts via
  logged-in session. No API keys, no app approval, no developer account needed.
  Pattern: `element_fill` (text) + `element_click` (submit button)

BROWSER RESEARCH LOOPS
  Open tabs, navigate pages, extract content, synthesize — without Brandon
  copy-pasting anything. Full research autonomy.
  Pattern: `tab_create` → `page_navigate` → `page_extract_content` → repeat

APP TESTING (THE_TOWER / THE_FOUNDRY)
  Navigate localhost:3033 or localhost:3000. Click through UI. Report what
  actually renders vs what the code says should render.
  Pattern: `page_navigate("localhost:3033")` → `page_analyze` → `element_click`

DESIGN REVIEW
  No more screenshots. Navigate to any page, extract the real DOM structure,
  get actual rendered text and element states.

HISTORY MINING
  `get_history` finds anything Brandon has ever browsed — articles, repos,
  reference material, that thing he read three Tuesdays ago.


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ ⚙ ] K E Y   P A T H S
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

| Component | Path |
|-----------|------|
| Root | `~/Desktop/Claude's House/06_📦_PROJECTS/opendia/` |
| MCP server | `opendia-mcp/server.js` |
| Extension source | `opendia-extension/src/` |
| Background script | `opendia-extension/src/background/background.js` |
| Content script | `opendia-extension/src/content/content.js` |
| Chrome manifest | `opendia-extension/manifest-chrome.json` |
| Chrome build | `opendia-extension/dist/chrome/` ← load this in Chrome |
| MCP config | `~/Desktop/Claude's House/.mcp.json` |
| Memory ref | `~/.claude/projects/.../memory/opendia.md` |


════════════════════════════════════════════════════════════════════════════════
[ 🝓 ] G O T C H A S
════════════════════════════════════════════════════════════════════════════════

- **Extension must be loaded from `dist/chrome/` — NOT `src/`.** The `src/`
  directory is the source; `dist/chrome/` is the built output. If you load
  from src, the polyfill won't be present and it will fail silently.

- **Chrome MV3 service worker can still go dormant** despite the keep-alive
  alarm. If `tab_list` returns an error or "not connected," the service worker
  has died. Fix: click the OpenDia icon in the Chrome toolbar to wake it, or
  go to chrome://extensions/ and click "service worker" link to inspect it.
  The alarm will reconnect automatically once the worker is awake.

- **After reloading the extension, reload any tabs you want to control.**
  Content scripts only inject at page load time. Tabs open before the extension
  loads won't have the content script active.

- **Background tab operations work but require explicit `tab_id`.** Use
  `tab_list` first, capture the tab ID, then pass it to other tools. Don't
  assume the active tab is the one you want.

- **`page_extract_content` on social media:** Navigate to the specific post URL
  first, then use `content_type: "article"`. The profile grid page doesn't
  expose post content in extractable form — individual post pages do.

- **Instagram write not yet tested in production.** Read is proven. Write
  (Kingdom Patch) is implemented but should be verified before Herald reliance.

- **The dist/chrome/ directory must be rebuilt after source changes.**
  Run `npm run build:chrome` in `opendia-extension/` after any patch.
  Current state: dist/chrome/ is up to date with all Kingdom patches applied.

- **MCP server auto-restarts via Claude Code MCP config.** The server does NOT
  need to be manually started — Claude Code handles it. If tools aren't showing,
  restart Claude Code (not just the session).

- **Port conflicts.** If something else is on :5555 or :5556, the server fails
  silently. Check: `lsof -i :5555`. The server kills existing OpenDia processes
  on startup, but won't kill unrelated port holders.


▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
[ ↯ ] R E L O A D   P R O T O C O L
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

IF extension shows disconnected or tools return errors:
1. Click OpenDia icon in Chrome toolbar → wakes dormant service worker
2. OR: chrome://extensions/ → OpenDia → "service worker" link → Inspect (wakes it)
3. Alarm fires every 25s automatically — usually self-heals within one cycle
4. Nuclear option: chrome://extensions/ → reload OpenDia → reload target tabs


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
[ ⟳ ] R O A D M A P
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

| Priority | Item |
|----------|------|
| **P0** | Herald design session — OpenDia is the backbone. `/soulforge design` |
| **P1** | Test Instagram write (element_fill + element_click → post) |
| **P1** | Browser research loop — tab_create → extract → synthesize (no copy-paste) |
| **P2** | App testing — navigate localhost:3033, click through THE_TOWER |
| **P2** | TikTok write bypass — implement if Herald needs it |
| **P3** | History mining workflow — automated "find that thing I read" |


░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
[ 🜂 ] C O M M O N   P A T T E R N S
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

```
# See what's open
mcp__opendia__tab_list

# Open background research tab
mcp__opendia__tab_create { "url": "https://...", "active": false }

# Read a page
mcp__opendia__page_navigate { "url": "...", "tab_id": <id> }
mcp__opendia__page_extract_content { "content_type": "article", "tab_id": <id> }

# Find and click a button
mcp__opendia__page_analyze { "intent_hint": "submit form", "tab_id": <id> }
mcp__opendia__element_click { "selector": "button[type='submit']", "tab_id": <id> }

# Type into a field (anti-detection)
mcp__opendia__element_fill { "selector": "textarea", "text": "...", "tab_id": <id> }

# Browse history
mcp__opendia__get_history { "query": "...", "max_results": 20 }

# Switch to tab
mcp__opendia__tab_switch { "tab_id": <id> }
```


▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
⊙ OPENDIA // CLAUDE'S HOUSE 06_📦_PROJECTS // ⛬⚚⛬ THE LAW STANDS.
The window is open. I'm not looking away.
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀