# NomoE2E

> Control WebViews in desktop applications through a unified API, supporting both CDP and WebDriver protocols

[![Python 3.13+](https://img.shields.io/badge/Python-3.13+-blue.svg)](https://www.python.org/)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-green.svg)](LICENSE)
[![Version: v0.9.1](https://img.shields.io/badge/Version-v0.9.1-blue.svg)](pyproject.toml)

## 🎯 Project Goals

Provide AI Agents with a practical, scalable, and cross-platform consistent desktop WebView automation capability.

- 🔗 **Dual Protocol Support**: Automatic switching between CDP and WebDriver.
- 🖱️ **Unified API**: `click`, `type_text`, `screenshot`, `execute_script`, etc.
- ✅ **Out of the Box**: Built on Playwright, no need to worry about protocol differences.
- 📸 **Observability**: Error collection, diagnostic snapshots, screenshots.
- 🚀 **Global Installation**: Like npm, install with one command and use anywhere.

## 📦 Supported Scenarios

| Environment | Protocol | Description |
|-------------|----------|-------------|
| Electron | CDP | Use `--remote-debugging-port` |
| Windows WebView2 | CDP | Enable remote debugging |
| Tauri (tauri-plugin-webdriver) | WebDriver | Standard WebDriver endpoint |

## 🚀 Quick Start

### Installation (Recommended)

```bash
# Install globally with uv (like npm i -g)
uv tool install -e .

# After installation, use directly from any directory
nomo-e2e --help
```

### Or use pip

```bash
# Install from source
pip install -e .

# Or from PyPI (after release)
pip install nomo-e2e
```

### Install Playwright Browser Driver

```bash
# Required for CDP/WebDriver connection
playwright install chromium
```

### CLI Quick Start

```bash
# CDP mode (Electron/WebView2) - Auto-detects CDP endpoints
nomo-e2e open http://localhost:9222
nomo-e2e snapshot
nomo-e2e click "#login"
nomo-e2e fill "#username" "admin"
nomo-e2e screenshot --filename result.png

# WebDriver mode (Tauri2) - Requires --driver flag
nomo-e2e open --driver webdriver http://localhost:4445
nomo-e2e click "button.submit"
nomo-e2e eval "document.title"

# View all commands
nomo-e2e --help
```

For the complete CLI command reference, see the [Skills Package](src/nomo_e2e_skills/).

### Python API

```python
from nomo_e2e import WebViewController

# CDP mode (Electron/WebView2) - Auto-detect
controller = WebViewController.connect("http://localhost:9222")

# Or specify driver explicitly
controller = WebViewController.connect(
    "http://localhost:9222",
    driver="cdp"
)

# WebDriver mode (Tauri)
controller = WebViewController.connect(
    "http://127.0.0.1:4445",
    driver="webdriver"
)

# Perform actions
controller.click("#submit-btn")
controller.type_text("#username", "admin")
controller.screenshot("/tmp/page.png")

# Get page info
print(controller.title)
print(controller.url)

# Diagnostic snapshot
snapshot = controller.diagnostics_snapshot()

# Disconnect
controller.disconnect()
```

### Using Context Manager

```python
from nomo_e2e import WebViewController

# Automatic connection lifecycle management
with WebViewController.connect("http://localhost:9222") as controller:
    controller.click("#login")
    controller.type_text("#username", "admin")
    controller.screenshot("./login.png")
# Automatically disconnected
```

## 🔧 Environment Configuration

### Enable CDP for Electron

Electron apps only need to add the `--remote-debugging-port` parameter at startup to enable the CDP debugging port.

**Startup command:**

```bash
# macOS/Linux
npx electron . --remote-debugging-port=9222

# Windows
.\node_modules\.bin\electron . --remote-debugging-port=9222
```

**Configure in package.json:**

```json
{
  "scripts": {
    "start:dev": "electron . --remote-debugging-port=9222"
  }
}
```

**Verify CDP port:**

```bash
# Check if port is open
lsof -i :9222

# Or access the debug endpoint
curl http://localhost:9222/json
```

**E2E test connection:**

```bash
# Auto-detect CDP
nomo-e2e open http://localhost:9222

# Or specify explicitly
nomo-e2e open --driver cdp http://localhost:9222
```

---

### Enable WebDriver for Tauri2

Tauri2 requires installing the `tauri-plugin-webdriver` plugin and enabling the WebDriver endpoint.

#### 1. Install the Plugin

```bash
# Add plugin (interactive)
cd your-tauri-app
cargo tauri add webdriver

# Or manually add dependency to Cargo.toml
[dependencies]
tauri-plugin-webdriver = "2"
```

#### 2. Configure the Plugin

**src-tauri/src/lib.rs:**

```rust
use tauri_plugin_webdriver::init;

fn run() {
    tauri::Builder::default()
        .plugin(init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
```

#### 3. Configure Permissions

**src-tauri/capabilities/main.json:**

```json
{
  "permissions": [
    "core:default",
    "webdriver:default"
  ]
}
```

#### 4. Start Dev Server

Tauri2 dev mode automatically enables the WebDriver endpoint:

```bash
# Start dev server (default port 4445)
cd your-tauri-app
cargo tauri dev

# Or specify port
WEBDRIVER_PORT=4445 cargo tauri dev
```

**Note:** WebDriver port is only enabled in debug/dev builds, release builds will not expose it.

#### 5. Verify WebDriver Endpoint

```bash
# Check if endpoint is ready
curl http://127.0.0.1:4445/status

# Expected response
# {"value":{"ready":true,"message":"Ready."}}
```

#### 6. E2E Test Connection

```bash
nomo-e2e open --driver webdriver http://localhost:4445
```

---

### Quick Reference Table

| Application | Protocol | Startup Parameter | Endpoint URL | Auto-detect |
|-------------|----------|-------------------|--------------|-------------|
| Electron | CDP | `--remote-debugging-port=9222` | `http://localhost:9222` | ✅ |
| Tauri2 | WebDriver | `cargo tauri dev` (auto) | `http://127.0.0.1:4445` | ❌ |
| WebView2 | CDP | `--remote-debugging-port=9222` | `http://localhost:9222` | ✅ |

## 📁 Project Structure

```
nomo-e2e/
├── src/
│   └── nomo_e2e/
│       ├── __init__.py          # Public exports
│       ├── controller.py        # Unified controller
│       ├── adapters/            # Protocol adapters
│       │   ├── base.py         # Abstract base class
│       │   ├── cdp.py          # CDP adapter
│       │   └── webdriver.py    # WebDriver adapter
│       ├── cli/                 # CLI commands
│       ├── exceptions.py        # Exception definitions
│       ├── models.py            # Data models
│       └── skills/              # Skills package
│           └── nomo_e2e_skills/
│               ├── SKILL.md     # Main skill package
│               └── references/   # Reference docs
├── tests/                      # Tests
├── INSTALL.md                  # Installation guide
├── ROADMAP.md                 # Development roadmap
└── AGENTS.md                  # AI development guidelines
```

## 📖 Documentation

| Document | Description |
|----------|-------------|
| [INSTALL.md](INSTALL.md) | Detailed installation and usage guide |
| [src/nomo_e2e_skills/](src/nomo_e2e_skills/) | Skills package (for LLM Agents) |
| [ROADMAP.md](ROADMAP.md) | Development roadmap and milestones |
| [AGENTS.md](AGENTS.md) | AI development guidelines |

## 🔧 Development

```bash
# Install dev dependencies
uv sync

# Code linting
uv run ruff check src/ tests/

# Code formatting
uv run ruff format src/ tests/

# Run tests
uv run pytest tests/ -v

# Type checking
uv run mypy src/
```

## ⚠️ Notes

- WebDriver port is only allowed in debug/dev builds
- Electron's `--remote-debugging-port` can be used in any build
- CDP endpoints (like localhost:9222) are auto-detected as CDP protocol
- WebDriver endpoints require `--driver webdriver` flag
- Ensure you have proper authorization before using on any application
- Some applications may have anti-debugging mechanisms

## 📝 License

Apache License 2.0 - see [LICENSE](LICENSE) for details.

Copyright (c) 2026 NomoAiT
