Changelog¶
All notable changes to Scherlok are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased¶
[1.0.2] — 2026-09-18¶
Fixed¶
- MCP server reported an empty version —
serverInfo.versionwas blank in everyinitializereply because the package version was never passed to the server class, so clients and registries listed the server without a version. It now reports__version__(mcp 2.x; mcp 1.xFastMCPtakes no version parameter and is unaffected). - Misleading error when an unsupported
mcpis installed — a release exposing neitherMCPServer(mcp 2.x) norFastMCP(mcp 1.x) produced "requires the 'mcp' package … re-install scherlok", which sends the operator down the wrong path. The message now names the installed version and the supported range. Themcpdependency is pinned to>=1.2,<3to match what is actually tested.
Added¶
- stdio handshake test —
tests/test_mcp_server.pynow spawns the installedscherlok-mcpentry point and speaks JSON-RPC over stdio (initialize + tools/list), the way an MCP client or a registry health check does. This is the layer where the two fixes above failed while every in-process test passed. glama.json— declares repository maintainers for the Glama MCP listing.- Documentation site at https://rbmuller.github.io/scherlok/ (MkDocs Material, deployed from
mainby.github/workflows/docs.yml, strict build checked in CI). Includes a sourced comparison with Elementary, Soda, Great Expectations and Monte Carlo; the README table now links to it and no longer quotes unpublished competitor prices. scherlok demo— a self-contained walkthrough that needs no database: seeds a sample DuckDB warehouse (3 tables, 22,500 rows), learns a baseline, ships a "bad deploy" (60% of orders gone, e-mails nulled, free-text plans, a dropped column) and catches it with the real detectors, in about a second. Runs entirely inside one temporary directory and never touches~/.scherlok;--keep/--dirpreserve the files,--output jsonemits the result for scripts. Requires theduckdbextra:uvx --from "scherlok[duckdb]" scherlok demo.DuckDBConnector.close()— releases the file handle so another writer can open the database.- MCP Registry publishing workflow —
.github/workflows/publish-mcp.ymlpublishesserver.jsonto the official MCP Registry after each successful Release run (GitHub OIDC, no stored token), so theio.github.rbmuller/scherloklisting no longer lags behind PyPI.
[1.0.1] — 2026-09-17¶
Fixed¶
- PyPI release — v1.0.0 was tagged and released on GitHub but never reached PyPI: the tag still carried
version = "0.9.0"inpyproject.toml, so the publish job tried to re-upload 0.9.0 and PyPI rejected it with HTTP 400. 1.0.1 ships the 1.0.0 changes below with the version metadata (pyproject.toml,dbt_project.yml,server.json,__version__) corrected and aligned.
[1.0.0] — 2026-09-03¶
Added¶
- Adaptive historical baselines — after enough valid history, volume and column metric detectors learn per-metric variability with robust median/MAD bands; cold-start and unusable histories retain the existing fixed behavior. (#62)
scherlok status --output json— emits a JSON array of table health objects (table,rows,columns,status,last_profiled) for CI parsers. Rich output is routed to stderr in JSON mode so stdout stays machine-readable. (#14)scherlok history --output json— emits a JSON array of anomaly records (detected_at,severity,table,type,message). Empty history returns[]instead of a text message. (#15)scherlok dbt-run-and-watch --output json— the wrapper now accepts the same--output jsonflag asscherlok dbt, so CI users get the wrapper's convenience and a machine-readable stdout payload in one step.dbt run's own stdout is rerouted to stderr in JSON mode so it never mixes with the payload; ifdbt runfails, stdout gets a small JSON error document (project_dir,error,returncode) instead of plain text. (#47)- Targeted
dbt-run-and-watchprofiling — after a successfuldbt run, the wrapper readstarget/run_results.jsonand profiles only successful model nodes from that invocation. Missing or malformed artifacts fail clearly rather than falling back to the full manifest. (#69) dbt buildsupport indbt-run-and-watch— pass--buildto rundbt build; on dbt's handled failure path (exit 1), successful model nodes fromrun_results.jsonare profiled even when tests fail and downstream models are skipped, while unhandled failures fail fast and preserve dbt's exit code. (#76)- Exposure-aware dbt lineage in anomaly alerts — downstream models remain identified separately from dbt exposures, whose labels and owner information are surfaced in the existing alert message without changing notification routing. (#70)
- Selective column profiling in dbt package — the
scherlok_column_metricsmodel now scansgraph.nodesfornull_anomalytest nodes and profiles only the columns that have tests attached, reducing warehouse queries on wide tables. (#71)
Fixed¶
- Clean JSON stdout on dbt early exits —
console.printcalls that leaked Rich markup to stdout on connection failures and missing manifests now useout_errorso they route to stderr in--output jsonmode. (#67)
[0.9.0] — 2026-08-10¶
Added¶
- dbt package — Scherlok is now installable as a native dbt package (
git:install from this repo; the dbt Package Hub listing is pending in dbt-labs/hubcap#456). Includes 4 instant tests (not_null_proportion,row_count_between,recency,unique_proportion) and 2 auto-learning anomaly detection tests (volume_anomaly,null_anomaly) backed by Shewhart control limits. Incrementalscherlok_metricsandscherlok_column_metricsmodels auto-discover and profile all materialized models. One repo, two distribution channels (PyPI + dbt Hub). (#64)
Fixed¶
- mcp 2.0 compatibility —
FastMCPwas renamed toMCPServerin mcp 2.0. Import now tries v2 first, falls back to v1. (#64) - MySQL/DuckDB view discovery —
list_tables()now includes views alongside base tables, matching the behavior of Postgres, BigQuery, and Snowflake connectors. (#63)
[0.8.0] — 2026-07-10¶
Added¶
--explain— Claude-augmented alerts onwatch,ci,check,dbt, anddbt-run-and-watch. When anomalies fire, one Anthropic API call per run (Claude Haiku 4.5 by default,SCHERLOK_EXPLAIN_MODELto override) turns the batch into a root-cause hypothesis — summary, likely cause, up to three diagnostic steps — injected into the Slack (attachment), Discord/Teams (text), generic-JSON (explanationfield), email, and console alerts, plus anexplanationkey ondbt --output json. dbt runs feed upstream lineage frommanifest.jsoninto the prompt so cascading failures trace to the source model. Aggregate data only (anomaly strings, model names, timestamps — never warehouse rows); fail-open by contract: any API failure delivers the unaugmented alert with a one-line(--explain unavailable: …)note, injected text is escaped and truncated per platform so an oversized hypothesis can never get an alert payload rejected, and the alert path is capped at ~30s worst case. Opt-in viapip install scherlok[explain]+ANTHROPIC_API_KEY. Seesrc/scherlok/explainer/README.md. (#58, #59)--explaindemo recording —examples/demo-explain.svg(asciinema-style cast of a real run), embedded in the README section.
0.7.0 — 2026-05-28¶
Added¶
- MCP server —
pip install scherloknow ships ascherlok-mcpstdio server that exposes Scherlok to AI coding agents (Claude Code, Claude Desktop, …) as MCP tools:list_tables,investigate,watch,status,history,check. The connection is resolved server-side (SCHERLOK_CONNECTION/scherlok config) and never passed by the model; every operation is read-only on the warehouse with no arbitrary-SQL tool, and output is bounded. Seesrc/scherlok/mcp/README.md. (#54, #55) server.json+ PyPI ownership marker — repo-rootserver.jsonand anmcp-name: io.github.rbmuller/scherlokmarker in the README so Scherlok can be published to the official MCP Registry (registry.modelcontextprotocol.io). (#56)
Changed¶
mcpis now a core dependency (moved out of the[mcp]extra) so the registry'spip install scherlokinstall path produces a workingscherlok-mcpwithout an extra step. The[mcp]extra is kept as a back-compat alias and still resolves cleanly. This adds ~15 transitive packages (anyio, pydantic, httpx, starlette, uvicorn family) to the base install; the trade was deliberate — first-class agent integration over a lean install.- Extracted the per-table profile-and-detect orchestration into
scherlok.serviceso the CLI and the MCP server share one transport-agnostic core (no behavior change).
0.6.0 — 2026-05-20¶
Added¶
Connectors¶
- MySQL connector —
pip install scherlok[mysql],scherlok connect mysql://user:pass@host:3306/db. Works with MariaDB and other compatible forks. (#45, closes #18) - DuckDB connector —
pip install scherlok[duckdb],scherlok connect duckdb:///path/to/file.db(orduckdb:///:memory:). For local-first analytics workflows. (#50, closes #19)
dbt integration¶
scherlok dbt-run-and-watch— wraps the typical CI sequence (dbt run->scherlok dbt) into one invocation. Streamsdbt runoutput live; ifdbt runfails, exits with the same code WITHOUT running scherlok against a stale or partial manifest. Passes--target,--profiles-dir, and--selectthrough todbt run. Requires thedbtbinary on PATH (dbt-core remains an opt-in dependency). (#40, closes #34)scherlok dbt --output json— emits a single JSON document on stdout (status + per-model anomalies) for CI parsers, with Rich chatter rerouted to stderr so stdout stays machine-readable. (#41, closes #33)scherlok dbt --include-snapshots— opt-in flag to also profile dbt snapshot nodes. Snapshots are SCD Type 2 tables that physically exist in the warehouse and are profilable like any other materialized model. When the flag is unset, behavior is unchanged. (#26, closes #22)- dbt lineage from
manifest.json— newscherlok.dbt.lineagemodule reads the manifest'sparent_map. Two surfaces consume it:scherlok dbt --show-lineage(also ondbt-run-and-watch) prints an ASCII upstream/downstream tree (├──/└──style) under each profiled model; and every anomaly message is suffixed with· Affects N downstream models: a, b, cwhen descendants exist, so webhook and email payloads tell on-call who's about to be paged downstream. Leaf marts get no suffix. (#49, closes #36)
Dashboard¶
- 14-day anomaly trend barchart — per-day severity bars in the HTML report. (#28, closes #20)
- Stale tables panel — surfaces tables whose last profile is older than the freshness threshold, to catch silent ETL failures. (#30, closes #21)
CLI¶
scherlok check— alias forscherlok ci --fail-on critical, the one-liner CI gate. (#44, closes #32)scherlok connectwith no args prints example connection strings for every supported adapter instead of erroring. (#24, closes #23)
Distribution¶
Changed¶
- Release workflow fails if the
linux/amd64image exceeds 100 MiB, so the published image can't silently bloat. (#43)
0.5.0 — 2026-04-30¶
Added¶
- dbt integration v0 — new
scherlok dbtcommand. Readstarget/manifest.json, discovers materialized models (table/incremental/view/materialized_view), auto-resolves the connection fromprofiles.yml(postgres / bigquery / snowflake), and runs investigate + watch per model with dbt-style ✓/✗ output. - Optional dependency:
pip install scherlok[dbt](adds PyYAML) - Flags:
--project-dir,--profiles-dir,--target,--connection-string,--select,--include-sources,--fail-on,--webhook,--email - Supports
{{ env_var('NAME', 'default') }}rendering inprofiles.yml - Requires dbt 1.6+ (manifest schema v10+)
- HTML dashboard — new
scherlok dashboardcommand. Generates a self-contained HTML report (~28 KB) from the local profile store: KPIs, per-table incidents grouped with summary/threshold/first-seen, schema-drift+/−/~diff, sparklines, and history. Auto dark/light theme viaprefers-color-scheme(--theme dark|lightto override). Addsjinja2>=3.0to core dependencies. examples/dbt_smoke/— runnable mini dbt project (3 models on top of the existing seeded Postgres inexamples/docker-compose.yml) for contributors to reproduce the dbt + dashboard flow end-to-end.
Changed¶
--verbose/-vand--quiet/-qglobal flags added to all commands.--quietsilences progress chatter while keeping anomaly results and errors (CI-friendly).--verboseadds per-table profiling timings and column counts.- Connector error messages now include actionable hints.
Failed to connect.is followed by a one-line explanation of what went wrong, plus a hint when applicable. - Postgres: classifies "connection refused" / "auth failed" / "database does not exist" / "SSL required" / timeout / unknown host
- Snowflake: detects missing
SNOWFLAKE_USER/SNOWFLAKE_PASSWORD, missing python connector, auth failures, account/warehouse/database not found - BigQuery: detects missing google-cloud-bigquery, missing Application Default Credentials, permission denied, project/dataset not found, billing not enabled
Fixed¶
- Views were silently skipped by
scherlok investigate/watch/dbton Postgres and Snowflake (list_tablesfiltered toBASE TABLEonly). Materialized dbt views (materialized: view, the default forstaging/models in layered dbt projects) are now discovered. (#7) - Release notes extraction in CI — the awk in
release.ymlwas using regex match against## [version], where[...]is interpreted as a character class. Switched to literal-substring match so v0.5.0 release notes are properly extracted fromCHANGELOG.mdinstead of falling back to the generic placeholder.
0.4.0 — 2026-04-27¶
Added¶
- Snowflake connector (
pip install scherlok[snowflake]) scherlok cicommand — all-in-one CI/CD (connect + watch + exit code) in one line- Email alerter —
scherlok watch --email user@company.com(configure viaSCHERLOK_SMTP_*env vars) - Multi-recipient support:
--emailis repeatable - Issue templates (bug, feature, new connector)
- CHANGELOG.md
- Automatic GitHub Release notes on tag push
0.3.0 — 2026-04-22¶
Added¶
- Generic webhook alerter — auto-detects Slack, Discord, Microsoft Teams, or generic JSON endpoints
--webhook/-wflag in thewatchcommand
Removed¶
- Removed legacy Slack-only path; replaced by the generic webhook
0.2.2 — 2026-04-22¶
Fixed¶
- Sync
__version__betweenpyproject.tomlandsrc/scherlok/__init__.py
0.2.0 — 2026-04-22¶
Added¶
- BigQuery connector (
pip install scherlok[bigquery]) - Detective logo (AI-generated illustration)
- Animated SVG demo in README
- Examples folder with Docker + PostgreSQL quick start
- 34 new tests across store, alerter, config, BigQuery (93 total)
- PyPI release workflow with trusted publishing
- Redesigned README
0.1.0 — 2026-04-15¶
Added¶
- Initial release
- PostgreSQL connector
- 6 anomaly detectors: volume, schema drift, freshness, nullability, distribution, cardinality
- CLI with Typer (
connect,investigate,watch,report,status,history,version) - Local SQLite storage + remote storage (S3, GCS, Azure Blob)
- Slack webhook integration
- 59 unit tests