Monaco Kusto

Kusto Query Language (KQL) support for the Monaco Editor — completions, validation, hovers, folding, and syntax highlighting out of the box.

Library
npm
v15.0.1
84stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
48/100Fair
Development Activity40
Maintenance32
Community48
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
68/100Good
Architecture76
Code Quality72
Innovation68
Learning Curve55

@kusto/monaco-kusto is Microsoft’s official Monaco Editor language plugin for Kusto Query Language (KQL), the query language behind Azure Data Explorer, Azure Monitor, and Microsoft Sentinel. It registers a kusto language mode with Monaco and wires up a dedicated web worker running a real Kusto parser and semantic analyzer — the same language service used by Azure’s own web tooling — so editors get accurate completions, syntax and semantic validation, hovers, folding, formatting, go-to-definition, find-references, and rename support instead of a generic regex-based grammar.

Because the underlying language service is a large C#-originated component bridged to JavaScript (distributed as @kusto/language-service and @kusto/language-service-next), all analysis work happens off the main thread inside the worker. Consumers push a live cluster schema via setSchema/setSchemaFromShowSchema so completions and diagnostics stay in sync with real table and column definitions, making the plugin the standard choice for any web-based KQL editing surface — from Kusto Explorer and Azure Data Explorer’s own web UX to third-party observability and security tooling built on Monaco.

What You Get

  • Full KQL language mode - registers a kusto language with Monaco covering .csl and .kql files
  • Schema-aware IntelliSense - setSchema/setSchemaFromShowSchema feed live cluster/database/table schemas into the completion and validation engine
  • Dedicated web worker - all parsing, semantic analysis, and Kusto language-service calls run off the main thread via getKustoWorker()
  • Rich editing features - hovers, folding, document/range formatting, go-to-definition, find-references, and rename, all wired through standard Monaco language provider APIs
  • Prebuilt syntax themes - ships kusto-light/kusto-dark Monaco themes plus Monarch tokenization and semantic highlighting

Common Use Cases

  • Embedding a KQL query editor - add Azure Data Explorer/Kusto query editing to an internal dashboard or admin tool built on Monaco
  • Building observability and security UIs - power query editors for Azure Monitor Logs, Microsoft Sentinel, or Application Insights-style log-analytics dashboards
  • Schema-driven autocomplete - surface table/column-aware completions once a cluster’s schema is fetched via .show schema as json
  • Client-side query validation - catch KQL syntax and semantic errors before submitting a query to a cluster

Under The Hood

Architecture The plugin layers cleanly from the outside in: monaco.contribution.ts registers the kusto language and exposes the public global API (monaco.languages.kusto), kustoMode.ts wires up all Monaco language-feature providers (completion, diagnostics, hover, folding, formatting, definition, rename, reference) against a shared AugmentedWorkerAccessor, workerManager.ts owns the lifecycle of the underlying web worker (idle-timeout handling, schema persistence across worker restarts, lazy worker creation), and kustoWorker.ts is the RPC surface actually running inside that worker, delegating to kustoLanguageService.ts which wraps the bridged Kusto language engine. Cross-thread schema propagation (setSchema/setSchemaFromShowSchema) and an onSchemaUpdateComplete emitter tie the layers together so semantic tokens stay consistent after a schema push. A handful of pragmatic workarounds — an Object.create/Object.assign proxy-safe override pattern for augmenting worker methods, an explicit throwaway ‘ignore’ postMessage before sending real worker init data, and a setTimeout-based suggest-dialog retrigger — reveal a codebase that has hardened around real Monaco/worker quirks over many releases rather than a theoretically pure design.

Tech Stack TypeScript targeting es5/esnext module output, bundled with Rollup into ESM-only release artifacts (AMD dropped as of v15), against a monaco-editor peer dependency pinned to ^0.55.0. The actual Kusto parsing/semantic-analysis engine ships as two dependencies, @kusto/language-service and @kusto/language-service-next, C#-originated code migrated to TypeScript via a Bridge.NET-style toolchain and consumed here as opaque global namespaces (Kusto.Language.*). Supporting libraries include xregexp for extended regex handling, vscode-languageserver-types/vscode-languageserver-textdocument for LSP-shaped data structures, and lodash-es. The repo is a Yarn 3 (Berry) workspace with package (the library) and samples/* (Parcel, Vite, Webpack+React integration examples) as separate workspace packages, built via ts-node scripts rather than a generic task runner.

Code Quality Unit tests run under Jest across src/**/*.spec.ts (completion filtering, semantic tokens registration, worker mode setup, range-HTML rendering), and a separate Playwright integration suite under tests/integration exercises the editor, completions, doc comments, and syntax highlighting end-to-end in a real browser. CI runs via .github/workflows/main.yml and pr.yml, and Prettier enforces formatting. Error handling favors defensive console.error + early null/Promise.resolve(null) returns over thrown exceptions when a document/model can’t be resolved, which is pragmatic for a worker RPC boundary but means callers must handle nulls throughout. No systemic use of stricter TypeScript strict-mode flags is evident in tsconfig.json beyond isolatedModules, so type safety leans on the bridged language-service’s own generated types rather than the plugin’s own code being maximally strict.

API Design The consumer-facing surface is small and focused: register the kusto language, call monaco.languages.kusto.getKustoWorker() to get a worker handle, and push a schema with setSchema. Most Monaco language-provider wiring (hover, completion, folding, etc.) happens automatically once a model’s language is set to kusto, so day-to-day usage requires little boilerplate. The rough edge is web-worker bundler wiring: consumers must configure MonacoEnvironment.getWorker/getWorkerUrl to route the 'kusto' label to a dedicated worker entry point that imports both the kusto worker and Monaco’s own editor worker — a requirement the README documents at length precisely because upstream monaco-editor changes (0.53+) silently broke the old routing approach. Naming is consistent with Monaco’s own APIs (registerHoverProvider-style adapters), lowering the learning curve for anyone who has used Monaco’s language API surface before.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search