Skip to main content

kq

CI PyPI Python versions License: MIT

KQL CLI — query Azure Data Explorer (Kusto) from the command line.

Like jq for JSON, but for Kusto/KQL. Run raw KQL, keep a git-versioned library of parameterized queries, and pipe results straight into your shell.

Installation

pip install kql-cli

The command you run is kq. The PyPI package is named kql-cli because kq was already taken on PyPI by an unrelated project.

Or from source:

git clone https://github.com/cptfinch/kq.git
cd kq
pip install -e .

Quick Start

# Configure your cluster
kq config set default_cluster https://mycluster.westeurope.kusto.windows.net
kq config set default_database mydb

# Authenticate
kq auth login

# Run queries
kq "MyTable | take 5"                    # Raw KQL
kq list                                   # List saved queries
kq run examples.sample MyTable 10         # Run saved query

Configuration

Config is stored in ~/.config/kq/config.yaml:

default_cluster: https://mycluster.westeurope.kusto.windows.net
default_database: mydb

clusters:
  prod:
    url: https://prod.westeurope.kusto.windows.net
    database: proddb
  dev:
    url: https://dev.westeurope.kusto.windows.net
    database: devdb

Configure via CLI:

kq config show                              # Show current config
kq config set default_cluster <url>         # Set default cluster
kq config set default_database <db>         # Set default database
kq config add-cluster prod <url> --database proddb  # Add named cluster

Commands

Command Description
kq auth login Authenticate to ADX
kq auth status Check authentication status
kq config show Show configuration
kq config set <key> <value> Set config value
kq list [category] List saved queries
kq show <query> Show query details
kq run <query> [params...] Run a saved query
kq "<kql>" Run raw KQL

Saved Queries

Queries are loaded from (in priority order):

  1. ./.kq/ - Project-local queries
  2. ~/.config/kq/queries/ - User queries
  3. Bundled examples

Query Format

Create YAML files in ~/.config/kq/queries/:

# ~/.config/kq/queries/myqueries.yaml
name: myqueries
description: My custom queries

queries:
  - name: recent
    description: Get recent records
    safety: safe
    parameters:
      - name: table
        description: Table name
        required: true
      - name: hours
        description: Hours to look back
        default: "24"
    query: |
      {table}
      | where Timestamp > ago({hours}h)
      | order by Timestamp desc
      | take 100
    example: "MyTable 24"

Then run:

kq list                        # Shows myqueries.recent
kq show myqueries.recent       # Show details
kq run myqueries.recent Events # Run with parameters

Output Formats

kq "MyTable | take 5" -f table    # Default - human readable
kq "MyTable | take 5" -f json     # JSON array
kq "MyTable | take 5" -f csv      # CSV

Authentication

Supports (in priority order):

  1. Service Principal - Set AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID
  2. Azure CLI - Run az login first
  3. Device Code - Interactive browser login (tokens cached ~90 days)

Query Safety

Queries have a safety level:

  • safe - Queries with proper time/scope filtering
  • caution - May scan significant data, use carefully
  • dangerous - Can scan entire tables, requires explicit filtering

Always filter by time first:

// Good - filters first, cheap
MyTable | where Timestamp > ago(1d) | where Category == 'Error'

// Bad - scans everything, expensive
MyTable | where Category == 'Error'

Why kq?

  • LLM-native - Works seamlessly with Claude Code, Copilot, etc.
  • Portable - Same queries work across clusters
  • Versionable - Git-controlled query libraries
  • Unix-friendly - Pipes, scripts, automation
  • Personal queries - User queries never overwritten by updates

Development

git clone https://github.com/cptfinch/kq.git
cd kq
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"

pytest            # run tests
ruff check .      # lint
python -m build   # build sdist + wheel

CI runs lint + tests across Python 3.9–3.13 on every push and pull request.

Releasing

Releases publish to PyPI automatically via Trusted Publishing (OIDC — no tokens stored in the repo). To cut a release:

  1. Bump __version__ in src/kq/__init__.py and update CHANGELOG.md.
  2. Tag and push: git tag v1.2.3 && git push origin v1.2.3.

The release.yml workflow builds the artifacts and publishes them. This requires a one-time PyPI setup: configure kql-cli's trusted publisher to point at this repository, workflow release.yml, environment pypi.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kql_cli-1.0.0.tar.gz (13.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kql_cli-1.0.0-py3-none-any.whl (15.6 kB view details)

Uploaded Python 3

File details

Details for the file kql_cli-1.0.0.tar.gz.

File metadata

  • Download URL: kql_cli-1.0.0.tar.gz
  • Upload date:
  • Size: 13.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for kql_cli-1.0.0.tar.gz
Algorithm Hash digest
SHA256 d10512197779180dda37e7aaa902d57fa01412cc3d37f1e529602d0e6b49283a
MD5 933783156e8ff7faab65bf1b3a8f53c0
BLAKE2b-256 2e0d6f824d8d869ba44b3e66ab0ac9f045c15434806186d58052e74e4b1c80c3

See more details on using hashes here.

Provenance

The following attestation bundles were made for kql_cli-1.0.0.tar.gz:

Publisher: release.yml on cptfinch/kq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kql_cli-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: kql_cli-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 15.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for kql_cli-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6f69819dffe32fc5eb7a90f58bdfcc97533f418777f300027ee356745603f176
MD5 1d3ea69e6e23101a87e117267d50f0a0
BLAKE2b-256 3bf034623de526a6036fad8024fddba052913e1469d480ba58fe951d70c28d8a

See more details on using hashes here.

Provenance

The following attestation bundles were made for kql_cli-1.0.0-py3-none-any.whl:

Publisher: release.yml on cptfinch/kq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page