Setting up¶
Warning
sphinx-redline is an early alpha release. The comment file format and the settings below may still change.
Setting up commenting for a documentation project has four parts:
Install the extension and enable it in
conf.py.Create a branch that holds the comments.
Choose how readers sign in.
Make the documentation build fetch the comments.
Install¶
Install it from PyPI:
pip install sphinx-redline
sphinx-redline needs Python 3.12 or newer and Sphinx 9.1 or newer. It works
with the HTML builders (html and dirhtml); other builders, such as
LaTeX for PDF output, are left untouched.
Then add it to conf.py:
extensions = [
# ...
"sphinx_redline",
]
With only this, the extension shows existing comments but readers cannot add new ones. The settings below turn on commenting.
Where comments are stored¶
Each comment is a small JSON file under comments/ on a git branch,
redline by default. The branch holds nothing else, so it starts empty.
Create it once:
git switch --orphan redline
git commit --allow-empty -m "Start the comments branch"
git push origin redline
git switch main
The branch can be in the documentation repository itself or in a separate repository. A separate repository is the safer choice when guests may comment (see Guest passphrase below): the token that saves comments then cannot touch the documentation sources.
Settings¶
Setting |
Default |
Meaning |
|---|---|---|
|
|
|
|
|
The repository holding the comments branch: |
|
|
The branch new comments are committed to. |
|
|
The forge’s web address, for GitHub Enterprise or a self-hosted GitLab,
for example |
|
|
The encrypted token for guest sign-in; see Guest passphrase. |
|
|
The application ID for “Sign in with GitLab”; see Sign in with GitLab. |
|
|
The git ref the build reads comments from. It must be available in the checkout the documentation is built from; see Building with comments. |
|
|
A link template to view the commented source, with the placeholders
|
A complete example for a GitHub-hosted project with comments in a separate repository:
import os
redline_forge = "github"
redline_repository = "owner/docs-comments"
redline_guest_key = os.environ.get("REDLINE_GUEST_KEY")
redline_comments_ref = "refs/redline/comments"
redline_source_url = "https://github.com/owner/docs/blob/{commit}/{path}#L{first}-L{last}"
Signing in¶
Saving a comment needs a token that may commit to the comments branch. sphinx-redline offers two ways for readers to get one without running any extra service. Both can be enabled at once.
Guest passphrase¶
The site owner provides one token for all guests, encrypted with a passphrase. Anyone who knows the passphrase can comment under a name of their choice.
Create a token that can write to the comments repository and nothing else:
- GitHub
A fine-grained personal access token (Settings → Developer settings → Fine-grained tokens) with access to only the comments repository and the permission Contents: Read and write.
- GitLab
A project access token on the comments project, with the role Developer and the scope api.
Open the guest key tool, which is published with every site that uses sphinx-redline at
_static/redline/keytool.html(for example this site’s key tool). Enter the token and a passphrase and copy the resulting key. Nothing you enter there is sent anywhere.Set the key as
redline_guest_key, typically from an environment variable set by CI. The key is published in every page, so it may be stored as a plain CI variable rather than a secret.Give the passphrase to the people who should be able to comment.
Important
Everyone who knows the passphrase can extract the token from the page and use it directly. That is why the token must be limited to the comments:
On GitHub, a fine-grained token cannot be limited to one branch. If the comments branch is in the documentation repository itself, the token can also push to your other branches. Either use a separate comments repository, or protect the default branch with a ruleset that has an empty bypass list: rulesets apply to the repository owner, and so to the owner’s tokens, unless the owner is on that list. A second ruleset that blocks force pushes and deletion of the comments branch keeps a token holder from erasing comments, while still allowing new ones. This repository uses the second approach.
On GitLab, the default branch is protected against Developer pushes by default, so a project token with the Developer role can only push to unprotected branches such as the comments branch.
The encrypted key is public, so a short passphrase could be guessed offline. The key tool enforces at least 16 characters; its Generate button creates a random one. To revoke guest access, delete the token and publish a new key with a new passphrase.
Sign in with GitLab¶
Readers who have an account on the GitLab instance sign in on GitLab’s own login page, and their comments carry their GitLab name.
Note
This mode, and guest mode on GitLab, are tested against a local GitLab CE (version 19.4), but not yet on gitlab.com or in production use. Please report how it works for you.
In GitLab, create an OAuth application (User settings → Applications, or for a group: Group settings → Applications):
Redirect URI: the root address of your documentation site, for example
https://docs.example.com/. Every page sends readers back there after signing in.Confidential: unchecked. A browser cannot keep a secret; sign-in uses PKCE instead.
Scopes:
api. GitLab has no narrower scope that allows creating files through the API.
Set
redline_gitlab_client_idto the application ID.
Readers need at least the Developer role on the comments project to save
comments. The api scope gives the page a token with the reader’s full
API access for about two hours; it is kept in the browser tab’s session
storage and never sent anywhere except to GitLab.
“Sign in with GitHub” is not offered: GitHub’s login endpoint does not allow requests from a web page, so it would need a server of its own.
Building with comments¶
The build reads comments from the git ref in redline_comments_ref and
uses the git history to follow comments to their current place. In CI that
means:
check out the full history (
fetch-depth: 0withactions/checkout), andfetch the comments branch before building.
For comments in the documentation repository itself:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Fetch comments
run: git fetch --no-tags origin redline:refs/remotes/origin/redline || true
For comments in a separate repository, fetch from there and set
redline_comments_ref = "refs/redline/comments":
- name: Fetch comments
run: git fetch --no-tags https://github.com/owner/docs-comments.git redline:refs/redline/comments || true
Nothing is fetched automatically: a local build shows the comments of
whatever origin/redline your last git fetch got.
New comments appear for everyone after the next build. The author sees their own new comments right away, marked “saved, not yet built”. To rebuild the documentation whenever a comment arrives, add a workflow on the comments branch that starts the documentation workflow:
# .github/workflows/rebuild-docs.yml on the redline branch
name: rebuild-docs
on:
push:
branches: [redline]
permissions:
actions: write
jobs:
dispatch:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- run: gh workflow run docs.yml --repo "$GITHUB_REPOSITORY" --ref main
env:
GH_TOKEN: ${{ github.token }}
The documentation workflow needs a workflow_dispatch trigger for this.
For a separate comments repository, a scheduled documentation build (for
example hourly) is the simplest alternative.
If a comment file is malformed, or the comments ref is missing, the build
logs it and carries on without failing, so -W builds are not affected.