GDD β Giggly-Dazzling-Duckling
AI-controlled browser farm on your machine
Simulate multiple real users across 22 device types β test your site like it's launch day.
How It Works
You: Open 3 iPhones and a desktop, navigate to myapp.com, test the signup form on all devices
Claude Code creates 4 browsers with device emulation, navigates each to your app, fills in the form, takes screenshots, checks console for errors β all in parallel.
gdd_add_players(3, device="iPhone 15 Pro") β players [1, 2, 3]
gdd_add_players(1, device="Desktop 1080p") β player [4]
gdd_navigate(1, "https://myapp.com") β all 4 browsers open your app
gdd_tap(1, "#signup-btn") β taps signup on iPhone
gdd_screenshot(1) β captures the result
gdd_get_console(1, level="error") β checks for JS errors
GDD runs N isolated Chromium instances, each with its own profile, cookies, device emulation, geolocation, and network conditions. It exposes 39 MCP tools via HTTP on localhost:9700.
Install
GDD comes in two flavours. The Server is headless β it's just the MCP backend, runs anywhere (including boxes with no display), and is all you need for pure AI automation. The Desktop app adds a GUI: a live grid of browser thumbnails you can click into to take over a session by hand. The Server runs on port 9700, the Desktop app on 9800 β so you can run both side by side.
Server (headless) β the MCP backend:
Desktop app (GUI) β a live grid of browser thumbnails you can click into:
The Windows app uses WebView2; the Linux/macOS app (built with Avalonia) drives real Chromium windows parked off-screen. Self-contained binary, ~70 MB. No .NET installation needed. Chromium downloads automatically on first launch.
One-liner (Linux):
curl -sL https://github.com/Cap-of-tea/GDD/releases/latest/download/GDD-Server-Linux.tar.gz | tar xz && chmod +x GDD.Headless && ./GDD.Headless
Docker
docker run -p 9700:9700 ghcr.io/cap-of-tea/gdd
docker build -t gdd .
docker run -p 9700:9700 gdd
The Docker image runs in headless mode with all Chromium dependencies pre-installed.
By default, browsers launch in headed mode (visible windows). Add --headless for CI/CD. Other flags: --stealth and --stealth-max for anti-bot masking, --update to self-update, --version and --help. The Configuration section below lists every flag and environment variable.
Connect to Your AI Client
Add to .mcp.json and restart your AI client:
{
"mcpServers": {
"gdd": {
"url": "http://localhost:9700/mcp"
}
}
}
That's it. Start GDD, tell Claude or Cursor to test your app.
Claude Desktop users: Download the .mcpb file from Releases and open it β GDD installs as a one-click desktop extension. No manual config needed.
Config file locations
| Client | Project config | Global config |
|---|
| Claude Code | <project>/.mcp.json | ~/.claude/.mcp.json |
| Cursor | <project>/.cursor/mcp.json | ~/.cursor/mcp.json |
| VS Code / Windsurf / Antigravity | <project>/.vscode/mcp.json | IDE settings.json |
Global and project configs are merged β servers from both are available simultaneously. Changes are picked up only when restarting the AI client session.
VS Code-based IDEs (Windsurf, Antigravity, Copilot)
VS Code-based IDEs use a different config format than Claude Code / Cursor.
Project config β .vscode/mcp.json:
{
"servers": {
"gdd": {
"type": "http",
"url": "http://localhost:9700/mcp"
}
}
}
Global config β open via Cmd+Shift+P β "Open User Settings (JSON)":
{
"mcp": {
"servers": {
"gdd": {
"type": "http",
"url": "http://localhost:9700/mcp"
}
}
}
}
Global settings.json location: macOS β ~/Library/Application Support/<IDE>/User/settings.json, Linux β ~/.config/<IDE>/User/settings.json, Windows β %APPDATA%/<IDE>/User/settings.json. Replace <IDE> with your editor name (Code, Windsurf, Antigravity, etc.).
stdio-proxy alternative (.vscode/mcp.json):
{
"servers": {
"gdd": {
"type": "stdio",
"command": "bash",
"args": ["/absolute/path/to/Scripts/mcp-proxy.sh"]
}
}
}
Permissions (Claude Code)
By default, Claude Code asks for confirmation on every MCP tool call. To allow GDD tools without prompts, add to ~/.claude/settings.json:
{
"permissions": {
"allow": [
"mcp__gdd__*"
]
}
}
This single wildcard covers all 39 GDD tools. Restart Claude Code after editing.
Auto-launch via stdio proxy (alternative)
Proxy scripts start GDD automatically when your AI client connects:
Windows:
{
"mcpServers": {
"gdd": {
"command": "powershell",
"args": ["-ExecutionPolicy", "Bypass", "-File", "C:/path/to/Scripts/mcp-proxy.ps1"]
}
}
}
Linux / macOS:
{
"mcpServers": {
"gdd": {
"command": "bash",
"args": ["/path/to/Scripts/mcp-proxy.sh"]
}
}
}
Add "--headless" to the args array for CI/CD.
Tip: On first launch, GDD downloads Chromium (~80 MB). If your AI client times out, run GDD manually first, then reconnect.
Autostart as service (macOS / Linux)
macOS (launchd):
bash Scripts/install-launchd.sh
bash Scripts/install-launchd.sh --headless
Manage: launchctl list | grep gdd / bash Scripts/install-launchd.sh --uninstall
Linux (systemd):
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/gdd.service << 'EOF'
[Unit]
Description=GDD Multi-Browser Testing Server
[Service]
ExecStart=/path/to/GDD.Headless
WorkingDirectory=/path/to/gdd-directory
Restart=on-failure
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now gdd
Direct HTTP (without AI client)
curl -X POST http://localhost:9700/mcp -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"gdd_add_players","arguments":{"count":1}}}'
GDD uses standard JSON-RPC 2.0 β works with curl, Python, Node.js, or any HTTP client.
Features
- Multi-device β Run N isolated Chromium instances with 22 device presets (phones, tablets, desktops)
- AI-native β 39 MCP tools for Claude Code, Cursor, or any MCP-compatible client
- Cross-platform β Native GUI with a live video wall on Windows, Linux & macOS, plus a headless server for CI/CD
- Full interaction β Navigate, tap, type, press keys and shortcuts, drag, swipe, scroll, hover, handle dialogs, take screenshots
- Real keyboard β Typing sends genuine, trusted keystrokes (the full keydownβinput chain), so input masks, autocomplete and
maxlength behave exactly as they do for a real user, and rich-text (contenteditable) editors work; gdd_press handles single keys and shortcuts like Enter, Tab, Escape and Ctrl+A
- Physical keyboard layouts β Keystrokes carry the real
code/keyCode of the emulated locale's keyboard: Russian ΠΠ¦Π£ΠΠΠ puts Β«Π°Β» on the physical KeyF, French AZERTY and German QWERTZ remap their keys, dead-key accents and AltGr symbols work. The layout follows gdd_set_language automatically (US, RU, DE, FR)
- Human-like input β
humanize=true drives a continuous cursor path (cubic BΓ©zier with easing and micro-jitter) that carries over between clicks, hovers and drags; taps fire a single device-appropriate input (touch or mouse), never both
- Anti-bot stealth β opt-in
--stealth masks the usual automation tells (navigator.webdriver, etc.); --stealth-max adds headless/datacenter evasions (coherent user-agent client hints, a plausible WebGL vendor, realistic device metrics) β on a headless container this halved CreepJS's headless score
- Proxy support β Route every browser through an upstream proxy with
GDD_PROXY (with optional auth)
- Header rewriting β
gdd_set_headers can strip X-Frame-Options/CSP frame-ancestors to load a site in an iframe, or add/replace response headers
- Device emulation β Screen size, DPR, touch, user agent, geolocation, timezone, language
- Network control β Simulate 4G, Fast 3G, Slow 3G, or offline per browser
- Diagnostics β Console errors, network traffic, performance metrics, push notifications
- Error beacon β Every tool response warns about JS errors across all browsers automatically
- Docker-ready β Official image on GHCR (
ghcr.io/cap-of-tea/gdd), listed on the MCP Registry
- Self-updating β Built-in version check and one-command update
Player Management
| Tool | Description |
|---|
gdd_add_players | Add N browser instances with optional device preset |
gdd_remove_player | Remove a browser instance by player ID |
gdd_list_windows | List all active browsers with current state |
Navigation
| Tool | Description |
|---|
gdd_navigate | Navigate to a URL |
gdd_wait | Wait for a CSS selector to appear (with timeout) |
gdd_reload | Reload page (hard=true bypasses cache) |
gdd_back | Navigate back |
gdd_forward | Navigate forward |
Interaction
| Tool | Description |
|---|
gdd_tap | Tap element by CSS selector or coordinates; sends a single device-appropriate input (touch on touch devices, mouse on desktop), never both. humanize=true adds a continuous human-like cursor path |
gdd_swipe | Swipe gesture (up/down/left/right) |
gdd_drag | Drag an element to (x, y) or onto another element via real pointer events (drives dnd-kit & HTML5 drag-and-drop) |
gdd_scroll | Scroll page or element |
gdd_type | Type text with real, trusted keystrokes (CDP dispatchKeyEvent β masks, autocomplete and maxlength behave as for a real user; works on contenteditable). Physical key codes follow the emulated layout (US/RU/DE/FR); humanize=true adds per-key jitter; paste=true inserts in one shot |
gdd_press | Press a single key or shortcut (Enter, Tab, Escape, Arrow keys, F1βF12, or a character) with optional modifiers (Control/Alt/Shift/Meta); character keys follow the emulated layout |
gdd_hover | Hover over element. humanize=true adds a continuous human-like cursor path |
gdd_select | Select option from <select> dropdown |
gdd_dialog | Handle JS alert/confirm/prompt dialogs |
Reading & Screenshots
| Tool | Description |
|---|
gdd_read | Read text content of an element |
gdd_read_all | Read text from all matching elements |
gdd_screenshot | Capture JPEG screenshot at CSS pixel resolution |
Emulation
| Tool | Description |
|---|
gdd_set_device | Set device preset (22 devices: phones, tablets, desktops) |
gdd_set_viewport | Set custom viewport dimensions |
gdd_set_location | Set geolocation, timezone, and locale |
gdd_set_network | Set network conditions (4G, 3G, offline) |
gdd_set_language | Set browser language |
gdd_set_headers | Rewrite response headers β strip X-Frame-Options/CSP to allow framing |
State & Diagnostics
| Tool | Description |
|---|
gdd_get_state | Browser state: URL, title, device, auth status |
gdd_get_console | Console output and uncaught exceptions |
gdd_get_network | Network requests with timing and status |
gdd_get_notifications | Received push notifications |
gdd_get_performance | Performance metrics (JS heap, DOM nodes, FPS) |
gdd_clear_logs | Clear console and/or network logs |
Auth & Execution
| Tool | Description |
|---|
gdd_quick_auth | Auto-register and login with generated credentials |
gdd_execute_js | Execute JavaScript and return result |
Browser Storage
| Tool | Description |
|---|
gdd_storage | Read/write/clear localStorage/sessionStorage |
gdd_cookies | Read or clear browser cookies |
Help & Updates
| Tool | Description |
|---|
gdd_get_manual | Full GDD manual for AI self-learning |
gdd_check_update | Check for newer versions |
gdd_update | Download and install update (restarts GDD) |
Device Presets (22)
Phones (11)
| Device | Resolution | Scale | Touch |
|---|
| iPhone SE | 375 x 667 | 2.0x | Yes |
| iPhone 14 | 390 x 844 | 3.0x | Yes |
| iPhone 15 Pro | 393 x 852 | 3.0x | Yes |
| iPhone 15 Pro Max | 430 x 932 | 3.0x | Yes |
| iPhone 16 Pro | 402 x 874 | 3.0x | Yes |
| iPhone 16 Pro Max | 440 x 956 | 3.0x | Yes |
| Pixel 9 | 412 x 915 | 2.625x | Yes |
| Pixel 9 Pro | 412 x 915 | 2.625x | Yes |
| Galaxy S24 | 360 x 780 | 3.0x | Yes |
| Galaxy S24 Ultra | 412 x 915 | 3.0x | Yes |
| OnePlus 12 | 412 x 915 | 3.5x | Yes |
Tablets (6)
| Device | Resolution | Scale |
|---|
| iPad Mini | 744 x 1133 | 2.0x |
| iPad Air | 820 x 1180 | 2.0x |
| iPad Pro 11" | 834 x 1194 | 2.0x |
| iPad Pro 13" | 1024 x 1366 | 2.0x |
| Galaxy Tab S9 | 800 x 1280 | 2.0x |
| Pixel Tablet | 800 x 1280 | 2.0x |
Desktops (5)
| Device | Resolution | Scale |
|---|
| Laptop HD | 1366 x 768 | 1.0x |
| Laptop HiDPI | 1440 x 900 | 2.0x |
| Desktop 1080p | 1920 x 1080 | 1.0x |
| Desktop 1440p | 2560 x 1440 | 1.0x |
| Desktop 4K | 3840 x 2160 | 2.0x |
Architecture
Client (AI agent / curl / script)
β POST /mcp (JSON-RPC 2.0)
βΌ
McpServer (:9700)
Streamable HTTP + SSE
β
βΌ
McpToolRegistry (39 tools)
Player Β· Navigation Β· Interaction Β· Read
Emulation Β· Auth Β· State Β· Diagnostics
β
βΌ
IPlayerManager
MainViewModel (WPF) / DesktopPlayerManager (Avalonia) / HeadlessPlayerManager
β
βΌ
IBrowserEngine Instances
WebView2 (Win GUI) | Playwright (Desktop GUI + headed/headless server)
Each: own profile, CDP session, emulation
Editions
GDD ships as three apps over one shared core. The two GUIs differ only in the desktop toolkit (WebView2 on Windows, Avalonia on Linux/macOS); all three expose the same 39 MCP tools.
| Windows GUI | Desktop GUI | Server |
|---|
| Binary | GDD.exe | GDD.Desktop | GDD.Headless (add --headless for no windows) |
| Engine | WebView2 | Playwright (headed) | Playwright (headed/headless) |
| UI | WPF video wall | Avalonia video wall | none β HTTP API only |
| MCP port | 9700 | 9800 | 9700 |
| Platforms | Windows | Linux, macOS | Windows, Linux, macOS |
Tech Stack
| Layer | Technology |
|---|
| Runtime | .NET 8.0 (self-contained) |
| UI (Windows) | WPF + CommunityToolkit.Mvvm |
| UI (Linux/macOS) | Avalonia + CommunityToolkit.Mvvm |
| Browser (Windows GUI) | Microsoft WebView2 |
| Browser (Desktop GUI + Server) | Microsoft Playwright |
| Protocol | MCP (Model Context Protocol) |
| Browser Control | Chrome DevTools Protocol (CDP) |
| Logging | Serilog |
Project Structure
BrowserXn.sln
βββ src/
β βββ GDD.Core/ β Shared library (net8.0)
β β βββ Abstractions/ β IBrowserEngine, IPlayerManager, ...
β β βββ Mcp/ β MCP server, tools, protocol
β β βββ Models/ β Device, Location, Network presets
β β βββ Services/ β CDP, Emulation, Monitoring services
β β βββ Collections/ β RingBuffer
β βββ BrowserXn/ β Windows GUI (WPF + WebView2)
β β βββ Engines/ β WebView2ControlAdapter
β β βββ ViewModels/ β MVVM (MainViewModel : IPlayerManager)
β β βββ Views/ β XAML + VideoWallPanel
β β βββ ...
β βββ GDD.Desktop/ β Linux/macOS GUI (Avalonia + Playwright)
β β βββ Engines/ β PlaywrightHeadedEngine (headed, parked off-screen)
β β βββ ViewModels/ β MainViewModel (DesktopPlayerManager)
β β βββ Views/ β AXAML + VideoWallPanel
β β βββ Scripts/ β mcp-proxy.sh, setup-macos.sh, install-deps.sh
β βββ GDD.Headless/ β Cross-platform server (Playwright)
β βββ Engines/ β PlaywrightEngine
β βββ Platform/ β HeadlessPlayerManager
β βββ Scripts/ β mcp-proxy.sh, mcp-proxy.ps1
βββ .github/workflows/ β CI/CD (8 build targets + auto-release)
Configuration
appsettings.json next to the executable:
{
"GDD": {
"FrontendUrl": "about:blank",
"BackendUrl": "http://localhost:8080/api/v1",
"BotToken": "",
"McpPort": 9700,
"DataFolderRoot": "",
"Stealth": false
}
}
| Key | Description | Default |
|---|
FrontendUrl | Default URL for new browsers | about:blank |
BackendUrl | Backend API for auth service | http://localhost:8080/api/v1 |
BotToken | Telegram bot token (for TG testing) | β |
McpPort | MCP server port (auto-fallback +1..+9) | 9700 |
DataFolderRoot | Browser profile storage root | %LOCALAPPDATA%\GDD\Profiles (Win), ~/.local/share/GDD/Profiles (Linux/macOS) |
Headed | Visible browser windows | true (override with --headless) |
Stealth | Opt-in anti-bot masking β launches Chromium with AutomationControlled disabled and hides the usual automation tells (navigator.webdriver, etc.). Playwright engines (GDD.Desktop, GDD Server) only | false |
Command-line flags
| Flag | Description |
|---|
--headed | Visible browser windows (default) |
--headless | No UI β for CI/CD |
--stealth | Enable anti-bot masking (same as GDD_STEALTH=true) |
--stealth-max | Full stealth β client-hints UA metadata, WebGL/device/timezone spoofing; implies --stealth (same as GDD_STEALTH_MAX=true) |
--update | Check for a newer version and install it if available |
--version | Print the version and exit |
--help | Show usage and exit |
Environment variables
Handy for Docker and CI, where an appsettings.json file is awkward:
| Variable | Description |
|---|
GDD_STEALTH | true/1 to enable anti-bot masking (same as --stealth) |
GDD_STEALTH_MAX | true/1 for full stealth (same as --stealth-max) |
GDD_PROXY | Upstream proxy for every browser, e.g. http://host:3128 or socks5://host:1080 (Server / Playwright engines) |
GDD_PROXY_USER / GDD_PROXY_PASS | Credentials for an authenticated proxy |
GDD_CHROME_CHANNEL | Launch an installed Chrome build (e.g. chrome, chrome-beta) instead of bundled Chromium |
GDD_TRACE | true/1 for verbose trace logging |
Building from Source
Requires .NET 8 SDK.
dotnet publish src/BrowserXn/BrowserXn.csproj -c Release -p:PublishSingleFile=true -o ./publish/win-gui
dotnet publish src/GDD.Headless/GDD.Headless.csproj -c Release -r linux-x64 --self-contained -o ./publish/linux-x64
dotnet publish src/GDD.Headless/GDD.Headless.csproj -c Release -r osx-arm64 --self-contained -o ./publish/osx-arm64
dotnet publish src/GDD.Headless/GDD.Headless.csproj -c Release -r win-x64 --self-contained -o ./publish/win-x64
Chromium installs automatically on first run.
Documentation
Privacy
Privacy Policy
GDD runs entirely on your local machine. No telemetry, no analytics, no data collection.
- No data leaves your machine β all browser profiles, screenshots, logs, and cookies stay in local storage
- Browser profiles β stored in
%LOCALAPPDATA%\GDD\Profiles (Windows) or ~/.local/share/GDD/Profiles (Linux/macOS)
- No third-party services β GDD does not contact any external APIs except GitHub Releases for optional update checks
- Update checks β
gdd_check_update makes a single read-only request to api.github.com. Opt out by not calling the tool, or set CheckForUpdates: false in appsettings.json
- MCP server β listens on
localhost only (default port 9700), never exposed to the network
Contact: 2vsmirnov@gmail.com
License
imVSΒ©, free for personal use.
Source Available β Non-Commercial. Free for personal use, education, and research. Commercial use requires a paid license. See LICENSE for full terms.
Commercial licensing: 2vsmirnov@gmail.com