The Real Picture

Dropping the Archived abilities-api Composer Package

⏱ 12 min

The wordpress/abilities-api Composer package was archived in February 2026, marked abandoned on Packagist with no replacement package suggested, because its functionality merged into WordPress core with 6.9. If it’s still in your composer.json, this lesson walks through removing it correctly, without breaking anything that depends on the functions it provided.

What you'll learn in this lesson
Confirming you actually depend on the old package
Checking composer.json, composer.lock, and your bootstrap code.
Removing the dependency safely
composer remove, then confirming core provides the same functions.
Replacing the version guard
Swapping a package-existence check for a WordPress version requirement.
What NOT to remove
The MCP Adapter dependency stays, this lesson only concerns the Abilities API package.
Prerequisites

Lesson 1’s corrected picture of what’s actually in core. A local WordPress environment you can safely test a dependency change in before touching production.

Step 1: Confirm you’re actually on the archived package

Check your project’s composer.json for the exact package name:

grep -n "wordpress/abilities-api" composer.json composer.lock

If nothing matches, you likely built directly against core’s Abilities API already and this specific lesson doesn’t apply to you, though the version-guard pattern in Step 3 is still worth reviewing. If you see a match, also search your plugin’s bootstrap file for a manual include, some early adopters of the package required it directly rather than through Composer’s autoloader:

grep -rn "abilities-api" --include="*.php" .

Step 2: Remove the package

# Removes the dependency and updates composer.json + composer.lock
composer remove wordpress/abilities-api
What composer remove does here
1
Deletes the require entry
wordpress/abilities-api is removed from composer.json.
2
Regenerates the autoloader
Any files the package registered for autoloading are dropped from vendor/composer/autoload_*.php.
3
Updates composer.lock
So a fresh composer install elsewhere won't try to re-fetch an archived, abandoned package.

If your bootstrap file had a manual require pointing at a path inside vendor/wordpress/abilities-api, delete that line too, composer remove won’t catch a hardcoded path.

// File: my-plugin.php

// Remove a line that looked like this:
// require_once __DIR__ . '/vendor/wordpress/abilities-api/src/bootstrap.php';

Step 3: Replace the package check with a version requirement

The standalone package’s whole design intent, as its own README stated, was to “ship first as a Composer package, then migrate smoothly to core,” meaning the function names you already call, wp_register_ability(), wp_get_ability(), wp_get_abilities(), wp_register_ability_category(), and their companions, are the same names core provides. Your migration is mostly about the dependency, not a function-by-function rewrite.

What does need to change is any guard code that checked for the package rather than the functions themselves. Replace a package-presence check with a straightforward function check, which now correctly reflects “is this running on WordPress 6.9+”:

// File: my-plugin.php
add_action( 'plugins_loaded', function () {
	if ( ! function_exists( 'wp_register_ability' ) ) {
		add_action( 'admin_notices', function () {
			echo '<div class="notice notice-error"><p>';
			esc_html_e( 'My Plugin requires WordPress 6.9 or later for the Abilities API.', 'my-plugin' );
			echo '</p></div>';
		} );
		return;
	}

	add_action( 'wp_abilities_api_init', 'my_plugin_register_abilities' );
} );

Also update your plugin’s readme.txt and main plugin file header, since these are what site owners and the plugin directory actually check:

// File: readme.txt
Requires at least: 6.9
Requires PHP: 7.4
You can drop the function_exists guard eventually too

If your plugin has already decided to require WordPress 6.9 as a hard minimum (via the readme.txt header above), the function_exists() check becomes a safety net rather than a strict requirement, WordPress itself won’t let a site running an older core install a plugin declaring Requires at least: 6.9. Keep the guard if you want a friendlier failure message instead of a blocked install; drop it if you’re comfortable relying on the readme.txt declaration alone.

Step 4: Confirm nothing else in your dependency tree pulls it back in

Some intermediate libraries or starter kits bundled the archived package transitively. Check your full lock file, not just your direct requirements:

composer why wordpress/abilities-api

If this returns a result after you’ve removed your own direct requirement, another dependency still requires it, and you’ll need to update or replace that dependency too, an abandoned package with no security coverage isn’t something you want lingering in a lock file even if nothing calls it directly.

Test it: confirm the swap didn’t break anything

composer install
wp eval 'var_dump( function_exists( "wp_register_ability" ) ); var_dump( wp_get_abilities() );'

The first var_dump should print bool(true) on a 6.9+ install with no Composer package involved at all. The second should print your plugin’s registered abilities exactly as before, since core’s function signatures and return shapes match what the standalone package provided.

Don't confuse this with removing the MCP Adapter

It’s easy to read “drop the old Abilities API dependency” and reflexively also remove wordpress/mcp-adapter from composer.json, especially if you’ve absorbed the mistaken idea that everything AI-related merged into core at once. Don’t. The MCP Adapter is a real, ongoing, separate dependency, covered again in Lesson 7. This lesson only concerns the archived Abilities API package.

Recap

The archived wordpress/abilities-api Composer package is safe to remove once your project targets WordPress 6.9 or later, since the same function names now live in core with no install step. Swap any package-existence guard for a function_exists() or readme.txt version requirement, check your lock file for transitive references, and confirm with wp eval that the functions still resolve correctly after the package is gone.

Resources & further reading

← What Actually Moved to Core, and What Didn't Updating .wp-env.json and Local Environments for Core Abilities →