docvet
[](https://github.com/Alberto-Codes/docvet/actions/workflows/ci.yml)
[](https://codecov.io/gh/Alberto-Codes/docvet)
[](https://pypi.org/project/docvet/)
[](https://pypi.org/project/docvet/)
[](https://github.com/Alberto-Codes/docvet/blob/main/LICENSE)
[](https://renovatebot.com)
[](https://github.com/astral-sh/ruff)
[](https://github.com/Alberto-Codes/docvet)
# docvet
**Better docstrings, better AI.**
## Why docvet?
ruff checks how your docstrings look. interrogate checks if they exist (but is unmaintained). docvet checks if they're right — and now covers presence too. Existing tools cover style; docvet delivers the layers they miss:
| Layer | Check | ruff | interrogate | pydoclint | **docvet** |
|-------|-------|------|-------------|-----------|------------|
| 1. Presence | "Does a docstring exist?" | -- | Yes (unmaintained) | -- | **Yes** |
| 2. Style | "Is it formatted correctly?" | Yes | -- | -- | -- |
| 3. Completeness | "Does it have all required sections?" | -- | -- | Partial | **Yes** |
| 4. Accuracy | "Does it match the current code?" | -- | -- | -- | **Yes** |
| 5. Rendering | "Will mkdocs render it correctly?" | -- | -- | -- | **Yes** |
| 6. Visibility | "Will mkdocs even see the file?" | -- | -- | -- | **Yes** |
**pydoclint** covers 3 structural categories (Args, Returns, Raises). docvet's enrichment alone has 20 rules, including Raises, Yields, Receives, Warns, Attributes, Examples, cross-references, parameter agreement, and more. Add presence (coverage metrics + threshold enforcement), freshness (git diff/blame staleness detection), griffe rendering compatibility, and mkdocs coverage: 31 rules across 5 checks, in territory no other tool touches.
**[Quickstart](#quickstart)** | **[GitHub Action](#github-action)** | **[Pre-commit](#pre-commit)** | **[Configuration](#configuration)** | **[AI Agent Integration](#ai-agent-integration)** | **[Docs](https://alberto-codes.github.io/docvet/)**
## What It Checks
**Presence** (existence) -- 2 rules:
`missing-docstring` `overload-has-docstring`
**Enrichment** (completeness) -- 20 rules:
`missing-raises` `missing-returns` `missing-yields` `missing-receives` `missing-warns` `missing-deprecation` `missing-param-in-docstring` `extra-param-in-docstring` `missing-other-parameters` `missing-attributes` `undocumented-init-params` `missing-typed-attributes` `missing-examples` `missing-cross-references` `extra-raises-in-docstring` `extra-yields-in-docstring` `extra-returns-in-docstring` `missing-return-type` `trivial-docstring` `prefer-fenced-code-blocks`
**Freshness** (accuracy) -- 5 rules:
`stale-signature` `stale-body` `stale-import` `stale-drift` `stale-age`
**Griffe** (rendering) -- 3 rules:
`griffe-unknown-param` `griffe-missing-type` `griffe-format-warning`
**Coverage** (visibility) -- 1 rule:
`missing-init`
## Quickstart
```bash
pip install docvet && docvet check --all
```
For optional griffe rendering checks:
```bash
pip install docvet[griffe]
```
Example output:
```
src/mypackage/helpers.py:1: missing-docstring Module has no docstring [required]
src/mypackage/utils.py:42: missing-raises Function 'parse_config' raises ValueError but has no Raises section [required]
src/mypackage/models.py:15: stale-signature Function 'process' signature changed but docstring not updated [required]
src/mypackage/api.py:1: missing-init Package directory missing __init__.py (invisible to mkdocs) [required]
```
## Configuration
Configure via `[tool.docvet]` in your `pyproject.toml`. All checks run and print findings. Checks listed in `fail-on` cause a non-zero exit code; unlisted checks are treated as warnings.
A check in `fail-on` that cannot run — most often `griffe` without the `docvet[griffe]` extra — never certified the gate you configured, so docvet reports it on stderr and exits 1. With `--format json` the `run` object reports `status: "unavailable"` and an `unavailable_checks` array, which is what distinguishes it from a gate that found problems. Set `fail-on-unavailable = false` (or pass `--no-fail-on-unavailable`) to warn and exit 0 instead. Unavailable checks that nothing gates on stay a quiet skip — though `fail-on` membership is not the only thing that gates: a `min-coverage` floor gates `presence` without naming it there.
```toml
[tool.docvet]
exclude = ["tests", "scripts"]
fail-on = ["griffe", "coverage"]
[tool.docvet.freshness]
drift-threshold = 30
age-threshold = 90
```
## Pre-commit
Add to your `.pre-commit-config.yaml`:
```yaml
repos:
- repo: https://github.com/Alberto-Codes/docvet
rev: v1.2.0
hooks:
- id: docvet
```
For griffe rendering checks, add the optional dependency:
```yaml
repos:
- repo: https://github.com/Alberto-Codes/docvet
rev: v1.2.0
hooks:
- id: docvet
additional_dependencies: [griffe]
```
## GitHub Action
Add docvet to your GitHub Actions workflow — findings appear as inline annotations on your PR:
```yaml
- uses: Alberto-Codes/docvet@v1
```
Select specific checks or pin a version:
```yaml
- uses: Alberto-Codes/docvet@v1
with:
checks: 'enrichment,freshness'
docvet-version: '1.9.0'
python-version: '3.13'
```
The griffe rendering check needs no setup: the action installs `docvet[griffe]`, pinned or not, so every check the `checks` input offers is available. Note that docvet releases before 1.7.0 declare that extra without an upper bound, so pinning one installs whatever griffe publishes at the time rather than a version docvet was released against.
> **Behavior change — this can turn a passing build red.**
>
> Earlier releases installed plain `docvet`, so the griffe check was skipped and contributed zero findings. It now runs. `determine_run_outcome` (`src/docvet/reporting.py`) returns exit code 1 as soon as any check listed in `fail-on` reports findings, so if your `pyproject.toml` has `griffe` in `[tool.docvet] fail-on`, your build goes from green to failing with no change on your side. This repository's own `ci.yml` docvet job is exactly such a consumer.
>
> These are not new problems — it is the check finally running on docstrings that were always broken. To get back to green, fix the griffe findings or remove `griffe` from `fail-on`.
## AI Agent Integration
For tool-specific integration snippets, see the [full AI Agent Integration guide](https://alberto-codes.github.io/docvet/ai-integration/).
Add docvet to your AI coding workflow. Drop this into your `CLAUDE.md`, `.cursorrules`, or agent configuration:
```markdown
## Docstring Quality
After modifying Python functions, classes, or modules, run `docvet check` and fix all findings before committing.
```
Recommended `pyproject.toml` configuration:
```toml
[tool.docvet]
fail-on = ["enrichment", "freshness", "coverage", "griffe"]
```
### Subcommand Quick Reference
| Command | Description |
|---------|-------------|
| `docvet check` | Run all enabled checks (default: git diff files) |
| `docvet check --all` | Run all checks on entire codebase |
| `docvet check --staged` | Run all checks on staged files only |
| `docvet presence` | Check for missing docstrings with coverage metrics |
| `docvet enrichment` | Check for missing docstring sections |
| `docvet freshness` | Detect stale docstrings via git |
| `docvet freshness --mode drift` | Sweep for long-stale docstrings via git blame |
| `docvet coverage` | Find files invisible to mkdocs |
| `docvet griffe` | Check mkdocs rendering compatibility |
| `docvet fix` | Scaffold missing docstring sections |
| `docvet fix --dry-run` | Preview scaffolding changes without writing files |
| `docvet config` | Show effective configuration with source annotations |
| `docvet lsp` | Start LSP server for real-time editor diagnostics |
| `docvet mcp` | Start MCP server for AI agent integration |
## Better Docstrings, Better AI
AI coding agents rely on docstrings as context when generating and modifying code. Agents modify code but often leave docstrings stale, and research shows stale or incorrect documentation is actively harmful, worse than no docs at all:
- Incorrect docs [degrade LLM task success by 22.6 percentage points](https://arxiv.org/abs/2404.03114)
- Comment density [improves code generation by 40-54%](https://arxiv.org/abs/2402.13013)
- Misleading comments [reduce LLM fault localization accuracy to 24.55%](https://arxiv.org/abs/2504.04372)
- Performance [drops substantially without docstrings](https://arxiv.org/abs/2508.09537)
As the [2025 DORA report](https://cloud.google.com/resources/content/2025-dora-ai-assisted-software-development-report) puts it: "AI doesn't fix a team; it amplifies what's already there." The [only signal correlating with AI productivity is code quality](https://stackoverflow.blog/2026/02/04/code-smells-for-ai-agents-q-and-a-with-eno-reyes-of-factory).
docvet's freshness checking catches the accuracy gap that stale docs create, and its enrichment rules ensure the docstring sections that agents use as context are complete. Run `docvet check` in your CI, pre-commit hooks, or agent toolchain.
## Badge
Add a badge to your project to show your docs are vetted:
```markdown
[](https://github.com/Alberto-Codes/docvet)
```
## Used By
Are you using docvet? Open a pull request to add your project here.
## License
MIT -- see [LICENSE](https://github.com/Alberto-Codes/docvet/blob/main/LICENSE) for details.
mcp-name: io.github.Alberto-Codes/docvet
TDQS
Scored across 2 tools
The two tools serve clearly distinct purposes: docvet_check executes checks and returns findings, while docvet_rules lists rule metadata and fix guidance. There is no overlap, and the check tool explicitly points to the rules tool for next steps.
Both tools use a consistent snake_case pattern with the shared 'docvet_' prefix. However, the second parts differ in form ('check' is an action, 'rules' is a resource), which is a minor deviation from a pure verb_noun convention.
Two tools are slightly under the typical 3-15 range, but each earns its place in this narrow, well-scoped docstring-checking domain. The check tool is feature-rich, so the set does not feel arbitrarily thin.
The core workflow—run checks, then look up rule guidance—is fully covered, and the check tool handles configuration errors gracefully. Minor gaps exist, such as no direct auto-fix or fix-application tool, but these are not essential for the stated purpose.