Pin your docs to your code. Prevent documentation drift by linking Markdown to code blocks.
Project description
docpin
Prevent documentation drift by linking Markdown files to specific code.
docpin tracks code references in your documentation and alerts you when the code changes but the docs haven't been updated. Perfect for CI/CD pipelines to catch stale docs before they reach production.
Pin your docs to your code.
Installation
pip install docpin
Or install from source:
git clone https://github.com/matthieudesprez/docpin.git
cd docpin
pip install -e .
Quick Start
1. Reference Code in Your Docs
In your Markdown files, add pin references to code:
# Authentication
The login function handles user authentication:
[pin:src/auth.py:10-25]
For the full module, see:
[pin:src/auth.py]
2. Record the Current State
docpin record
This updates your markdown files in-place with content hashes:
[pin:src/auth.py:10-25 @a1b2c3d4e5f6g7h8]
3. Check for Drift
docpin check
If any referenced code has changed since the last record, docpin will:
- List all stale documentation references
- List any unrecorded references (missing hashes)
- Exit with code 1 (useful for CI/CD)
Reference Syntax
| Syntax | Description |
|---|---|
[pin:path/to/file.py] |
Track entire file |
[pin:path/to/file.py:42] |
Track single line |
[pin:path/to/file.py:42-58] |
Track line range |
[pin:path/to/file.py#function_name] |
Track function by name |
[pin:path/to/file.py#ClassName] |
Track class by name |
[pin:path/to/file.py#ClassName.method] |
Track method by name |
[pin:path/to/file.py#CONSTANT] |
Track top-level variable |
After recording, hashes are appended inline: [pin:path/to/file.py:42-58 @a1b2c3d4]
Symbol References (Python only)
Symbol references let you track code by name instead of line numbers. This is more resilient to code changes that shift line numbers:
The authentication is handled by the login function:
[pin:src/auth.py#login]
The `Auth` class manages user sessions:
[pin:src/auth.py#Auth]
Specifically, the logout method:
[pin:src/auth.py#Auth.logout]
Symbol references support:
- Functions (sync and async)
- Classes
- Methods (including nested classes)
- Top-level variables and constants
- Decorated functions and classes (includes decorator lines)
How It Works
┌─────────────────────────────────────────────────────────────────────┐
│ SETUP PHASE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ docs/auth.md src/auth.py │
│ ┌────────────────────────┐ ┌────────────────────────┐ │
│ │ ## Login Flow │ │ 10: def login(user): │ │
│ │ │ │ 11: validate(user) │ │
│ │ [pin:src/auth.py:10-15] ───────▶│ 12: token = gen() │ │
│ │ │ │ 13: return token │ │
│ │ The login function... │ │ ... │ │
│ └────────────────────────┘ └────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────┐
│ docpin record │
└────────┬─────────┘
│ hashes lines 10-15
▼
┌──────────────────────────────────┐
│ docs/auth.md (updated in-place) │
│ [pin:src/auth.py:10-15 @a1b2] │
└──────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ CHECK PHASE (CI/CD) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Developer changes src/auth.py line 12: │
│ │
│ - token = gen() │
│ + token = generate_secure_token() │
│ │
│ ┌──────────────────┐ ┌─────────────────────────────────────┐ │
│ │ docpin check │────▶│ ⚠ Stale: docs/auth.md:5 │ │
│ └──────────────────┘ │ [pin:src/auth.py:10-15] │ │
│ │ │ Exit code: 1 │ │
│ ▼ └─────────────────────────────────────┘ │
│ CI fails ❌ │
│ │
└─────────────────────────────────────────────────────────────────────┘
Integration
docpin check is a single command that exits non-zero on stale docs. Wire it in wherever you run other checks.
GitHub Actions:
- name: Check documentation freshness
run: |
pip install docpin
docpin check
GitLab CI:
docs-check:
script:
- pip install docpin
- docpin check
Makefile:
check-docs:
docpin check docs/
Pass a path to scope the check (e.g. docpin check docs/) if you only want to scan part of the repo.
Commands
| Command | Description |
|---|---|
docpin record |
Scan docs and record hashes of referenced code inline |
docpin check |
Compare current code against recorded hashes |
docpin status |
Show status of all tracked references |
Why docpin?
- Zero source code changes - References live in your docs, not your code
- No extra files - Hashes are stored inline in your markdown
- Simple syntax - Just
[pin:file:lines]in Markdown - CI/CD ready - Exit code 1 on stale docs
- Lightweight - No dependencies, pure Python
License
MIT
Project details
Release history Release notifications | RSS feed
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 docpin-1.0.0.tar.gz.
File metadata
- Download URL: docpin-1.0.0.tar.gz
- Upload date:
- Size: 16.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb1b663c3876aa1b0ef2b5654edeb3eaf50e37cf11c604f7b7c9688746a60721
|
|
| MD5 |
74f2cfde604e075dea94078a0a36b72b
|
|
| BLAKE2b-256 |
a92a6e97d07292f267ef13f24fc2b22a6268381dd902601c2504da42782ca188
|
Provenance
The following attestation bundles were made for docpin-1.0.0.tar.gz:
Publisher:
release-please.yml on matthieudesprez/docpin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
docpin-1.0.0.tar.gz -
Subject digest:
fb1b663c3876aa1b0ef2b5654edeb3eaf50e37cf11c604f7b7c9688746a60721 - Sigstore transparency entry: 1470699779
- Sigstore integration time:
-
Permalink:
matthieudesprez/docpin@71c5783bb43994c587e9c8c7b7abd9ff330d4592 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/matthieudesprez
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@71c5783bb43994c587e9c8c7b7abd9ff330d4592 -
Trigger Event:
push
-
Statement type:
File details
Details for the file docpin-1.0.0-py3-none-any.whl.
File metadata
- Download URL: docpin-1.0.0-py3-none-any.whl
- Upload date:
- Size: 18.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6250844e2a1b2f8a1b0497ed77807ae23af8ea0443435ac6bdca67497106871
|
|
| MD5 |
b99872d57637c5892821c7c82768d4df
|
|
| BLAKE2b-256 |
dfc736d1a67a5b31c0ff8c3979b8fed101ed0e2436bef7926d4a2834c43fa1c1
|
Provenance
The following attestation bundles were made for docpin-1.0.0-py3-none-any.whl:
Publisher:
release-please.yml on matthieudesprez/docpin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
docpin-1.0.0-py3-none-any.whl -
Subject digest:
e6250844e2a1b2f8a1b0497ed77807ae23af8ea0443435ac6bdca67497106871 - Sigstore transparency entry: 1470700175
- Sigstore integration time:
-
Permalink:
matthieudesprez/docpin@71c5783bb43994c587e9c8c7b7abd9ff330d4592 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/matthieudesprez
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@71c5783bb43994c587e9c8c7b7abd9ff330d4592 -
Trigger Event:
push
-
Statement type: