Skip to content

Fix WP-CLI tool calls from Studio Code when using the native PHP runtime #3847

Open
fredrikekelund wants to merge 4 commits into
rsm-3958-add-php-mode-switch-ui-and-clifrom
f26d/studio-code-wp-cli-native-php-fixes-extended
Open

Fix WP-CLI tool calls from Studio Code when using the native PHP runtime #3847
fredrikekelund wants to merge 4 commits into
rsm-3958-add-php-mode-switch-ui-and-clifrom
f26d/studio-code-wp-cli-native-php-fixes-extended

Conversation

@fredrikekelund

Copy link
Copy Markdown
Contributor

Related issues

  • Fixes RSM-4390

How AI was used in this PR

Claude was used iteratively to review and implement individual pieces of this. I leaned on it more for review than implementation in this case, but the stripLeadingShebang is one case where the implementation is basically all Claude.

Proposed Changes

tl;dr: Studio Code was using the sendWpCliCommand function to run the wp_cli tool. This function doesn't work with the native PHP runtime. This PR fixes the issue by replacing sendWpCliCommand with runWpCliCommandWithMessaging (a wrapper around runWpCliCommand).

gs;wm:
The new runWpCliCommandWithMessaging function checks if the target site uses the Playground runtime and if the server is running. If so, it'll forward the WP-CLI command as an IPC message to the child process. This is the same behavior that we had with sendWpCliCommand, except the new function falls back to runWpCliCommand, meaning the server doesn't need to be running (or using the native PHP runtime).

So, aside from making Studio Code work with the native PHP runtime, we also gain more flexibility with the wp_cli tool.

Moreover, I've streamlined apps/cli/commands/wp.ts to also use the runWpCliCommand function. To do this, I had to add an stdio option to that function, to allow the native PHP child process to be spawned with stdio: 'inherit' (which is what sets apps/cli/commands/wp.ts apart from other runWpCliCommand callers).

Testing Instructions

  1. npm run cli:build
  2. STUDIO_RUNTIME=native-php node apps/cli/dist/cli/main.mjs code
  3. Create a new site
  4. Ensure that the Create site output includes Checking PHP N.N binary…
  5. Ensure that the entire process works smoothly and that the WP-CLI tool calls don't stall

Pre-merge Checklist

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

@youknowriad

Copy link
Copy Markdown
Contributor

Going to give this a try. I wanted to note something as well in our skills and system prompt we have some guidelines in places to tell the agent exactly how to use wp cli (avoid file paths...) in order to make it work with playground. I believe that part is probably not necessary with the php runtime and we could have some condition to drop these entirely from the system prompt and just let the agent do what it thinks is best.

const result = await sendWpCliCommand( siteId, [ 'theme', 'activate', slug ] );
if ( result.exitCode !== 0 ) {
const detail = ( result.stderr || result.stdout || '' ).trim();
await using command = await runWpCliCommandWithMessaging( site, [

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.

If you're not familiar with the using keyword, I recommend a quick read-up on JavaScript resource management.

In short, it saves us from having to call a cleanup function because the JS runtime automatically calls the method identified by Symbol.dispose when exiting the scope.

Why do we need a cleanup function, you ask? Because when the site is using the Playground runtime but isn't running, we have to instantiate a new PHP-WASM instance that needs to be killed when we're done. We could kill the PHP-WASM instance once all stdout/stderr content has been buffered, but because PHP-WASM also provides streams for stdout/stderr, and we sometimes want to use those streams instead of the buffered output, we need to do it this way.

@sejas sejas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I tested it and everything worked well. I didn't catch any regression.
I was able to create a new site which showed Runtime Native, then I created a new post and installed a plugin which executed wp-cli for both actions. Everything worked as expected.

Riad makes a great point. I'll create a separate issue to tackle it separately, and load Playground differences conditionally.
Will the PHP runtime be managed per site? That could complicate things a bit.

Create site

Image

Create post

Image

Install plugin

Image

@youknowriad

Copy link
Copy Markdown
Contributor

Works well in my testing as well.

sejas commented Jun 16, 2026

Copy link
Copy Markdown
Member

I created STU-1840 to address Studio Code Playground paths, and other specifics in a separate PR.

@bcotrim bcotrim left a comment

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 found a regression on a edge case, but still worth a fix.
Changing the php version (to a never used one) on a stopped sites, makes all studio wp commands fail since we no longer do ensurePhpBinaryAvailable

npm run cli:build
# Site must be stopped
studio site set --runtime native --php ${VERSION} --path ${SITE_PATH}
studio wp --path ${SITE_PATH} option get blogname

Will result in

❯ sdev wp --path ~/Studio/my-calm-website option get blogname
✖ Failed to run WP-CLI command: spawn /Users/bcotrim/.studio/php-bin/8.2.31/php ENOENT

@fredrikekelund

Copy link
Copy Markdown
Contributor Author

Thanks for staying alert, @bcotrim! I've added a ensurePhpBinaryAvailable call to runNativeWpCliCommand and confirmed that it works as expected

@fredrikekelund fredrikekelund requested a review from bcotrim June 17, 2026 06:51
@fredrikekelund

Copy link
Copy Markdown
Contributor Author

Will the PHP runtime be managed per site? That could complicate things a bit.

Yes, it will be. I'm happy to discuss this further. Might be helpful with a bit of handover here. cc @sejas

@bcotrim bcotrim left a comment

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.

LGTM 👍

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