Skip to content

Use raw PHP-WASM to run WP-CLI commands#2376

Merged
fredrikekelund merged 8 commits intodev/studio-cli-i2from
f26d/wp-cli-command-php-runtime
Jan 15, 2026
Merged

Use raw PHP-WASM to run WP-CLI commands#2376
fredrikekelund merged 8 commits intodev/studio-cli-i2from
f26d/wp-cli-command-php-runtime

Conversation

@fredrikekelund
Copy link
Copy Markdown
Contributor

@fredrikekelund fredrikekelund commented Jan 9, 2026

Related issues

Proposed Changes

Instead of instantiating Playground CLI, use a "raw" PHP-WASM instance to execute WP-CLI commands. In my quick benchmarks, this shows significantly better performance (wp option get takes 1.93s on this branch compared to 4.94s on the base branch).

This is essentially the same strategy that we already use on trunk. @bgrgicak very graciously helped me with some modifications to fix some issues we were having with network requests (wp plugin install commands would previously fail, for example).

Testing Instructions

  1. Run npm run cli:build
  2. Run node dist/cli/main.js wp --path PATH_TO_STUDIO_SITE
  3. Ensure that the help contents are printed
  4. Try a bunch of commands!

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

@fredrikekelund fredrikekelund requested a review from a team January 9, 2026 15:26
@fredrikekelund fredrikekelund self-assigned this Jan 9, 2026
@fredrikekelund fredrikekelund marked this pull request as ready for review January 13, 2026 13:42
@wojtekn
Copy link
Copy Markdown
Contributor

wojtekn commented Jan 15, 2026

Based on a quick test, it works as expected. It's faster than 5 seconds, but still much slower than the native wp call. I guess it's acceptable given that it goes through PHP-WASM.

I noticed that table formatting is different. Here is the native wp:

% time wp plugin list --path=PATH
+------------------------+----------+------------------------------+----------+----------------+-------------+
| name                   | status   | update                       | version  | update_version | auto_update |
+------------------------+----------+------------------------------+----------+----------------+-------------+
| akismet                | active   | none                         | 5.6      |                | off         |
| classic-editor         | inactive | none                         | 1.6.7    |                | off         |
| crowdsignal-forms      | active   | none                         | 1.7.2    |                | off         |
| polldaddy              | active   | none                         | 3.1.4    |                | off         |
| gutenberg              | active   | available                    | 22.2.0   | 22.3.0         | off         |
| hello-dolly-complainer | active   | none                         | 1.0.0    |                | on          |
| jetpack                | active   | version higher than expected | 15.5-a.1 |                | off         |
| layout-grid            | active   | version higher than expected | 1.8.5    |                | off         |
| page-optimize          | active   | none                         | 0.5.8    |                | off         |
| db.php                 | dropin   |                              |          |                | off         |
+------------------------+----------+------------------------------+----------+----------------+-------------+
wp plugin list --path=PATH  0.25s user 0.07s system 43% cpu 0.732 total

And one from Studio CLI:

% time node dist/cli/main.js wp plugin list --path=PATH
+-------------+----------+-------------+----------+-------------+--------------+
| name        | status   | update      | version  | update_vers | auto_update  |
|             |          |             |          | ion         |              |
+-------------+----------+-------------+----------+-------------+--------------+
| akismet     | active   | none        | 5.6      |             | off          |
| classic-edi | inactive | none        | 1.6.7    |             | off          |
| tor         |          |             |          |             |              |
| crowdsignal | active   | none        | 1.7.2    |             | off          |
| -forms      |          |             |          |             |              |
| polldaddy   | active   | none        | 3.1.4    |             | off          |
| gutenberg   | active   | available   | 22.2.0   | 22.3.0      | off          |
| hello-dolly | active   | none        | 1.0.0    |             | on           |
| -complainer |          |             |          |             |              |
| jetpack     | active   | version hig | 15.5-a.1 |             | off          |
|             |          | her than ex |          |             |              |
|             |          | pected      |          |             |              |
| layout-grid | active   | version hig | 1.8.5    |             | off          |
|             |          | her than ex |          |             |              |
|             |          | pected      |          |             |              |
| page-optimi | active   | none        | 0.5.8    |             | off          |
| ze          |          |             |          |             |              |
| db.php      | dropin   |             |          |             | off          |
+-------------+----------+-------------+----------+-------------+--------------+
node dist/cli/main.js wp plugin list --path=PATH  2.45s user 0.14s system 135% cpu 1.907 total

...args,
] );
// Setup SSL certificates
php.writeFile( '/tmp/ca-bundle.crt', rootCertificates.join( '\n' ) );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to set up an SSL certificate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tested without it, but WP-CLI sends network requests as part of several different commands, so I kind of assume this is needed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tested running several commands, e.g. wp plugin install with the code commented out and they run without issues.

createNodeFsMountHandler( loaderMuPluginHostPath )
);
await php.mount( '/tmp/wp-cli.phar', createNodeFsMountHandler( getWpCliPharPath() ) );
await php.mount( '/tmp/sqlite-command', createNodeFsMountHandler( getSqliteCommandPath() ) );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Would it make sense to use an array and a map here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a matter of preference, IMO. I think the current approach reads clearly, and changing it to an array that we iterate over won't really make the code more compact

Comment thread cli/lib/run-wp-cli-command.ts Outdated
() => php.exit(),
];
} catch ( error ) {
throw new Error( __( 'An error occurred while running the WP-CLI command.', 'wp-playground' ) );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be translated? If yes, do we need to use a domain?

Copy link
Copy Markdown
Contributor

@ivan-ottinger ivan-ottinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't worked with PHP-WASM much yet, but the changes look good to me and the commands run well.

I have tested with several commands, including the ones that make network requests (e.g. wp plugin install) and all of them run as expected. 👍🏼

@fredrikekelund
Copy link
Copy Markdown
Contributor Author

Thanks for the reviews, @wojtekn and @ivan-ottinger

table formatting

I'll take a look at this in a follow-up PR

@fredrikekelund fredrikekelund merged commit 1bcc143 into dev/studio-cli-i2 Jan 15, 2026
3 of 4 checks passed
@fredrikekelund fredrikekelund deleted the f26d/wp-cli-command-php-runtime branch January 15, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants