← SkillSafe / KQL Lens

Your Kusto query, read the way the engine reads it

Paste one KQL query. The page splits it into pipeline stages in your browser — string-aware, comment-aware, resolving your let bindings — and tells you for free what it found before any model is involved: the missing time filter, the contains that should be has, the join with no kind=.

Both examples ship with a saved model run for every lane, so you can see a full review, a full rewrite and a full explanation without signing in and without spending a credit.

nothing pasted yet
Drag a .kql or .csl file in, or Everything is read in your browser. Nothing uploads until you run.
nothing to mask yet
Paste a query to price the run.

What this does, and what it does not

The instant read is a real KQL reader, not a keyword search. It scans the query character by character first, so it knows which // starts a comment and which one is inside a string; it splits statements on ; and stages on | only at bracket depth zero, so a pipe inside a join (T | where …) subquery or inside a string literal never splits a stage; and it resolves one level of let bindings, so let lookback = 30d; T | where TimeGenerated > ago(lookback) is correctly read as bounded rather than reported as a missing time filter. Everything it finds is handed to the model as facts it must reconcile, and the reply is checked against them afterwards — if a flag is neither confirmed nor set aside, this page says so.

Masking runs before the read, not before the send. GUIDs, email addresses, IPv4 and IPv6 literals, Azure resource ids, cluster URIs and credential-shaped values are replaced with stable placeholders, so the stage quotes, the findings and the context box are all derived from already-masked text and no field can carry a raw value by construction. The assembled request is then re-checked for every value the masker found, and the run button is disabled — not merely flagged — if one survived.

It reads; it does not run anything. It never connects to your cluster, never sees your data, and cannot tell you how many gigabytes a query scans — it has no table statistics, so it describes the shape of the cost and says unknown where a number would be a guess. A rewrite is a suggestion to read before you run it, not a validated query plan.

Nothing to hand? Load the , which joins two tables with no kind= and filters the time range after the join, or the , which is well-ordered but sorts a whole result set to take a hundred rows. Both replay a saved run for free.