Axle Category & Tag Trash developer reference

Hooks

Every default, limit and message has a filter, and every change fires an action.

axle_category_tag_trash_supports_taxonomyFilter
( bool $keep, string $taxonomy )

Return false to delete a taxonomy’s terms for good, as WordPress normally does. Menus (nav_menu) are never kept

axle_category_tag_trash_keep_termFilter
( bool $keep, WP_Term $term )

Whether one deleted term goes to the trash, for example to let empty tags go for good

axle_category_tag_trash_retention_daysFilter
( int $days )

Days a trashed term is kept. Wins over the setting on the screen

axle_category_tag_trash_retention_choicesFilter
( int[] $days )

Periods offered on the screen. Default 7, 30, 90 and 365

axle_category_tag_trash_undo_secondsFilter
( int $seconds )

How long the Undo notice after a bulk delete stays. Default 300

axle_category_tag_trash_trashedAction
( int $item_id, Snapshot $snapshot )

A deleted term landed in the trash

axle_category_tag_trash_deletedAction
( int $item_id, Snapshot $snapshot )

A trashed term is about to be deleted for good: Empty trash, Delete permanently or the daily clean-up. Not on restore

axle_category_tag_trash_purgedAction
( int $deleted )

The daily clean-up deleted this many expired terms

axle_category_tag_trash_restoredAction
( int $term_id, string $taxonomy, Snapshot $snapshot, int[] $object_ids )

Fires once the term is back. $object_ids holds the objects re-attached in that request, at most 5,000

axle_category_tag_trash_objects_restoredAction
( int $term_id, string $taxonomy, int[] $object_ids )

Fires for every batch of objects re-attached, in the request and in the background

axle_category_tag_trash_restore_completeAction
( int $term_id, string $taxonomy, Snapshot $snapshot )

Fires once every object is back

axle_category_tag_trash_restore_batch_sizeFilter
( int $size )

Objects re-attached per request or cron run. Default 5000

axle_category_tag_trash_capabilityFilter
( string $capability )

Capability for Tools > Axle Category & Tag Trash. Default manage_categories. Each restore and delete still checks the term’s own taxonomy

WP-CLI

wp axle-category-tag-trash list [--taxonomy=<taxonomy>] [--format=table|csv|json|count|ids]
wp axle-category-tag-trash restore <id>...
wp axle-category-tag-trash delete <id>...
wp axle-category-tag-trash delete --all [--yes]

Abilities

What AI agents can do through the WordPress Abilities API and MCP, with the same permissions as the screen.

axle-category-tag-trash/list

Read-only. Trashed terms, newest first, with what a restore brings back. Input: taxonomy, search, limit, page

Who can run it: the Axle Category & Tag Trash capability. Terms of taxonomies you cannot manage are left out

axle-category-tag-trash/restore

Restores trash item id with its posts, child terms and menu links

Who can run it: the Axle Category & Tag Trash capability and the term’s own taxonomy

axle-category-tag-trash/delete

Deletes trash item id for good. Destructive, so the REST API runs it with DELETE

Who can run it: the Axle Category & Tag Trash capability and the term’s own taxonomy

Built from REFERENCE.md for version 3.0.0.

More on hooks

// Never keep deleted tags.
add_filter( 'axle_category_tag_trash_supports_taxonomy', function ( $keep, $taxonomy ) {
	return 'post_tag' === $taxonomy ? false : $keep;
}, 10, 2 );

// Let empty categories go for good, keep the rest.
add_filter( 'axle_category_tag_trash_keep_term', fn( $keep, $term ) => $keep && $term->count > 0, 10, 2 );

// Offer a 14-day option.
add_filter( 'axle_category_tag_trash_retention_choices', fn( $days ) => array_merge( $days, array( 14 ) ) );

More on abilities

On WordPress 6.9 and later, Axle Category & Tag Trash registers abilities, which AI agents find and run through the MCP adapter and anything else through the REST API under /wp-abilities/v1/. Each one is marked public, which the MCP adapter needs before it lists an ability. An agent that deleted the wrong category can put it back.

More on WP-CLI

<id> is the trash item ID from wp axle-category-tag-trash list, not the term ID. restore re-attaches every object in the same run, even for a term on a million posts, and also finishes a restore that is running in the background.

PHP API

$plugin = AryanX\Axle\CategoryTagTrash\Plugin::instance();

$plugin->trash()->find( array( 'taxonomy' => 'category', 'per_page' => 100 ) ); // [ 'ids' => [...], 'total' => n ], at most 500 per page
$plugin->restorer()->restore( $item_id );        // [ 'term_id' => n, 'notes' => [...], 'background' => bool ] or WP_Error
$plugin->restorer()->restore( $item_id, true );  // the same, with every object re-attached before it returns

Data

Each trashed term is an axle_ctt_item post (hidden, not exported, kept when its author is deleted). Its post meta holds:

Meta keyWhat
_axle_category_tag_trash_snapshotthe term row, meta, children, menu links, object count and a sample of object IDs
_axle_category_tag_trash_objectsone row per 1,000 objects, packed as id:order,id:order
_axle_category_tag_trash_fallbackone row per 1,000 objects that only had this term, packed as id,id
_axle_category_tag_trash_restore_statewhere a background restore is up to

Items in the trash have the status publish, items being restored in the background pending. The setting is the axle_category_tag_trash_settings option. The cron events are axle_category_tag_trash_purge (daily), axle_category_tag_trash_empty and axle_category_tag_trash_restore_batch.

Uninstalling removes all of it on every site of a multisite network, 100 sites at a time.