Contributing to Scherlok¶
Thanks for considering a contribution. Scherlok is small, opinionated, and pragmatic — most changes can land in a weekend.
Ways to contribute¶
- Pick a good first issue — bite-sized tasks (1–2 hours) with clear acceptance criteria
- Add a new connector — Postgres / BigQuery / Snowflake live in
src/scherlok/connectors/; each implementsBaseConnector(connect, list_tables, get_row_count, get_columns, get_column_stats, get_last_modified) - Add a new detector —
src/scherlok/detector/— a function that takes(table, current_profile, stored_profile)and returns anomaly dicts - Improve docs — module READMEs, examples, error messages
- Report bugs — use the bug template; include the failing connection scheme + connector version
Development setup¶
git clone https://github.com/rbmuller/scherlok
cd scherlok
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" # base + tests + lint
pip install -e ".[dbt]" # if you'll touch dbt integration
ruff check src/ tests/
pytest # 200+ tests, runs in <1s
To exercise the full flow end-to-end against a real Postgres + real dbt, see examples/dbt_smoke/ — a runnable mini dbt project.
Code style¶
- Python 3.10+, type hints on public APIs
- Ruff for linting (config in
pyproject.toml); CI fails on warnings - Line length 100
- Prefer explicit imports; avoid wildcard
- Use
pathlib.Pathoveros.path - String literals: define constants for anything used twice (no magic strings)
- No new comments unless they explain why something non-obvious is happening; well-named identifiers carry intent
Testing¶
- All new code paths need tests. Aim for ≥1 happy-path test + ≥1 edge case
- Use mocks for connectors that need cloud creds (see
tests/test_bigquery.py,tests/test_snowflake.py) - Use fixtures for shared test data (see
tests/fixtures/dbt/) - Snapshot tests for the dashboard guard against accidental UI regressions
Commit format¶
Conventional Commits lite — Scherlok uses these prefixes:
feat:— user-visible new functionalityfix:— bug fixchore:— non-user-facing maintenance (build, deps, refactor, release prep)docs:— docs/comments onlytest:— test-only changes
Subject line ≤72 chars. Body explains the why, not the what. Multi-line is fine.
Pull request flow¶
- Branch from
main—feat/<short-description>orfix/<short-description> - One PR per logical change. Don't bundle a feature with unrelated cleanup
- Run
ruff check src/ tests/andpytestlocally before pushing — CI mirrors these - Open the PR with a body that covers: what changed, why, how to test, screenshots if UI
- Wait for review — single approval required to merge
- Squash merge is the default
Adding a new connector¶
The fastest path is to read postgres.py and clone its shape. Then:
- Create
src/scherlok/connectors/<name>.pyextendingBaseConnector - Register the scheme(s) in
src/scherlok/connectors/__init__.py; wrap the import intry/except ImportErrorif the driver is heavy - Add the optional dependency in
pyproject.tomlunder[project.optional-dependencies] - Add tests in
tests/test_<name>.pyusing mocks (see existing connector tests) - Document in the README's "Supported adapters" section
If your warehouse is one users wire up via dbt, add the adapter mapping in src/scherlok/dbt/profiles.py too.
Adding a new alerter¶
src/scherlok/alerter/ hosts webhook + email today. To add another channel:
- Create
src/scherlok/alerter/<name>.pywith asend_<name>(target, anomalies)function - Wire it into the dispatch path in
src/scherlok/cli.py(look for_dispatch_alerts) - Add tests with mocked HTTP / SMTP
Release process¶
For maintainers only:
- Bump the version in all four places:
versioninpyproject.toml,__version__insrc/scherlok/__init__.py,versionindbt_project.yml, and bothversionfields inserver.json(grep -rn "X.Y.Z"on the previous version to catch every one; a partial bump is how v1.0.0 never reached PyPI) - Move
[Unreleased]to[X.Y.Z] — YYYY-MM-DDinCHANGELOG.md - PR + merge to main
git tag vX.Y.Z && git push origin vX.Y.Z.github/workflows/release.ymlruns tests, publishes to PyPI via trusted publishing, creates GitHub Release with auto-extracted notes.github/workflows/publish-mcp.ymlthen publishesserver.jsonto the MCP Registry (GitHub OIDC). Check the listing at https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.rbmuller/scherlok; re-run it withgh workflow run publish-mcp.yml --ref mainif needed
Code of conduct¶
Be helpful. Assume good faith. Disagree on technical merits, not on people. Threads should leave both sides smarter than they entered.