Skip to content

Usage

ope redline ROOT --from-commit REF [--to-commit REF] [OPTIONS]
ope redline ROOT --from-path PATH [OPTIONS]

ROOT is the folder to compare, the same folder ope export takes, or a single note. With --from-commit, the command must run inside the git repository that holds ROOT, and both commits must be in its history. With --from-path, ROOT is the newer version on disk and PATH the older one, and no git is needed (see Without git).

cd MyVault                      # anywhere inside the repository
ope redline ./Handbook --from-commit v1.0.0

Flags

Flag Default Meaning
--from-commit REF The older version, the baseline, as a git commit.
--to-commit REF HEAD The newer version, as a git commit.
--from-path PATH The older version as a folder or note on disk; ROOT on disk is the newer one. Not together with --from-commit, --to-commit or --blame.
-o PATH, --output PATH ./.export/<title>_redline.pdf Where the PDF goes. .export/ is made in the current folder.
-t TEXT, --title TEXT the folder name, or the note name Title on the first page and in the header.
--subtitle TEXT Changes from <from> to <to> Replaces the subtitle. The version label in the footer keeps the hashes (or the names of the two folders or notes).
-T NAME\|PATH, --template NAME\|PATH redline Another template, see Styling the redline.
-O redline.style=STYLE blackline blackline or side-by-side, see Styles and options.
-O redline.collapse=on off Show only the changes and the headings of their sections.
-O KEY=VALUE, --option KEY=VALUE Other options for steps, plugins and the template, as for export.
--blame off A strip next to every page with the author, date and commit message of each changed block, see Blame. Needs --from-commit.
--disable-plugin NAME Skip a plugin in both versions.
--toc/--no-toc --toc Table of contents at the start.
--debug off Keep the build folder _build_<name>/ next to the PDF, with redline_assembled.md (the diffed Markdown) and redline_final.html.

export flags that have no meaning for a redline, such as --version, --date, --include and --exclude, are not available. The date in the footer is the day of the export. The full list is in the CLI reference.

Which versions

--from-commit and --to-commit take tags, branches, commit hashes and relative refs such as HEAD~3. Both sides are read from git, so uncommitted changes are not included. When ROOT does not exist in one of the two commits, that side counts as empty: a folder that is new since --from-commit comes out as one big insertion. Comparing versions has the details: releases, pull requests and the history of one note.

--from-path compares two folders or two notes on disk instead, without git:

ope redline ./Handbook --from-path ./archive/Handbook

Output name and title block

Without -o, the PDF is ./.export/<title>_redline.pdf, for example .export/Handbook_redline.pdf. With --title "Team handbook" it is .export/Team handbook_redline.pdf. With . as ROOT the title is the name of the current folder.

The title block names the two versions as they were given, and the footer has the short hashes and the date:

Handbook
Changes from v1.0.0 to HEAD

--subtitle "Changes since release 1.0" replaces the second line. The change summary below the title lists both commits with their hashes, dates and authors, and the commits in between.

One document or a whole folder

ROOT decides what is compared. A folder with subfolders gives one redline of the whole document, with all sections and one table of contents. A section folder gives a redline of that section alone.

ope redline ./Handbook --from-commit v1.0.0                  # the whole handbook
ope redline ./Handbook/Security --from-commit v1.0.0         # one section

A redline for each top-level folder:

for folder in Policies/*/; do
  ope redline "$folder" --from-commit v1.0.0 -o "out/$(basename "$folder") redline.pdf"
done

In CI

The checkout needs the history of both commits, so set fetch-depth: 0. Install ope and its native libraries the same way as for exports in CI.

A redline for every pull request

This workflow builds the redline of a pull request against the point where it left the base branch, uploads it as an artifact and links it in a comment on the pull request:

.github/workflows/redline-pr.yml
name: Redline

on:
  pull_request:
    paths:
      - "Handbook/**"

permissions:
  contents: read
  pull-requests: write

jobs:
  redline:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # both commits must be in the history
      - uses: astral-sh/setup-uv@v6
      - run: uv tool install obsidian-pdf-exporter
      - run: ope setup --yes

      - name: Build the redline
        env:
          BASE_REF: ${{ github.base_ref }}
          HEAD_SHA: ${{ github.event.pull_request.head.sha }}
        run: |
          base=$(git merge-base "origin/$BASE_REF" "$HEAD_SHA")
          ope redline ./Handbook --from-commit "$base" --to-commit "$HEAD_SHA" -o redline.pdf

      - name: Upload the PDF
        id: upload
        uses: actions/upload-artifact@v4
        with:
          name: redline
          path: redline.pdf

      - name: Link the PDF in the pull request
        env:
          GH_TOKEN: ${{ github.token }}
          PR: ${{ github.event.pull_request.number }}
          URL: ${{ steps.upload.outputs.artifact-url }}
        run: |
          gh pr comment "$PR" --repo "$GITHUB_REPOSITORY" --body "Redline PDF of this pull request: $URL"

The token of a pull request from a fork cannot write comments. For those, keep the upload step and drop the comment step.

A redline attached to every release

This workflow runs when a release is published. It compares the tag of the release with the tag before it and attaches the PDF to the release:

.github/workflows/redline-release.yml
name: Redline release

on:
  release:
    types: [published]

permissions:
  contents: write # to upload the PDF to the release

jobs:
  redline:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # all tags and their history
      - uses: astral-sh/setup-uv@v6
      - run: uv tool install obsidian-pdf-exporter
      - run: ope setup --yes

      - name: Build the redline against the previous release
        env:
          TAG: ${{ github.event.release.tag_name }}
        run: |
          previous=$(git describe --tags --abbrev=0 "$TAG^")
          ope redline ./Handbook --from-commit "$previous" --to-commit "$TAG" \
            --subtitle "Changes from $previous to $TAG" -o "Handbook $TAG redline.pdf"

      - name: Attach the PDF to the release
        env:
          GH_TOKEN: ${{ github.token }}
          TAG: ${{ github.event.release.tag_name }}
        run: gh release upload "$TAG" "Handbook $TAG redline.pdf" --repo "$GITHUB_REPOSITORY"