From a92a4d47dc5e73d44f961dd63f01592d39fa6066 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 09:30:52 +0000 Subject: [PATCH 1/9] Flag commands and options not in the latest stable release The handbook is generated from the nightly build, so it can document commands and options that are not released yet (e.g. `wp block`). `wp handbook gen-commands` / `gen-all` now accept `--stable-phar=`. When given, the generator dumps the commands of the stable Phar and adds a note to every command page that is missing from it, or that documents options missing from it, pointing to the nightly build. Commands that already accepted arbitrary options in the stable release are not flagged for newly documented options. Unreleased commands are also marked with `"unreleased": true` in the commands manifest. The regenerate workflow downloads the latest stable Phar and passes it. See #666. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RVPkwDuM5DHXdSF4YW4qqr --- .github/workflows/regenerate-handbook.yml | 5 +- bin/Handbook_Command.php | 189 +++++++++++++++++++++- bin/templates/subcmd-list.mustache | 4 +- 3 files changed, 194 insertions(+), 4 deletions(-) diff --git a/.github/workflows/regenerate-handbook.yml b/.github/workflows/regenerate-handbook.yml index c558c3eb..7a7159f7 100644 --- a/.github/workflows/regenerate-handbook.yml +++ b/.github/workflows/regenerate-handbook.yml @@ -33,11 +33,14 @@ jobs: sudo mv wp-cli-nightly.phar /usr/local/bin/wp sudo chmod +x /usr/local/bin/wp + - name: Download latest stable WP-CLI for comparison + run: curl -sSfL -o "$RUNNER_TEMP/wp-cli-stable.phar" https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar + - name: Install non-bundled packages run: bash bin/install_packages.sh - name: Generate handbook - run: wp handbook gen-all + run: wp handbook gen-all --stable-phar="$RUNNER_TEMP/wp-cli-stable.phar" env: WP_CLI_PACKAGES_DIR: bin/packages WP_CLI_CONFIG_PATH: /dev/null diff --git a/bin/Handbook_Command.php b/bin/Handbook_Command.php index c8385efe..312db0a5 100644 --- a/bin/Handbook_Command.php +++ b/bin/Handbook_Command.php @@ -14,6 +14,29 @@ * @when before_wp_load */ class Handbook_Command { + /** + * Sentence used to flag commands missing from the latest stable release. + * + * Also used to detect such commands when generating the commands manifest. + */ + const UNRELEASED_COMMAND_NOTE = 'This command is not yet available in the latest stable release of WP-CLI'; + + /** + * Version of the latest stable WP-CLI release, if a stable Phar was given. + * + * @var string|null + */ + private static $stable_version = null; + + /** + * Commands available in the latest stable release, mapped to their options. + * + * `generic` is true if the command accepts arbitrary options, e.g. `[--=]`. + * + * @var array|null + */ + private static $stable_commands = null; + /** * @return string */ @@ -29,10 +52,13 @@ protected static function get_handbook_path() { * [--verbose] * : If set will list command pages as they are generated. * + * [--stable-phar=] + * : Path to the latest stable WP-CLI Phar. If set, commands and options missing from it are flagged as unreleased. + * * @subcommand gen-all * * @param string[] $args Positional arguments. Unused. - * @param array{verbose?: bool} $assoc_args Associative arguments. + * @param array{verbose?: bool, stable-phar?: string} $assoc_args Associative arguments. * @return void */ public function gen_all( $args, $assoc_args ) { @@ -236,10 +262,13 @@ function ( $parameter ) { * [--verbose] * : If set will list command pages as they are generated. * + * [--stable-phar=] + * : Path to the latest stable WP-CLI Phar. If set, commands and options missing from it are flagged as unreleased. + * * @subcommand gen-commands * * @param string[] $args Positional arguments. Unused. - * @param array{verbose?: bool} $assoc_args Associative arguments. + * @param array{verbose?: bool, stable-phar?: string} $assoc_args Associative arguments. * @return void */ public function gen_commands( $args, $assoc_args ) { @@ -258,6 +287,11 @@ public function gen_commands( $args, $assoc_args ) { WP_CLI::error( sprintf( "Install non-bundled packages by running '%s' first.", 'bin/install_packages.sh' ) ); } + $stable_phar = Utils\get_flag_value( $assoc_args, 'stable-phar' ); + if ( $stable_phar ) { + self::load_stable_reference( $stable_phar ); + } + self::empty_dir( self::get_handbook_path() . '/commands/' ); $wp = WP_CLI::runcommand( @@ -281,6 +315,153 @@ public function gen_commands( $args, $assoc_args ) { WP_CLI::success( 'Generated all command pages.' ); } + /** + * Loads the commands and options available in the latest stable release. + * + * @param string $phar Path to the stable WP-CLI Phar. + * @return void + */ + private static function load_stable_reference( $phar ) { + if ( ! is_file( $phar ) ) { + WP_CLI::error( "Stable Phar not found: {$phar}" ); + } + + $version = self::run_phar( $phar, 'cli version' ); + if ( ! preg_match( '/(\d+\.\d+\.\d+)/', $version, $matches ) ) { + WP_CLI::error( "Could not determine version of stable Phar: {$version}" ); + } + self::$stable_version = $matches[1]; + + $dump = json_decode( self::run_phar( $phar, 'cli cmd-dump' ), true ); + if ( ! is_array( $dump ) || ! isset( $dump['subcommands'] ) || ! is_array( $dump['subcommands'] ) ) { + WP_CLI::error( 'Could not dump commands of stable Phar.' ); + } + + self::$stable_commands = []; + foreach ( $dump['subcommands'] as $cmd ) { + self::flatten_cmd_dump( $cmd, [], self::$stable_commands ); + } + + WP_CLI::log( sprintf( 'Comparing against WP-CLI %s (%d commands).', self::$stable_version, count( self::$stable_commands ) ) ); + } + + /** + * Runs a WP-CLI command using the given Phar, inheriting the current environment. + * + * @param string $phar Path to the WP-CLI Phar. + * @param string $command WP-CLI command to run, without the leading `wp`. + * @return string Trimmed STDOUT. + */ + private static function run_phar( $phar, $command ) { + $stderr_file = (string) tempnam( sys_get_temp_dir(), 'wp-cli-handbook' ); + $process = proc_open( + Utils\esc_cmd( '%s %s', PHP_BINARY, $phar ) . ' ' . $command, + [ + 1 => [ 'pipe', 'w' ], + 2 => [ 'file', $stderr_file, 'w' ], + ], + $pipes + ); + if ( ! is_resource( $process ) ) { + WP_CLI::error( "Could not run '{$command}' using {$phar}." ); + } + $stdout = (string) stream_get_contents( $pipes[1] ); + fclose( $pipes[1] ); + $return_code = proc_close( $process ); + $stderr = (string) file_get_contents( $stderr_file ); + unlink( $stderr_file ); + + if ( 0 !== $return_code ) { + WP_CLI::error( "Running '{$command}' using {$phar} failed: {$stderr}" ); + } + + return trim( $stdout ); + } + + /** + * Flattens a `cli cmd-dump` command tree into a list of command paths and their options. + * + * Aliases are not included, as older versions of `cli cmd-dump` don't list them. + * Alias pages reuse the note of the command they point to instead. + * + * @param array $cmd Command as returned by `cli cmd-dump`. + * @param string[] $parent Names of the parent commands. + * @param array $out Command paths mapped to their options. + * @return void + */ + private static function flatten_cmd_dump( $cmd, $parent, &$out ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.parentFound + $synopsis = isset( $cmd['synopsis'] ) ? (string) $cmd['synopsis'] : ''; + $options = [ + 'options' => self::get_option_names( $synopsis ), + 'generic' => in_array( 'generic', array_column( WP_CLI\SynopsisParser::parse( $synopsis ), 'type' ), true ), + ]; + + $out[ implode( ' ', array_merge( $parent, [ (string) $cmd['name'] ] ) ) ] = $options; + + if ( isset( $cmd['subcommands'] ) && is_array( $cmd['subcommands'] ) ) { + foreach ( $cmd['subcommands'] as $subcmd ) { + self::flatten_cmd_dump( $subcmd, array_merge( $parent, [ (string) $cmd['name'] ] ), $out ); + } + } + } + + /** + * Extracts the option names (e.g. `--format`) from a command synopsis. + * + * @param string $synopsis Command synopsis. + * @return string[] + */ + private static function get_option_names( $synopsis ) { + $options = []; + foreach ( WP_CLI\SynopsisParser::parse( $synopsis ) as $param ) { + if ( in_array( $param['type'], [ 'assoc', 'flag' ], true ) && isset( $param['name'] ) ) { + $options[] = '--' . $param['name']; + } + } + return $options; + } + + /** + * Builds a note about parts of a command that are not in the latest stable release yet. + * + * @param string $full_name Full command name, e.g. `block type list`. + * @param string $synopsis Command synopsis. + * @return string Markdown note, or an empty string if everything is released or no stable Phar was given. + */ + private static function get_release_note( $full_name, $synopsis ) { + if ( null === self::$stable_commands ) { + return ''; + } + + $nightly = 'To use %s now, [switch to the nightly build](https://make.wordpress.org/cli/handbook/guides/installing/#updating-wp-cli) with `wp cli update --nightly`. If you installed the command as a separate package, updating that package may be enough.'; + + if ( ! isset( self::$stable_commands[ $full_name ] ) ) { + return sprintf( + '> **Note:** %s (%s). %s', + self::UNRELEASED_COMMAND_NOTE, + self::$stable_version, + sprintf( $nightly, 'it' ) + ); + } + + // Commands accepting arbitrary options might have supported a newly documented option already. + if ( self::$stable_commands[ $full_name ]['generic'] ) { + return ''; + } + + $unreleased = array_diff( self::get_option_names( $synopsis ), self::$stable_commands[ $full_name ]['options'] ); + if ( empty( $unreleased ) ) { + return ''; + } + + return sprintf( + '> **Note:** The following options are not yet available in the latest stable release of WP-CLI (%s): %s. %s', + self::$stable_version, + '`' . implode( '`, `', $unreleased ) . '`', + sprintf( $nightly, 'them' ) + ); + } + /** * Update the commands data array with new data * @@ -397,6 +578,9 @@ public function gen_commands_manifest() { if ( ! empty( $commands_data[ $title ] ) ) { $manifest[ $cmd_path ] = array_merge( $manifest[ $cmd_path ], $commands_data[ $title ] ); } + if ( false !== strpos( $contents, self::UNRELEASED_COMMAND_NOTE ) ) { + $manifest[ $cmd_path ]['unreleased'] = true; + } } } file_put_contents( self::get_handbook_path() . '/bin/commands-manifest.json', json_encode( $manifest, JSON_PRETTY_PRINT ) ); @@ -593,6 +777,7 @@ private static function gen_cmd_pages( $cmd, $parent = [], $verbose = false ) { } } $binding['has-subcommands'] = isset( $cmd['subcommands'] ) ? [ true ] : false; + $binding['release-note'] = self::get_release_note( $binding['synopsis'], $cmd['synopsis'] ?? '' ); $hook_name = $cmd['hook']; $hook_description = $hook_name ? Utils\get_hook_description( $hook_name ) : null; diff --git a/bin/templates/subcmd-list.mustache b/bin/templates/subcmd-list.mustache index b8afc700..4326f714 100644 --- a/bin/templates/subcmd-list.mustache +++ b/bin/templates/subcmd-list.mustache @@ -2,6 +2,8 @@ {{description}}{{#alias}} -**Alias:** `{{alias}}`{{/alias}} +**Alias:** `{{alias}}`{{/alias}}{{#release-note}} + +{{{release-note}}}{{/release-note}} {{{docs}}} From 76c3ce41b0bb5744db1e9881ab630cb57cbb047d Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 09:33:52 +0000 Subject: [PATCH 2/9] Document --stable-phar in README Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RVPkwDuM5DHXdSF4YW4qqr --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1bd0632d..a00bc072 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,13 @@ bin/install_packages.sh WP_CLI_PACKAGES_DIR=bin/packages WP_CLI_CONFIG_PATH=/dev/null wp handbook gen-all ``` +Since the command pages are generated from the nightly build, they can document commands and options that are not part of a stable release yet. To flag those on the generated pages, pass the latest stable Phar using `--stable-phar`: + +``` +curl -o /tmp/wp-cli-stable.phar https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar +WP_CLI_PACKAGES_DIR=bin/packages WP_CLI_CONFIG_PATH=/dev/null wp handbook gen-all --stable-phar=/tmp/wp-cli-stable.phar +``` + ## Automated Handbook Generation The handbook can be regenerated automatically using the "Regenerate Handbook" GitHub Actions workflow. This workflow can be triggered in two ways: @@ -28,8 +35,9 @@ The handbook can be regenerated automatically using the "Regenerate Handbook" Gi The workflow will: - Install WP-CLI nightly build +- Download the latest stable WP-CLI release - Install non-bundled packages -- Run `wp handbook gen-all` +- Run `wp handbook gen-all --stable-phar=...`, flagging commands and options that are not in the latest stable release yet - Commit and push any changes to the repository ## Documentation Import From ff94b60162116c3849c797b4336b5a084f9a5312 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 09:34:47 +0000 Subject: [PATCH 3/9] Run the stable Phar outside of the handbook directory Avoids loading the handbook's wp-cli.yml (and with it the handbook's Composer autoloader) into the stable Phar, and keeps PHP notices out of the JSON output of `cli cmd-dump`. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RVPkwDuM5DHXdSF4YW4qqr --- bin/Handbook_Command.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bin/Handbook_Command.php b/bin/Handbook_Command.php index 312db0a5..fa4f0dc8 100644 --- a/bin/Handbook_Command.php +++ b/bin/Handbook_Command.php @@ -348,19 +348,29 @@ private static function load_stable_reference( $phar ) { /** * Runs a WP-CLI command using the given Phar, inheriting the current environment. * + * The command runs outside of the handbook directory, so that the handbook's `wp-cli.yml` isn't loaded. + * * @param string $phar Path to the WP-CLI Phar. * @param string $command WP-CLI command to run, without the leading `wp`. * @return string Trimmed STDOUT. */ private static function run_phar( $phar, $command ) { + $env = getenv(); + if ( ! empty( $env['WP_CLI_PACKAGES_DIR'] ) && realpath( $env['WP_CLI_PACKAGES_DIR'] ) ) { + $env['WP_CLI_PACKAGES_DIR'] = (string) realpath( $env['WP_CLI_PACKAGES_DIR'] ); + } + $stderr_file = (string) tempnam( sys_get_temp_dir(), 'wp-cli-handbook' ); $process = proc_open( - Utils\esc_cmd( '%s %s', PHP_BINARY, $phar ) . ' ' . $command, + // Keep PHP notices out of STDOUT, which might be JSON. + Utils\esc_cmd( '%s -d display_errors=stderr %s', PHP_BINARY, (string) realpath( $phar ) ) . ' ' . $command, [ 1 => [ 'pipe', 'w' ], 2 => [ 'file', $stderr_file, 'w' ], ], - $pipes + $pipes, + sys_get_temp_dir(), + $env ); if ( ! is_resource( $process ) ) { WP_CLI::error( "Could not run '{$command}' using {$phar}." ); From a7f53d7bd4849c3d942801b16965f142af8f9b43 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 09:35:06 +0000 Subject: [PATCH 4/9] Show in which release commands and options first appeared Adds `bin/command-history.json`, which records for every bundled command and option the stable release it first appeared in. Command pages now show "Available since WP-CLI X.Y.Z" and "Options added later: ..." based on it. Nothing is shown for things that were already part of the oldest recorded release. `wp handbook gen-commands --stable-phar=...` records the stable release on every regeneration, so the history keeps itself up to date. The new `wp handbook update-command-history ...` command can backfill it from older releases. The history was backfilled from all releases since 2.4.0, the oldest release that still runs on PHP 8. See #666. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RVPkwDuM5DHXdSF4YW4qqr --- README.md | 10 + bin/Handbook_Command.php | 214 +- bin/command-history.json | 3308 ++++++++++++++++++++++++++++ bin/templates/subcmd-list.mustache | 4 +- 4 files changed, 3523 insertions(+), 13 deletions(-) create mode 100644 bin/command-history.json diff --git a/README.md b/README.md index a00bc072..d0fc5cef 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,16 @@ curl -o /tmp/wp-cli-stable.phar https://raw.githubusercontent.com/wp-cli/builds/ WP_CLI_PACKAGES_DIR=bin/packages WP_CLI_CONFIG_PATH=/dev/null wp handbook gen-all --stable-phar=/tmp/wp-cli-stable.phar ``` +This also records the stable release in `bin/command-history.json`, which keeps track of the release in which each command and option first appeared. Command pages show this as "Available since WP-CLI X.Y.Z" and "Options added later". Nothing is shown for commands and options that were already part of the oldest recorded release (`baseline`). + +To backfill the history from older releases, pass their Phars to `wp handbook update-command-history`. Releases can be given in any order, and the oldest release is kept for every command and option: + +``` +WP_CLI_CONFIG_PATH=/dev/null wp handbook update-command-history wp-cli-2.4.0.phar wp-cli-2.5.0.phar +``` + +The initial history was backfilled from all releases since 2.4.0, the oldest release that runs on PHP 8. + ## Automated Handbook Generation The handbook can be regenerated automatically using the "Regenerate Handbook" GitHub Actions workflow. This workflow can be triggered in two ways: diff --git a/bin/Handbook_Command.php b/bin/Handbook_Command.php index fa4f0dc8..c883096b 100644 --- a/bin/Handbook_Command.php +++ b/bin/Handbook_Command.php @@ -21,6 +21,16 @@ class Handbook_Command { */ const UNRELEASED_COMMAND_NOTE = 'This command is not yet available in the latest stable release of WP-CLI'; + /** + * Commands that are not bundled with WP-CLI, but documented in the handbook. + */ + const NON_BUNDLED_COMMANDS = [ 'admin', 'find', 'profile', 'dist-archive' ]; + + /** + * Commands that are not documented in the handbook. + */ + const IGNORED_COMMANDS = [ 'website', 'handbook' ]; + /** * Version of the latest stable WP-CLI release, if a stable Phar was given. * @@ -37,6 +47,15 @@ class Handbook_Command { */ private static $stable_commands = null; + /** + * Releases in which commands and options first appeared, as stored in `bin/command-history.json`. + * + * `baseline` is the oldest recorded release. Anything available in it may be older. + * + * @var array{baseline: string|null, commands: array}>}|null + */ + private static $command_history = null; + /** * @return string */ @@ -280,16 +299,20 @@ public function gen_commands( $args, $assoc_args ) { // Check non-bundled commands installed. $runner = WP_CLI::get_runner(); $have_nonbundled_installed = true; - foreach ( [ 'admin', 'find', 'profile', 'dist-archive' ] as $cmd ) { + foreach ( self::NON_BUNDLED_COMMANDS as $cmd ) { $have_nonbundled_installed = $have_nonbundled_installed && is_array( $runner->find_command_to_run( [ $cmd ] ) ); } if ( ! $have_nonbundled_installed ) { WP_CLI::error( sprintf( "Install non-bundled packages by running '%s' first.", 'bin/install_packages.sh' ) ); } + self::$command_history = self::load_command_history(); + $stable_phar = Utils\get_flag_value( $assoc_args, 'stable-phar' ); if ( $stable_phar ) { self::load_stable_reference( $stable_phar ); + self::record_command_history( self::$command_history, (string) self::$stable_version, (array) self::$stable_commands ); + self::save_command_history( self::$command_history ); } self::empty_dir( self::get_handbook_path() . '/commands/' ); @@ -306,7 +329,7 @@ public function gen_commands( $args, $assoc_args ) { $verbose = Utils\get_flag_value( $assoc_args, 'verbose', false ); foreach ( $wp['subcommands'] as $cmd ) { - if ( in_array( $cmd['name'], [ 'website', 'handbook' ], true ) ) { + if ( in_array( $cmd['name'], self::IGNORED_COMMANDS, true ) ) { continue; } self::gen_cmd_pages( $cmd, [] /*parent*/, $verbose ); @@ -315,6 +338,39 @@ public function gen_commands( $args, $assoc_args ) { WP_CLI::success( 'Generated all command pages.' ); } + /** + * Records in which releases commands and options first appeared. + * + * Updates `bin/command-history.json`, which is used to add "Available since" information to command pages. + * Releases can be given in any order. For each command and option, the oldest release is kept. + * + * Packages are skipped, so only bundled commands are recorded. + * + * ## OPTIONS + * + * ... + * : Paths to Phars of stable WP-CLI releases. + * + * ## EXAMPLES + * + * $ wp handbook update-command-history wp-cli-2.11.0.phar wp-cli-2.12.0.phar + * + * @subcommand update-command-history + * + * @param string[] $args Paths to WP-CLI Phars. + * @return void + */ + public function update_command_history( $args ) { + $history = self::load_command_history(); + foreach ( $args as $phar ) { + list( $version, $commands ) = self::dump_phar_commands( $phar, '--skip-packages' ); + self::record_command_history( $history, $version, $commands ); + WP_CLI::log( sprintf( 'Recorded WP-CLI %s (%d commands).', $version, count( $commands ) ) ); + } + self::save_command_history( $history ); + WP_CLI::success( sprintf( 'Updated bin/command-history.json with %d commands.', count( $history['commands'] ) ) ); + } + /** * Loads the commands and options available in the latest stable release. * @@ -322,27 +378,39 @@ public function gen_commands( $args, $assoc_args ) { * @return void */ private static function load_stable_reference( $phar ) { + list( self::$stable_version, self::$stable_commands ) = self::dump_phar_commands( $phar ); + + WP_CLI::log( sprintf( 'Comparing against WP-CLI %s (%d commands).', self::$stable_version, count( self::$stable_commands ) ) ); + } + + /** + * Gets the version and the commands of a WP-CLI Phar. + * + * @param string $phar Path to the WP-CLI Phar. + * @param string $global_args Global arguments to pass, e.g. `--skip-packages`. + * @return array{0: string, 1: array} Version and flattened commands. + */ + private static function dump_phar_commands( $phar, $global_args = '' ) { if ( ! is_file( $phar ) ) { - WP_CLI::error( "Stable Phar not found: {$phar}" ); + WP_CLI::error( "Phar not found: {$phar}" ); } - $version = self::run_phar( $phar, 'cli version' ); - if ( ! preg_match( '/(\d+\.\d+\.\d+)/', $version, $matches ) ) { - WP_CLI::error( "Could not determine version of stable Phar: {$version}" ); + $version = self::run_phar( $phar, trim( "{$global_args} cli version" ) ); + if ( ! preg_match( '/^WP-CLI (\S+)$/', $version, $matches ) ) { + WP_CLI::error( "Could not determine version of {$phar}: {$version}" ); } - self::$stable_version = $matches[1]; - $dump = json_decode( self::run_phar( $phar, 'cli cmd-dump' ), true ); + $dump = json_decode( self::run_phar( $phar, trim( "{$global_args} cli cmd-dump" ) ), true ); if ( ! is_array( $dump ) || ! isset( $dump['subcommands'] ) || ! is_array( $dump['subcommands'] ) ) { - WP_CLI::error( 'Could not dump commands of stable Phar.' ); + WP_CLI::error( "Could not dump commands of {$phar}." ); } - self::$stable_commands = []; + $commands = []; foreach ( $dump['subcommands'] as $cmd ) { - self::flatten_cmd_dump( $cmd, [], self::$stable_commands ); + self::flatten_cmd_dump( $cmd, [], $commands ); } - WP_CLI::log( sprintf( 'Comparing against WP-CLI %s (%d commands).', self::$stable_version, count( self::$stable_commands ) ) ); + return [ $matches[1], $commands ]; } /** @@ -472,6 +540,127 @@ private static function get_release_note( $full_name, $synopsis ) { ); } + /** + * Loads the command history from `bin/command-history.json`. + * + * @return array{baseline: string|null, commands: array}>} + */ + private static function load_command_history() { + $file = self::get_handbook_path() . '/bin/command-history.json'; + $history = is_file( $file ) ? json_decode( (string) file_get_contents( $file ), true ) : null; + if ( ! is_array( $history ) ) { + return [ + 'baseline' => null, + 'commands' => [], + ]; + } + return $history; + } + + /** + * Saves the command history to `bin/command-history.json`. + * + * @param array{baseline: string|null, commands: array}>} $history + * @return void + */ + private static function save_command_history( $history ) { + ksort( $history['commands'] ); + $data = $history; + foreach ( $data['commands'] as $full_name => $entry ) { + // Keep options a JSON object even if empty. + $data['commands'][ $full_name ]['options'] = (object) $entry['options']; + } + file_put_contents( + self::get_handbook_path() . '/bin/command-history.json', + json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) . PHP_EOL + ); + } + + /** + * Records the commands and options of a release in the command history, keeping the oldest release for each. + * + * @param array{baseline: string|null, commands: array}>} $history + * @param string $version Stable release version, e.g. `2.12.0`. + * @param array $commands Flattened commands of that release. + * @return void + */ + private static function record_command_history( &$history, $version, $commands ) { + if ( ! preg_match( '/^\d+\.\d+\.\d+$/', $version ) ) { + WP_CLI::error( "Only stable releases can be recorded in the command history, got {$version}." ); + } + + $is_older = static function ( $since ) use ( $version ) { + return null === $since || version_compare( $version, $since, '<' ); + }; + + if ( $is_older( $history['baseline'] ) ) { + $history['baseline'] = $version; + } + + $skipped = array_merge( self::NON_BUNDLED_COMMANDS, self::IGNORED_COMMANDS ); + foreach ( $commands as $full_name => $command ) { + if ( in_array( explode( ' ', $full_name )[0], $skipped, true ) ) { + continue; + } + + $entry = isset( $history['commands'][ $full_name ] ) ? $history['commands'][ $full_name ] : [ + 'since' => null, + 'generic' => false, + 'options' => [], + ]; + + if ( $is_older( $entry['since'] ) ) { + $entry['since'] = $version; + } + $entry['generic'] = $entry['generic'] || $command['generic']; + foreach ( $command['options'] as $option ) { + if ( $is_older( isset( $entry['options'][ $option ] ) ? $entry['options'][ $option ] : null ) ) { + $entry['options'][ $option ] = $version; + } + } + ksort( $entry['options'] ); + + $history['commands'][ $full_name ] = $entry; + } + } + + /** + * Builds a note about the releases in which a command and its options first appeared. + * + * Nothing is shown for commands and options that were already part of the oldest recorded release. + * + * @param string $full_name Full command name, e.g. `block type list`. + * @param string $synopsis Command synopsis. + * @return string Markdown note, or an empty string if there is nothing to show. + */ + private static function get_since_note( $full_name, $synopsis ) { + if ( empty( self::$command_history['commands'][ $full_name ] ) ) { + return ''; + } + + $entry = self::$command_history['commands'][ $full_name ]; + $parts = []; + + if ( $entry['since'] !== self::$command_history['baseline'] ) { + $parts[] = sprintf( 'Available since WP-CLI %s.', $entry['since'] ); + } + + // Commands accepting arbitrary options might have supported a newly documented option already. + if ( ! $entry['generic'] ) { + $later_options = []; + foreach ( self::get_option_names( $synopsis ) as $option ) { + if ( isset( $entry['options'][ $option ] ) && version_compare( $entry['options'][ $option ], $entry['since'], '>' ) ) { + $later_options[] = sprintf( '`%s` (%s)', $option, $entry['options'][ $option ] ); + } + } + if ( $later_options ) { + $parts[] = sprintf( 'Options added later: %s.', implode( ', ', $later_options ) ); + } + } + + return implode( ' ', $parts ); + } + /** * Update the commands data array with new data * @@ -788,6 +977,7 @@ private static function gen_cmd_pages( $cmd, $parent = [], $verbose = false ) { } $binding['has-subcommands'] = isset( $cmd['subcommands'] ) ? [ true ] : false; $binding['release-note'] = self::get_release_note( $binding['synopsis'], $cmd['synopsis'] ?? '' ); + $binding['since-note'] = self::get_since_note( $binding['synopsis'], $cmd['synopsis'] ?? '' ); $hook_name = $cmd['hook']; $hook_description = $hook_name ? Utils\get_hook_description( $hook_name ) : null; diff --git a/bin/command-history.json b/bin/command-history.json new file mode 100644 index 00000000..2ef60670 --- /dev/null +++ b/bin/command-history.json @@ -0,0 +1,3308 @@ +{ + "baseline": "2.4.0", + "commands": { + "cache": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cache add": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cache decr": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cache delete": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cache flush": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cache flush-group": { + "since": "2.8.0", + "generic": false, + "options": {} + }, + "cache get": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cache incr": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cache patch": { + "since": "2.12.0", + "generic": false, + "options": { + "--format": "2.12.0", + "--group": "2.12.0" + } + }, + "cache pluck": { + "since": "2.12.0", + "generic": false, + "options": { + "--format": "2.12.0", + "--group": "2.12.0" + } + }, + "cache replace": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cache set": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cache supports": { + "since": "2.8.0", + "generic": false, + "options": {} + }, + "cache type": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cap": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cap add": { + "since": "2.4.0", + "generic": false, + "options": { + "--grant": "2.4.0" + } + }, + "cap list": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0", + "--show-grant": "2.4.0" + } + }, + "cap remove": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cli": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cli alias": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cli alias add": { + "since": "2.4.0", + "generic": false, + "options": { + "--config": "2.4.0", + "--grouping": "2.4.0", + "--set-http": "2.4.0", + "--set-path": "2.4.0", + "--set-ssh": "2.4.0", + "--set-url": "2.4.0", + "--set-user": "2.4.0" + } + }, + "cli alias delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--config": "2.4.0" + } + }, + "cli alias get": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cli alias is-group": { + "since": "2.8.0", + "generic": false, + "options": {} + }, + "cli alias list": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "cli alias update": { + "since": "2.4.0", + "generic": false, + "options": { + "--config": "2.4.0", + "--grouping": "2.4.0", + "--set-http": "2.4.0", + "--set-path": "2.4.0", + "--set-ssh": "2.4.0", + "--set-url": "2.4.0", + "--set-user": "2.4.0" + } + }, + "cli cache": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cli cache clear": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cli cache prune": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cli check-update": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--major": "2.4.0", + "--minor": "2.4.0", + "--patch": "2.4.0" + } + }, + "cli cmd-dump": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cli completions": { + "since": "2.4.0", + "generic": false, + "options": { + "--line": "2.4.0", + "--point": "2.4.0" + } + }, + "cli has-command": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cli info": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "cli param-dump": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0", + "--with-values": "2.4.0" + } + }, + "cli update": { + "since": "2.4.0", + "generic": false, + "options": { + "--insecure": "2.5.0", + "--major": "2.4.0", + "--minor": "2.4.0", + "--nightly": "2.4.0", + "--patch": "2.4.0", + "--stable": "2.4.0", + "--yes": "2.4.0" + } + }, + "cli version": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment approve": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment count": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment create": { + "since": "2.4.0", + "generic": true, + "options": { + "--porcelain": "2.4.0" + } + }, + "comment delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--force": "2.4.0" + } + }, + "comment exists": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment generate": { + "since": "2.4.0", + "generic": false, + "options": { + "--count": "2.4.0", + "--format": "2.4.0", + "--post_id": "2.4.0" + } + }, + "comment get": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "comment list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "comment meta": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment meta add": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "comment meta delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0" + } + }, + "comment meta get": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0", + "--single": "2.12.0" + } + }, + "comment meta list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0", + "--keys": "2.4.0", + "--order": "2.4.0", + "--orderby": "2.4.0", + "--unserialize": "2.4.0" + } + }, + "comment meta patch": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "comment meta pluck": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "comment meta update": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "comment recount": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment spam": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment status": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment trash": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment unapprove": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment unspam": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment untrash": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "comment update": { + "since": "2.4.0", + "generic": true, + "options": {} + }, + "config": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "config create": { + "since": "2.4.0", + "generic": false, + "options": { + "--config-file": "2.6.0", + "--dbcharset": "2.4.0", + "--dbcollate": "2.4.0", + "--dbhost": "2.4.0", + "--dbname": "2.4.0", + "--dbpass": "2.4.0", + "--dbprefix": "2.4.0", + "--dbuser": "2.4.0", + "--extra-php": "2.4.0", + "--force": "2.4.0", + "--insecure": "2.5.0", + "--locale": "2.4.0", + "--skip-check": "2.4.0", + "--skip-salts": "2.4.0" + } + }, + "config delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--config-file": "2.6.0", + "--type": "2.4.0" + } + }, + "config edit": { + "since": "2.4.0", + "generic": false, + "options": { + "--config-file": "2.6.0" + } + }, + "config get": { + "since": "2.4.0", + "generic": false, + "options": { + "--config-file": "2.6.0", + "--format": "2.4.0", + "--type": "2.4.0" + } + }, + "config has": { + "since": "2.4.0", + "generic": false, + "options": { + "--config-file": "2.6.0", + "--type": "2.4.0" + } + }, + "config is-true": { + "since": "2.9.0", + "generic": false, + "options": { + "--config-file": "2.9.0", + "--type": "2.9.0" + } + }, + "config list": { + "since": "2.4.0", + "generic": false, + "options": { + "--config-file": "2.6.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--strict": "2.4.0" + } + }, + "config path": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "config set": { + "since": "2.4.0", + "generic": false, + "options": { + "--add": "2.4.0", + "--anchor": "2.4.0", + "--config-file": "2.6.0", + "--placement": "2.4.0", + "--raw": "2.4.0", + "--separator": "2.4.0", + "--type": "2.4.0" + } + }, + "config shuffle-salts": { + "since": "2.4.0", + "generic": false, + "options": { + "--config-file": "2.6.0", + "--force": "2.5.0", + "--insecure": "2.5.0" + } + }, + "core": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "core check-update": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--force-check": "2.10.0", + "--format": "2.4.0", + "--major": "2.4.0", + "--minor": "2.4.0" + } + }, + "core download": { + "since": "2.4.0", + "generic": false, + "options": { + "--extract": "2.7.0", + "--force": "2.4.0", + "--insecure": "2.5.0", + "--locale": "2.4.0", + "--path": "2.4.0", + "--skip-content": "2.4.0", + "--version": "2.4.0" + } + }, + "core install": { + "since": "2.4.0", + "generic": false, + "options": { + "--admin_email": "2.4.0", + "--admin_password": "2.4.0", + "--admin_user": "2.4.0", + "--locale": "2.7.0", + "--skip-email": "2.4.0", + "--title": "2.4.0", + "--url": "2.4.0" + } + }, + "core is-installed": { + "since": "2.4.0", + "generic": false, + "options": { + "--network": "2.4.0" + } + }, + "core multisite-convert": { + "since": "2.4.0", + "generic": false, + "options": { + "--base": "2.4.0", + "--skip-config": "2.8.0", + "--subdomains": "2.4.0", + "--title": "2.4.0" + } + }, + "core multisite-install": { + "since": "2.4.0", + "generic": false, + "options": { + "--admin_email": "2.4.0", + "--admin_password": "2.4.0", + "--admin_user": "2.4.0", + "--base": "2.4.0", + "--skip-config": "2.4.0", + "--skip-email": "2.4.0", + "--subdomains": "2.4.0", + "--title": "2.4.0", + "--url": "2.4.0" + } + }, + "core update": { + "since": "2.4.0", + "generic": false, + "options": { + "--force": "2.4.0", + "--insecure": "2.5.0", + "--locale": "2.4.0", + "--minor": "2.4.0", + "--version": "2.4.0" + } + }, + "core update-db": { + "since": "2.4.0", + "generic": false, + "options": { + "--dry-run": "2.4.0", + "--network": "2.4.0" + } + }, + "core verify-checksums": { + "since": "2.4.0", + "generic": false, + "options": { + "--exclude": "2.12.0", + "--include-root": "2.8.0", + "--insecure": "2.5.0", + "--locale": "2.4.0", + "--version": "2.4.0" + } + }, + "core version": { + "since": "2.4.0", + "generic": false, + "options": { + "--extra": "2.4.0" + } + }, + "cron": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cron event": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cron event delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.11.0", + "--due-now": "2.11.0", + "--exclude": "2.11.0" + } + }, + "cron event list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "cron event run": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--due-now": "2.4.0", + "--exclude": "2.8.0" + } + }, + "cron event schedule": { + "since": "2.4.0", + "generic": true, + "options": {} + }, + "cron event unschedule": { + "since": "2.5.0", + "generic": false, + "options": {} + }, + "cron schedule": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "cron schedule list": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "cron test": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "db": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "db check": { + "since": "2.4.0", + "generic": true, + "options": { + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.5.0" + } + }, + "db clean": { + "since": "2.4.0", + "generic": false, + "options": { + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.6.0", + "--yes": "2.4.0" + } + }, + "db cli": { + "since": "2.4.0", + "generic": true, + "options": { + "--database": "2.4.0", + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--default-character-set": "2.4.0", + "--defaults": "2.5.0" + } + }, + "db columns": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "db create": { + "since": "2.4.0", + "generic": false, + "options": { + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.6.0" + } + }, + "db drop": { + "since": "2.4.0", + "generic": false, + "options": { + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.6.0", + "--yes": "2.4.0" + } + }, + "db export": { + "since": "2.4.0", + "generic": true, + "options": { + "--add-drop-table": "2.12.0", + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.5.0", + "--exclude_tables": "2.4.0", + "--include-tablespaces": "2.5.0", + "--porcelain": "2.4.0", + "--tables": "2.4.0" + } + }, + "db import": { + "since": "2.4.0", + "generic": true, + "options": { + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.5.0", + "--skip-optimization": "2.4.0" + } + }, + "db optimize": { + "since": "2.4.0", + "generic": true, + "options": { + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.5.0" + } + }, + "db prefix": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "db query": { + "since": "2.4.0", + "generic": true, + "options": { + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.5.0" + } + }, + "db repair": { + "since": "2.4.0", + "generic": true, + "options": { + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.5.0" + } + }, + "db reset": { + "since": "2.4.0", + "generic": false, + "options": { + "--dbpass": "2.4.0", + "--dbuser": "2.4.0", + "--defaults": "2.6.0", + "--yes": "2.4.0" + } + }, + "db search": { + "since": "2.4.0", + "generic": false, + "options": { + "--after_context": "2.4.0", + "--all-tables": "2.4.0", + "--all-tables-with-prefix": "2.4.0", + "--before_context": "2.4.0", + "--fields": "2.11.0", + "--format": "2.11.0", + "--id_color": "2.4.0", + "--match_color": "2.4.0", + "--matches_only": "2.4.0", + "--network": "2.4.0", + "--one_line": "2.4.0", + "--regex": "2.4.0", + "--regex-delimiter": "2.4.0", + "--regex-flags": "2.4.0", + "--stats": "2.4.0", + "--table_column_color": "2.4.0", + "--table_column_once": "2.4.0" + } + }, + "db size": { + "since": "2.4.0", + "generic": false, + "options": { + "--all-tables": "2.4.0", + "--all-tables-with-prefix": "2.4.0", + "--decimals": "2.6.0", + "--format": "2.4.0", + "--human-readable": "2.4.0", + "--network": "2.4.0", + "--order": "2.7.0", + "--orderby": "2.7.0", + "--scope": "2.4.0", + "--size_format": "2.4.0", + "--tables": "2.4.0" + } + }, + "db tables": { + "since": "2.4.0", + "generic": false, + "options": { + "--all-tables": "2.4.0", + "--all-tables-with-prefix": "2.4.0", + "--format": "2.4.0", + "--network": "2.4.0", + "--scope": "2.4.0" + } + }, + "embed": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "embed cache": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "embed cache clear": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "embed cache find": { + "since": "2.4.0", + "generic": false, + "options": { + "--discover": "2.4.0", + "--height": "2.4.0", + "--width": "2.4.0" + } + }, + "embed cache trigger": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "embed fetch": { + "since": "2.4.0", + "generic": false, + "options": { + "--discover": "2.4.0", + "--do-shortcode": "2.4.0", + "--height": "2.4.0", + "--limit-response-size": "2.4.0", + "--post-id": "2.4.0", + "--raw": "2.4.0", + "--raw-format": "2.4.0", + "--skip-cache": "2.4.0", + "--skip-sanitization": "2.4.0", + "--width": "2.4.0" + } + }, + "embed handler": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "embed handler list": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "embed provider": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "embed provider list": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--force-regex": "2.4.0", + "--format": "2.4.0" + } + }, + "embed provider match": { + "since": "2.4.0", + "generic": false, + "options": { + "--discover": "2.4.0", + "--limit-response-size": "2.4.0", + "--link-type": "2.4.0" + } + }, + "eval": { + "since": "2.4.0", + "generic": false, + "options": { + "--skip-wordpress": "2.4.0" + } + }, + "eval-file": { + "since": "2.4.0", + "generic": false, + "options": { + "--skip-wordpress": "2.4.0", + "--use-include": "2.8.0" + } + }, + "export": { + "since": "2.4.0", + "generic": false, + "options": { + "--allow_orphan_terms": "2.9.0", + "--author": "2.4.0", + "--category": "2.4.0", + "--dir": "2.4.0", + "--end_date": "2.4.0", + "--filename_format": "2.4.0", + "--include_once": "2.8.0", + "--max_file_size": "2.4.0", + "--max_num_posts": "2.4.0", + "--post__in": "2.4.0", + "--post_status": "2.4.0", + "--post_type": "2.4.0", + "--post_type__not_in": "2.4.0", + "--skip_comments": "2.4.0", + "--start_date": "2.4.0", + "--start_id": "2.4.0", + "--stdout": "2.4.0", + "--with_attachments": "2.4.0" + } + }, + "help": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "i18n": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "i18n make-json": { + "since": "2.4.0", + "generic": false, + "options": { + "--domain": "2.12.0", + "--extensions": "2.12.0", + "--pretty-print": "2.4.0", + "--purge": "2.4.0", + "--update-mo-files": "2.6.0", + "--use-map": "2.6.0" + } + }, + "i18n make-mo": { + "since": "2.5.0", + "generic": false, + "options": {} + }, + "i18n make-php": { + "since": "2.10.0", + "generic": false, + "options": {} + }, + "i18n make-pot": { + "since": "2.4.0", + "generic": false, + "options": { + "--domain": "2.4.0", + "--exclude": "2.4.0", + "--file-comment": "2.4.0", + "--headers": "2.4.0", + "--ignore-domain": "2.4.0", + "--include": "2.4.0", + "--location": "2.6.0", + "--merge": "2.4.0", + "--package-name": "2.4.0", + "--skip-audit": "2.4.0", + "--skip-blade": "2.7.0", + "--skip-block-json": "2.5.0", + "--skip-js": "2.4.0", + "--skip-php": "2.5.0", + "--skip-theme-json": "2.6.0", + "--slug": "2.4.0", + "--subtract": "2.4.0", + "--subtract-and-merge": "2.6.0" + } + }, + "i18n update-po": { + "since": "2.7.0", + "generic": false, + "options": {} + }, + "import": { + "since": "2.4.0", + "generic": false, + "options": { + "--authors": "2.4.0", + "--skip": "2.4.0" + } + }, + "language": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "language core": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "language core activate": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "language core install": { + "since": "2.4.0", + "generic": false, + "options": { + "--activate": "2.4.0" + } + }, + "language core is-installed": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "language core list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "language core uninstall": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "language core update": { + "since": "2.4.0", + "generic": false, + "options": { + "--dry-run": "2.4.0" + } + }, + "language plugin": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "language plugin install": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--format": "2.4.0" + } + }, + "language plugin is-installed": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "language plugin list": { + "since": "2.4.0", + "generic": true, + "options": { + "--all": "2.4.0", + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "language plugin uninstall": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.9.0", + "--format": "2.9.0" + } + }, + "language plugin update": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--dry-run": "2.4.0" + } + }, + "language theme": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "language theme install": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--format": "2.4.0" + } + }, + "language theme is-installed": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "language theme list": { + "since": "2.4.0", + "generic": true, + "options": { + "--all": "2.4.0", + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "language theme uninstall": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.9.0", + "--format": "2.9.0" + } + }, + "language theme update": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--dry-run": "2.4.0" + } + }, + "maintenance-mode": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "maintenance-mode activate": { + "since": "2.4.0", + "generic": false, + "options": { + "--force": "2.4.0" + } + }, + "maintenance-mode deactivate": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "maintenance-mode is-active": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "maintenance-mode status": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "media": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "media fix-orientation": { + "since": "2.4.0", + "generic": false, + "options": { + "--dry-run": "2.4.0" + } + }, + "media image-size": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "media import": { + "since": "2.4.0", + "generic": false, + "options": { + "--alt": "2.4.0", + "--caption": "2.4.0", + "--desc": "2.4.0", + "--featured_image": "2.4.0", + "--file_name": "2.10.0", + "--porcelain": "2.4.0", + "--post_id": "2.4.0", + "--post_name": "2.8.0", + "--preserve-filetime": "2.4.0", + "--skip-copy": "2.4.0", + "--title": "2.4.0" + } + }, + "media regenerate": { + "since": "2.4.0", + "generic": false, + "options": { + "--delete-unknown": "2.11.0", + "--image_size": "2.4.0", + "--only-missing": "2.4.0", + "--skip-delete": "2.4.0", + "--yes": "2.4.0" + } + }, + "menu": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "menu create": { + "since": "2.4.0", + "generic": false, + "options": { + "--porcelain": "2.4.0" + } + }, + "menu delete": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "menu item": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "menu item add-custom": { + "since": "2.4.0", + "generic": false, + "options": { + "--attr-title": "2.4.0", + "--classes": "2.4.0", + "--description": "2.4.0", + "--parent-id": "2.4.0", + "--porcelain": "2.4.0", + "--position": "2.4.0", + "--target": "2.4.0" + } + }, + "menu item add-post": { + "since": "2.4.0", + "generic": false, + "options": { + "--attr-title": "2.4.0", + "--classes": "2.4.0", + "--description": "2.4.0", + "--link": "2.4.0", + "--parent-id": "2.4.0", + "--porcelain": "2.4.0", + "--position": "2.4.0", + "--target": "2.4.0", + "--title": "2.4.0" + } + }, + "menu item add-term": { + "since": "2.4.0", + "generic": false, + "options": { + "--attr-title": "2.4.0", + "--classes": "2.4.0", + "--description": "2.4.0", + "--link": "2.4.0", + "--parent-id": "2.4.0", + "--porcelain": "2.4.0", + "--position": "2.4.0", + "--target": "2.4.0", + "--title": "2.4.0" + } + }, + "menu item delete": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "menu item list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "menu item update": { + "since": "2.4.0", + "generic": false, + "options": { + "--attr-title": "2.4.0", + "--classes": "2.4.0", + "--description": "2.4.0", + "--link": "2.4.0", + "--parent-id": "2.4.0", + "--position": "2.4.0", + "--target": "2.4.0", + "--title": "2.4.0" + } + }, + "menu list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "menu location": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "menu location assign": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "menu location list": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "menu location remove": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "network": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "network meta": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "network meta add": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "network meta delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0" + } + }, + "network meta get": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0", + "--single": "2.12.0" + } + }, + "network meta list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0", + "--keys": "2.4.0", + "--order": "2.4.0", + "--orderby": "2.4.0", + "--unserialize": "2.4.0" + } + }, + "network meta patch": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "network meta pluck": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "network meta update": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "option": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "option add": { + "since": "2.4.0", + "generic": false, + "options": { + "--autoload": "2.4.0", + "--format": "2.4.0" + } + }, + "option delete": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "option get": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "option get-autoload": { + "since": "2.8.0", + "generic": false, + "options": {} + }, + "option list": { + "since": "2.4.0", + "generic": false, + "options": { + "--autoload": "2.4.0", + "--exclude": "2.4.0", + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--order": "2.4.0", + "--orderby": "2.4.0", + "--search": "2.4.0", + "--transients": "2.4.0", + "--unserialize": "2.4.0" + } + }, + "option patch": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "option pluck": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "option set-autoload": { + "since": "2.8.0", + "generic": false, + "options": {} + }, + "option update": { + "since": "2.4.0", + "generic": false, + "options": { + "--autoload": "2.4.0", + "--format": "2.4.0" + } + }, + "package": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "package browse": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "package install": { + "since": "2.4.0", + "generic": false, + "options": { + "--insecure": "2.5.0" + } + }, + "package list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "package path": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "package uninstall": { + "since": "2.4.0", + "generic": false, + "options": { + "--insecure": "2.6.0" + } + }, + "package update": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "plugin": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "plugin activate": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--exclude": "2.7.0", + "--network": "2.4.0" + } + }, + "plugin auto-updates": { + "since": "2.5.0", + "generic": false, + "options": {} + }, + "plugin auto-updates disable": { + "since": "2.5.0", + "generic": false, + "options": { + "--all": "2.5.0", + "--enabled-only": "2.5.0" + } + }, + "plugin auto-updates enable": { + "since": "2.5.0", + "generic": false, + "options": { + "--all": "2.5.0", + "--disabled-only": "2.5.0" + } + }, + "plugin auto-updates status": { + "since": "2.5.0", + "generic": false, + "options": { + "--all": "2.5.0", + "--disabled-only": "2.5.0", + "--enabled-only": "2.5.0", + "--field": "2.5.0", + "--format": "2.8.0" + } + }, + "plugin deactivate": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--exclude": "2.7.0", + "--network": "2.4.0", + "--uninstall": "2.4.0" + } + }, + "plugin delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--exclude": "2.7.0" + } + }, + "plugin get": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "plugin install": { + "since": "2.4.0", + "generic": false, + "options": { + "--activate": "2.4.0", + "--activate-network": "2.4.0", + "--force": "2.4.0", + "--ignore-requirements": "2.12.0", + "--insecure": "2.5.0", + "--version": "2.4.0" + } + }, + "plugin is-active": { + "since": "2.4.0", + "generic": false, + "options": { + "--network": "2.5.0" + } + }, + "plugin is-installed": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "plugin list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--recently-active": "2.11.0", + "--skip-update-check": "2.6.0", + "--status": "2.5.0" + } + }, + "plugin path": { + "since": "2.4.0", + "generic": false, + "options": { + "--dir": "2.4.0" + } + }, + "plugin search": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--page": "2.4.0", + "--per-page": "2.4.0" + } + }, + "plugin status": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "plugin toggle": { + "since": "2.4.0", + "generic": false, + "options": { + "--network": "2.4.0" + } + }, + "plugin uninstall": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--deactivate": "2.4.0", + "--exclude": "2.7.0", + "--skip-delete": "2.4.0" + } + }, + "plugin update": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--dry-run": "2.4.0", + "--exclude": "2.4.0", + "--format": "2.4.0", + "--insecure": "2.5.0", + "--minor": "2.4.0", + "--patch": "2.4.0", + "--version": "2.4.0" + } + }, + "plugin verify-checksums": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--exclude": "2.9.0", + "--format": "2.4.0", + "--insecure": "2.5.0", + "--strict": "2.4.0", + "--version": "2.8.0" + } + }, + "post": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "post create": { + "since": "2.4.0", + "generic": true, + "options": { + "--comment_status": "2.4.0", + "--edit": "2.4.0", + "--from-post": "2.4.0", + "--guid": "2.4.0", + "--menu_order": "2.4.0", + "--meta_input": "2.4.0", + "--ping_status": "2.4.0", + "--pinged": "2.4.0", + "--porcelain": "2.4.0", + "--post_author": "2.4.0", + "--post_category": "2.4.0", + "--post_content": "2.4.0", + "--post_content_filtered": "2.4.0", + "--post_date": "2.4.0", + "--post_date_gmt": "2.4.0", + "--post_excerpt": "2.4.0", + "--post_mime_type": "2.4.0", + "--post_modified": "2.4.0", + "--post_modified_gmt": "2.4.0", + "--post_name": "2.4.0", + "--post_parent": "2.4.0", + "--post_password": "2.4.0", + "--post_status": "2.4.0", + "--post_title": "2.4.0", + "--post_type": "2.4.0", + "--tags_input": "2.4.0", + "--tax_input": "2.4.0", + "--to_ping": "2.4.0" + } + }, + "post delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--defer-term-counting": "2.4.0", + "--force": "2.4.0" + } + }, + "post edit": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "post exists": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "post generate": { + "since": "2.4.0", + "generic": false, + "options": { + "--count": "2.4.0", + "--format": "2.4.0", + "--max_depth": "2.4.0", + "--post_author": "2.4.0", + "--post_content": "2.4.0", + "--post_date": "2.4.0", + "--post_date_gmt": "2.4.0", + "--post_status": "2.4.0", + "--post_title": "2.4.0", + "--post_type": "2.4.0" + } + }, + "post get": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "post list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "post meta": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "post meta add": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "post meta clean-duplicates": { + "since": "2.7.0", + "generic": false, + "options": {} + }, + "post meta delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0" + } + }, + "post meta get": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0", + "--single": "2.12.0" + } + }, + "post meta list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0", + "--keys": "2.4.0", + "--order": "2.4.0", + "--orderby": "2.4.0", + "--unserialize": "2.4.0" + } + }, + "post meta patch": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "post meta pluck": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "post meta update": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "post term": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "post term add": { + "since": "2.4.0", + "generic": false, + "options": { + "--by": "2.4.0" + } + }, + "post term list": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "post term remove": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--by": "2.4.0" + } + }, + "post term set": { + "since": "2.4.0", + "generic": false, + "options": { + "--by": "2.4.0" + } + }, + "post update": { + "since": "2.4.0", + "generic": true, + "options": { + "--comment_status": "2.4.0", + "--defer-term-counting": "2.4.0", + "--guid": "2.4.0", + "--menu_order": "2.4.0", + "--meta_input": "2.4.0", + "--ping_status": "2.4.0", + "--pinged": "2.4.0", + "--post_author": "2.4.0", + "--post_category": "2.4.0", + "--post_content": "2.4.0", + "--post_content_filtered": "2.4.0", + "--post_date": "2.4.0", + "--post_date_gmt": "2.4.0", + "--post_excerpt": "2.4.0", + "--post_mime_type": "2.4.0", + "--post_modified": "2.4.0", + "--post_modified_gmt": "2.4.0", + "--post_name": "2.4.0", + "--post_parent": "2.4.0", + "--post_password": "2.4.0", + "--post_status": "2.4.0", + "--post_title": "2.4.0", + "--post_type": "2.4.0", + "--tags_input": "2.4.0", + "--tax_input": "2.4.0", + "--to_ping": "2.4.0" + } + }, + "post url-to-id": { + "since": "2.10.0", + "generic": false, + "options": {} + }, + "post-type": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "post-type get": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "post-type list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "rewrite": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "rewrite flush": { + "since": "2.4.0", + "generic": false, + "options": { + "--hard": "2.4.0" + } + }, + "rewrite list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0", + "--match": "2.4.0", + "--source": "2.4.0" + } + }, + "rewrite structure": { + "since": "2.4.0", + "generic": false, + "options": { + "--category-base": "2.4.0", + "--hard": "2.4.0", + "--tag-base": "2.4.0" + } + }, + "role": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "role create": { + "since": "2.4.0", + "generic": false, + "options": { + "--clone": "2.4.0" + } + }, + "role delete": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "role exists": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "role list": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "role reset": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0" + } + }, + "scaffold": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "scaffold block": { + "since": "2.4.0", + "generic": false, + "options": { + "--category": "2.4.0", + "--dashicon": "2.4.0", + "--force": "2.4.0", + "--plugin": "2.4.0", + "--theme": "2.4.0", + "--title": "2.4.0" + } + }, + "scaffold child-theme": { + "since": "2.4.0", + "generic": false, + "options": { + "--activate": "2.4.0", + "--author": "2.4.0", + "--author_uri": "2.4.0", + "--enable-network": "2.4.0", + "--force": "2.4.0", + "--parent_theme": "2.4.0", + "--theme_name": "2.4.0", + "--theme_uri": "2.4.0" + } + }, + "scaffold plugin": { + "since": "2.4.0", + "generic": false, + "options": { + "--activate": "2.4.0", + "--activate-network": "2.4.0", + "--ci": "2.4.0", + "--dir": "2.4.0", + "--force": "2.4.0", + "--plugin_author": "2.4.0", + "--plugin_author_uri": "2.4.0", + "--plugin_description": "2.4.0", + "--plugin_name": "2.4.0", + "--plugin_uri": "2.4.0", + "--skip-tests": "2.4.0" + } + }, + "scaffold plugin-tests": { + "since": "2.4.0", + "generic": false, + "options": { + "--ci": "2.4.0", + "--dir": "2.4.0", + "--force": "2.4.0" + } + }, + "scaffold post-type": { + "since": "2.4.0", + "generic": false, + "options": { + "--dashicon": "2.4.0", + "--force": "2.4.0", + "--label": "2.4.0", + "--plugin": "2.4.0", + "--raw": "2.4.0", + "--textdomain": "2.4.0", + "--theme": "2.4.0" + } + }, + "scaffold taxonomy": { + "since": "2.4.0", + "generic": false, + "options": { + "--force": "2.4.0", + "--label": "2.4.0", + "--plugin": "2.4.0", + "--post_types": "2.4.0", + "--raw": "2.4.0", + "--textdomain": "2.4.0", + "--theme": "2.4.0" + } + }, + "scaffold theme-tests": { + "since": "2.4.0", + "generic": false, + "options": { + "--ci": "2.4.0", + "--dir": "2.4.0", + "--force": "2.4.0" + } + }, + "scaffold underscores": { + "since": "2.4.0", + "generic": false, + "options": { + "--activate": "2.4.0", + "--author": "2.4.0", + "--author_uri": "2.4.0", + "--enable-network": "2.4.0", + "--force": "2.4.0", + "--sassify": "2.4.0", + "--theme_name": "2.4.0", + "--woocommerce": "2.4.0" + } + }, + "search-replace": { + "since": "2.4.0", + "generic": false, + "options": { + "--after_context": "2.4.0", + "--all-tables": "2.4.0", + "--all-tables-with-prefix": "2.4.0", + "--before_context": "2.4.0", + "--dry-run": "2.4.0", + "--export": "2.4.0", + "--export_insert_size": "2.4.0", + "--format": "2.4.0", + "--include-columns": "2.4.0", + "--log": "2.4.0", + "--network": "2.4.0", + "--precise": "2.4.0", + "--recurse-objects": "2.4.0", + "--regex": "2.4.0", + "--regex-delimiter": "2.4.0", + "--regex-flags": "2.4.0", + "--regex-limit": "2.4.0", + "--report": "2.4.0", + "--report-changed-only": "2.4.0", + "--skip-columns": "2.4.0", + "--skip-tables": "2.4.0", + "--verbose": "2.4.0" + } + }, + "server": { + "since": "2.4.0", + "generic": false, + "options": { + "--config": "2.4.0", + "--docroot": "2.4.0", + "--host": "2.4.0", + "--port": "2.4.0" + } + }, + "shell": { + "since": "2.4.0", + "generic": false, + "options": { + "--basic": "2.4.0" + } + }, + "sidebar": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "sidebar list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "site": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "site activate": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "site archive": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "site create": { + "since": "2.4.0", + "generic": false, + "options": { + "--email": "2.4.0", + "--network_id": "2.4.0", + "--porcelain": "2.4.0", + "--private": "2.4.0", + "--slug": "2.4.0", + "--title": "2.4.0" + } + }, + "site deactivate": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "site delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--keep-tables": "2.4.0", + "--slug": "2.4.0", + "--yes": "2.4.0" + } + }, + "site empty": { + "since": "2.4.0", + "generic": false, + "options": { + "--uploads": "2.4.0", + "--yes": "2.4.0" + } + }, + "site generate": { + "since": "2.11.0", + "generic": false, + "options": { + "--count": "2.11.0", + "--email": "2.11.0", + "--format": "2.11.0", + "--network_id": "2.11.0", + "--private": "2.11.0", + "--slug": "2.11.0" + } + }, + "site list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--network": "2.4.0", + "--site__in": "2.4.0", + "--site_user": "2.10.0" + } + }, + "site mature": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "site meta": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "site meta add": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "site meta delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0" + } + }, + "site meta get": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0", + "--single": "2.12.0" + } + }, + "site meta list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0", + "--keys": "2.4.0", + "--order": "2.4.0", + "--orderby": "2.4.0", + "--unserialize": "2.4.0" + } + }, + "site meta patch": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "site meta pluck": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "site meta update": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "site option": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "site option add": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "site option delete": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "site option get": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "site option list": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--search": "2.4.0", + "--site_id": "2.4.0" + } + }, + "site option patch": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "site option pluck": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "site option update": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "site private": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "site public": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "site spam": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "site switch-language": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "site unarchive": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "site unmature": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "site unspam": { + "since": "2.4.0", + "generic": false, + "options": { + "--slug": "2.9.0" + } + }, + "super-admin": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "super-admin add": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "super-admin list": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "super-admin remove": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "taxonomy": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "taxonomy get": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "taxonomy list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "term": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "term create": { + "since": "2.4.0", + "generic": false, + "options": { + "--description": "2.4.0", + "--parent": "2.4.0", + "--porcelain": "2.4.0", + "--slug": "2.4.0" + } + }, + "term delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--by": "2.4.0" + } + }, + "term generate": { + "since": "2.4.0", + "generic": false, + "options": { + "--count": "2.4.0", + "--format": "2.4.0", + "--max_depth": "2.4.0" + } + }, + "term get": { + "since": "2.4.0", + "generic": false, + "options": { + "--by": "2.4.0", + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "term list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "term meta": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "term meta add": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "term meta delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0" + } + }, + "term meta get": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0", + "--single": "2.12.0" + } + }, + "term meta list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0", + "--keys": "2.4.0", + "--order": "2.4.0", + "--orderby": "2.4.0", + "--unserialize": "2.4.0" + } + }, + "term meta patch": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "term meta pluck": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "term meta update": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "term migrate": { + "since": "2.4.0", + "generic": false, + "options": { + "--by": "2.4.0", + "--from": "2.4.0", + "--to": "2.4.0" + } + }, + "term recount": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "term update": { + "since": "2.4.0", + "generic": false, + "options": { + "--by": "2.4.0", + "--description": "2.4.0", + "--name": "2.4.0", + "--parent": "2.4.0", + "--slug": "2.4.0" + } + }, + "theme": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "theme activate": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "theme auto-updates": { + "since": "2.5.0", + "generic": false, + "options": {} + }, + "theme auto-updates disable": { + "since": "2.5.0", + "generic": false, + "options": { + "--all": "2.5.0", + "--enabled-only": "2.5.0" + } + }, + "theme auto-updates enable": { + "since": "2.5.0", + "generic": false, + "options": { + "--all": "2.5.0", + "--disabled-only": "2.5.0" + } + }, + "theme auto-updates status": { + "since": "2.5.0", + "generic": false, + "options": { + "--all": "2.5.0", + "--disabled-only": "2.5.0", + "--enabled-only": "2.5.0", + "--field": "2.5.0", + "--format": "2.8.0" + } + }, + "theme delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--force": "2.4.0" + } + }, + "theme disable": { + "since": "2.4.0", + "generic": false, + "options": { + "--network": "2.4.0" + } + }, + "theme enable": { + "since": "2.4.0", + "generic": false, + "options": { + "--activate": "2.4.0", + "--network": "2.4.0" + } + }, + "theme get": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "theme install": { + "since": "2.4.0", + "generic": false, + "options": { + "--activate": "2.4.0", + "--force": "2.4.0", + "--ignore-requirements": "2.12.0", + "--insecure": "2.5.0", + "--version": "2.4.0" + } + }, + "theme is-active": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "theme is-installed": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "theme list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--skip-update-check": "2.6.0", + "--status": "2.5.0" + } + }, + "theme mod": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "theme mod get": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--field": "2.4.0", + "--format": "2.4.0" + } + }, + "theme mod list": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--format": "2.4.0" + } + }, + "theme mod remove": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0" + } + }, + "theme mod set": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "theme path": { + "since": "2.4.0", + "generic": false, + "options": { + "--dir": "2.4.0" + } + }, + "theme search": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--page": "2.4.0", + "--per-page": "2.4.0" + } + }, + "theme status": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "theme update": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--dry-run": "2.4.0", + "--exclude": "2.4.0", + "--format": "2.4.0", + "--insecure": "2.5.0", + "--minor": "2.10.0", + "--patch": "2.10.0", + "--version": "2.4.0" + } + }, + "transient": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "transient delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--expired": "2.4.0", + "--network": "2.4.0" + } + }, + "transient get": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0", + "--network": "2.4.0" + } + }, + "transient list": { + "since": "2.4.0", + "generic": false, + "options": { + "--exclude": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--human-readable": "2.4.0", + "--network": "2.4.0", + "--search": "2.4.0", + "--unserialize": "2.4.0" + } + }, + "transient patch": { + "since": "2.12.0", + "generic": false, + "options": { + "--expiration": "2.12.0", + "--format": "2.12.0", + "--network": "2.12.0" + } + }, + "transient pluck": { + "since": "2.12.0", + "generic": false, + "options": { + "--format": "2.12.0", + "--network": "2.12.0" + } + }, + "transient set": { + "since": "2.4.0", + "generic": false, + "options": { + "--network": "2.4.0" + } + }, + "transient type": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user add-cap": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user add-role": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user application-password": { + "since": "2.6.0", + "generic": false, + "options": {} + }, + "user application-password create": { + "since": "2.6.0", + "generic": false, + "options": { + "--app-id": "2.6.0", + "--porcelain": "2.6.0" + } + }, + "user application-password delete": { + "since": "2.6.0", + "generic": false, + "options": { + "--all": "2.6.0" + } + }, + "user application-password exists": { + "since": "2.6.0", + "generic": false, + "options": {} + }, + "user application-password get": { + "since": "2.6.0", + "generic": false, + "options": { + "--field": "2.6.0", + "--fields": "2.6.0", + "--format": "2.6.0" + } + }, + "user application-password list": { + "since": "2.6.0", + "generic": true, + "options": { + "--field": "2.6.0", + "--fields": "2.6.0", + "--format": "2.6.0", + "--order": "2.6.0", + "--orderby": "2.6.0" + } + }, + "user application-password record-usage": { + "since": "2.6.0", + "generic": false, + "options": {} + }, + "user application-password update": { + "since": "2.6.0", + "generic": true, + "options": {} + }, + "user check-password": { + "since": "2.4.0", + "generic": false, + "options": { + "--escape-chars": "2.5.0" + } + }, + "user create": { + "since": "2.4.0", + "generic": false, + "options": { + "--description": "2.4.0", + "--display_name": "2.4.0", + "--first_name": "2.4.0", + "--last_name": "2.4.0", + "--nickname": "2.4.0", + "--porcelain": "2.4.0", + "--rich_editing": "2.4.0", + "--role": "2.4.0", + "--send-email": "2.4.0", + "--user_nicename": "2.4.0", + "--user_pass": "2.4.0", + "--user_registered": "2.4.0", + "--user_url": "2.4.0" + } + }, + "user delete": { + "since": "2.4.0", + "generic": false, + "options": { + "--network": "2.4.0", + "--reassign": "2.4.0", + "--yes": "2.4.0" + } + }, + "user exists": { + "since": "2.11.0", + "generic": false, + "options": {} + }, + "user generate": { + "since": "2.4.0", + "generic": false, + "options": { + "--count": "2.4.0", + "--format": "2.4.0", + "--role": "2.4.0" + } + }, + "user get": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "user import-csv": { + "since": "2.4.0", + "generic": false, + "options": { + "--send-email": "2.4.0", + "--skip-update": "2.4.0" + } + }, + "user list": { + "since": "2.4.0", + "generic": true, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0", + "--network": "2.4.0", + "--role": "2.4.0" + } + }, + "user list-caps": { + "since": "2.4.0", + "generic": false, + "options": { + "--exclude-role-names": "2.10.0", + "--format": "2.4.0", + "--origin": "2.10.0" + } + }, + "user meta": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user meta add": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "user meta delete": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user meta get": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "user meta list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0", + "--keys": "2.4.0", + "--order": "2.4.0", + "--orderby": "2.4.0", + "--unserialize": "2.4.0" + } + }, + "user meta patch": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "user meta pluck": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "user meta update": { + "since": "2.4.0", + "generic": false, + "options": { + "--format": "2.4.0" + } + }, + "user remove-cap": { + "since": "2.4.0", + "generic": false, + "options": { + "--force": "2.12.0" + } + }, + "user remove-role": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user reset-password": { + "since": "2.4.0", + "generic": false, + "options": { + "--porcelain": "2.8.0", + "--show-password": "2.8.0", + "--skip-email": "2.4.0" + } + }, + "user session": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user session destroy": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0" + } + }, + "user session list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "user set-role": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user signup": { + "since": "2.11.0", + "generic": false, + "options": {} + }, + "user signup activate": { + "since": "2.11.0", + "generic": false, + "options": {} + }, + "user signup delete": { + "since": "2.11.0", + "generic": false, + "options": { + "--all": "2.11.0" + } + }, + "user signup get": { + "since": "2.11.0", + "generic": false, + "options": { + "--field": "2.11.0", + "--fields": "2.11.0", + "--format": "2.11.0" + } + }, + "user signup list": { + "since": "2.11.0", + "generic": true, + "options": { + "--field": "2.11.0", + "--fields": "2.11.0", + "--format": "2.11.0", + "--per_page": "2.11.0" + } + }, + "user spam": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user term": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user term add": { + "since": "2.4.0", + "generic": false, + "options": { + "--by": "2.4.0" + } + }, + "user term list": { + "since": "2.4.0", + "generic": false, + "options": { + "--field": "2.4.0", + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "user term remove": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0", + "--by": "2.4.0" + } + }, + "user term set": { + "since": "2.4.0", + "generic": false, + "options": { + "--by": "2.4.0" + } + }, + "user unspam": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "user update": { + "since": "2.4.0", + "generic": true, + "options": { + "--description": "2.4.0", + "--display_name": "2.4.0", + "--first_name": "2.4.0", + "--last_name": "2.4.0", + "--nickname": "2.4.0", + "--rich_editing": "2.4.0", + "--role": "2.4.0", + "--skip-email": "2.4.0", + "--user_email": "2.4.0", + "--user_nicename": "2.4.0", + "--user_pass": "2.4.0", + "--user_registered": "2.4.0", + "--user_url": "2.4.0" + } + }, + "widget": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "widget add": { + "since": "2.4.0", + "generic": true, + "options": {} + }, + "widget deactivate": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "widget delete": { + "since": "2.4.0", + "generic": false, + "options": {} + }, + "widget list": { + "since": "2.4.0", + "generic": false, + "options": { + "--fields": "2.4.0", + "--format": "2.4.0" + } + }, + "widget move": { + "since": "2.4.0", + "generic": false, + "options": { + "--position": "2.4.0", + "--sidebar-id": "2.4.0" + } + }, + "widget reset": { + "since": "2.4.0", + "generic": false, + "options": { + "--all": "2.4.0" + } + }, + "widget update": { + "since": "2.4.0", + "generic": true, + "options": {} + } + } +} diff --git a/bin/templates/subcmd-list.mustache b/bin/templates/subcmd-list.mustache index 4326f714..2dbd8361 100644 --- a/bin/templates/subcmd-list.mustache +++ b/bin/templates/subcmd-list.mustache @@ -4,6 +4,8 @@ **Alias:** `{{alias}}`{{/alias}}{{#release-note}} -{{{release-note}}}{{/release-note}} +{{{release-note}}}{{/release-note}}{{#since-note}} + +{{{since-note}}}{{/since-note}} {{{docs}}} From ee5ed48ac42e0ddaaa81ad5cc47a4418d7396457 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 09:48:52 +0000 Subject: [PATCH 5/9] Fix PHPStan error in command history recording Start new history entries at the recorded release instead of null, so `since` is always a string. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RVPkwDuM5DHXdSF4YW4qqr --- bin/Handbook_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/Handbook_Command.php b/bin/Handbook_Command.php index c883096b..e015456c 100644 --- a/bin/Handbook_Command.php +++ b/bin/Handbook_Command.php @@ -604,7 +604,7 @@ private static function record_command_history( &$history, $version, $commands ) } $entry = isset( $history['commands'][ $full_name ] ) ? $history['commands'][ $full_name ] : [ - 'since' => null, + 'since' => $version, 'generic' => false, 'options' => [], ]; From 3c5481f93d96cc569986f86dc4909dc49616f516 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 09:49:16 +0000 Subject: [PATCH 6/9] Reject prerelease Phars as stable reference Comparing against a nightly Phar would silently drop the notes. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RVPkwDuM5DHXdSF4YW4qqr --- bin/Handbook_Command.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/Handbook_Command.php b/bin/Handbook_Command.php index fa4f0dc8..cdaccb97 100644 --- a/bin/Handbook_Command.php +++ b/bin/Handbook_Command.php @@ -327,8 +327,8 @@ private static function load_stable_reference( $phar ) { } $version = self::run_phar( $phar, 'cli version' ); - if ( ! preg_match( '/(\d+\.\d+\.\d+)/', $version, $matches ) ) { - WP_CLI::error( "Could not determine version of stable Phar: {$version}" ); + if ( ! preg_match( '/^WP-CLI (\d+\.\d+\.\d+)$/', $version, $matches ) ) { + WP_CLI::error( "Not a stable WP-CLI release: {$version}" ); } self::$stable_version = $matches[1]; From bcdca8bf80ec978163aecc473af64b9cd50d32fa Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 09:50:35 +0000 Subject: [PATCH 7/9] Drop the version number from the unreleased notes "Not available in the latest stable release (2.12.0)" reads as if the command should be in 2.12.0. Say it's not part of a stable release yet instead, which also keeps flagged pages from changing on every release. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RVPkwDuM5DHXdSF4YW4qqr --- bin/Handbook_Command.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/bin/Handbook_Command.php b/bin/Handbook_Command.php index cdaccb97..aaaab19b 100644 --- a/bin/Handbook_Command.php +++ b/bin/Handbook_Command.php @@ -19,7 +19,7 @@ class Handbook_Command { * * Also used to detect such commands when generating the commands manifest. */ - const UNRELEASED_COMMAND_NOTE = 'This command is not yet available in the latest stable release of WP-CLI'; + const UNRELEASED_COMMAND_NOTE = 'This command is not part of a stable WP-CLI release yet.'; /** * Version of the latest stable WP-CLI release, if a stable Phar was given. @@ -447,9 +447,8 @@ private static function get_release_note( $full_name, $synopsis ) { if ( ! isset( self::$stable_commands[ $full_name ] ) ) { return sprintf( - '> **Note:** %s (%s). %s', + '> **Note:** %s %s', self::UNRELEASED_COMMAND_NOTE, - self::$stable_version, sprintf( $nightly, 'it' ) ); } @@ -465,8 +464,7 @@ private static function get_release_note( $full_name, $synopsis ) { } return sprintf( - '> **Note:** The following options are not yet available in the latest stable release of WP-CLI (%s): %s. %s', - self::$stable_version, + '> **Note:** The following options are not part of a stable WP-CLI release yet: %s. %s', '`' . implode( '`, `', $unreleased ) . '`', sprintf( $nightly, 'them' ) ); From 8467924619d80dacbebbd7ea2103c97257389e6f Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 10:53:19 +0000 Subject: [PATCH 8/9] Compare option aliases too Nightly synopses can declare option aliases, e.g. `[--dbpass|db_password=]`. Treat every alias as an option name, so a newly added alias like `config create --db_password` is flagged as unreleased as well. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RVPkwDuM5DHXdSF4YW4qqr --- bin/Handbook_Command.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bin/Handbook_Command.php b/bin/Handbook_Command.php index aaaab19b..02c38249 100644 --- a/bin/Handbook_Command.php +++ b/bin/Handbook_Command.php @@ -418,6 +418,8 @@ private static function flatten_cmd_dump( $cmd, $parent, &$out ) { // phpcs:igno /** * Extracts the option names (e.g. `--format`) from a command synopsis. * + * Option aliases (e.g. `--dbpass|db_password`) are included as separate names. + * * @param string $synopsis Command synopsis. * @return string[] */ @@ -426,6 +428,9 @@ private static function get_option_names( $synopsis ) { foreach ( WP_CLI\SynopsisParser::parse( $synopsis ) as $param ) { if ( in_array( $param['type'], [ 'assoc', 'flag' ], true ) && isset( $param['name'] ) ) { $options[] = '--' . $param['name']; + foreach ( isset( $param['aliases'] ) ? (array) $param['aliases'] : [] as $alias ) { + $options[] = '--' . $alias; + } } } return $options; From 50fe929d62cf09040c8a4707f0a842163b423861 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 10:53:42 +0000 Subject: [PATCH 9/9] Clarify that the history records bundle releases Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RVPkwDuM5DHXdSF4YW4qqr --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d0fc5cef..2dbc87e4 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ curl -o /tmp/wp-cli-stable.phar https://raw.githubusercontent.com/wp-cli/builds/ WP_CLI_PACKAGES_DIR=bin/packages WP_CLI_CONFIG_PATH=/dev/null wp handbook gen-all --stable-phar=/tmp/wp-cli-stable.phar ``` -This also records the stable release in `bin/command-history.json`, which keeps track of the release in which each command and option first appeared. Command pages show this as "Available since WP-CLI X.Y.Z" and "Options added later". Nothing is shown for commands and options that were already part of the oldest recorded release (`baseline`). +This also records the stable release in `bin/command-history.json`, which keeps track of the first bundled WP-CLI release in which each command and option appeared. Command pages show this as "Available since WP-CLI X.Y.Z" and "Options added later". This is the bundle release, not the version of the package that provides the command: if a package is updated on its own, a command can be available earlier. Nothing is shown for commands and options that were already part of the oldest recorded release (`baseline`). To backfill the history from older releases, pass their Phars to `wp handbook update-command-history`. Releases can be given in any order, and the oldest release is kept for every command and option: