thunderbird-patch-review

Easy-to-use patch review interface for Thunderbird

Contribute: ~marcc/thunderbird-review-plugin@lists.sr.ht

git clone git://mccd.space/thunderbird-patch-review

patch-review.1 (6952B)

      1 .TH PATCH\-REVIEW 1 "July 2026" "patch-review 0.1.0" "Thunderbird Patch Review"
      2 .SH NAME
      3 patch\-review \- review git patches from email inside Thunderbird
      4 .SH SYNOPSIS
      5 A Thunderbird MailExtension.
      6 Open a patch email, press
      7 .BR Review ,
      8 comment on hunks, send the review as a mailing-list reply, and apply the
      9 series to a local repository with
     10 .BR git\-am (1).
     11 .SH DESCRIPTION
     12 .B patch\-review
     13 brings a review interface to git-by-email workflows
     14 .RB ( git\-send\-email (1)
     15 style).
     16 When the selected messages (or thread) look like a patch \(em a
     17 .B [PATCH]
     18 subject tag or a unified diff in the body \(em the
     19 .B Review
     20 button in the main toolbar becomes active.
     21 It opens a dedicated review tab that shows the whole series:
     22 cover letter, per-patch commit messages, and every file and hunk rendered
     23 as a colored diff.
     24 Within replaced lines, the span that actually changed gets a stronger
     25 highlight, computed from the common prefix and suffix of each
     26 deleted/added line pair.
     27 .PP
     28 Clicking a diff line attaches an inline comment to it; comments are saved
     29 as drafts (keyed by Message-ID) and survive restarting Thunderbird.
     30 .B Send review
     31 turns the comments of each commented patch into one plain-text reply-to-all,
     32 quoting the relevant hunks kernel-style with the comments interleaved
     33 unquoted below the lines they target, and sends the replies immediately;
     34 the draft comments are then cleared and the review tab closes.
     35 The attached drop-down offers
     36 .I "Preview in compose"
     37 instead, which leaves the reply drafts open in compose windows.
     38 A reply that fails to send also stays open, so nothing is lost.
     39 .B Apply series
     40 runs
     41 .B git am \-\-3way
     42 on the raw patch messages in the configured repository.
     43 On conflict
     44 .B git am \-\-abort
     45 is run and its output reported, leaving the repository untouched.
     46 Its drop-down offers
     47 .I "Modify and apply"
     48 \(em apply, then open the touched files in your editor \(em and
     49 .I "Download patchset"
     50 \(em save the raw series as one mbox file, ready for
     51 .BR "git am" .
     52 .SH INSTALLATION
     53 Package the extension as an
     54 .B .xpi
     55 and install it via the Add-ons Manager gear menu
     56 .RB ( "Install Add-on From File..." ).
     57 From the project root:
     58 .RS
     59 .PP
     60 (cd extension && zip -qrX ../patch\-review.xpi .)
     61 .RE
     62 .PP
     63 The subshell runs the
     64 .BR zip (1)
     65 from inside
     66 .I extension/
     67 so the archive holds
     68 .B manifest.json
     69 at its root, not under
     70 .IR extension/ .
     71 .BR git (1)
     72 is a dependency (for
     73 .BR Apply ).
     74 For development, instead pick
     75 .IR "Tools \(-> Developer Tools \(-> Debug Add\-ons \(-> Load Temporary Add\-on..." ,
     76 and select
     77 .BR extension/manifest.json ;
     78 it is dropped on restart.
     79 .SH CONFIGURATION
     80 Open the extension's preferences:
     81 .TP
     82 .B Editor command
     83 Run from the repository after a successful apply, with the changed files as
     84 arguments.
     85 Use a non-blocking GUI-capable command such as
     86 .B code \-n
     87 or
     88 .BR "emacsclient \-n" ;
     89 a bare terminal editor has no terminal to open in.
     90 Empty means
     91 .BR $EDITOR .
     92 .TP
     93 .B Apply strategy
     94 .B git am \-\-3way
     95 (default) or plain
     96 .BR "git am" .
     97 .TP
     98 .B Repository mappings
     99 Substring matches against a patch's List-Id header or sender, mapped to an
    100 absolute repository path.
    101 When no mapping matches, the last path a series was applied to is used;
    102 it is remembered until changed.
    103 .PP
    104 Repository paths can be chosen with the
    105 .B Browse
    106 button, which opens Thunderbird's native directory chooser; the path field
    107 stays editable either way.
    108 .SH PERMISSIONS
    109 The extension requests the fewest permissions it needs;
    110 none are granted to remote content.
    111 .TP
    112 .B messagesRead
    113 Reads the selected message and its sibling patches in the same folder
    114 (subject, author, body) to build the review.
    115 .TP
    116 .B accountsRead
    117 Resolves the default identity of the account that owns the reviewed
    118 message, for the From-address label and send-as.
    119 .TP
    120 .B storage
    121 Persists draft comments (keyed by Message-ID) across restarts,
    122 plus the editor command, apply strategy, repo mappings, and the last
    123 applied repository path.
    124 .TP
    125 .BR compose , " (compose.send)"
    126 Opens reply-to-all compose windows from
    127 .B "Send review"
    128 and sends them in
    129 .I "Send now"
    130 mode.
    131 Without
    132 .B compose.send
    133 the review can only be previewed in compose, never sent.
    134 .TP
    135 .B downloads
    136 Writes the
    137 .I "Download patchset"
    138 .B .mbox
    139 to disk.
    140 .TP
    141 .B tabs
    142 Opens the review tab and removes it after a successful send.
    143 .PP
    144 The privileged
    145 .BR Apply ,
    146 .IR "Browse... " ,
    147 and
    148 .I "Open editor"
    149 code does not use a Mozilla permission:
    150 it is a WebExtension Experiment
    151 .RB ( experiment_apis.patchHost )
    152 shipped inside the XPI and runs only when the extension is loaded.
    153 .SH SOURCEHUT INTEGRATION
    154 When the series arrives via a sourcehut mailing list (a
    155 .B lists.sr.ht
    156 address in the List-Id or recipients), the review tab shows a
    157 .B "set status"
    158 checkbox with the patchset states sourcehut understands:
    159 APPROVED, NEEDS_REVISION, REJECTED, PROPOSED, SUPERSEDED, APPLIED.
    160 When enabled, the first reply of the review carries an
    161 .B X\-Sourcehut\-Patchset\-Update
    162 header with the chosen status, which sourcehut applies to the patchset.
    163 A status can also be sent without any line comments \(em
    164 .B Send review
    165 then sends a single, empty reply to the cover letter (or first patch)
    166 carrying just the header.
    167 .SH REVIEW WORKFLOW
    168 .nf
    169 1. Select any message of the series \(em or the whole
    170    thread \(em and press Review in the main toolbar.
    171 2. The tab collects the sibling patches from the same folder
    172    (same series tag, version, and patch count).
    173 3. Click lines, write comments; Ctrl+Enter saves.
    174    "Comment on patch" attaches a general remark instead.
    175 4. Send review: one reply per commented patch, sent
    176    immediately (or use the drop-down to preview first).
    177 5. Apply series: git am into the mapped repository,
    178    then Open editor on the touched files.
    179 .fi
    180 .SH FILES
    181 .TP
    182 .I extension/
    183 The MailExtension (manifest v2, vanilla ES modules, no build step).
    184 .TP
    185 .I extension/api/patchHost/
    186 The privileged part (a WebExtension Experiment): runs
    187 .BR git\-am (1)
    188 and the editor through Thunderbird's Subprocess API and shows the
    189 directory chooser with nsIFilePicker.
    190 Everything outside this directory runs as ordinary sandboxed WebExtension
    191 code.
    192 .TP
    193 .I tests/
    194 .B node tests/run.mjs
    195 exercises the pure modules (subject parsing, diff parsing, reply
    196 formatting) against fixtures generated by
    197 .BR git\-format\-patch (1),
    198 and checks the experiment's manifest wiring.
    199 Regenerate fixtures with
    200 .BR tests/gen\-fixtures.sh .
    201 .SH CAVEATS
    202 Patches arriving as attachments, HTML-only mail, and reviewing from a git
    203 worktree preview are not supported yet.
    204 Series collection searches the folder of the opened message only.
    205 .SH SEE ALSO
    206 .PP
    207 The introductory post can be found at
    208 .MT https://mccd.space/posts/26-07-18/3-patch-review-tool-for-thunderbird
    209 .ME
    210 .SH CONTRIBUTING
    211 Disclaimer: this plugin was vibe coded \(em written by an AI agent under
    212 human direction.
    213 .PP
    214 Contributions and bug reports go to the mailing list:
    215 .MT ~marcc/thunderbird\-review\-plugin@lists.sr.ht
    216 .ME 
    217 .SH AUTHOR
    218 Marc Coquand
    219 .MT marc@coquand.email
    220 .ME