Skip to main content

snippetdrift

snippetdrift keeps code snippets in your markdown documentation honest. It syncs source code directly into your docs and detects when those regions change — so you always know when documentation may have gone stale.


What it does

Add a sentinel comment above any fenced code block pointing to a source file and line range. snippetdrift will:

  1. Sync — copy those exact lines from the source file into the code block
  2. Hash — record a SHA-256 fingerprint of the region
  3. Check — on every subsequent run, recompute the hash and fail if the source has changed

The result: your docs always show real, current code, and CI tells you the moment a referenced region drifts.


Installation

# Recommended
uv tool install snippetdrift

# Or with pip
pip install snippetdrift

Quickstart

1. Add a sentinel comment above an empty code block

<!-- snippetdrift: src/api/models.py#L27-34 -->
```python

The path is relative to the repo root. The code block can be empty — `init` will fill it in.

### 2. Initialize: sync content + write hashes

```bash
snippetdrift init docs/

This copies the referenced source lines into the code block and writes the hash and today's date into the sentinel comment, in-place:

<!-- snippetdrift: src/api/models.py#L27-34 hash:a3f9b2c1 reviewed:2025-04-09 -->
```python
class IngestRequest(BaseModel):
    document_id: str
    content: str
    ...

Commit the updated markdown files.

### 3. Check for drift in CI

```bash
snippetdrift check docs/

Exit code 0 = all snippets match. Exit code 1 = drift detected.

4. When drift is detected

Review the diff that snippetdrift check prints, update any surrounding prose, then sync the new content and accept:

snippetdrift sync docs/          # pull current source lines into code blocks
snippetdrift accept docs/        # reset hashes, mark as reviewed today

Or, if you're happy to accept the source as-is without manual editing:

snippetdrift accept --sync docs/

Comment syntax reference

Field Description
src/api/models.py#L27-34 Path relative to repo root, with line range
hash:a3f9b2c1 First 8 hex chars of SHA-256 of the source lines (written by init/accept)
reviewed:2025-04-09T14:32:00 Datetime when the hash was last confirmed correct (written by init/accept)

CLI commands

Command Description
snippetdrift init [PATH] Sync source into code blocks + write hashes for uninitialized snippets. Use --no-sync to skip content sync.
snippetdrift sync [PATH] Copy current source lines into code blocks. Does not change hashes.
snippetdrift check [PATH] Detect drift. Exit 0 = ok, 1 = drift.
snippetdrift accept [PATH] Reset hashes after reviewing drift. Add --sync to also update code block content.
snippetdrift status [PATH] Show a summary table of all tracked snippets and their status.

All commands accept a path to a markdown file or directory (default: current directory, recursive).

snippetdrift accept also accepts --snippet <source-path> to scope acceptance to a single source file.

What each command touches

Code block content hash: in sentinel reviewed: in sentinel Cache
init ✅ (default, skip with --no-sync) ✅ written ✅ set to now ✅ written
sync ✅ updated ❌ ❌ ❌
check ❌ read-only ❌ read-only ❌ read-only ❌
accept ❌ (opt-in with --sync) ✅ recomputed ✅ set to now ✅ updated
status ❌ read-only ❌ read-only ❌ read-only ❌

The reviewed: timestamp is the human sign-off marker — only init and accept update it, because those are the points where someone confirms the documentation is correct.


Typical workflows

First time setup:

snippetdrift init docs/          # sync source into code blocks + write hashes
git add docs/
git commit -m "docs: initialize snippet hashes"

Day to day — source code changes:

# change source code
snippetdrift check docs/         # drift detected → exit 1
snippetdrift sync docs/          # pull new source lines into code blocks
# review the diff, edit surrounding prose if needed
snippetdrift accept docs/        # reset hashes, mark as reviewed
git add docs/
git commit -m "docs: accept drift in api_guide"

CI integration

name: Snippet Drift Check

on:
  push:
    branches: [main]
  pull_request:

jobs:
  snippetdrift:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v5
      - run: uv tool install snippetdrift
      - run: snippetdrift check docs/

Pre-commit with lefthook

A suggested lefthook.yml is included in this repo:

pre-commit:
  commands:
    snippetdrift:
      run: snippetdrift check {staged_files}
      glob: "*.md"

This is a suggestion — snippetdrift check on staged files only checks committed files. You may prefer to always run snippetdrift check docs/ unconditionally.


Cache

snippetdrift writes a .snippetdrift_cache/ directory at the repo root containing:

  • index.json — maps each sentinel to its full hash and metadata
  • snippets/<hash>.txt — the accepted source lines at the time of last accept, used to render diffs

The markdown file itself is the source of truth for the short hash. The cache is supplementary.

To commit or not: Committing the cache lets CI show rich diffs even on the first run after a drift. Excluding it means the cache is rebuilt locally on the next accept. Either works — add to .gitignore if you prefer not to commit it:

.snippetdrift_cache/

Contributing

uv sync --dev
uv run ruff check src/ tests/
uv run ruff format src/ tests/
uv run ty check src/
uv run pytest

Metadata

Release files for snippetdrift 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 snippetdrift 0.1.0
File Size Uploaded Provenance
snippetdrift-0.1.0.tar.gz 50.9 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 65.4 kB

Release files / snippetdrift-0.1.0.tar.gz

Download URL snippetdrift-0.1.0.tar.gz
Size 50.9 kB
Tags Source
SHA-256 checksum
How to use checksums
1c121de83c98a0f7f927b92dff46ccd974c804f511baf8eecd4fce2918dec64c
BLAKE2b-256 checksum
How to use checksums
e026c9b568d4444e251448bc238a09c8db6de1ad72359124e291eea1510eef41
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.8

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

Download URL snippetdrift-0.1.0-py3-none-any.whl
Size 14.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
21072ceda9edded4433bb7777403102710e8a7ac984e63e09ee7d366e7468f62
BLAKE2b-256 checksum
How to use checksums
eb04c06a2f9b6eb023d23ebbffc104ab0ea82d677f5f8766052553a9d07d1e70
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.8

Security for snippetdrift 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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