Expand description
Cross-target instrumentation for AI-assisted egui development.
eguidev captures widget state at frame boundaries and injects input
through egui’s raw_input_hook, keeping automation aligned with the app’s
real event loop. This crate is the instrumentation half of the automation
stack: it is valid for native and wasm32 builds, and it intentionally does
not ship the embedded script runtime, MCP server, or screenshot machinery.
§Quick start
Add a DevMcp handle to your app state, wrap each frame with
FrameGuard, and forward raw input to raw_input_hook. The handle
stays inert until a native app opts into eguidev_runtime and attaches the
embedded runtime in one bootstrap location.
use eframe::{App, egui};
use eguidev::{DevMcp, DevUiExt, FrameGuard};
struct MyApp {
devmcp: DevMcp,
name: String,
}
impl MyApp {
fn new() -> Self {
Self {
devmcp: DevMcp::new(),
name: String::new(),
}
}
}
impl App for MyApp {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
let ctx = ui.ctx().clone();
let _guard = FrameGuard::new(&self.devmcp, &ctx);
egui::Frame::central_panel(ui.style()).show(ui, |ui| {
ui.dev_text_edit("app.name", &mut self.name);
if ui.dev_button("app.submit", "Submit").clicked() {
// ...
}
});
}
fn raw_input_hook(&mut self, ctx: &egui::Context, raw_input: &mut egui::RawInput) {
eguidev::raw_input_hook(&self.devmcp, ctx, raw_input);
}
}§Build modes
- Cross-target instrumentation: depend on
eguidevonly.DevMcp,FrameGuard,raw_input_hook, widget tagging, and fixtures all compile for native andwasm32targets. - Native embedded runtime: add an app-local feature that enables the
optional
eguidev_runtimedependency, then calleguidev_runtime::attach(devmcp)in one bootstrap location. Keep that branch local to startup code instead of pushing#[cfg]into widget code.
§Instrumenting widgets
Use the DevUiExt trait for standard widgets. Each dev_* method takes
an explicit string id and auto-populates role, label, and value metadata:
ui.dev_button("settings.save", "Save");
ui.dev_text_edit("settings.name", &mut name);
ui.dev_checkbox("settings.enabled", &mut enabled, "Enabled");
ui.dev_slider("settings.level", &mut level, 0.0..=100.0);For custom widgets, use id (geometry only) or id_with_meta (explicit
role/value/label). If you already have an egui::Response, use
track_response_full to register it after the fact. Use container to
annotate hierarchy so scripts can traverse parent/child relationships.
Custom widgets that should accept scripted set_value(...) calls must also
consume queued overrides before rendering:
let id = "settings.mode";
if let Some(crate::WidgetValue::Int(index)) = take_widget_value_override(ui, id) {
*selected = index as usize;
}
let response = render_custom_mode_picker(ui, selected);
track_response_full(
id,
&response,
WidgetMeta {
role: WidgetRole::ComboBox,
value: Some(WidgetValue::Int(*selected as i64)),
role_state: Some(RoleState::ComboBox {
options: mode_labels.clone(),
}),
..Default::default()
},
);Widget ids are the one canonical selector in the scripting API. Explicit ids must be unique within a captured frame; duplicates are treated as a hard automation fault.
§Fixtures
Apps register fixtures with DevMcp::fixtures and a handler callback
with DevMcp::on_fixture. Each fixture must be independently invokable
from any prior state and must leave the app in a baseline that can be
described with readiness anchors. Scripts call fixture("name") to apply
the named baseline, wait for fresh captures, and verify those anchors
before returning. Widget and viewport handles resolve fresh across fixture
boundaries, so rebinding root() after each fixture is usually unnecessary.
Use fixture_raw("name") only when you explicitly want the old
fire-and-forget behavior for debugging or manual setup flows.
§Scripting reference
The canonical Luau API, direct script evaluation helpers, and the smoketest
runner all live in eguidev_runtime. edev serves those checked-in
definitions through script_api and edev --script-docs.
Structs§
- Anchor
- A single readiness anchor for a fixture baseline.
- Button
Options - Options for selected-aware buttons.
- Checkbox
Options - Options for third-state checkboxes.
- Container
Guard - RAII guard that pops a container scope when dropped.
- DevMcp
- DevMCP handle stored in app state.
- Fixture
Spec - Fixture metadata advertised by an app.
- Frame
Guard - RAII guard that calls
begin_frameandend_frameautomatically. - Progress
BarOptions - Options for progress bars.
- Scroll
Area Meta - Scroll metadata captured for a scroll area.
- Scroll
Area State - Scroll area state tracker with one-shot offset jumps.
- Text
Edit Options - Options for text-edit widgets.
- Widget
Layout - Layout metadata captured for a widget when available.
- Widget
Meta - Metadata for a widget used during tracking and layout analysis.
- Widget
Range - Min/max bounds for a numeric widget.
- Widget
State - Live widget snapshot exposed to scripting surfaces.
Enums§
- Anchor
Check - Declarative readiness checks for fixture anchors.
- Role
State - Role-specific widget metadata kept on internal registry entries.
- Widget
Role - Widget role taxonomy for automation and scripting filters.
- Widget
Value - Captured widget value for stateful controls.
Traits§
- DevScroll
Area Ext - Helper extensions for recording scroll areas with explicit ids.
- DevUi
Ext - Helper extensions for recording common widgets with explicit ids.
Functions§
- container
- Run a closure within a container scope with an explicit id.
- id
- Record a widget with an explicit id and geometry only.
- id_
with_ meta - Record a widget with an explicit id and explicit metadata.
- raw_
input_ hook - Forward the raw input hook into the DevMcp handler.
- take_
widget_ value_ override - Consume a queued widget value override for a custom instrumented widget.
- track_
response_ full - Track an already-created widget response with explicit metadata.
Type Aliases§
- Fixture
Handler - Handler that applies a named fixture to the app state.