Inspector / Dev Panel
createAskableInspector mounts a floating overlay panel on the page that shows what Askable is currently tracking — useful for development and for creating demos.
The panel also shows registered context sources, so you can confirm that app-owned sources such as tables, documents, charts, or MCP bridges are mounted and refreshing while you test interactions.
Use the Copy action in the header to copy the exact prompt context currently shown in the panel.
What it shows
The panel updates in real time whenever the focused element changes:
┌─────────────────────────────────────────────┐
│ ✦ Askable Inspector │
├─────────────────────────────────────────────┤
│ Element │
│ div#revenue-card.widget-card │
│ │
│ Meta │
│ { │
│ metric: "revenue", │
│ value: "$2.3M", │
│ delta: "+12%" │
│ } │
│ │
│ Text │
│ Revenue: $2.3M │
│ │
│ Prompt context │
│ User is focused on: — metric: revenue, │
│ value: $2.3M, delta: +12% — value │
│ "Revenue: $2.3M" │
└─────────────────────────────────────────────┘Quick start
import { createAskableContext, createAskableInspector } from '@askable-ui/core';
const ctx = createAskableContext();
ctx.observe(document);
// Mount the inspector — only do this in development
if (process.env.NODE_ENV === 'development') {
createAskableInspector(ctx);
}Options
createAskableInspector(ctx, {
position: 'bottom-right', // 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
highlight: true, // outline the focused element
tools: true, // buttons for region, circle, lasso, text, and clear
sourcePreview: true, // include registered source data in preview/copy
promptOptions: { // forwarded to toPromptContext()
preset: 'compact',
},
});| Option | Type | Default | Description |
|---|---|---|---|
position | string | 'bottom-right' | Where to anchor the panel |
highlight | boolean | true | Draw an outline on the focused element |
tools | boolean | true | Show buttons for region, circle, lasso, text selection, and clear |
promptOptions | AskablePromptContextOptions | — | Options for the prompt output preview |
sourcePreview | boolean | AskableInspectorSourcePreviewOptions | false | Resolve app-owned sources into the preview and Copy output |
Use sourcePreview when you want the inspector to show the same source-backed context a chat bridge receives from toPromptContextAsync().
createAskableInspector(ctx, {
sourcePreview: {
sources: [{ id: 'accounts', mode: 'all', maxItems: 20 }],
sourceErrorMode: 'include',
},
});React
// components/DevInspector.tsx
'use client';
import { AskableInspector, useAskable } from '@askable-ui/react';
export function DevInspector() {
useAskable({ events: ['click'] });
if (process.env.NODE_ENV !== 'development') return null;
return <AskableInspector events={['click']} position="bottom-left" />;
}// app/layout.tsx
import { DevInspector } from '@/components/DevInspector';
export default function Layout({ children }) {
return (
<>
{children}
{process.env.NODE_ENV === 'development' && <DevInspector />}
</>
);
}If your React app uses a custom ctx, name, events, or viewport setting, pass the same values to <AskableInspector /> so the panel follows the same context instead of falling back to the default click/hover/focus observer.
const ctx = createAskableContext();
ctx.observe(document, { events: ['click'] });
function DevInspector() {
useAskable({ ctx });
return process.env.NODE_ENV === 'development'
? <AskableInspector ctx={ctx} />
: null;
}Vue
<!-- components/DevInspector.vue -->
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue';
import { createAskableInspector } from '@askable-ui/core';
import { useAskable } from '@askable-ui/vue';
const { ctx } = useAskable();
let handle: { destroy(): void } | null = null;
onMounted(() => {
if (import.meta.env.DEV) {
handle = createAskableInspector(ctx, { position: 'bottom-left' });
}
});
onUnmounted(() => handle?.destroy());
</script>
<template></template>Cleanup
createAskableInspector returns a handle object with a destroy() method:
const inspector = createAskableInspector(ctx);
// Remove the panel and detach all listeners
inspector.destroy();Calling createAskableInspector again while a panel is already visible replaces the existing panel — you won't end up with multiple overlays.
Guards
Always guard the inspector behind a development check so it never ships to production:
// Vite / Next.js
if (import.meta.env.DEV) {
createAskableInspector(ctx);
}
// Node environment variable
if (process.env.NODE_ENV === 'development') {
createAskableInspector(ctx);
}