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.

Terminal
pnpm add -D @sigx/devtools

The 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:

TSX
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:

TSX
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.

TSX
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.