src/Rewrite_Command.php
public function list_( $args, $assoc_args ) {
		global $wp_rewrite;

		$rules = get_option( 'rewrite_rules' );
		if ( ! $rules ) {
			$rules = [];
			WP_CLI::warning( 'No rewrite rules.' );
		}

		self::check_skip_plugins_themes();

		$defaults   = [
			'source' => '',
			'match'  => '',
			'format' => 'table',
			'fields' => 'match,query,source',
		];
		$assoc_args = array_merge( $defaults, $assoc_args );

		$rewrite_rules_by_source             = [];
		$rewrite_rules_by_source['post']     = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->permalink_structure, EP_PERMALINK );
		$rewrite_rules_by_source['date']     = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_date_permastruct(), EP_DATE );
		$rewrite_rules_by_source['root']     = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->root . '/', EP_ROOT );
		$rewrite_rules_by_source['comments'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->root . $wp_rewrite->comments_base, EP_COMMENTS, true, true, true, false );
		$rewrite_rules_by_source['search']   = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_search_permastruct(), EP_SEARCH );
		$rewrite_rules_by_source['author']   = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_author_permastruct(), EP_AUTHORS );
		$rewrite_rules_by_source['page']     = $wp_rewrite->page_rewrite_rules();

		// Extra permastructs including tags, categories, etc.
		foreach ( $wp_rewrite->extra_permastructs as $permastructname => $permastruct ) {
			if ( is_array( $permastruct ) ) {
				$rewrite_rules_by_source[ $permastructname ] = $wp_rewrite->generate_rewrite_rules( $permastruct['struct'], $permastruct['ep_mask'], $permastruct['paged'], $permastruct['feed'], $permastruct['forcomments'], $permastruct['walk_dirs'], $permastruct['endpoints'] );
			} else {
				$rewrite_rules_by_source[ $permastructname ] = $wp_rewrite->generate_rewrite_rules( $permastruct, EP_NONE );
			}
		}

		// Apply the filters used in core just in case
		foreach ( $rewrite_rules_by_source as $source => $source_rules ) {
			// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- Can't prefix dynamic hooks here, calling hooks for custom permastructs.
			$rewrite_rules_by_source[ $source ] = apply_filters( $source . '_rewrite_rules', $source_rules );
			if ( 'post_tag' === $source ) {
				if ( Utils\wp_version_compare( '3.1.0', '>=' ) ) {
					// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Calling native WordPress hook.
					$rewrite_rules_by_source[ $source ] = apply_filters( 'post_tag_rewrite_rules', $source_rules );
				} else {
					// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Calling native WordPress hook.
					$rewrite_rules_by_source[ $source ] = apply_filters( 'tag_rewrite_rules', $source_rules );
				}
			}
		}

		$rule_list = [];
		foreach ( $rules as $match => $query ) {

			if ( ! empty( $assoc_args['match'] ) && ! preg_match( "!^$match!", trim( $assoc_args['match'], '/' ) ) ) {
				continue;
			}

			$source = 'other';
			foreach ( $rewrite_rules_by_source as $rules_source => $source_rules ) {
				if ( array_key_exists( $match, $source_rules ) ) {
					$source = $rules_source;
				}
			}

			if ( ! empty( $assoc_args['source'] ) && $source !== $assoc_args['source'] ) {
				continue;
			}

			$rule_list[] = compact( 'match', 'query', 'source' );
		}

		Utils\format_items( $assoc_args['format'], $rule_list, explode( ',', $assoc_args['fields'] ) );
	}
public function list_( $args, $assoc_args ) {
		global $wp_rewrite;

		$rules = get_option( 'rewrite_rules' );
		if ( ! $rules ) {
			$rules = [];
			WP_CLI::warning( 'No rewrite rules.' );
		}

		self::check_skip_plugins_themes();

		$defaults   = [
			'source' => '',
			'match'  => '',
			'format' => 'table',
			'fields' => 'match,query,source',
		];
		$assoc_args = array_merge( $defaults, $assoc_args );

		$rewrite_rules_by_source             = [];
		$rewrite_rules_by_source['post']     = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->permalink_structure, EP_PERMALINK );
		$rewrite_rules_by_source['date']     = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_date_permastruct(), EP_DATE );
		$rewrite_rules_by_source['root']     = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->root . '/', EP_ROOT );
		$rewrite_rules_by_source['comments'] = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->root . $wp_rewrite->comments_base, EP_COMMENTS, true, true, true, false );
		$rewrite_rules_by_source['search']   = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_search_permastruct(), EP_SEARCH );
		$rewrite_rules_by_source['author']   = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_author_permastruct(), EP_AUTHORS );
		$rewrite_rules_by_source['page']     = $wp_rewrite->page_rewrite_rules();

		// Extra permastructs including tags, categories, etc.
		foreach ( $wp_rewrite->extra_permastructs as $permastructname => $permastruct ) {
			if ( is_array( $permastruct ) ) {
				$rewrite_rules_by_source[ $permastructname ] = $wp_rewrite->generate_rewrite_rules( $permastruct['struct'], $permastruct['ep_mask'], $permastruct['paged'], $permastruct['feed'], $permastruct['forcomments'], $permastruct['walk_dirs'], $permastruct['endpoints'] );
			} else {
				$rewrite_rules_by_source[ $permastructname ] = $wp_rewrite->generate_rewrite_rules( $permastruct, EP_NONE );
			}
		}

		// Apply the filters used in core just in case
		foreach ( $rewrite_rules_by_source as $source => $source_rules ) {
			// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- Can't prefix dynamic hooks here, calling hooks for custom permastructs.
			$rewrite_rules_by_source[ $source ] = apply_filters( $source . '_rewrite_rules', $source_rules );
			if ( 'post_tag' === $source ) {
				if ( Utils\wp_version_compare( '3.1.0', '>=' ) ) {
					// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Calling native WordPress hook.
					$rewrite_rules_by_source[ $source ] = apply_filters( 'post_tag_rewrite_rules', $source_rules );
				} else {
					// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Calling native WordPress hook.
					$rewrite_rules_by_source[ $source ] = apply_filters( 'tag_rewrite_rules', $source_rules );
				}
			}
		}

		$rule_list = [];
		foreach ( $rules as $match => $query ) {

			if ( ! empty( $assoc_args['match'] ) && ! preg_match( "!^$match!", trim( $assoc_args['match'], '/' ) ) ) {
				continue;
			}

			$source = 'other';
			foreach ( $rewrite_rules_by_source as $rules_source => $source_rules ) {
				if ( array_key_exists( $match, $source_rules ) ) {
					$source = $rules_source;
				}
			}

			if ( ! empty( $assoc_args['source'] ) && $source !== $assoc_args['source'] ) {
				continue;
			}

			$rule_list[] = compact( 'match', 'query', 'source' );
		}

		Utils\format_items( $assoc_args['format'], $rule_list, explode( ',', $assoc_args['fields'] ) );
	}
Gets a list of the current rewrite rules.

## OPTIONS

[--match=<url>]
: Show rewrite rules matching a particular URL.

[--source=<source>]
: Show rewrite rules from a particular source.

[--fields=<fields>]
: Limit the output to specific fields. Defaults to match,query,source.

[--format=<format>]
: Render output in a particular format.
---
default: table
options:
- table
- csv
- json
- count
- yaml
---

## EXAMPLES

$ wp rewrite list --format=csv
match,query,source
^wp-json/?$,index.php?rest_route=/,other
^wp-json/(.*)?,index.php?rest_route=/$matches[1],other
category/(.+?)/feed/(feed|rdf|rss|rss2|atom)/?$,index.php?category_name=$matches[1]&feed=$matches[2],category
category/(.+?)/(feed|rdf|rss|rss2|atom)/?$,index.php?category_name=$matches[1]&feed=$matches[2],category
category/(.+?)/embed/?$,index.php?category_name=$matches[1]&embed=true,category

@subcommand list