kq
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 namedkql-clibecausekqwas 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):
./.kq/- Project-local queries~/.config/kq/queries/- User queries- 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):
- Service Principal - Set
AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_TENANT_ID - Azure CLI - Run
az loginfirst - Device Code - Interactive browser login (tokens cached ~90 days)
Query Safety
Queries have a safety level:
safe- Queries with proper time/scope filteringcaution- May scan significant data, use carefullydangerous- 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:
- Bump
__version__insrc/kq/__init__.pyand updateCHANGELOG.md. - 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d10512197779180dda37e7aaa902d57fa01412cc3d37f1e529602d0e6b49283a
|
|
| MD5 |
933783156e8ff7faab65bf1b3a8f53c0
|
|
| BLAKE2b-256 |
2e0d6f824d8d869ba44b3e66ab0ac9f045c15434806186d58052e74e4b1c80c3
|
Provenance
The following attestation bundles were made for kql_cli-1.0.0.tar.gz:
Publisher:
release.yml on cptfinch/kq
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kql_cli-1.0.0.tar.gz -
Subject digest:
d10512197779180dda37e7aaa902d57fa01412cc3d37f1e529602d0e6b49283a - Sigstore transparency entry: 2217561931
- Sigstore integration time:
-
Permalink:
cptfinch/kq@216ad727186421a8369f94e1e5a1ade0926685a8 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/cptfinch
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@216ad727186421a8369f94e1e5a1ade0926685a8 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f69819dffe32fc5eb7a90f58bdfcc97533f418777f300027ee356745603f176
|
|
| MD5 |
1d3ea69e6e23101a87e117267d50f0a0
|
|
| BLAKE2b-256 |
3bf034623de526a6036fad8024fddba052913e1469d480ba58fe951d70c28d8a
|
Provenance
The following attestation bundles were made for kql_cli-1.0.0-py3-none-any.whl:
Publisher:
release.yml on cptfinch/kq
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kql_cli-1.0.0-py3-none-any.whl -
Subject digest:
6f69819dffe32fc5eb7a90f58bdfcc97533f418777f300027ee356745603f176 - Sigstore transparency entry: 2217561946
- Sigstore integration time:
-
Permalink:
cptfinch/kq@216ad727186421a8369f94e1e5a1ade0926685a8 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/cptfinch
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@216ad727186421a8369f94e1e5a1ade0926685a8 -
Trigger Event:
push
-
Statement type: