Crux
API Reference@use-crux/core

Devtools Plugin

API reference for connecting @use-crux/core observability to the local devtools runtime.

import { enableDevtools, withDevtools } from "@use-crux/core/observability";
import type { RuntimeBridgeOptions } from "@use-crux/core/runtime-bridge";

This page documents the SDK APIs that connect a Crux application to a running @use-crux/local devtools server. The devtools surface is for local UI/control/tunnel/bridge behavior; production telemetry and remote collectors are configured through explicit observability config or telemetry plugins. CLI commands, web UI workflows, and TUI navigation live in the @use-crux/local reference and Devtools guide.

The Project Index devtools surface includes Storage Beta inventory and relations when source indexing can see RecordStore, VectorStore, AssetStore, storage(), and storage.scope() wiring. The UI shows record/vector capabilities and warnings without exposing record values, vector contents, or asset bodies by default.

withDevtools(options)

Creates a CruxPlugin that installs the canonical local observability transport.

import { config } from "@use-crux/core";
import { withDevtools } from "@use-crux/core/observability";

config({
  plugins: [
    withDevtools({
      prompts: [],
      serverUrl: "http://localhost:4400",
    }),
  ],
});

Signature

function withDevtools(options: DevtoolsOptions): CruxPlugin;

Parameters

FieldTypeDefaultDescription
promptsPrompt[][]Prompt definitions to include in runtime index snapshots.
contextsContext[][]Context definitions to include in runtime index snapshots.
toolsFlowToolDef[][]Tool definitions to include in runtime index snapshots.
pathsMap<string, string[]>n/aAuthored namespace paths from createPrompts() / createContexts().
serverUrlstringn/aURL of the running @use-crux/local server.
sessionIdstringn/aOptional session id used to group emitted runtime records.
bridgeboolean | RuntimeBridgeOptionsfalseEnables the local Runtime Bridge command plane for long-lived Node runtimes.

Returns

CruxPlugin with the name crux:devtools. The plugin cleanup hook restores the previously installed observability transport and returns a bounded flush promise so plugin runners can wait for queued local records before shutdown.

enableDevtools(options)

Imperative helper for installing the same local devtools transport outside the plugin system. Most applications should prefer config({ devtools: ... }) or withDevtools() when they explicitly need runtime records sent to a local server or tunnel.

Signature

function enableDevtools(options: EnableDevtoolsOptions): () => void;

Parameters

FieldTypeDefaultDescription
serverUrlstringn/aURL of the running @use-crux/local server.
promptsPrompt[][]Prompt definitions to snapshot.
contextsContext[][]Context definitions to snapshot.
toolsFlowToolDef[][]Tool definitions to snapshot.

Returns

Cleanup function that restores the previous observability transport.

Auto-Install Through config()

When devtools.serverUrl is explicitly set and no observability transport is configured, config() installs the local devtools transport. Ordinary local Eval runs do not require this boilerplate; the CLI coordinates against the local project directly. For tunneled serverless runtimes, prefer observability.serverUrl plus observability.token so the remote worker receives only scoped ingest access.

import { config } from "@use-crux/core";

config({
  observability: {
    serverUrl: process.env.DEVTOOLS_URL,
    token: process.env.CRUX_DEVTOOLS_TOKEN,
  },
  devtools: {
    bridge: true,
  },
});

Neither withDevtools() nor enableDevtools() starts the server. Start it with crux dev from @use-crux/local.

Runtime Bridge Types

Runtime Bridge schemas and helper types are exported from @use-crux/core/runtime-bridge.

import {
  BridgeCommandRequestSchema,
  BridgeCommandResultSchema,
  RuntimeBridgeMessageSchema,
  RuntimePeerHelloSchema,
  connectRuntimeBridge,
  executeRuntimeBridgeCommand,
  getRuntimeBridgeManifest,
} from "@use-crux/core/runtime-bridge";

The bridge is a local-dev command plane. Long-lived Node runtimes can open a /ws/runtime peer; framework integrations such as @use-crux/convex use the same contract over HTTP.

With devtools.bridge: true, Go services can send typed local-dev commands such as store.read to the live app. Primitives register inspectable resources automatically, so devtools can ask for memory:<id> or blackboard:<id> and read the attached store instead of reconstructing state from traces. Eval coordination and observability use their normal Go-owned paths; Web Devtools and the TUI never call runtime peers directly.

During crux dev, the Go server auto-discovers a Convex HTTP bridge peer from CRUX_BRIDGE_URL, CONVEX_SITE_URL, or Convex cloud URL variables such as CONVEX_URL / NEXT_PUBLIC_CONVEX_URL in the shell or project .env.local / .env. If only a .convex.cloud URL is present, Crux derives the matching .convex.site/crux/bridge URL before fetching the manifest.

Resource APIs

For user-facing resource inspection, clients call the Go server's resource APIs instead of bridge endpoints:

  • GET /api/resources/capabilities
  • GET /api/resources/{resourceId}
  • GET /api/resources/{resourceId}/entries

The response is product-shaped: ok for data, partial when only projections are available, unavailable when a bridge/runtime is required, or error when a live command failed. Capabilities are UI hints for showing actions, not guarantees; every resource read returns a structured reason and docs link when it cannot be served. Product screens should prefer domain read models when they exist: the Memory screen reads GET /api/memory/stores/{id} and uses its embedded inspection object instead of composing generic resource calls in the client.

Run lists and run details are intentionally different read paths. The web UI and TUI list newest runs from a bounded page where the backend performs only cheap count/identity enrichment; a single run detail then reads the graph tables needed for the exact RunDetail projection. Raw record payloads are available through the graph/debug route, not the normal detail route.

On this page