{"id":371870,"date":"2026-09-21T07:33:48","date_gmt":"2026-09-21T07:33:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/revision-autopilot\/"},"modified":"2026-09-21T07:55:01","modified_gmt":"2026-09-21T07:55:01","slug":"revision-autopilot","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/revision-autopilot\/","author":23518353,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.2.0","stable_tag":"0.2.0","tested":"7.1.1","requires":"6.9","requires_php":"8.1","requires_plugins":null,"header_name":"Revision Autopilot","header_author":"Takahiro Nishii","header_description":"Exposes post revision cleanup as machine-readable abilities and WP-CLI commands, so agents and scripts can measure and reclaim revision bloat without a human clicking through wp-admin.","assets_banners_color":"363b42","last_updated":"2026-09-21 07:55:01","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/takahiro-nishii.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":50,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.1.0":{"tag":"0.1.0","author":"takahironishii","date":"2026-09-21 07:33:12","revision":3705036},"0.2.0":{"tag":"0.2.0","author":"takahironishii","date":"2026-09-21 07:55:01","revision":3705091}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3705036,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3705036,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3705036,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3705036,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.1.0","0.2.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3705036,"resolution":"1","location":"assets","locale":"","width":1280,"height":644},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3705036,"resolution":"2","location":"assets","locale":"","width":1280,"height":594},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3705036,"resolution":"3","location":"assets","locale":"","width":1280,"height":521}},"screenshots":{"1":"<code>wp revision-autopilot count<\/code> reports the total, the estimated content size, and a breakdown by parent post type.","2":"Deletion is bounded. <code>--dry-run<\/code> reports a scope without touching it, and <code>--all<\/code> repeats one batch at a time, saying what remains after each.","3":"<code>wp revision-autopilot optimize<\/code> runs OPTIMIZE TABLE on the two allowlisted tables, and a second count confirms what is left."}},"plugin_section":[],"plugin_tags":[251511,569,3786,3937,4574],"plugin_category":[],"plugin_contributors":[268733],"plugin_business_model":[],"class_list":["post-371870","plugin","type-plugin","status-publish","hentry","plugin_tags-abilities","plugin_tags-automation","plugin_tags-cleanup","plugin_tags-revision","plugin_tags-wp-cli","plugin_contributors-takahironishii","plugin_committers-takahironishii"],"banners":{"banner":"https:\/\/ps.w.org\/revision-autopilot\/assets\/banner-772x250.png?rev=3705036","banner_2x":"https:\/\/ps.w.org\/revision-autopilot\/assets\/banner-1544x500.png?rev=3705036","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/revision-autopilot\/assets\/icon-128x128.png?rev=3705036","icon_2x":"https:\/\/ps.w.org\/revision-autopilot\/assets\/icon-256x256.png?rev=3705036","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/revision-autopilot\/assets\/screenshot-1.png?rev=3705036","caption":"<code>wp revision-autopilot count<\/code> reports the total, the estimated content size, and a breakdown by parent post type."},{"src":"https:\/\/ps.w.org\/revision-autopilot\/assets\/screenshot-2.png?rev=3705036","caption":"Deletion is bounded. <code>--dry-run<\/code> reports a scope without touching it, and <code>--all<\/code> repeats one batch at a time, saying what remains after each."},{"src":"https:\/\/ps.w.org\/revision-autopilot\/assets\/screenshot-3.png?rev=3705036","caption":"<code>wp revision-autopilot optimize<\/code> runs OPTIMIZE TABLE on the two allowlisted tables, and a second count confirms what is left."}],"raw_content":"<!--section=description-->\n<p>WordPress keeps a full copy of a post every time you update it. Over a few years those copies quietly become the largest thing in your database. Plenty of plugins will show you a button to delete them.<\/p>\n\n<p>This one does not have a button.<\/p>\n\n<p>Revision Autopilot publishes revision cleanup as <strong>abilities<\/strong> \u2014 named operations with input and output schemas, permission callbacks and behavioural annotations \u2014 using the Abilities API introduced in WordPress 6.9. Anything that can discover abilities can find these, understand what they take and return, check whether it is allowed to run them, and read back a structured result. The same operations are available as WP-CLI commands for scripts and cron.<\/p>\n\n<p>It is built for sites where cleanup should happen without a person watching: agent-driven maintenance, scheduled scripts, fleets of sites managed from one place.<\/p>\n\n<h4>What it exposes<\/h4>\n\n<p>Four abilities, all under the <code>revision-autopilot\/<\/code> namespace:<\/p>\n\n<ul>\n<li><code>count-revisions<\/code> \u2014 how many revisions exist, their estimated content size, and the same broken down by parent post type. Read-only.<\/li>\n<li><code>list-revisions<\/code> \u2014 one page of individual revisions with their parent post and timestamps. Read-only.<\/li>\n<li><code>delete-revisions<\/code> \u2014 deletes one bounded batch for a scope and reports how many remain. Destructive.<\/li>\n<li><code>optimize-tables<\/code> \u2014 runs OPTIMIZE TABLE on the posts and postmeta tables. Destructive.<\/li>\n<\/ul>\n\n<p>And three WP-CLI commands over the same code:<\/p>\n\n<pre><code>wp revision-autopilot count\nwp revision-autopilot delete --scope=post --limit=100\nwp revision-autopilot optimize\n<\/code><\/pre>\n\n<h4>How it stays safe<\/h4>\n\n<p>Handing destructive operations to a script deserves more care than putting them behind a button, not less.<\/p>\n\n<ul>\n<li><strong>Every ability checks permission itself.<\/strong> There is no admin form and no nonce in this path, so authorisation is never inherited from the surrounding request. Reading needs <code>edit_posts<\/code>; deleting or optimizing needs <code>manage_options<\/code>. Both are filterable.<\/li>\n<li><strong>Deletion is always bounded.<\/strong> One call never removes more than 1000 revisions however large the scope. The result says how many remain, so a caller loops deliberately rather than firing one unbounded request.<\/li>\n<li><strong>Only revisions are deleted.<\/strong> Every candidate is checked against <code>wp_is_post_revision()<\/code> before removal, and deletion goes through <code>wp_delete_post_revision()<\/code> so related metadata is cleaned up with it. Published content is never touched.<\/li>\n<li><strong>Only two tables are ever optimized<\/strong>, from a fixed allowlist: posts and postmeta.<\/li>\n<li><strong>Refusals explain themselves.<\/strong> A caller without permission gets a <code>WP_Error<\/code> saying which capability is missing, not a bare false.<\/li>\n<\/ul>\n\n<h4>Relationship to Takahiro Revision Cleanup<\/h4>\n\n<p>The same author publishes <a href=\"https:\/\/wordpress.org\/plugins\/takahiro-revision-cleanup\/\">Takahiro Revision Cleanup<\/a>, which does revision cleanup through a screen under Tools. The two are for different situations and do not overlap in how they are used:<\/p>\n\n<ul>\n<li>Takahiro Revision Cleanup is for a person who wants to look at their revisions and click delete.<\/li>\n<li>Revision Autopilot has no screen at all. It is for scripts, CLI and agents.<\/li>\n<\/ul>\n\n<p>Install whichever matches how the work gets done on your site. Running both is harmless.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin to <code>\/wp-content\/plugins\/revision-autopilot\/<\/code>, or install it through the plugins screen.<\/li>\n<li>Activate it.<\/li>\n<li>There is no settings page, by design. Verify it with <code>wp revision-autopilot count<\/code>, or list the registered abilities from your client of choice.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"where%20is%20the%20settings%20page%3F\"><h3>Where is the settings page?<\/h3><\/dt>\n<dd><p>There isn't one. This plugin exists to be called by something other than a human. If you want a screen, use Takahiro Revision Cleanup instead.<\/p><\/dd>\n<dt id=\"is%20deleting%20revisions%20reversible%3F\"><h3>Is deleting revisions reversible?<\/h3><\/dt>\n<dd><p>No. Revisions are deleted permanently. Take a backup first, and use <code>--dry-run<\/code> or <code>count-revisions<\/code> to see what would go before it goes.<\/p><\/dd>\n<dt id=\"why%20does%20one%20call%20not%20delete%20everything%3F\"><h3>Why does one call not delete everything?<\/h3><\/dt>\n<dd><p>Because an unbounded delete on a large site is a request that runs until something kills it, leaving you with no idea how far it got. Each call removes a bounded batch and tells you how many remain, so the caller stays in control. <code>wp revision-autopilot delete --all<\/code> loops for you.<\/p><\/dd>\n<dt id=\"deleting%20revisions%20did%20not%20shrink%20my%20database.\"><h3>Deleting revisions did not shrink my database.<\/h3><\/dt>\n<dd><p>Deleting rows does not shrink the table file; only OPTIMIZE does. Run <code>optimize-tables<\/code> after deleting.<\/p><\/dd>\n<dt id=\"does%20it%20work%20without%20the%20abilities%20api%3F\"><h3>Does it work without the Abilities API?<\/h3><\/dt>\n<dd><p>The abilities need WordPress 6.9 or newer. On an older site the WP-CLI commands still work, and the plugin does not error.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.2.0<\/h4>\n\n<ul>\n<li>Added a Japanese translation, bundled in languages\/ as a fallback until language packs exist on translate.wordpress.org.<\/li>\n<li>Registered the plugin text domain on init, so bundled translations are actually loaded. The Domain Path header alone does not do this.<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>Initial release: four abilities and three WP-CLI commands.<\/li>\n<\/ul>","raw_excerpt":"Post revision cleanup for scripts and agents: machine-readable abilities and WP-CLI commands, with no admin screen.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/371870","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=371870"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/takahironishii"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=371870"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=371870"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=371870"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=371870"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=371870"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=371870"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}