Skip to main content
The debugger is controlled almost entirely with environment variables. Once your agent is instrumented, you turn debug mode on and pick a replay boundary by setting variables on the run command. Runs group into a session automatically: the first run writes .lmnr/debug-session.json and every later run in the same directory rejoins it, so you don’t pass a session id around. No code changes are needed in the general case.

General setup

1. Install the CLI

npm install -g lmnr-cli
# or run on demand with: npx lmnr-cli@latest

2. Run setup

lmnr-cli setup
setup logs you in (the debug commands authenticate as you, the signed-in user), links the directory to a project via .lmnr/project.json, writes LMNR_PROJECT_API_KEY to your env file so the SDK can send traces, and installs the Laminar skill into your project so your coding agent knows how to drive the debugger. The CLI itself never uses the project API key; that key is only for the SDK in your agent. See the CLI page for details.

3. Ask your coding agent to instrument your agent

The debugger works on top of normal Laminar tracing. With the skill installed, ask your coding agent to instrument your agent and it will wire up the right integration for you: the Getting Started onboarding prompt is the fastest way to hand it off. Caching is limited to a specific set of integrations (see how caching works), but the record, inspect, and replay loop runs with everything Laminar traces. If you use the AI SDK, see the AI SDK caching note below for one extra wrapper.

4. Ask your coding agent to run the debugger

Once your agent is instrumented, ask your coding agent to run the full debugger loop. It records a run, reads the trace, edits your code, and replays from a checkpoint, all on its own. The debugger process page walks through every step it runs. To drive it yourself instead, add LMNR_DEBUG=true to your run command to record a session. From there, a handful of environment variables control replay:
VariableRequiredDescription
LMNR_DEBUGYesSet to true, 1, yes, or on to enable debug mode.
LMNR_DEBUG_REPLAY_TRACE_IDFor replayTrace id of the run to replay from.
LMNR_DEBUG_CACHE_UNTILFor replaySpan id of the last LLM call to replay (inclusive); calls after it run live. Accepts a full UUID, the last two UUID groups, the 16-char OTel id, or any hex suffix.
LMNR_DEBUG_SESSION_IDOptionalPin a run to a specific session. You rarely need this: after the first run, .lmnr/debug-session.json rejoins the same session automatically. Set it to override the file or to join a session created elsewhere.
LMNR_TRACE_METADATAOptionalJSON object attached to the trace. Use key rollout.note for the pre-run annotation.
The first LMNR_DEBUG=true run mints a session, registers it with Laminar, writes .lmnr/debug-session.json, and opens the session in your browser. Later runs in the same directory read that file and rejoin the session silently (no second browser tab). To start a clean session on purpose, run lmnr-cli debug session new, which resets the file. The debugger process page walks through using these variables end to end.

AI SDK caching

For the AI SDK (TypeScript), caching needs one extra step on top of the normal telemetry integration: wrap each model with wrapLanguageModel. The wrapper is what hashes the span input and consults the Laminar backend for a cached response. Without it, your AI SDK calls are traced and replayable as part of the transcript, but they will not serve from cache.
import { generateText, gateway } from 'ai';
// or
import { anthropic } from '@ai-sdk/anthropic';
import { Laminar, wrapLanguageModel, getTracer } from '@lmnr-ai/lmnr';

Laminar.initialize();

await generateText({
  // this line is what enables debugger caching
  model: wrapLanguageModel(gateway('openai/gpt-5')),
  // or
  // model: wrapLanguageModel(anthropic('claude-opus-4-5')),
  // ... other params

  // general Laminar telemetry integration
  experimental_telemetry: {
    isEnabled: true,
    tracer: getTracer(),
  },
});
AI SDK v7 replaces experimental_telemetry with a telemetry option that takes integrations. The wrapLanguageModel step is the same; only the telemetry wiring changes.
import { generateText, gateway } from 'ai';
// or
import { anthropic } from '@ai-sdk/anthropic';
import { Laminar, wrapLanguageModel, LaminarAiSdkTelemetry } from '@lmnr-ai/lmnr';

Laminar.initialize();

await generateText({
  // this line is what enables debugger caching
  model: wrapLanguageModel(gateway('openai/gpt-5')),
  // or
  // model: wrapLanguageModel(anthropic('claude-opus-4-5')),
  // ... other params

  // general Laminar telemetry integration
  telemetry: {
    isEnabled: true,
    integrations: [new LaminarAiSdkTelemetry()],
  },
});

What’s next

The debugger process

The full loop your coding agent runs: record, inspect, and replay.

How caching works

What gets cached, the input hash, and which integrations support it.