Skip to content

Studio Code: Run WP-CLI as wp in the agent's shell, and drop the prompt rule against it - #5166

Closed
chubes4 wants to merge 6 commits into
trunkfrom
studio-code/bash-wp-runs-studio-wp
Closed

chubes4 wants to merge 6 commits into
trunkfrom
studio-code/bash-wp-runs-studio-wp

Conversation

@chubes4

@chubes4 chubes4 commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Related issues

How AI was used in this PR

Claude (via the Pi coding agent in a Roadie session) traced why the prompt forbids wp in Bash, wrote the change and its tests, and ran the checks and agent runs below. Opened as a draft for human review.

Proposed Changes

The prompt told Studio Code: "Never run wp commands via Bash — always use the wp_cli tool instead." That rule dates from when sites ran in PHP-WASM and a system wp ran on a different PHP (#2632, #2970). Sites now run on native PHP, and studio wp runs the same runWpCliCommand as wp_cli. So Studio Code now runs WP-CLI the normal way, as wp in its shell:

  • wp in the agent's shell is Studio's WP-CLI. The Bash tool's spawnHook puts a directory first on PATH holding a one-line wp script: exec node <studio cli> wp "$@". So wp runs on Studio's bundled PHP at the site's version, with the SQLite mu-plugins and Reprint runtimes, and gets the shell's stdin, environment and exit code. A system wp, where one is installed at all, has none of these.
  • studio wp finds the site from any directory inside it, the way WP-CLI does. Before, it needed the exact site root. This also helps people using the CLI directly.
  • Studio Code no longer gets the wp_cli tool (shellRunsStudioWp). With both available, the agent kept picking the tool. The MCP server keeps wp_cli for external agents.
  • wp_cli's checks:
    • The typographic-dash option check (–porcelain) moves into studio wp, so it applies to every route.
    • The $(cat file) post-content check stays with wp_cli, the only place it applies: in a real shell, $(cat file) is simply correct.
  • Skills use plain WP-CLI notation (wp plugin list, wp eval-file …) instead of naming a Studio tool. Studio Code runs them as written. External agents get one line saying to run a skill's wp commands with wp_cli or studio wp, the same convention as the STUDIO.md installed into site folders.
  • Taxonomist: its steps told the agent to set TAXONOMIST_* environment variables for eval-file, which wp_cli cannot do. They are now single shell commands (TAXONOMIST_OUTPUT=… wp eval-file …), matching the usage lines in the scripts themselves.
  • Prompt: the "never run wp via Bash" rule is gone, with nothing replacing it. Once wp_cli is gone, the agent reaches for wp in its shell without any hint. An earlier version stated the fact in the Bash tool's description; runs without that sentence passed just the same, so it was dropped.
  • Why the MCP server keeps wp_cli: studio mcp documents Claude Desktop as a target. It has no shell on the user's machine, so wp_cli is its only way to run WP-CLI.

Testing Instructions

  • Unit tests: npx vitest run apps/cli/ai/tests/studio-wp-shim.test.ts apps/cli/lib/cli-config/tests/sites.test.ts apps/cli/lib/tests/wp-cli-options.test.ts apps/cli/ai/tests/tools.test.ts
    • The shim tests run wp through /bin/sh the way the Bash tool does, with a stand-in for PHP. They check that the arguments, stdin, an inline environment variable (TAXONOMIST_MODE=apply wp …) and the exit code all reach it.
  • By hand, from a built CLI: in the agent's Bash tool, run cd ~/Studio/<site>/wp-content/plugins && wp option get siteurl && wp cli version. It prints the site URL and Studio's bundled WP-CLI (2.12.0 here), not a system wp.
  • Time per call (wp option get siteurl, median of 7, on a heavily loaded machine, so compare the rows rather than the absolute numbers):
Route Median
wp_cli tool, in-process 1,539 ms
wp in Bash, through studio wp 4,047 ms

On a quieter run, studio wp took 1.55 s against 0.63 s for PHP and WP-CLI alone.

  • Agent runs, with prompts that never mention Bash or WP-CLI, judged on the resulting site: 4 of 4 passed.
    • "Which plugins are installed on this site?" (2 runs)
    • "Set this site's tagline to "Fresh bread daily", and make sure search engines are allowed to index it." (2 runs)
    • Each run used cd <site> && wp … in Bash. The same 4 runs, repeated without any mention of wp in the Bash tool description, also passed 4 of 4.

Pre-merge Checklist

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

@chubes4 chubes4 changed the title Studio Code: Run Studio's WP-CLI for wp in the agent's shell instead of forbidding it Studio Code: Run WP-CLI as wp in the agent's shell, and drop the prompt rule against it Oct 16, 2026
chubes4 added a commit that referenced this pull request Oct 21, 2026
## Related issues

- Related to #5166, which runs WP-CLI as `studio wp` from the agent's
shell, so `studio` startup time adds to every WP-CLI call.

## How AI was used in this PR

Claude (via the Pi coding agent in a Roadie session) profiled `studio`
startup, traced the import chain, wrote the change and the test, and
took the timings below. I reviewed the diff and the numbers.

## Proposed Changes

Every `studio` command loaded the whole agent runtime before running.
The CLI entry imports each command module up front, and
`commands/mcp.ts` imported the MCP server at its top, which brings every
agent tool and the Pi agent with them (highlight.js, typebox, undici,
…). `studio --version` loaded 3,765 modules, and about 4,000 in the
shipped 1.24.0 app.

- `studio mcp` now loads the MCP server inside the command, the same way
`studio ai` already loads its runtime.
- A test imports everything the CLI entry imports statically and checks
the agent runtime stays unloaded. It reads the imports from `index.ts`,
so a command added later is covered too. It fails on trunk.
- Vitest gets the `@studio/local` alias the build already has. Without
it, no test could load `commands/ui.ts`.

## Testing Instructions

- `npx vitest run apps/cli/tests/startup-imports.test.ts` passes; with
the `commands/mcp.ts` change reverted, it fails.
- `npx vitest run --project cli`: 1,158 pass.
- From a built CLI (`cd apps/cli && npx vite build --config
./vite.config.dev.ts`), same machine, 5 runs each:

| Command | Trunk | This branch |
|---|---|---|
| `node dist/cli/main.mjs --version` | 1.8 s, 3,765 modules | 0.7 s,
1,132 modules |
| `node dist/cli/main.mjs wp --path=<site> option get siteurl` |
1.29–1.57 s (median 1.40) | 0.93–1.15 s (median 1.00) |

- `studio mcp` still starts the MCP server: after `initialize`,
`tools/list` returns its 30 tools.

## Pre-merge Checklist

- [x] Have you checked for TypeScript, React or other console errors?
@chubes4

chubes4 commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

Closing to focus on #5146 as the larger architectural proof.

@chubes4 chubes4 closed this Oct 24, 2026
chubes4 added a commit that referenced this pull request Oct 24, 2026
`wp` in Studio Code's Bash is Studio's WP-CLI for the site the command runs
in (the PATH shim from #5166), so the rule that refused `wp` in the shell,
added because a bare `wp` reached the system binary, has nothing left to
guard. The wp_cli tool leaves Studio Code; `studio mcp` keeps it for clients
without a shell.

The checks that only wp_cli had leave with it, as the shell already runs
without them: the irreversible WP-CLI and other-site confirmations (Studio's
own tools keep theirs), and the refusal of post content from a file with open
validation problems. Block markup is still validated as it is written, and a
shell call waits for that validation and reports it, as wp_cli did. The
preview reloads after a successful shell call.
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.

1 participant