# eguidev
[](https://discord.gg/fHmRmuBDxF)
[](https://crates.io/crates/eguidev)
[](https://docs.rs/eguidev)
[](https://opensource.org/licenses/MIT)
Like [Playwright](https://playwright.dev/) for [egui](https://github.com/emilk/egui)
apps. eguidev lets AI agents drive your UI end-to-end -- inspecting widget
state, injecting input, taking screenshots of windows or individual widgets --
all from inside the process with no pixel guessing.
Join the [Discord server](https://discord.gg/fHmRmuBDxF) for discussion and
release updates.
## How it works
eguidev instruments your app from the inside. You tag widgets with string ids,
and eguidev captures their state (role, label, value, geometry) at every frame
boundary and injects input in step with the real event loop.
Agents talk to the app through MCP, and the agent-facing surface is
[Luau](https://luau.org/) scripts rather than fine-grained RPC: a single
`script_eval` call can inspect widgets, click and type, wait for state changes,
take screenshots, and return structured results in one round trip.
Three pieces make this work:
- **`eguidev`** -- the instrumentation library your app depends on. Compiles
for native and `wasm32`.
- **`eguidev_runtime`** -- the native-only embedded runtime: script evaluation,
screenshots, and the in-process MCP server. Attached once at app startup.
- **`edev`** -- the CLI. It launches your app, proxies MCP to the agent, and
runs scripts, fixtures, and smoketest suites directly.
## Getting started
**1. Instrument your app.** Add `eguidev` as a dependency, create a `DevMcp`
handle, wrap each frame with `FrameGuard`, and tag widgets with the `dev_*`
helpers:
```rust
let _guard = FrameGuard::new(&self.devmcp, &ctx);
ui.dev_text_edit("app.name", &mut self.name);
if ui.dev_button("app.submit", "Submit").clicked() { /* ... */ }
```
**2. Attach the runtime.** Put `eguidev_runtime` behind an app feature and
enable it in one bootstrap location:
```toml
[features]
devtools = ["dep:eguidev_runtime"]
```
```rust
let devmcp = eguidev_runtime::attach(devmcp);
```
The `DevMcp` handle is inert until the runtime is attached, so widget code
stays unconditional and `wasm32` builds are unaffected.
**3. Tell `edev` how to launch your app.** Install the CLI with
`cargo install edev`, then drop a `.edev.toml` next to your project with the
full launch command:
```toml
[app]
command = ["cargo", "run", "-p", "myapp", "--features", "devtools"]
```
See [`examples/edev.toml`](./examples/edev.toml) for a commented reference of
all options.
**4. Connect your agent.** Register `edev mcp` as an MCP server -- for
example, with Claude Code:
```sh
claude mcp add eguidev -- edev mcp
```
The agent gets tools to start, stop, and observe the app, plus `script_eval`
to drive it. The repo also ships an agent skill at
[`skills/SKILL.md`](./skills/SKILL.md) that teaches agents the workflow.
## Beyond the MCP server
The same scripting surface powers developer-facing tooling:
- `edev smoke` runs a directory of self-contained `.luau` smoketests against
the live app -- regression tests that double as executable documentation of
your UI.
- `edev eval` runs a single script and prints the structured result.
- `edev fixtures` / `edev fixture <name>` list registered fixtures and launch
the app in a known baseline state for manual testing.
Run `edev --help` for the details.
## Documentation
- Luau scripting API: `edev docs`, or the `script_api` MCP tool. The
definition file is
[`eguidev.d.luau`](./crates/eguidev_runtime/luau/eguidev.d.luau).
- Rust API: [docs.rs/eguidev](https://docs.rs/eguidev), including integration
details for custom widgets, fixtures, and multi-viewport apps.
## License
MIT