docpr

Documentation

Keep docs in sync with every merged PR

docpr analyzes your code changes with Claude, identifies affected documentation in a separate repo, and opens a pull request with the updates — automatically.

01 PR merges in your code repository.
02 LLM reads the diff and produces a structured change analysis.
03 Affected doc files are identified in your docs repo.
04 Updated content is generated preserving tone and structure.
05 A PR lands in your docs repo with changes linked back to the source.

Quick Start

Add this workflow to your source repository at .github/workflows/docpr.yml. The action triggers when a pull request is merged and handles everything else.

.github/workflows/docpr.yml
name: docpr

on:
  pull_request:
    types: [closed]

jobs:
  sync-docs:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - name: Sync documentation
        uses: peterj/docpr@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          docs_repo: "your-org/your-docs-repo"
          docs_repo_token: ${{ secrets.DOCS_REPO_TOKEN }}
          docs_path: "docs/"

Tip — You only need three secrets: an Anthropic API key and a GitHub token with write access to the docs repo. The source repo token defaults to github.token.

Inputs

Input Description Default
anthropic_api_key required Anthropic API key for Claude.
docs_repo required Documentation repository in owner/repo format.
docs_repo_token required GitHub token with contents: write and pull-requests: write on the docs repo.
docs_base_branch Base branch in the docs repo to branch from and PR into. main
docs_path Subdirectory to search for documentation files (e.g. docs/ or content/). ""
source_repo_token Token for reading the source repository. github.token
model Claude model to use for analysis and generation. claude-opus-4-5
max_doc_files Maximum number of doc files to fetch and analyze. Controls token usage on large doc repos. 20
pr_label Label applied to created documentation PRs. docpr

Outputs

Output Description
docs_pr_url URL of the created documentation PR. Empty if no changes were needed.
updated_files JSON array of updated file paths, e.g. ["docs/api.md","docs/config.md"].

Full Example

A complete workflow showing all optional inputs and a follow-up step that reports results.

.github/workflows/docpr.yml
name: docpr

on:
  pull_request:
    types: [closed]

jobs:
  sync-docs:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - name: Sync documentation
        id: sync-docs
        uses: peterj/docpr@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          docs_repo: "your-org/your-docs-repo"
          docs_repo_token: ${{ secrets.DOCS_REPO_TOKEN }}
          docs_base_branch: "main"
          docs_path: "docs/"
          model: "claude-opus-4-5"
          max_doc_files: "20"
          pr_label: "docpr"

      - name: Report result
        if: always()
        run: |
          PR_URL="${{ steps.sync-docs.outputs.docs_pr_url }}"
          FILES="${{ steps.sync-docs.outputs.updated_files }}"
          if [ -n "$PR_URL" ]; then
            echo "Documentation PR created: $PR_URL"
            echo "Updated files: $FILES"
          else
            echo "No documentation updates needed."
          fi

How It Works

When a pull request is merged, docpr runs a seven-step pipeline. Each step can exit early if no documentation changes are needed.

01

Fetch the PR diff

Retrieves the unified diff of the merged pull request. Large diffs are truncated to 80,000 characters (keeping head and tail) to control token usage.

02

Analyze changes

Claude reads the diff along with the PR title and body, and produces a structured analysis covering API changes, behavior changes, new features, deprecations, configuration changes, and documentation impact.

03

List documentation files

Fetches the file tree from your docs repo and filters for supported documentation formats. If docs_path is set, only files under that directory are considered. Results are capped at max_doc_files.

04

Identify relevant docs

Claude reviews the change analysis against the list of doc file paths and returns a JSON array of files that need updating.

05

Fetch file contents

Loads the full content of each identified documentation file from the docs repo.

06

Generate updates

For each file, Claude generates an updated version that reflects the code changes while preserving tone and structure. If the updated content is significantly shorter than the original, a warning is flagged for human review.

07

Create the docs PR

A new branch is created in the docs repo (docpr/pr-{number}-{title}-{timestamp}), the updated files are committed, and a pull request is opened with a summary of what changed and why.

Supported Formats

docpr scans your docs repo for files matching these extensions:

  • .md — Markdown
  • .mdx — MDX (Markdown + JSX)
  • .rst — reStructuredText
  • .txt — Plain text
  • .adoc / .asciidoc — AsciiDoc

Token Usage

docpr makes three separate Claude calls per run (analysis, doc matching, and one generation call per file). Two controls help manage cost:

  • max_doc_files — limits how many files are fetched and passed to the matching step. Default is 20.
  • Diff truncation — diffs longer than 80,000 characters are automatically trimmed, keeping both the beginning and end of the diff.

Note — Each documentation file that needs updating triggers its own Claude call (max 4,096 tokens per file). Repos with many affected docs will use more tokens.

Permissions

Source repository

The workflow needs contents: read to allow the action to fetch the PR diff. The default github.token is sufficient.

Documentation repository

The docs_repo_token must have:

  • contents: write — to create branches and commit files
  • pull-requests: write — to open and label pull requests

Tip — A fine-grained personal access token scoped to just the docs repo is the most secure approach.

Trigger events

The action supports both pull_request and pull_request_target event types. It verifies that the PR was actually merged before proceeding.