The CLI

One self-contained file. Download xql-lint.mjs from a release, run it with Node 18+, and you have the real XQL grammar and semantic checks on the command line — no install, no node_modules.

Every block on this page is real output. The site build runs the CLI for each example and embeds exactly what it printed, so nothing here can drift from what the tool actually does.

Getting it

gunzip xql-intellisense.json.gz
node xql-lint.mjs --schema xql-intellisense.json query.xql

Put xql-intellisense.json next to xql-lint.mjs and the --schema flag becomes unnecessary.

Examples

A query that checks out
node xql-lint.mjs --schema xql-intellisense.json -e 'dataset = xdr_data | limit 10'
no problems found
exit 0
A column that does not exist
node xql-lint.mjs --schema xql-intellisense.json -e 'dataset = xdr_data | fields bogus_zzz'
<query>:1:29  error  bogus_zzz is not a valid field

1 error, 0 warnings
exit 1
A syntax error
node xql-lint.mjs --schema xql-intellisense.json -e 'dataset = xdr_data | filter (_time = 1'
<query>:1:38  error  missing  ')'

1 error, 0 warnings
exit 1
Without a schema: syntax only, and it says so on stderr
node xql-lint.mjs query.xql
xql-lint: no tenant schema found — validating syntax only. See --help.
no problems found
exit 0
The same file with a schema: the unknown column surfaces too
node xql-lint.mjs --schema xql-intellisense.json query.xql
query.xql:3:13  error  field is invalid - does not exist

1 error, 0 warnings
exit 1
Machine-readable, for CI
node xql-lint.mjs --schema xql-intellisense.json --json -e 'dataset = xdr_data | fields bogus_zzz'
[
  {
    "file": "<query>",
    "line": 1,
    "column": 29,
    "endLine": 1,
    "endColumn": 30,
    "severity": "error",
    "message": "bogus_zzz is not a valid field"
  }
]
exit 1
Warnings promoted to errors
node xql-lint.mjs --schema xql-intellisense.json --strict -e 'datamodel = xdr_data | limit 5'
<query>:1:1  error  datamodel is planned for deprecation within the next year. We recommend transitioning to the new XDM schema-on-write datasets for enhanced performance and usability.
<query>:1:13  error  xdr_data is not a valid datamodel
<query>:1:22  error  operator is missing

3 errors, 0 warnings
exit 1
The full option list
node xql-lint.mjs --help
xql-lint 1.0.0 — validate XQL queries offline.

Usage:
  xql-lint [options] [file ...]
  xql-lint [options] -e '<query>'
  cat query.xql | xql-lint [options]

Options:
  -e, --eval <query>   Lint the query given on the command line.
  -s, --schema <path>  Tenant schema JSON (get_intellisense_values output).
      --json           Emit findings as JSON.
      --strict         Treat warnings as errors.
  -q, --quiet          Print findings only — no summary, no schema notice.
  -v, --version        Print the version.
  -h, --help           Print this help.

Schema resolution, first hit wins:
  --schema <path>
  $XQL_SCHEMA
  xql-intellisense.json next to this script
  ~/.config/xql-toolchain/xql-intellisense.json
  ../crtxtool/config/xql-schema.json

Without a schema, validation degrades to syntax only: the grammar still reports
malformed queries, but field and dataset names cannot be resolved.

Refresh the schema with:  crtxtool xql schema
exit 0

How it does against the query library

Linting all 416 queries in the library takes a couple of seconds. 344 of 416 (83%) come back clean; 58 report warnings only and 14 report at least one error.

Those findings are against the community-sourced schema, which is one snapshot from one tenant. A “not a valid field” on a column your tenant really has is a gap in that schema, not a fault in the query. Generate your own with crtxtool xql schema for results you can act on. You can page through every one of these queries on the editor page.

Where it looks for a schema

First hit wins:

  1. --schema <path>
  2. $XQL_SCHEMA
  3. xql-intellisense.json next to the script
  4. ~/.config/xql-toolchain/xql-intellisense.json
  5. ../crtxtool/config/xql-schema.json

With no schema at all it still runs, reporting syntax errors only — and says so on stderr rather than passing a partial check off as a clean one.

Exit codes

codemeaning
0no errors (warnings alone do not fail, unless --strict)
1at least one error
2usage or I/O problem — bad flag, unreadable file, unparseable schema

Which makes it a one-liner in CI:

node xql-lint.mjs --strict queries/*.xql || exit 1