How To Add Custom Commands to the WordPress Command Palette

Command Center - License: Adobe Stock Editorial
Command Center – License: Adobe Stock Editorial

WordPress 6.3, which is currently a month away from releasing, will release with a new feature called the Command Palette.

Within this tutorial I will explain what the Command Palette is, what it can be used for, and how to add your own items to it.

What is the Command Palette?

If you’re a Mac user, you probably use Spotlight on occasion to open up new programs or perform searches. The WordPress Command Palette seems very similar. You’d use CMD+K (CTRL+K on Windows) to open up the palette and it provides some handy shortcuts as you type.

Such shortcuts can be adding a new post, creating a new template, and toggling settings in the site or block editors.

Opening and Browsing the Command Palette
Opening and Browsing the Command Palette

Right now the Command Palette only works in the site editor and in the block editor. I’m hoping this will change and that you can use the Command Palette throughout the entire WordPress admin.

What is the Command Palette useful for?

As previously mentioned, you can use the Command Palette for shortcuts or toggling settings. For example, you can create a new post from the Command Palette.

Toggle Settings in the WordPress Command Palette
Toggle Settings in the WordPress Command Palette

For plugin authors, you’re able to add in your own commands. A command you might add might be a shortcut to a setting in your plugin’s admin panel.

If you have a post integration, you can use the Command Palette to launch a popover or modal so that a user can easily tweak some settings without digging through sidebars and hidden tool menus. For example, if you have an SEO plugin, it might make sense to launch a snippet editor so that users can quickly edit their meta settings.

I imagine as the Command Palette is further polished that there will be more use-cases that open up for plugin authors to take advantage of.

For the remainder of this tutorial, let’s go over how you would add in your own command.

Setting the plugin structure

Let’s set up a structure that will use the @wordpress/scripts dependency to compile our JavaScript. The scripts package assumes that our main file is at src/index.js. The build files will end up in the build folder.

.
└── dlx-command-add-featured-image/
    ├── build/
    │   └── index.js
    ├── src/
    │   └── index.js
    ├── dlx-command-add-featured-image.php
    └── package.jsonCode language: AsciiDoc (asciidoc)

Setting the plugin headers

Let’s create a file called dlx-command-add-featured-image.php and add in the plugin headers.

<?php
/**
 * Plugin Name: DLX Command - Add Featured Image
 * Plugin URI: https://dlxplugins.com/plugins/
 * Description: Demonstrates adding a new command to the WordPress command palette.
 * Author: DLX Plugins
 * Version: 0.0.1
 * Requires at least: 5.1
 * Requires PHP: 7.2
 * Author URI: https://dlxplugins.com
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 *
 * @package DLXCommandAddFeaturedImage
 */

namespace DLXPlugins\DLXCommandAddFeaturedImage;Code language: PHP (php)

Setting up package.json

The package.json file will hold all of the script dependencies we need. The package.json file can typically be created by typing in npm init while in terminal and in the plugin folder.

Here’s an example of. a barebones package.json that’ll help get us started.

{
	"name": "dlx-command-add-featured-image",
	"version": "1.0.0",
	"description": "Demonstrates adding a new command to the WordPress command palette.",
	"repository": {
		"type": "git",
		"url": "git+https://github.com/dlxplugins/dlx-command-add-featured-image/"
	},
	"author": "Ronald Huereca",
	"license": "ISC",
	"bugs": {
		"url": "https://github.com/dlxplugins/dlx-command-add-featured-image/"
	},
	"homepage": "https://dlxplugins.com/plugins/dlx-command-add-featured-image/",
	"devDependencies": {},
	"dependencies": {}
}Code language: JSON / JSON with Comments (json)

Open up your terminal app and navigate to the plugin directory. We’ll install the @wordpress/scripts package.

npm install --save-dev @wordpress/scriptsCode language: Bash (bash)

Next, we’ll add in some actions to package.json in order to build the scripts.

{
	"name": "dlx-command-add-featured-image",
	"version": "1.0.0",
	"description": "Demonstrates adding a new command to the WordPress command palette.",
	"scripts": {
		"start": "wp-scripts start --env mode=development",
		"dev": "wp-scripts start --env mode=development",
		"build": "wp-scripts build --env mode=production"
	},
	"repository": {
		"type": "git",
		"url": "git+https://github.com/dlxplugins/dlx-command-add-featured-image/"
	},
	"author": "Ronald Huereca",
	"license": "ISC",
	"bugs": {
		"url": "https://github.com/dlxplugins/dlx-command-add-featured-image/"
	},
	"homepage": "https://dlxplugins.com/plugins/dlx-command-add-featured-image/",
	"devDependencies": {
		"@wordpress/scripts": "^26.7.0"
	},
	"dependencies": {}
}

Code language: JSON / JSON with Comments (json)

Assuming there’s a file in src/index.js, we can begin building the JavaScript. Let’s go ahead and run npm run build, which will run a production build.

Running Build Scripts Locally
Running Build Scripts Locally

If all is well, you should have two files in the build directory: index.asset.php and index.js.

.
└── dlx-command-add-featured-image/
    ├── build/
    │   ├── index.asset.php
    │   └── index.js
    ├── src/
    │   └── index.js
    ├── dlx-command-add-featured-image.php
    └── package.jsonCode language: AsciiDoc (asciidoc)

Enqueuing the script

Let’s go ahead and add in a console.log statement in the JavaScript file so we can ensure that it’s running when we enqueue it.

console.log( 'script is running' );Code language: JavaScript (javascript)

Next, we’ll edit dlx-command-add-featured-image.php and enqueue the script in the block editor.

// Enqueue block editor assets.
add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\enqueue_block_editor_assets' );

/**
 * Enqueue block editor assets.
 *
 * @return void
 */
function enqueue_block_editor_assets() {
	wp_enqueue_script(
		'dlx-command-add-featured-image',
		plugins_url( 'build/index.js', __FILE__ ),
		array(),
		'1.0.0',
		true
	);
}Code language: PHP (php)

Let’s go ahead and run npm run build from the terminal again to ensure the script has the console.log statement.

npm run buildCode language: Bash (bash)

If all is well, when we visit a block editor post, we should receive a console statement.

Console.log Script Output
Console.log Script Output

Adding the commands dependency

In order to add a command to the Command Palette, we’ll need to be able to mount a React component and make use of the new useCommand hook that is part of the @wordpress/commands dependency.

We’ll start by running the following in the terminal in the plugin directory:

npm install --save-dev @wordpress/commandsCode language: Bash (bash)

The dependency should now be added to our package.json file.

{
	"name": "dlx-command-add-featured-image",
	"version": "1.0.0",
	"description": "Demonstrates adding a new command to the WordPress command palette.",
	"scripts": {
		"start": "wp-scripts start --env mode=development",
		"dev": "wp-scripts start --env mode=development",
		"build": "wp-scripts build --env mode=production"
	},
	"repository": {
		"type": "git",
		"url": "git+https://github.com/dlxplugins/dlx-command-add-featured-image/"
	},
	"author": "Ronald Huereca",
	"license": "ISC",
	"bugs": {
		"url": "https://github.com/dlxplugins/dlx-command-add-featured-image/"
	},
	"homepage": "https://dlxplugins.com/plugins/dlx-command-add-featured-image/",
	"devDependencies": {
		"@wordpress/commands": "^0.7.0",
		"@wordpress/scripts": "^26.7.0"
	},
	"dependencies": {}
}

Code language: JSON / JSON with Comments (json)

Adding the plugins and icons dependency

We’ll need to register a block editor plugin in order to add in the command to the Command Palette. Since the useCommand hook must be attached to a React component, we’ll be creating the plugin and return null for the output.

First, we need to add in the @wordpress/plugins dependency.

npm install --save-dev @wordpress/pluginsCode language: Bash (bash)

Next, we’ll need to add in a dependency for WordPress icons, which will use the @wordpress/icons package.

npm install --save-dev @wordpress/iconsCode language: Bash (bash)

Here’s an example of our package.json file with all of the dependencies (the version numbers may differ from yours):

{
	"name": "dlx-command-add-featured-image",
	"version": "1.0.0",
	"description": "Demonstrates adding a new command to the WordPress command palette.",
	"scripts": {
		"start": "wp-scripts start --env mode=development",
		"dev": "wp-scripts start --env mode=development",
		"build": "wp-scripts build --env mode=production"
	},
	"repository": {
		"type": "git",
		"url": "git+https://github.com/dlxplugins/dlx-command-add-featured-image/"
	},
	"author": "Ronald Huereca",
	"license": "ISC",
	"bugs": {
		"url": "https://github.com/dlxplugins/dlx-command-add-featured-image/"
	},
	"homepage": "https://dlxplugins.com/plugins/dlx-command-add-featured-image/",
	"devDependencies": {
		"@wordpress/commands": "^0.7.0",
		"@wordpress/icons": "^9.27.0",
		"@wordpress/plugins": "^6.4.0",
		"@wordpress/scripts": "^26.7.0"
	},
	"dependencies": {}
}
Code language: JSON / JSON with Comments (json)

Adding a block editor plugin

Back in our src/index.js file, let’s add in some code that’ll register a block editor plugin and output something to the console.

import { useCommand } from '@wordpress/commands';
import { registerPlugin } from '@wordpress/plugins';
import { image } from '@wordpress/icons';

const FeaturedImageCommand = () => {
	console.log( 'FeaturedImageCommand' );
	return <></>;
}
registerPlugin( 'dlx-command-add-featured-image', { render: FeaturedImageCommand } );

export default FeaturedImageCommand;Code language: JavaScript (javascript)

Go ahead and run npm run start to start the build process and begin a watch for any changes to the file.

When you visit the post editor, you’ll see a console statement showing that our code is running correctly.

Console Output for the Block Editor Plugin
Console Output for the Block Editor Plugin

Adding the command to the block editor plugin

As mentioned earlier, we’ll be using the useCommand hook to register our command. Let’s take a look at what this all looks like.

import { useCommand } from '@wordpress/commands';
import { registerPlugin } from '@wordpress/plugins';
import { image } from '@wordpress/icons';

const FeaturedImageCommand = () => {
	useCommand( {
		name: 'add-featured-image',
		label: 'Add Featured Image',
		icon: image,
		callback: () => {
			console.log('Featured Image');
		},
		context: 'block-editor',
	} );
	return null;
}
registerPlugin( 'dlx-command-add-featured-image', { render: FeaturedImageCommand } );

export default FeaturedImageCommand;Code language: JavaScript (javascript)

The useCommand hook takes an object with 5 properties:

  • name (string): A name or slug of your command. This should be unique.
  • label (string): A label of the command, which is also needed for searching for the command.
  • icon (string, element): The icon that should show next to your command.
  • callback (function): Provide a callback function that will be called when someone selects your command.
  • context (string): Provide a context (categorization) for your command. Currently, I’ve only seen site-editor in use for context, but adding block-editor here doesn’t seem to affect things negatively.

If all is well, we should now be able to open the Command Palette (using CMD+K for Mac or CTRL+K on windows) and type in “add” in order to see the command for adding a featured image.

Showing the Add Featured Image Command
Showing the Add Featured Image Command

Right now when “Add Featured Image” is clicked, it’ll output “Featured Image” to the console.

Add Featured Image Command
Add Featured Image Command

Executing the Add Featured Image command

When “Add Featured Image” is clicked, the media library should launch and the user should be able to quickly select a new featured image.

// Set up the command.
useCommand( {
	name: 'add-featured-image',
	label: 'Add Featured Image',
	icon: image,
	callback: () => {
		const uploader = wp.media({
			states: [
				new wp.media.controller.Library({
					title: "Set Featured Image",
					library: wp.media.query({type: 'image'}),
					multiple: false,
					date: false,
					priority: 20,
					syncSelection: true,
				}),
			],
			title: "Set Featured Image",
			button: {
				text: "Set Featured Image",
			},
			multiple: false,
		});
		
		//For when the Add Profile Image is clicked
		uploader.on('select', function () {
			const featured = uploader.state().get('selection').single();
			if ( ! featured.id ) {
				return;
			}
			// Set the post featured id.
			wp.data.dispatch( 'core/editor' ).editPost( { featured_media: featured.id } );
		});

		// For when the uploader is opened.
		uploader.on('open', function () {
			// Select the current featured image if there is one.
			const featuredImageId = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'featured_media' );
			if ( featuredImageId ) {
				const attachment = wp.media.attachment(featuredImageId);
				attachment.fetch();
				const selection = uploader.state('library').get('selection');
				selection.add( attachment );
			}
		} );

		// Open media library.
		uploader.open();
	},
	context: 'block-editor',
} );Code language: JavaScript (javascript)

The code above launches the media library modal and sets the featured image if you select something from the media library. Here’s a demo below:

Add a Featured Image From a Command Palette Command
Add a Featured Image From a Command Palette Command

Let’s add a “Refresh Permalinks” shortcut command

You’re not limited to adding just one command. Add as many as you like. Let’s add a command for a shortcut to the Permalinks admin setting.

// Set up a command for going to the refresh permalinks screen.
useCommand( {
	name: 'refresh-permalinks',
	label: 'Go to Refresh Permalinks Settings Screen',
	icon: external,
	callback: () => {
		document.location.href = 'options-permalink.php';
	},
	context: 'block-editor'
} );Code language: JavaScript (javascript)

Here’s how it looks in the Command Palette:

A Demo of a Refresh Permalinks Command Shortcut
A Demo of a Refresh Permalinks Command Shortcut

Don’t feel limited to just admin shortcuts. You can link to admin panel settings, external documentation, or third-party sites.

Adding a user from the Command Palette

Let’s do one last command, with this one launching a modal that’ll create a new user. I’m not going to wire up the back-end for this example, so this is just a proof-of-concept.

I’ll need to set some state and output a modal component, so let’s add a few more dependencies: @wordpress/components and @wordpress/element.

npm install --save-dev @wordpress/components @wordpress/elementCode language: Bash (bash)

Here are the updated import statements for everything we’ll need to create the modal.

import { useState } from '@wordpress/element';
import { useCommand } from '@wordpress/commands';
import { registerPlugin } from '@wordpress/plugins';
import { image, external, commentAuthorAvatar } from '@wordpress/icons';
import { Modal, Button, TextControl } from '@wordpress/components';Code language: JavaScript (javascript)

Here’s the component for showing the modal:

const UserModal = ( props ) => {
	return (
		<>
			<Modal
				title="Add New User"
				onRequestClose={ () => {
					props.onRequestClose();
				}}
				shouldCloseOnClickOutside={ false }
				shouldCloseOnEsc={ false }
			>
				<TextControl
					label="Username"
					placeholder="Enter username"
				/>
				<TextControl
					label="Email"
					placeholder="Enter email"
				/>
				<Button
					variant="primary"
					onClick={ () => {
						// Do ajax or rest call to save user.
						props.onRequestClose();
					}}
				>
					Save User
				</Button>
				<Button
					variant="secondary"
					onClick={ () => {
						props.onRequestClose();
					}}
				>
					Cancel
				</Button>
			</Modal>
		</>
	);
};Code language: JavaScript (javascript)

I need some state to keep track of when the modal should be open. I’ve added it to the top of the FeaturedImageCommand component.

const FeaturedImageCommand = () => {
	// For showing the add user modal.
	const [ isAddUserModalOpen, setIsAddUserModalOpen ] = useState( false );

	// Get the current post type
	const postType = wp.data.select("core/editor").getCurrentPostType();

	// Get the post type object
	const postTypeObject = wp.data.select("core").getPostType(postType);

	// If post type does not support thumbnails, exit.
	if ( postTypeObject.supports && ! postTypeObject.supports.thumbnail) {
		return null;
	}

	/* rest of the code.*/
};Code language: JavaScript (javascript)

Finally, I can add the command that will launch the modal.

// Set up a command for showing a modal for adding a user.
useCommand( {
	name: 'add-new-user',
	label: 'Add New User',
	icon: commentAuthorAvatar,
	callback: () => {
		setIsAddUserModalOpen( true );
	},
	context: 'block-editor'
} );

if ( isAddUserModalOpen ) {
	return (
		<UserModal
			onRequestClose={ () => {
				setIsAddUserModalOpen( false );
			}}
		/>
	);
}

return null;Code language: JavaScript (javascript)

Here’s how the command looks in practice:

Add New User Shortcut Command
Add New User Shortcut Command

Conclusion

Within this tutorial I explained what the WordPress Command Palette is and demonstrated how to add several items to it. If you have any questions or updates on the Command Palette, please leave a comment.

Ronald Huereca
By: Ronald Huereca
Published On: on July 2, 2023

Ronald Huereca founded DLX Plugins in 2022 with the goal of providing deluxe plugins available for download. Find out more about DLX Plugins, check out some tutorials, and check out our plugins.

Shopping Cart
  • Your cart is empty.
Scroll to Top