{"id":397280,"date":"2026-11-02T10:41:01","date_gmt":"2026-11-02T10:41:01","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/patchmark\/"},"modified":"2026-11-04T13:53:10","modified_gmt":"2026-11-04T13:53:10","slug":"patchmark","status":"publish","type":"plugin","link":"https:\/\/bre.wordpress.org\/plugins\/patchmark\/","author":23591328,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.1.0","stable_tag":"1.1.0","tested":"7.1.4","requires":"6.6","requires_php":"7.4","requires_plugins":null,"header_name":"Patchmark","header_author":"CC Software","header_description":"See exactly what a plugin zip changes before it replaces the installed copy: files, risky code, changelog and removed functions.","assets_banners_color":"787c81","last_updated":"2026-11-04 13:53:10","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/ClearanceClarence-Software\/Patchmark","header_author_uri":"https:\/\/github.com\/ClearanceClarence-Software","rating":0,"author_block_rating":0,"active_installs":0,"downloads":288,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"cccode","date":"2026-11-02 10:40:49","revision":3779576},"1.1.0":{"tag":"1.1.0","author":"cccode","date":"2026-11-04 13:53:10","revision":3784067}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3779574,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3779574,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3779574,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3779574,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3779574,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3784068,"resolution":false,"location":"assets","locale":"","contents":"{\"$schema\":\"https:\\\/\\\/playground.wordpress.net\\\/blueprint-schema.json\",\"meta\":{\"title\":\"Patchmark sample review\",\"description\":\"Opens Patchmark's sample review in Tools \\u203a Patchmark: a made-up plugin's update, with findings, diffs, changelog and API changes.\",\"author\":\"cccode\"},\"landingPage\":\"\\\/wp-admin\\\/tools.php?page=patchmark&review=demo\",\"preferredVersions\":{\"php\":\"8.3\",\"wp\":\"latest\"},\"features\":{\"networking\":true},\"steps\":[{\"step\":\"login\",\"username\":\"admin\",\"password\":\"password\"},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"patchmark\"},\"options\":{\"activate\":true}}]}"}},"all_blocks":[],"tagged_versions":["1.0.0","1.1.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3784067,"resolution":"1","location":"assets","locale":"","width":1440,"height":900},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3784067,"resolution":"2","location":"assets","locale":"","width":1440,"height":900},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3784067,"resolution":"3","location":"assets","locale":"","width":1440,"height":900},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3784067,"resolution":"4","location":"assets","locale":"","width":1440,"height":900},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3784067,"resolution":"5","location":"assets","locale":"","width":1440,"height":900},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3784067,"resolution":"6","location":"assets","locale":"","width":1440,"height":900}},"screenshots":{"1":"The review: what changes, most serious first, linked to files and lines.","2":"The file browser with a split diff and word highlights.","3":"Changelog entries between the two versions, with the upgrade notice.","4":"API changes: removed and added functions, hooks and routes, and bundled libraries.","5":"Tools \u203a Patchmark: installed plugins checked against WordPress.org's checksums.","6":"Reviewing an update from WordPress.org before installing it, in the dark theme."}},"plugin_section":[],"plugin_tags":[290263,9151,173015,3998,600],"plugin_category":[54],"plugin_contributors":[289578],"plugin_business_model":[],"class_list":["post-397280","plugin","type-plugin","status-publish","hentry","plugin_tags-code-review","plugin_tags-diff","plugin_tags-integrity","plugin_tags-plugin-update","plugin_tags-security","plugin_category-security-and-spam-protection","plugin_contributors-cccode","plugin_committers-cccode"],"banners":{"banner":"https:\/\/ps.w.org\/patchmark\/assets\/banner-772x250.png?rev=3779574","banner_2x":"https:\/\/ps.w.org\/patchmark\/assets\/banner-1544x500.png?rev=3779574","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/patchmark\/assets\/icon.svg?rev=3779574","icon":"https:\/\/ps.w.org\/patchmark\/assets\/icon.svg?rev=3779574","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/patchmark\/assets\/screenshot-1.png?rev=3784067","caption":"The review: what changes, most serious first, linked to files and lines."},{"src":"https:\/\/ps.w.org\/patchmark\/assets\/screenshot-2.png?rev=3784067","caption":"The file browser with a split diff and word highlights."},{"src":"https:\/\/ps.w.org\/patchmark\/assets\/screenshot-3.png?rev=3784067","caption":"Changelog entries between the two versions, with the upgrade notice."},{"src":"https:\/\/ps.w.org\/patchmark\/assets\/screenshot-4.png?rev=3784067","caption":"API changes: removed and added functions, hooks and routes, and bundled libraries."},{"src":"https:\/\/ps.w.org\/patchmark\/assets\/screenshot-5.png?rev=3784067","caption":"Tools \u203a Patchmark: installed plugins checked against WordPress.org's checksums."},{"src":"https:\/\/ps.w.org\/patchmark\/assets\/screenshot-6.png?rev=3784067","caption":"Reviewing an update from WordPress.org before installing it, in the dark theme."}],"raw_content":"<!--section=description-->\n<p>When you upload a zip for a plugin or theme that is already installed, WordPress shows a small table (name, version, author, requirements) and a button to replace it. Patchmark takes over that screen and turns it into a proper review, with Cancel and Replace in its top bar. When there are serious findings, Replace takes a second click.<\/p>\n\n<p>The same review is available in three more places:<\/p>\n\n<ul>\n<li><strong>Updates from WordPress.org.<\/strong> Every update row on the Plugins screen gets a <strong>Review the changes first<\/strong> link. Patchmark downloads the update, compares it with what you have, and puts <strong>Update<\/strong> in its top bar.<\/li>\n<li><strong>Integrity check.<\/strong> Tools \u203a Patchmark checks installed plugins against the checksums WordPress.org publishes for every version it hosts, and lists files that were modified, added or deleted since installation. <strong>See what changed<\/strong> opens a full review of your copy against WordPress.org's original.<\/li>\n<li><strong>WP-CLI.<\/strong> <code>wp patchmark diff<\/code>, <code>wp patchmark update<\/code> and <code>wp patchmark check<\/code> print the same findings as a table, JSON or Markdown, and exit with status 1 on serious findings, for deploy scripts and CI.<\/li>\n<\/ul>\n\n<h4>Review<\/h4>\n\n<p>Everything worth a second look, most serious first, each linked to the exact file and line:<\/p>\n\n<ul>\n<li><strong>Header changes<\/strong>: older version than installed, same version with different files, a different plugin name or author, a new <strong>Update URI<\/strong> (future updates would come from somewhere else), new requirements, missing required plugins, a renamed main file (the plugin would be deactivated), a changed text domain.<\/li>\n<li><strong>Unusual files<\/strong>: .htaccess and .user.ini, PHP files with odd extensions (.phtml, .phar, image.jpg.php), PHP in image or font folders, executables and shell scripts, bundled archives.<\/li>\n<li><strong>Risky code<\/strong> that is new in the upload: eval and decode-and-run, shell commands, includes and unserialize of request data, long encoded strings, names hidden in \\x escapes or chr() chains, minified PHP, code that creates users or roles or grants capabilities, browser beacons, new outgoing requests and new web addresses.<\/li>\n<li><strong>What it adds to the site<\/strong>: new scheduled events, database tables and admin screens.<\/li>\n<li><strong>Themes<\/strong>: a parent theme that isn't installed, a changed parent theme, and whether the theme (or its parent) is the one visitors see.<\/li>\n<\/ul>\n\n<p>PHP is read with the tokenizer, so <code>$db-&gt;exec()<\/code> or \"eval\" in a comment is not mistaken for the real thing, and only code that was not in the installed copy of the same file is reported.<\/p>\n\n<h4>Files<\/h4>\n\n<ul>\n<li>A folder tree of every added, removed, modified, moved and whitespace-only file, with line counts.<\/li>\n<li>Split or unified diffs with syntax highlighting (PHP, JavaScript, TypeScript, CSS, SCSS, JSON, HTML, YAML, SQL, Markdown and more), word highlights, folded context you can expand, and an option to ignore whitespace.<\/li>\n<li>Before and after previews for images.<\/li>\n<li>Filter by name or status, search inside the changed files, and step through files with j and k.<\/li>\n<li><strong>Download .patch<\/strong>: a git-style patch of the text changes that <code>git apply<\/code> applies to the installed copy.<\/li>\n<\/ul>\n\n<h4>Changelog<\/h4>\n\n<p>The entries from readme.txt (or CHANGELOG.md) between the installed and the uploaded version, plus the Upgrade Notice for the new version. For a downgrade, the entries you would give up.<\/p>\n\n<h4>API changes<\/h4>\n\n<p>Functions, classes, public methods, hooks, REST routes, shortcodes, post types, blocks, scheduled events, admin screens, database tables, options and capabilities the new version adds or removes, plus Composer libraries that are added, removed or updated. Removed names are what breaks themes, snippets and other plugins that rely on them.<\/p>\n\n<h4>Export<\/h4>\n\n<p>Save any review as an HTML report (opens in any browser, prints to PDF), as Markdown for a ticket or pull request, or as a .patch. It is built in your browser from what is already on the page.<\/p>\n\n<h4>Dark theme<\/h4>\n\n<p>One click in the top bar. The choice is saved for your user and applies on every screen Patchmark shows.<\/p>\n\n<h4>Light<\/h4>\n\n<p>Nothing runs on the front end. On the upload screen Patchmark only steps in when the plugin or theme is already installed, and only files that changed are read. Reviews are never stored: leaving the page discards them. The only thing saved is your light or dark choice, as user meta.<\/p>\n\n<p>A clean review is not a guarantee. Only install code from sources you trust.<\/p>\n\n<h3>External services<\/h3>\n\n<p>Patchmark contacts WordPress.org only when you ask it to, and only downloads.wordpress.org:<\/p>\n\n<ul>\n<li><strong>Review the changes first<\/strong> downloads the update package WordPress has already found for that plugin (the same URL WordPress would install from).<\/li>\n<li><strong>Check<\/strong> and <strong>Check all plugins<\/strong> on Tools \u203a Patchmark download the checksum list for each plugin's installed version from <code>https:\/\/downloads.wordpress.org\/plugin-checksums\/&lt;slug&gt;\/&lt;version&gt;.json<\/code>.<\/li>\n<li><strong>See what changed<\/strong> downloads WordPress.org's zip of the installed version from <code>https:\/\/downloads.wordpress.org\/plugin\/&lt;slug&gt;.&lt;version&gt;.zip<\/code>.<\/li>\n<\/ul>\n\n<p>The requests carry the plugin slug and version in the address, and the headers WordPress sends with every request it makes (including your site's address in the user agent). Nothing about your site's content or users is sent. WordPress.org's terms: https:\/\/wordpress.org\/about\/privacy\/<\/p>\n\n<h3>Development<\/h3>\n\n<p>The files in build\/ are compiled from TypeScript and SCSS but not minified, so you can read them as they are.<\/p>\n\n<p>The source code and build setup are on GitHub: https:\/\/github.com\/ClearanceClarence-Software\/Patchmark<\/p>\n\n<p>To build it yourself you need Node 20 or newer:<\/p>\n\n<pre><code>npm ci\nnpm run build\n\nnpm run zip makes the same plugin zip that's published here.&lt;h3&gt;Credits&lt;\/h3&gt;\n<\/code><\/pre>\n\n<p>Patchmark bundles the Bricolage Grotesque font (Copyright 2022 The Bricolage Grotesque Project Authors) and the Atkinson Hyperlegible Next and Atkinson Hyperlegible Mono fonts (Copyright 2020-2024 The Atkinson Hyperlegible Next \/ Mono Project Authors), all licensed under the SIL Open Font License 1.1. The license texts are in the licenses\/ folder. The fonts are served from the plugin folder, not from Google.<\/p>\n\n<p>Syntax highlighting uses Prism (https:\/\/prismjs.com), MIT license, bundled with the plugin.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate Patchmark.<\/li>\n<li>Upload a zip of a plugin or theme you already have installed (<strong>Plugins \u203a Add New \u203a Upload Plugin<\/strong>, or <strong>Appearance \u203a Themes \u203a Add New \u203a Upload Theme<\/strong>), or click <strong>Review the changes first<\/strong> next to a plugin update.<\/li>\n<li>Read the review, then choose <strong>Replace<\/strong> or <strong>Update<\/strong>, or <strong>Cancel<\/strong>, in its top bar.<\/li>\n<li>To check installed plugins against WordPress.org, go to <strong>Tools \u203a Patchmark<\/strong>.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"can%20i%20try%20it%20without%20a%20zip%3F\"><h3>Can I try it without a zip?<\/h3><\/dt>\n<dd><p>Yes. Tools \u203a Patchmark \u203a <strong>See a sample review<\/strong> builds a review of a made-up plugin's update in a temporary folder and removes it again. Nothing is installed. The <strong>Live Preview<\/strong> button on this page opens the same sample in WordPress Playground.<\/p><\/dd>\n<dt id=\"where%20are%20the%20settings%3F\"><h3>Where are the settings?<\/h3><\/dt>\n<dd><p>There are none. The review appears on the upload screen when it has something to compare, and the integrity check is under Tools \u203a Patchmark.<\/p><\/dd>\n<dt id=\"does%20it%20work%20for%20themes%3F\"><h3>Does it work for themes?<\/h3><\/dt>\n<dd><p>Yes, for theme zips you upload. Update reviews and the integrity check are for plugins, since WordPress.org only publishes checksums for plugins.<\/p><\/dd>\n<dt id=\"which%20plugins%20can%20the%20integrity%20check%20verify%3F\"><h3>Which plugins can the integrity check verify?<\/h3><\/dt>\n<dd><p>Plugins hosted on WordPress.org, at a version WordPress.org still has. Premium plugins and plugins from GitHub show as \"can't check\"; review their updates by uploading the zip.<\/p><\/dd>\n<dt id=\"how%20do%20i%20use%20it%20from%20the%20command%20line%3F\"><h3>How do I use it from the command line?<\/h3><\/dt>\n<dd><p>wp patchmark diff woocommerce ~\/woocommerce.9.4.0.zip\n    wp patchmark diff .\/old-folder .\/new.zip --format=markdown &gt; review.md\n    wp patchmark update akismet --fail-on=warn\n    wp patchmark check --all --diff<\/p>\n\n<p>Each side of <code>diff<\/code> can be a folder, a zip, or the folder name of an installed plugin or theme. <code>--format<\/code> is table, json or markdown. The commands exit with status 1 when there are serious findings (or, for <code>check<\/code>, changed plugins).<\/p><\/dd>\n<dt id=\"how%20large%20a%20plugin%20can%20it%20handle%3F\"><h3>How large a plugin can it handle?<\/h3><\/dt>\n<dd><p>Plugins with up to 20,000 files. A plugin like Formidable Forms (about 1,800 files, 29 MB) is compared in well under a second. Files over 512 KB, and anything past 8 MB of changed text, are compared and checked but their contents are not shown, to keep the page light.<\/p><\/dd>\n<dt id=\"is%20the%20code%20check%20a%20malware%20scanner%3F\"><h3>Is the code check a malware scanner?<\/h3><\/dt>\n<dd><p>No. It points at changes worth reading. It can't prove a plugin is safe, and it reports things that are normal in some plugins (a membership plugin creates users).<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>New: themes. Uploading a zip for an installed theme gets the same review, with checks for a missing or changed parent theme and the active theme.<\/li>\n<li>New: review updates from WordPress.org before installing them, from a link in each update row on the Plugins screen.<\/li>\n<li>New: Tools \u203a Patchmark checks installed plugins against WordPress.org's checksums, and compares a changed plugin with WordPress.org's original.<\/li>\n<li>New: WP-CLI commands <code>wp patchmark diff<\/code>, <code>update<\/code> and <code>check<\/code>, with table, JSON and Markdown output and an exit status for CI.<\/li>\n<li>New: export a review as an HTML report or Markdown, next to the .patch download.<\/li>\n<li>New: dark theme, saved per user.<\/li>\n<li>New checks: names hidden in escapes or chr() chains, minified PHP, preg_replace \/e, strrev, add_cap(), navigator.sendBeacon(), and new scheduled events, database tables and admin screens.<\/li>\n<li>API changes now also list scheduled events, admin screens, database tables, options and capabilities.<\/li>\n<li>New: a sample review under Tools \u203a Patchmark, and a Live Preview in WordPress Playground.<\/li>\n<li>A translation template is included, ready for translate.wordpress.org.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First release: takes over the \"already installed\" upload screen with a review, a file browser with split and unified diffs, the changelog in between and API changes.<\/li>\n<\/ul>","raw_excerpt":"See what a plugin or theme zip, or an update, changes before it replaces the installed copy. Check plugins against WordPress.org.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/397280","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=397280"}],"author":[{"embeddable":true,"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/cccode"}],"wp:attachment":[{"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=397280"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=397280"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=397280"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=397280"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=397280"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/bre.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=397280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}