Context
![ -f repomatic/__init__.py ] && echo "CANONICAL_REPO" || echo "DOWNSTREAM"
![ -d docs ] && echo "docs/ exists" || echo "No docs/ directory"
![ -f docs/conf.py ] && head -5 docs/conf.py || echo "No docs/conf.py"
!ls ../*/docs/conf.py 2>/dev/null | head -20 || echo "No sibling projects with docs/conf.py"
Instructions
You audit Sphinx documentation consistency against a reference: the upstream kdeldycke/repomatic canonical docs when run in a downstream repo, or sibling projects when run inside the canonical repo (see § Discover projects for how the reference is chosen). Find discrepancies in both directions: improvements this project can borrow from the reference, and improvements it can push back.
This skill is the procedure layer; the rule layer is .claude/agents/sphinx-docs.md. It carries the canonical conventions: {click:run} directives, recipes for configuration.md/cli.md/install.md, the standard page roster, conf.py hygiene, MyST/admonition rules, high-frequency lapses. When a discrepancy maps to a rule, cite the agent section so the user reads the rationale alongside the proposed change. When you find a pattern not yet codified, propose adding it to the agent rather than fixing it in each repo independently.
Discover projects
If $ARGUMENTS are provided, each argument is a local directory path or a GitHub repository URL (https://github.com/owner/repo or owner/repo). For GitHub URLs, clone into a tmpdir with gh repo clone.
When no $ARGUMENTS are given, the default reference depends on which repo you are in (the ## Context block reports CANONICAL_REPO or DOWNSTREAM):
DOWNSTREAM: compare this project's docs/ against the canonical kdeldycke/repomatic reference, cloned into a tmpdir with gh repo clone kdeldycke/repomatic. This is the "align me with the source of truth" default, mirroring how /repomatic-audit treats workflows and configs.
CANONICAL_REPO (you are inside kdeldycke/repomatic): comparing against kdeldycke/repomatic would diff the repo against itself, so scan the parent directory of the cwd for sibling projects with a docs/conf.py and push conventions outward to them instead.
When scanning siblings, filter out forks: check git remote get-url origin and skip projects whose upstream repo name doesn't match the directory name (a local click/ pointing to a fork of pallets/click). Focus on the user's own projects.
List the discovered projects (or the chosen reference) and confirm with the user before proceeding.
Collect documentation inventory
Build first, and count the warnings. A static read of conf.py and the page tree misses the findings that matter most, because nothing in the source says a module is documented twice or a cross-reference resolves nowhere. Run the project's own builder ([tool.repomatic] sphinx.builder, html unless set) into a scratch directory before touching anything, tally WARNING lines by shape, and keep the log: that baseline is what turns "this page repeats an automodule" into "192 duplicate object descriptions", and it is the only way to prove a proposed change inert. Re-run after applying and diff the distinct unresolved targets, not just the totals, since a count can hold steady while one warning replaces another. The venv usually already carries sphinx-build, so invoke it directly rather than syncing a dependency group and disturbing the project's environment. Settle any "is this setting still needed?" question with the same pair of builds: remove it, rebuild, compare.
For each project, collect (parallelize with sub-Agents when possible). For each artifact, the agent section in parentheses is where the convention lives — diff the project against that section, not against your own preferences.
docs/conf.py (agent § docs/conf.py hygiene, § Standard extension set). Read the full file. Surface settings present in some projects but missing from others; deprecated/renamed settings; conditional imports for Python versions below the project's floor; read_text() calls without encoding=. Cross-check the extension list against the canonical set; flag projects missing sphinx_issues, sphinxext.opengraph, or sphinxcontrib.mermaid that would benefit from them. Confirm myst_enable_extensions matches the canonical alphabetized list. Verify click_extra.sphinx.myst_docstrings ordering (must precede sphinx_autodoc_typehints) and corresponding click-extra[sphinx] entry in [dependency-groups] docs.
conf.py warning/strictness governance (agent § suppress_warnings governance, § nitpick_ignore governance, § Linkcheck and intersphinx). Audit each suppress_warnings, nitpick_ignore, and linkcheck_ignore entry: does it carry a comment naming the failing case and the reason for suppression? Flag uncommented entries. Re-test linkcheck-ignored hosts on each audit pass; remove entries that have started working again. Suggest migrating per-anchor linkcheck_anchors_ignore patterns to per-host linkcheck_anchors_ignore_for_url when the entire host is JS-rendered.
docs/index.md (agent § Standard page roster). Diff toctree shape, page ordering, octicon icons (cross-check against the canonical octicon registry), and presence/absence of standard pages.
docs/install.md (agent § Recipes › install.md). Diff section roster, install-method tab order, executables table format, Repology badge, Python compatibility matrix structure, gh attestation verify section.
docs/cli.md and docs/configuration.md (agent § Recipes). Diff the auto-region between markers, then compare the regenerator script (docs/docs_update.py) across the projects that still carry one. The agent's recipes render both pages live, so a project with no script has already migrated and is not missing anything.
- Auto-region marker naming (agent § Auto-generated reference tables, marker naming convention). Grep all
docs/*.md for <!-- start -->/<!-- end --> pairs; flag any bare markers, recommend renaming to <!-- {feature}-{kind}-start -->. Confirm that named markers across siblings use consistent {kind} slugs (table, sankey, mindmap, chart, autodata, automodule, autodoc, reference).
- Theme assets (agent §
conf.py hygiene › Theme assets and OpenGraph). Confirm the sidebar logo is Furo's light_logo/dark_logo pair in html_theme_options, each name also listed in html_static_path, with html_logo unset — Furo prefers html_logo and skips the pair when it is present, so a lingering html_logo is drift to report, never the thing to confirm. Confirm html_favicon = "assets/favicon.svg", and that ogp_image is an absolute raw.githubusercontent.com URL rather than a site-relative assets/... path (docs/assets/ is not copied into the built site, so a relative value 404s for social crawlers). Flag projects with sphinxext.opengraph enabled but no ogp_image set. Suggest the user run /brand-assets on flagged projects to regenerate or backfill the asset set in one pass.
sphinx_issues migration (agent § Migrating off sphinx_issues). Grep each project for {issue} /{pr} / {user} /{commit} (MyST) and :issue: /:pr: / :user: /:commit: (reST) across *.md, *.rst, *.py. Flag every occurrence and offer to apply the migration recipe in one pass per repo. After replacement, drop "sphinx_issues" from extensions in conf.py, "sphinx-issues>=…" from [dependency-groups] docs, and any issues_github_path setting unused by other extensions.
pyproject.toml docs dependency group. Compare against what conf.py actually imports — flag undeclared imports and declared-but-unimported deps. Don't change version pins unless provably stale (a conditional dep on a Python version below the project's floor; a transitively-constrained loose pin held by a meta-extra like click-extra[sphinx]).
readme.md. Compare badge sets and section structure. Flag a ## Development section when claude.md exists in the same repo (per agent § High-frequency lapses).
- Sphinx tests (agent § Sphinx tests). Look for
tests/sphinx/, tests/test_sphinx_*.py, or test_sphinx_crossrefs.py. Note which projects have render-tests and which don't; suggest adopting cross-reference render tests where the docs surface complex {role} cross-refs.
- Static assets and auto-generated files. Compare
docs/_static/, docs/assets/, .rst files, docs_update.py. Hunt for stale .rst orphans from past package renames.
Compare and report
Present findings as tables organized by category:
### Category name
| Issue | Severity | Direction | Projects |
|:------|:---------|:----------|:---------|
| description (cite agent § X) | bug/align/enhance | borrow/push | list |
Group, in this order:
- Bug fixes (stale deps, missing declared deps, broken links).
- Structural alignment (toctree, page naming,
conf.py settings).
- Content improvements (install.md sections, extra-deps tables, badges).
For each row, name the agent section that authorizes the change (e.g., "agent § Standard page roster: docs/subagents toctree entry missing"). If a discrepancy doesn't map to any agent section, flag it as a candidate for new agent content rather than a fix to push.
Implement
After presenting the report, ask the user which items to apply. When they confirm, group edits by project to minimize context switches.
Procedural guards
These are about how you run the audit, not what counts as a violation:
- Always verify file existence before recommending changes based on cross-project patterns. A "missing" file may not apply (e.g., shell completion only matters for CLI projects; binaries only for projects with
nuitka.enabled in [tool.repomatic]).
- When a dependency appears in multiple groups (main, extras, docs), the version may be intentionally loose in one group because it's transitively constrained. Verify before flagging.
- Respect project-specific opt-outs:
[tool.repomatic] exclude and include lists are authoritative. A page or component listed in exclude is intentionally absent.
- Never silently bump a version pin. Loose pins are sometimes intentional; tight pins always have a reason. Flag, don't fix.
- Adding a docs dependency to
pyproject.toml is half the change: every workflow here installs with uv run --frozen, so an unregenerated uv.lock fails the docs job on the next push. Re-lock in the same pass, with XDG_CONFIG_HOME pointed at an empty directory so a machine-wide uv.toml cannot write its own exclude-newer-package entries into the project's lockfile. Never reach for --no-config, which discards the project's [tool.uv] along with it.
- Before flagging download-URL or asset-name findings, list the real release assets (
gh release view {tag} --json assets). Releases in this lineage attach unversioned alias binaries alongside the version-stamped ones, so releases/latest/download/ links that look impossible against stamped filenames are in fact valid.
- A marker or format deviating from the current convention may already be self-healing: check the generator for a legacy-marker migration shim before reporting drift (repomatic's binaries page auto-migrates legacy
binaries-start and binaries-chart-start opens to the bare binaries-chart on next touch).
- Sandboxed sessions usually cannot re-test
linkcheck_ignore hosts: network allowlists make denials indistinguishable from real 403s. Hand the probe list to the user or defer to a local sphinx-build -b linkcheck run instead of silently skipping the re-test.
Next steps
Suggest the user run:
/repomatic-audit for broader workflow and config alignment across the same projects.
/repomatic-deps to analyze dependency graphs for projects with stale or divergent docs deps.
- Opting into the
sphinx-docs agent (repomatic init subagents/sphinx-docs) on any project that drifted significantly — Claude will then auto-load the conventions when working in that repo.
1---2name: sphinx-docs-sync3description: Compare and synchronize Sphinx documentation against the upstream `kdeldycke/repomatic` reference, or across sibling projects. Downstream repos compare against upstream by default. Find the differences in conf.py, install.md, the index.md toctree, pyproject.toml docs dependencies, extra-deps sections, readme badges and static assets. Use when you align documentation structure, catch stale dependencies, or push improvements across Sphinx-enabled repositories.4---56## Context78!`[ -f repomatic/__init__.py ] && echo "CANONICAL_REPO" || echo "DOWNSTREAM"`9!`[ -d docs ] && echo "docs/ exists" || echo "No docs/ directory"`10!`[ -f docs/conf.py ] && head -5 docs/conf.py || echo "No docs/conf.py"`11!`ls ../*/docs/conf.py 2>/dev/null | head -20 || echo "No sibling projects with docs/conf.py"`1213## Instructions1415You audit Sphinx documentation consistency against a reference: the upstream `kdeldycke/repomatic` canonical docs when run in a downstream repo, or sibling projects when run inside the canonical repo (see § Discover projects for how the reference is chosen). Find discrepancies in both directions: improvements this project can borrow from the reference, and improvements it can push back.1617**This skill is the procedure layer; the rule layer is `.claude/agents/sphinx-docs.md`.** It carries the canonical conventions: `{click:run}` directives, recipes for `configuration.md`/`cli.md`/`install.md`, the standard page roster, `conf.py` hygiene, MyST/admonition rules, high-frequency lapses. When a discrepancy maps to a rule, cite the agent section so the user reads the rationale alongside the proposed change. When you find a pattern not yet codified, propose adding it to the agent rather than fixing it in each repo independently.1819### Discover projects2021If `$ARGUMENTS` are provided, each argument is a local directory path or a GitHub repository URL (`https://github.com/owner/repo` or `owner/repo`). For GitHub URLs, clone into a tmpdir with `gh repo clone`.2223When no `$ARGUMENTS` are given, the default reference depends on which repo you are in (the `## Context` block reports `CANONICAL_REPO` or `DOWNSTREAM`):2425- **`DOWNSTREAM`**: compare this project's `docs/` against the canonical `kdeldycke/repomatic` reference, cloned into a tmpdir with `gh repo clone kdeldycke/repomatic`. This is the "align me with the source of truth" default, mirroring how `/repomatic-audit` treats workflows and configs.26- **`CANONICAL_REPO`** (you are inside `kdeldycke/repomatic`): comparing against `kdeldycke/repomatic` would diff the repo against itself, so scan the parent directory of the cwd for sibling projects with a `docs/conf.py` and push conventions outward to them instead.2728When scanning siblings, filter out forks: check `git remote get-url origin` and skip projects whose upstream repo name doesn't match the directory name (a local `click/` pointing to a fork of `pallets/click`). Focus on the user's own projects.2930List the discovered projects (or the chosen reference) and confirm with the user before proceeding.3132### Collect documentation inventory3334**Build first, and count the warnings.** A static read of `conf.py` and the page tree misses the findings that matter most, because nothing in the source says a module is documented twice or a cross-reference resolves nowhere. Run the project's own builder (`[tool.repomatic] sphinx.builder`, `html` unless set) into a scratch directory before touching anything, tally `WARNING` lines by shape, and keep the log: that baseline is what turns "this page repeats an `automodule`" into "192 duplicate object descriptions", and it is the only way to prove a proposed change inert. Re-run after applying and diff the distinct unresolved targets, not just the totals, since a count can hold steady while one warning replaces another. The venv usually already carries `sphinx-build`, so invoke it directly rather than syncing a dependency group and disturbing the project's environment. Settle any "is this setting still needed?" question with the same pair of builds: remove it, rebuild, compare.3536For each project, collect (parallelize with sub-Agents when possible). For each artifact, the agent section in parentheses is where the convention lives — diff the project against that section, not against your own preferences.3738- **`docs/conf.py`** (agent § `docs/conf.py` hygiene, § Standard extension set). Read the full file. Surface settings present in some projects but missing from others; deprecated/renamed settings; conditional imports for Python versions below the project's floor; `read_text()` calls without `encoding=`. Cross-check the extension list against the canonical set; flag projects missing `sphinx_issues`, `sphinxext.opengraph`, or `sphinxcontrib.mermaid` that would benefit from them. Confirm `myst_enable_extensions` matches the canonical alphabetized list. Verify `click_extra.sphinx.myst_docstrings` ordering (must precede `sphinx_autodoc_typehints`) and corresponding `click-extra[sphinx]` entry in `[dependency-groups] docs`.39- **`conf.py` warning/strictness governance** (agent § `suppress_warnings` governance, § `nitpick_ignore` governance, § Linkcheck and intersphinx). Audit each `suppress_warnings`, `nitpick_ignore`, and `linkcheck_ignore` entry: does it carry a comment naming the failing case and the reason for suppression? Flag uncommented entries. Re-test linkcheck-ignored hosts on each audit pass; remove entries that have started working again. Suggest migrating per-anchor `linkcheck_anchors_ignore` patterns to per-host `linkcheck_anchors_ignore_for_url` when the entire host is JS-rendered.40- **`docs/index.md`** (agent § Standard page roster). Diff toctree shape, page ordering, octicon icons (cross-check against the canonical octicon registry), and presence/absence of standard pages.41- **`docs/install.md`** (agent § Recipes › `install.md`). Diff section roster, install-method tab order, executables table format, Repology badge, Python compatibility matrix structure, gh attestation verify section.42- **`docs/cli.md` and `docs/configuration.md`** (agent § Recipes). Diff the auto-region between markers, then compare the regenerator script (`docs/docs_update.py`) across the projects that still carry one. The agent's recipes render both pages live, so a project with no script has already migrated and is not missing anything.43- **Auto-region marker naming** (agent § Auto-generated reference tables, marker naming convention). Grep all `docs/*.md` for `<!-- start -->`/`<!-- end -->` pairs; flag any bare markers, recommend renaming to `<!-- {feature}-{kind}-start -->`. Confirm that named markers across siblings use consistent `{kind}` slugs (`table`, `sankey`, `mindmap`, `chart`, `autodata`, `automodule`, `autodoc`, `reference`).44- **Theme assets** (agent § `conf.py` hygiene › Theme assets and OpenGraph). Confirm the sidebar logo is Furo's `light_logo`/`dark_logo` **pair** in `html_theme_options`, each name also listed in `html_static_path`, with `html_logo` **unset** — Furo prefers `html_logo` and skips the pair when it is present, so a lingering `html_logo` is drift to report, never the thing to confirm. Confirm `html_favicon = "assets/favicon.svg"`, and that `ogp_image` is an **absolute** `raw.githubusercontent.com` URL rather than a site-relative `assets/...` path (`docs/assets/` is not copied into the built site, so a relative value 404s for social crawlers). Flag projects with `sphinxext.opengraph` enabled but no `ogp_image` set. Suggest the user run `/brand-assets` on flagged projects to regenerate or backfill the asset set in one pass.45- **`sphinx_issues` migration** (agent § Migrating off `sphinx_issues`). Grep each project for `{issue}` `/`{pr}` ` / `{user}` `/`{commit}` ` (MyST) and `:issue:` `/`:pr:` ` / `:user:` `/`:commit:` ` (reST) across `*.md`, `*.rst`, `*.py`. Flag every occurrence and offer to apply the migration recipe in one pass per repo. After replacement, drop `"sphinx_issues"` from `extensions` in `conf.py`, `"sphinx-issues>=…"` from `[dependency-groups] docs`, and any `issues_github_path` setting unused by other extensions.46- **`pyproject.toml` docs dependency group**. Compare against what `conf.py` actually imports — flag undeclared imports and declared-but-unimported deps. Don't change version pins unless provably stale (a conditional dep on a Python version below the project's floor; a transitively-constrained loose pin held by a meta-extra like `click-extra[sphinx]`).47- **`readme.md`**. Compare badge sets and section structure. Flag a `## Development` section when `claude.md` exists in the same repo (per agent § High-frequency lapses).48- **Sphinx tests** (agent § Sphinx tests). Look for `tests/sphinx/`, `tests/test_sphinx_*.py`, or `test_sphinx_crossrefs.py`. Note which projects have render-tests and which don't; suggest adopting cross-reference render tests where the docs surface complex `{role}` cross-refs.49- **Static assets and auto-generated files**. Compare `docs/_static/`, `docs/assets/`, `.rst` files, `docs_update.py`. Hunt for stale `.rst` orphans from past package renames.5051### Compare and report5253Present findings as tables organized by category:5455```56### Category name5758| Issue | Severity | Direction | Projects |59|:------|:---------|:----------|:---------|60| description (cite agent § X) | bug/align/enhance | borrow/push | list |61```6263Group, in this order:64651. Bug fixes (stale deps, missing declared deps, broken links).662. Structural alignment (toctree, page naming, `conf.py` settings).673. Content improvements (install.md sections, extra-deps tables, badges).6869For each row, name the agent section that authorizes the change (e.g., "agent § Standard page roster: docs/subagents toctree entry missing"). If a discrepancy doesn't map to any agent section, flag it as a candidate for new agent content rather than a fix to push.7071### Implement7273After presenting the report, ask the user which items to apply. When they confirm, group edits by project to minimize context switches.7475### Procedural guards7677These are about *how* you run the audit, not what counts as a violation:7879- Always verify file existence before recommending changes based on cross-project patterns. A "missing" file may not apply (e.g., shell completion only matters for CLI projects; binaries only for projects with `nuitka.enabled` in `[tool.repomatic]`).80- When a dependency appears in multiple groups (main, extras, docs), the version may be intentionally loose in one group because it's transitively constrained. Verify before flagging.81- Respect project-specific opt-outs: `[tool.repomatic] exclude` and `include` lists are authoritative. A page or component listed in `exclude` is intentionally absent.82- Never silently bump a version pin. Loose pins are sometimes intentional; tight pins always have a reason. Flag, don't fix.83- Adding a docs dependency to `pyproject.toml` is half the change: every workflow here installs with `uv run --frozen`, so an unregenerated `uv.lock` fails the docs job on the next push. Re-lock in the same pass, with `XDG_CONFIG_HOME` pointed at an empty directory so a machine-wide `uv.toml` cannot write its own `exclude-newer-package` entries into the project's lockfile. Never reach for `--no-config`, which discards the project's `[tool.uv]` along with it.84- Before flagging download-URL or asset-name findings, list the real release assets (`gh release view {tag} --json assets`). Releases in this lineage attach unversioned alias binaries alongside the version-stamped ones, so `releases/latest/download/` links that look impossible against stamped filenames are in fact valid.85- A marker or format deviating from the current convention may already be self-healing: check the generator for a legacy-marker migration shim before reporting drift (repomatic's binaries page auto-migrates legacy `binaries-start` and `binaries-chart-start` opens to the bare `binaries-chart` on next touch).86- Sandboxed sessions usually cannot re-test `linkcheck_ignore` hosts: network allowlists make denials indistinguishable from real 403s. Hand the probe list to the user or defer to a local `sphinx-build -b linkcheck` run instead of silently skipping the re-test.8788### Next steps8990Suggest the user run:9192- `/repomatic-audit` for broader workflow and config alignment across the same projects.93- `/repomatic-deps` to analyze dependency graphs for projects with stale or divergent docs deps.94- Opting into the `sphinx-docs` agent (`repomatic init subagents/sphinx-docs`) on any project that drifted significantly — Claude will then auto-load the conventions when working in that repo.