# Sphinx Docs Sync

> 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.

- Skill: `kdeldycke/sphinx-docs-sync` (Agent Skill)
- Install (CLI): `npx skillmds@latest add kdeldycke/sphinx-docs-sync`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kdeldycke/sphinx-docs-sync/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: kdeldycke (https://skillmd.com/u/kdeldycke)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kdeldycke/sphinx-docs-sync

---


## 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:

1. Bug fixes (stale deps, missing declared deps, broken links).
2. Structural alignment (toctree, page naming, `conf.py` settings).
3. 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.

