Appearance
Three I/O Modes
FreshSource: BIBLE.md (Three I/O backends), bible/understand-everything.md (The three modes)

Every browser session runs in one of three modes, dispatched by hybrid-router.mjs.
Mode comparison
| Mode | Input source | CDP traces | Use case | Latency |
|---|---|---|---|---|
| Ghost | OS-level (desktop) or ADB (mobile) plus vision | Zero | Reddit, LinkedIn, Facebook, Instagram, Nextdoor | ~50 ms (desktop), ~20 ms (mobile) |
| Hybrid | OS-level for clicks/typing, CDP for reading | Minimal (reads only) | Yelp, Substack, Gmail | ~50 ms input, ~5 ms reads |
| Speed | Pure CDP (same as V1) | Full | YouTube, Google Search | ~5 ms |
Per-platform defaults
ghost: reddit, linkedin, facebook, instagram, twitter, nextdoor
hybrid: yelp, substack, gmail
speed: youtube, googleBackends
Three I/O backends decide where the events actually go:
| Backend | Use | isTrusted |
|---|---|---|
cdp | Puppeteer, desktop, speed mode default | false |
os | Windows SendInput, desktop, ghost and hybrid mode default | true |
adb | Android Debug Bridge, mobile, always forces ghost mode | true |
Mode plus backend selection
flowchart TD
L[POST /browser/launch] --> P{platform default}
P -- reddit --> G[mode=ghost, backend=os]
P -- yelp --> H[mode=hybrid, backend=os]
P -- google --> S[mode=speed, backend=cdp]
L -. override .-> O[Explicit mode in body]
M[POST /mobile/connect] --> A[mode=ghost, backend=adb]Why three modes exist
V1's CDP-only architecture has a ceiling. Platforms like Reddit, LinkedIn, and Facebook check whether input events came from real hardware. CDP produces isTrusted: false on every event. That is a dead giveaway.
Ghost Engine fixes this with three new capabilities. The router picks which mode is needed per platform.
Ghost mode
Everything OS-level or ADB plus vision. Zero CDP interaction traces.
- Mouse clicks go through Windows SendInput.
isTrusted: true - Keyboard goes through Windows SendInput.
isTrusted: true - Navigation uses vision: screenshot to VLM to coordinates
- Zero CDP interaction traces
Hybrid mode
Best of both worlds. OS-level for the things that matter for detection (clicks and typing). CDP for reads (which do not leave detectable traces).
- Clicks and typing OS-level (
isTrusted: true) - Reads, navigation, evaluation, cookies via CDP
Speed mode
Identical to V1. Maximum throughput, full CDP traces.
- All input via CDP
Input.dispatchMouseEvent/KeyEvent - All reads via CDP
- isTrusted is false
- Multiple parallel sessions allowed
How to use each mode
Launch with a specific mode
bash
# Ghost mode (default for Reddit)
curl -s -X POST http://localhost:4700/browser/launch \
-H "Content-Type: application/json" \
-H "x-api-key: ghost-engine-key" \
-d '{"email":"someone@gmail.com","mode":"ghost","platform":"reddit","headless":false}'
# Hybrid mode for Yelp
curl -s -X POST http://localhost:4700/browser/launch \
-H "Content-Type: application/json" \
-H "x-api-key: ghost-engine-key" \
-d '{"email":"someone@gmail.com","mode":"hybrid","platform":"yelp","headless":false}'
# Speed mode for YouTube (default)
curl -s -X POST http://localhost:4700/browser/launch \
-H "Content-Type: application/json" \
-H "x-api-key: ghost-engine-key" \
-d '{"email":"someone@gmail.com","mode":"speed","platform":"youtube","headless":false}'Switch mode mid-session
bash
curl -s -X POST http://localhost:4700/browser/abc123/set-mode \
-H "Content-Type: application/json" \
-d '{"mode":"speed"}'Mobile (always ghost)
bash
curl -s -X POST http://localhost:4700/mobile/connect \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.100:5555"}'The router automatically sets mode=ghost, backend=adb, vision=true.
RouterSession class
Tracks per-session state:
instanceId: session IDmode: ghost, hybrid, or speedbackend: cdp, os, or adbserial: ADB device (mobile only)vision: whether vision-based navigation is enabledplatform: platform identifier (reddit, yelp, etc.)windowBounds: cached for OS mode (5-second refresh)screenSize: cached for ADB mode
Cost control
Vision is expensive: about $0.003 per VLM call (Claude Sonnet). Use it only for navigation decisions in ghost mode. Data reads (get text, check URL, extract content) always go through CDP regardless of mode.
Constraints
- One desktop ghost session at a time. SendInput goes to the foreground window
- Mobile ghost sessions are unlimited. Each ADB session targets a unique serial
- Ghost mode requires window focus on desktop
- Vision calls have probabilistic accuracy. Use a 0.5 confidence threshold with 2 retries