Skip to main content

🐕 Hound

Hound watches the third-party APIs your code depends on, and tells you exactly when — and where — a change will break you.

CI PyPI License: MIT Python 3.10+

Most API changelogs are noise. A vendor renames a field, deprecates a param, or tightens a rate limit — and you find out in production, three weeks later, from a stack trace.

Hound doesn't just diff the spec. It cross-references every change against how your codebase actually calls that API, so you only get paged when something you use is actually affected — with the exact file and line to fix.

$ hound check

🐕 Hound found 1 breaking change

  stripe · /v1/charges
  ⚠ BREAKING: field `source` is being removed (deprecated since 2026-05-01)
  → used in src/services/payments/charge.py:42

  1 non-breaking change suppressed (run with --verbose to see all)

Table of contents


Why Hound

Every team that integrates a third-party API eventually gets burned by a silent change. The existing options are unsatisfying:

  • Do nothing — find out in production.
  • Watch the changelog manually — doesn't scale past 2–3 dependencies, and most changes don't matter to your usage.
  • Generic OpenAPI diff tools — tell you the spec changed, not whether your code is affected. Every run is noisy, so teams mute the alerts within a month.

Hound's premise: a change only matters if your code touches it. So it builds a map of what your codebase actually reads and writes on each API, and only raises an alert when a real change intersects that map.

How it works

┌─────────────────┐     ┌──────────────────┐     ┌───────────────────┐
│  Spec Fetcher    │────▶│   Diff Engine     │────▶│                   │
│ (OpenAPI/Swagger)│     │ (structural +     │     │                   │
└─────────────────┘     │  semantic)        │     │    Correlator     │────▶ Report
┌─────────────────┐     └──────────────────┘     │ (blast-radius      │    (GitHub Issue /
│  Usage Scanner   │────────────────────────────▶│  matching)         │     Slack / JSON)
│ (AST over your   │                              │                   │
│  codebase)        │                              └───────────────────┘
└─────────────────┘
  1. Fetch — pulls the current OpenAPI/Swagger spec (or scrapes changelog pages when no spec exists) and compares it against the last known-good snapshot stored in .hound/snapshots/.
  2. Diff — computes a structural diff (added/removed/renamed fields, changed required-ness, new deprecations, type changes) plus a semantic diff for prose-only changes (deprecation notices, rate-limit language) using sentence-embedding similarity.
  3. Scan — walks your codebase with AST parsing to build a usage table: every endpoint, field, and parameter your code actually touches, with file and line number.
  4. Correlate — intersects the diff against the usage table. Only intersecting changes are surfaced as actionable; everything else is available in verbose output but doesn't trigger a notification.
  5. Report — opens a GitHub Issue (or posts to Slack) with the exact change, severity, and the file:line that needs attention.

Install

pip install hound-watchdog

Or run without installing, via uvx:

uvx hound-watchdog check

Requires Python 3.10+.

Quick start

# 1. Initialize config in your repo
hound init

# 2. Add an API to watch
hound add stripe \
  --spec-url https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json \
  --scan-path src/services/payments/

# 3. Run a check
hound check

# 4. (optional) Set up scheduled watching via GitHub Actions
hound init --with-action

The first run establishes a baseline snapshot — no alerts fire. Every subsequent run diffs against that baseline and advances it once the diff is reported.

Configuration

hound.yaml, created by hound init:

version: 1

watch:
  - name: stripe
    spec_url: https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json
    scan_paths:
      - src/services/payments/
    language: python

  - name: github-api
    spec_url: https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json
    scan_paths:
      - src/integrations/github/
    language: python
    ignore_fields:
      - "*.deprecated_beta_field"   # explicitly acknowledged, don't re-alert

report:
  github_issues:
    enabled: true
    labels: ["hound", "dependency-risk"]
    assignees: []
  slack:
    enabled: false
    webhook_url: ${SLACK_WEBHOOK_URL}
  min_severity: breaking   # breaking | deprecation | non_breaking

llm:
  provider: openai          # openai | azure_openai | huggingface_local | none
  model: gpt-4o-mini
  api_key: ${OPENAI_API_KEY}
  # provider: none  -> disables prose summarization; structural diffs only

Config is validated against a versioned JSON schema on every run (hound validate), so a bad config fails fast in CI rather than silently skipping a watch target.

GitHub Action

Zero-infrastructure scheduled watching:

# .github/workflows/hound.yml
name: Hound API Watch
on:
  schedule:
    - cron: '0 9 * * 1'   # every Monday, 9am UTC
  workflow_dispatch: {}

jobs:
  watch:
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - uses: actions/checkout@v4
      - uses: your-org/hound-action@v1
        with:
          config: hound.yaml
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

CLI reference

Command Description
hound init Scaffold hound.yaml in the current repo
hound add <name> --spec-url <url> --scan-path <path> Register a new API to watch
hound check Run a full check: fetch, diff, scan, correlate, report
hound check --dry-run Run without writing reports or advancing the snapshot
hound check --verbose Show all changes, including non-breaking / unaffected ones
hound validate Validate hound.yaml against the config schema
hound baseline reset <name> Discard stored snapshot and re-baseline on next check
hound diff <name> Show the raw structural diff without running the correlator

Exit codes: 0 no breaking changes, 1 breaking change found, 2 config or fetch error — designed to gate CI pipelines.

Severity model

Severity Meaning Default action
breaking A field/endpoint your code uses was removed, renamed, or made incompatible Issue opened, CI can be gated to fail
deprecation A field/endpoint your code uses is marked deprecated but still functional Issue opened, non-blocking
non_breaking Spec changed but doesn't intersect your usage table Logged only, suppressed from notifications by default

Severity classification for structural changes is deterministic (rule-based on the OpenAPI diff). Severity for prose-only changes (rate limits, policy notices) is LLM-assisted and always shown with the source excerpt it was derived from, so you can verify the classification rather than trust it blindly.

Supported languages & API types

v1 (current):

  • Spec format: OpenAPI 3.x / Swagger 2.0
  • Codebase scanning: Python (requests, httpx, and popular SDK call patterns)

Planned (see Roadmap): TypeScript/JavaScript scanning, GraphQL schema diffing, docs-only (non-spec) API tracking via semantic diff.

If your API has no published spec, or your language isn't supported yet, Hound will tell you explicitly rather than silently skipping — check hound check --verbose output for unsupported_target warnings.

Architecture

hound/
├── hound/
│   ├── fetchers/
│   │   ├── openapi_fetcher.py     # spec retrieval + parsing
│   │   └── docs_fetcher.py        # fallback for non-spec APIs
│   ├── diffing/
│   │   ├── spec_diff.py           # structural diff
│   │   └── semantic_diff.py       # embedding-based diff for prose
│   ├── usage_scanner/
│   │   ├── ast_scanner.py         # AST walk for API call sites
│   │   └── field_extractor.py     # endpoint/field usage table
│   ├── correlator.py              # blast-radius matching
│   ├── reporter/
│   │   ├── github_issue.py
│   │   └── slack_notify.py
│   ├── store/
│   │   └── snapshot_store.py      # baseline persistence
│   └── agent.py                   # orchestration (fetch → diff → scan → correlate → report)
├── cli.py
├── configs/schema.json            # versioned config schema
└── tests/

Design principles:

  • Deterministic core, LLM-assisted edges. Structural diffing and correlation never depend on an LLM call — they work with llm.provider: none. The LLM only summarizes prose changes and drafts human-readable issue text.
  • Idempotent runs. Re-running hound check without a new spec change produces no duplicate issues; snapshot state is only advanced after a successful report.
  • Fails loud, not silent. Fetch failures, schema-validation failures, and unsupported targets all surface as explicit warnings/errors, never a quiet no-op.
  • No required external infra. Local snapshot storage by default (.hound/); S3/GCS backend is optional for teams running Hound centrally across many repos.

Comparison with other tools

Hound Generic OpenAPI diff Dependabot/Renovate
Detects spec changes ✅ ✅ ❌ (version bumps only)
Tells you your blast radius ✅ ❌ ❌
File:line of affected code ✅ ❌ ❌
Works with no spec (docs-only APIs) 🔜 planned ❌ ❌
Noise level Low (usage-filtered) High (alerts on every change) N/A

Roadmap

  • TypeScript/JavaScript AST scanning
  • GraphQL schema diffing
  • Docs-only API tracking (semantic diff without a formal spec)
  • Hosted mode (multi-repo dashboard, no self-managed cron)
  • VS Code extension surfacing warnings inline at the call site

Contributing

Issues and PRs welcome. Before opening a PR:

git clone https://github.com/8dazo/hound
cd hound
pip install -e ".[dev]"
pytest

See CONTRIBUTING.md for coding standards and how to add support for a new language scanner.

Security

Hound only reads public spec URLs and your local codebase — it never transmits your source code to an LLM provider; only extracted, minimal context (field names, endpoint paths) is sent when llm.provider is set to a hosted model. Set llm.provider: none or use huggingface_local for a fully offline run. Report vulnerabilities via SECURITY.md, not public issues.

License

MIT — see LICENSE.

Metadata

Release files for hound-watchdog 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hound-watchdog 0.1.0
File Size Uploaded
hound_watchdog-0.1.0.tar.gz 224.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hound-watchdog 0.1.0
File Interpreter ABI Platform
hound_watchdog-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 268.4 kB

Release files / hound_watchdog-0.1.0.tar.gz

Download URL hound_watchdog-0.1.0.tar.gz
Size 224.7 kB
Tags Source
SHA-256 checksum
How to use checksums
23a787528c01d7bd1442f981b717aca5ae83cc4e861f1824470177d68f31abc1
BLAKE2b-256 checksum
How to use checksums
375c72e4b4526e77a5e5bb84bdb5872990c6aeaa5451e18426cbc01597dc2759
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / hound_watchdog-0.1.0-py3-none-any.whl

Download URL hound_watchdog-0.1.0-py3-none-any.whl
Size 43.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
10504b61ff355708ee6547611a6661ccc169d32a06decd8c034929d3c2260395
BLAKE2b-256 checksum
How to use checksums
01d255db1d49d4ebbdcabe14e565dc9b289c7baf1cf919f4641c4d5fdaec98ed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page