Skip to main content

wp shell

Overview

wp shell opens an interactive PHP REPL (Read-Eval-Print Loop) with the full WordPress environment loaded. Type PHP, press Enter, see the result — instantly. It is the fastest way to experiment with WordPress functions, explore object properties, and verify assumptions without writing a script file or a wp eval one-liner.

What It Does

When you run wp shell, WP-CLI bootstraps WordPress (config, core, plugins, themes) and then drops you into an interactive PHP session. Every expression you type is evaluated inside this live WordPress context. The session persists until you type exit or quit.

Syntax

wp shell [--basic-shell]

Options

FlagDescription
--basic-shellUse a simple stdin/stdout loop instead of the psysh REPL (useful when psysh is not installed)
psysh

wp shell uses psysh by default for a rich experience with syntax highlighting, tab completion, and inline docs. If psysh is not available, it falls back to a basic REPL.

Install psysh globally:

wp package install wp-cli/shell-command:@stable

Starting a Session

wp shell

Output:

Starting 6 second timer... hit any key to cancel.
Psy Shell v0.12.0 (PHP 8.2.0 — cli) by Justin Hileman
>>>

Basic Examples

>>> echo get_option("siteurl");
https://example.com

Get the site name

>>> echo get_bloginfo("name");
My WordPress Site

Inspect the current WordPress version

>>> global $wp_version; echo $wp_version;
6.4.2

Dump an option to inspect its structure

>>> var_dump(get_option("active_plugins"));
array(4) {
[0] =>
string(27) "akismet/akismet.php"
[1] =>
string(31) "woocommerce/woocommerce.php"
[2] =>
string(29) "yoast-seo/wp-seo-main.php"
[3] =>
string(25) "my-plugin/my-plugin.php"
}

Count published posts

>>> echo wp_count_posts("post")->publish;
142

Flash inspect a user object

>>> $user = get_user_by("login", "admin");
>>> echo $user->user_email;
admin@example.com
>>> print_r($user->roles);
Array
(
[0] => administrator
)

Iterating and Debugging

Check if a plugin is active

>>> var_dump(is_plugin_active("woocommerce/woocommerce.php"));
bool(true)

Run a WP_Query and inspect results

>>> $q = new WP_Query(["post_type" => "product", "posts_per_page" => 3]);
>>> echo $q->found_posts;
87
>>> echo $q->posts[0]->post_title;
Red Running Shoes

Update an option interactively

>>> update_option("blogdescription", "Catch up on everything.");
=> true
>>> echo get_option("blogdescription");
Catch up on everything.

Explore a class interactively

>>> $q = new WP_Query(["post_type" => "post","posts_per_page" => 1]);
>>> print_r(array_keys((array)$q));
Array
(
[0] => query
[1] => query_vars
[2] => tax_query
[3] => meta_query
[4] => date_query
...
)

Test a custom action hook

>>> do_action("my_plugin_queue_worker");

(No output means it ran silently — hooks with echo output will print here.)

Multi-Line Expressions in the REPL

In psysh, multi-line expressions are supported natively:

>>> $results = get_posts([
... "post_type" => "post",
... "post_status" => "publish",
... "numberposts" => 5
... ]);
>>> foreach ($results as $p) {
... echo $p->post_title . "\n";
... }
First Blog Post
Second Blog Post
Third Blog Post
Fourth Blog Post
Fifth Blog Post

Database Queries in the Shell

>>> global $wpdb;
>>> $count = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_status = 'trash'");
>>> echo "Trashed posts: $count";
Trashed posts: 12

Inspecting Plugin/Theme Objects

>>> $theme = wp_get_theme();
>>> echo $theme->get("Name");
Twenty Twenty-Four

>>> echo $theme->get("Version");
1.0

>>> echo $theme->get("Template");
twentytwentyfour

psysh-Specific Features

Inline Documentation with doc

>>> doc get_posts
function get_posts(array|null $args = null): WP_Post[]|int[]
Retrieves an array of the latest posts, or posts matching the given criteria.
...

Listing variables with ls

>>> $a = 1; $b = "test";
>>> ls
Variables: $a, $b

Show last exception

>>> throw new Exception("Oops");
>>> show

Exiting the Shell

>>> exit

Or press Ctrl+D.

Running Without psysh (Basic Shell)

If psysh is unavailable:

wp shell --basic-shell

Session looks like:

wp> echo get_option("siteurl");
https://example.com
wp>

wp-shell vs. wp eval

Featurewp shellwp eval
Interactive✅ Yes❌ No (single command)
Multi-statement session✅ YesLimited
Tab completion✅ psysh❌ No
Inline documentation✅ psysh doc❌ No
State persists between lines✅ Yes❌ Each wp eval is fresh
Scriptable❌ No✅ Yes

Best Practices

  1. Use wp shell for exploration — when you're not sure what a function returns, the REPL lets you experiment safely before committing to a script.
  2. Use var_dump heavily — it reveals types, making it easier to understand serialized data.
  3. Don't modify production data interactively — easy to make typos; use wp eval-file with a proper script for writes that matter.
  4. Use doc FUNCTION (psysh) to get immediate WordPress function documentation without leaving the terminal.
  5. Keep sessions short — for long operations, move code to wp eval-file.

Quick Reference

wp shell                          # Start interactive REPL
wp shell --basic-shell # Start without psysh
wp shell --skip-plugins # Load WP without plugins

Inside the shell:

>>> echo get_option("siteurl");   # Basic output
>>> var_dump($GLOBALS["wpdb"]); # Inspect globals
>>> doc get_posts # Inline docs (psysh)
>>> ls # List variables (psysh)
>>> exit # Exit session

Next Steps

  • wp eval — for quick, non-interactive one-liners.
  • wp eval-file — for executing a full PHP migration script.
  • wp help — look up any WP-CLI command's syntax.