lmnr-cli signal creates, inspects, updates, and deletes Signals from your terminal. Keep a Signal’s prompt and schema in your repo, ship changes from CI, or hand the surface to a coding agent that can shell out.
signal ships in the standalone lmnr-cli npm package. You do not need the @lmnr-ai/lmnr SDK installed to use it.Install and authenticate
setup once per project:
.lmnr/project.json, so every signal command in that directory (or any subdirectory) targets that project. Override per command with --project-id <uuid>. See Authenticate and Directory-scoped projects.
The rest of this page assumes a global install. With npx, prefix each command with npx lmnr-cli@latest.
Create a Signal
A Signal is a prompt, a schema, a trigger, and filters. At minimumsignal create needs a name, --prompt, and --schema:
llm profile: env means the Signal runs on the deployment’s own model credentials, which is how every Signal on Laminar Cloud runs. On a self-hosted deployment you pick a profile instead: see Run a Signal on an LLM profile.
The trigger defaults to root-span-finished, the filter to total_token_count > 1000, and the mode to realtime, so the Signal is already live on new traces. See Triggers and Filters for how they work.
--schema takes a JSON Schema object:
- Field names must be identifiers:
^[a-zA-Z_][a-zA-Z0-9_]*$. - Field types are
string,number, orboolean. For a fixed set of values, use"type": "string"with anenumarray. - Every field is required.
typeandrequiredare filled in for you if you omit them.
--filter takes JSON {"column":"...","operator":"...","value":"..."} and is repeatable. Columns: total_token_count, status, span_names. Pass it on create to replace the default.
--span-name is the trigger flag. span_names is a filter column: it matches a name anywhere in the trace.--sample-rate <1-95>evaluates only that percentage of matching traces. Omit it for no sampling.--disabledcreates the Signal paused. Turn it on later withsignal update --no-disabled.
Creating a Signal also creates two alerts: a Critical-severity event alert and, when clustering is enabled, a New cluster alert. Both notify you in-app and by email. Route them to Slack, change their severity, or add output-schema filters from the Signal’s Settings > Alerts section. See Alerts.
List and inspect Signals
signal get to see one Signal in full:
<signal> accepts either an id or a name, so you rarely need to look up a uuid. An ambiguous name is an error listing the candidates rather than a silent pick, since update and delete change things:
signal get renders the trigger and filters in the same syntax the flags accept, so its output is copy-pasteable into signal update.
Machine-readable output
Every subcommand takes--json, which prints structured JSON to stdout while human-facing messages go to stderr. That keeps pipes clean for scripts and coding agents:
version is the current version of the judge definition (the prompt and schema). The full history is signal versions, below. llmProfileId, llmProfileName, and model are null when the Signal runs on the deployment’s own credentials.
Version history
Editing a Signal appends a new version of its definition: the name, prompt, schema, trigger, filters, mode, sampling, status, and LLM route as they were at that moment. An edit that changes nothing appends nothing.signal versions prints that history, oldest first, so you can see what the judge was asked at the time an old event was extracted:
get, it takes an id or a name. The human output shows the prompt and the payload fields of each version; with --json each entry is {"version","createdAt","definition"} and definition carries the whole snapshot. The version field on signal get is only the current pointer; this command is the log.
Update a Signal
signal update is a partial patch: any flag you omit keeps its stored value. Changing the prompt cannot clear your sampling, reactivate a paused Signal, or alter when it fires.
Run a Signal on an LLM profile
Pointing a Signal at an LLM profile is available on self-hosted deployments. On Laminar Cloud, Signals run on Laminar’s own model credentials and the flags below are rejected.
--llm-profile-id and --model set the pair, and they are required together on signal create:
signal update takes the same pair to move a Signal onto a different profile or model:
- Passing only one of the two is rejected. So is passing either one on Laminar Cloud.
- The model has to be one the profile declares. Discover both with
lmnr-cli llm-profile list. - There is no flag for moving a Signal back to the deployment’s environment credentials. Signals created before you added profiles keep running on them until you pin a profile.
- Deleting a profile, or removing a model a Signal is pinned to, is refused while that Signal exists.
signal get shows the pair, with the profile name for readability:
Delete a Signal
Reference
signal subcommand:
signal create
signal update
signal list, get, versions, delete
What’s next
Signals
How a Signal reads a whole trace and turns it into structured events.
Quickstart
Write your first Signal in the UI and run it over historical traces.
Alerts
Fire Slack or email notifications on the events your Signal produces.
CLI
The rest of
lmnr-cli: setup, SQL queries, datasets, and debug sessions.