Installation
Package
@sigx/devtools is ESM-only and ships a single entry point (@sigx/devtools). Add it
as a dev dependency — you should not ship it in production builds.
pnpm add -D @sigx/devtoolsThe package version is 0.0.1. The wire PROTOCOL_VERSION is 1, and the agent
version reported in the hello event is 0.0.3.
Engines
Node ^20.19.0 || >=22.12.0.
Reactive core
The plugin attaches to the global devtools hook on @sigx/reactivity and reads the
component/inspection events from @sigx/runtime-core — but you don't install those
separately. They come bundled in the SignalX umbrella your app already runs on
(sigx on the web, @sigx/lynx on native, @sigx/terminal in the terminal), so
adding @sigx/devtools is enough.
@sigx/reactivity supplies the shared reactivity hook (the plugin calls
ensureDevtoolsHook() to attach), and @sigx/runtime-core emits the component
lifecycle events and hosts the inspection registry (@sigx/runtime-core/inspect)
that store discovery is built on.
No build configuration required
There is no Vite plugin and no special build step needed to use the package. You install it the same way as any other SignalX plugin:
import { defineApp } from 'sigx';
import { devtools } from '@sigx/devtools';
import { App } from './App';
defineApp(<App />)
.use(devtools())
.mount('#app');
The plugin's install() resolves a transport, attaches to the hook, bridges component
and reactivity events to the panel, and sends a hello event once the wire is up. In
SSR or Node, with no window and no custom transport, it returns early and does
nothing — so it is safe to leave in shared entry code.
Keeping it out of production
Because the package has sideEffects: false, a dynamic import behind a dev flag lets
your bundler drop it from release builds entirely:
import { defineApp } from 'sigx';
import { App } from './App';
const app = defineApp(<App />);
if (import.meta.env.DEV) {
const { devtools } = await import('@sigx/devtools');
app.use(devtools());
}
app.mount('#app');
Stores and the router
Stores need no wiring: every @sigx/store instance is discovered automatically
through the core inspection registry (@sigx/runtime-core/inspect) — including stores
created after the plugin installs. Set includeStores: false to opt out. The router is
still passed explicitly and must expose a reactive currentRoute; any @sigx/router
instance satisfies that shape.
import { defineApp } from 'sigx';
import { devtools } from '@sigx/devtools';
import { createRouter } from '@sigx/router';
import { App } from './App';
const router = createRouter({ routes: [/* ... */] });
defineApp(<App />)
.use(router)
.use(devtools({
appName: 'shop',
router,
}))
.mount('#app');
See Connecting an inspector for how to choose a transport and attach a panel.
