Inspector
Learn how to look at your app's data, and let agents debug it, through your own backend.The Inspector lets you browse and edit your app's data, follow relations, see a table's schema and
permissions, and look at the app as a given user would. Your backend serves it at
<basePath>/inspect/, by default /jazz/inspect/, and decides who may open it. The same access
works from the CLI and as MCP tools for agents.
Who may inspect
Pass inspect to createJazz. It gets the request and returns who the person is, for the audit
log, or null to refuse:
jazz.server.tsexport const jazz = createJazz({app,permissions,store: sqlite({ path: "./data/jazz" }),authenticate,// Staff behind your SSO proxy, VPN or Vercel deployment protectioninspect: async (request) => {const staff = await verifyStaff(request);return staff ? { by: staff.email, write: staff.isAdmin } : null;},});
Without inspect, only local development gets in: a request from this machine while NODE_ENV is
"development". Jazz can only check that on hosts that hand it the Node request (attach() and
nodeHandler). On Next.js route handlers, Hono, Bun and Deno it can't see where a request comes
from, so the default is off there; pass an inspect hook to use the Inspector. Pass () => null to
turn it off everywhere.
Every call is audited, allowed or refused. By default that's one console.info line per call; pass
inspector: { audit } to send events to your own log.
The Inspector page
Open /jazz/inspect/ on your app. Besides the data grid, it has:
- View as user: browse the data under one user's permissions.
- Sessions: who is connected right now.
- Linked queries: follow a query from a session or an agent's answer.
Links into the Inspector carry their place in the URL fragment (#q, #table, #row, #as), and
hold no credential, so you can paste them into a chat or an issue. The page can't be framed by other
sites.
Agents
An agent gets access only when a person approves it in the browser:
Terminalnpx jazz-tools inspect login --app https://my-app.com
--app is your app's URL, or the URL Jazz is served at if you changed basePath.
This opens the Inspector on an approval page. Once you approve, the browser hands the token straight
to the waiting command on your machine, which keeps it in ~/.config/jazz/inspect-tokens.json,
so nothing goes into .env. When the agent runs elsewhere,
the page shows the token to paste instead.
jazz-tools inspect <whoami|schema|query|get|history|insert|update|delete|sessions|link>prints JSON.jazz-tools inspect mcp --app <url>serves the same operations as MCP tools over stdio, for exampleclaude mcp add jazz -- npx jazz-tools inspect mcp --app <url>. An agent without a token calls therequest_accesstool, which starts the same approval.
Tokens are read-only unless you allow writes, can be limited to some tables, and expire (after a day
at most, inspector.maxTokenTtlSeconds). To keep columns from agents, pass
inspector: { redact: { users: ["email"] } }: those values read as "[redacted]". To revoke every
token, set inspector.tokensIssuedAfter to now.
On vercel(), and on remote() with a backend credential, set inspector.tokenSecret so every
instance signs tokens the same way. Changing it also revokes every token.
Inside a local-first page
To look at a local-first page's own database, including writes that haven't synced yet, mount the overlay:
import { mountInspector } from "jazz-tools/inspector";mountInspector(db);
It docks the Inspector in the page, loaded from <serverUrl>/inspect/embedded.html. The page and
your backend must share an origin; another origin is refused as not supported yet. Importing
jazz-tools/inspector is safe on a server: the overlay loads on first mount.
Not supported yet
- Explaining which policy let a row through or refused it (
explain).