1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00

Add egui_inspection protocol and plugin (#8234)

Introduces live inspection for running egui apps over a small TCP
request/response protocol, plus the `egui::Plugin` that serves it.

This is the minimal surface to get the egui mcp in, we may want to
extend this in the future to add support for the inspection gui.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lucas Meurer
2026-06-18 11:26:18 +02:00
committed by GitHub
parent 172fb54f7f
commit 86fcffb229
16 changed files with 869 additions and 14 deletions

View File

@@ -116,6 +116,12 @@ x11 = [
## This is used to generate images for examples.
__screenshot = []
## Enable the [`egui_inspection`] plugin. When the `EGUI_INSPECTION` (or
## `EGUI_INSPECTION_ADDR`) env var is set, eframe opens a TCP inspection port on startup that
## lets an external tool (e.g. the `egui_mcp` server) read the AccessKit tree, inject input,
## and capture screenshots. Off unless the env var is set; no-op on wasm.
inspection = ["dep:egui_inspection", "accesskit"]
[dependencies]
egui = { workspace = true, default-features = false, features = ["bytemuck"] }
@@ -131,6 +137,7 @@ web-time.workspace = true
# Optional dependencies
egui_glow = { workspace = true, optional = true, default-features = false }
egui_inspection = { workspace = true, optional = true, features = ["plugin"] }
glow = { workspace = true, optional = true }
ron = { workspace = true, optional = true, features = ["integer128"] }
serde = { workspace = true, optional = true }

View File

@@ -209,6 +209,35 @@ pub use native::file_storage::storage_dir;
#[cfg(not(target_arch = "wasm32"))]
pub mod icon_data;
// ----------------------------------------------------------------------------
/// Attach an [`egui_inspection::InspectionPlugin`] to `ctx` when enabled via the environment.
#[cfg(all(feature = "inspection", not(target_arch = "wasm32")))]
pub(crate) fn maybe_attach_inspection_plugin(ctx: &egui::Context, label: Option<String>) {
match egui_inspection::attach_from_env(ctx, label) {
Ok(true) => log::info!("egui_inspection plugin attached"),
Ok(false) => {}
Err(err) => log::warn!("egui_inspection attach failed: {err}"),
}
}
/// Fallback for native builds without the `inspection` feature. Logs warning if inspection env
/// var was set.
#[cfg(all(
not(feature = "inspection"),
not(target_arch = "wasm32"),
any(feature = "glow", feature = "wgpu_no_default_features")
))]
pub(crate) fn maybe_attach_inspection_plugin(_ctx: &egui::Context, _label: Option<String>) {
if let Ok(value) = std::env::var("EGUI_INSPECTION")
&& value != "0"
&& value != "false"
&& !value.is_empty()
{
log::warn!("Inspection env var set but app was compiled without eframe/inspection feature");
}
}
/// This is how you start a native (desktop) app.
///
/// The first argument is name of your app, which is an identifier

View File

@@ -299,6 +299,9 @@ impl<'app> GlowWinitApp<'app> {
let app_creator = std::mem::take(&mut self.app_creator)
.expect("Single-use AppCreator has unexpectedly already been taken");
#[cfg(all(not(feature = "inspection"), not(target_arch = "wasm32")))]
crate::maybe_attach_inspection_plugin(&integration.egui_ctx, Some(self.app_name.clone()));
let app: Box<dyn 'app + App> = {
// Use latest raw_window_handle for eframe compatibility
use raw_window_handle::{HasDisplayHandle as _, HasWindowHandle as _};

View File

@@ -291,6 +291,9 @@ impl<'app> WgpuWinitApp<'app> {
let app_creator = std::mem::take(&mut self.app_creator)
.expect("Single-use AppCreator has unexpectedly already been taken");
crate::maybe_attach_inspection_plugin(&egui_ctx, Some(self.app_name.clone()));
let cc = CreationContext {
egui_ctx: egui_ctx.clone(),
integration_info: integration.frame.info().clone(),