Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 14 additions & 88 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,7 @@
[![Latest release](https://img.shields.io/github/v/release/WordPress/experimental-wp-dev-env)](https://github.com/WordPress/experimental-wp-dev-env/releases/latest)
[![Downloads](https://img.shields.io/github/downloads/WordPress/experimental-wp-dev-env/total)](https://github.com/WordPress/experimental-wp-dev-env/releases)

The [WordPress Core Dev Environment Toolkit](https://github.com/WordPress/experimental-wp-dev-env) is a desktop electron application (available for macOS on Apple Silicon, Windows, and Linux) that sets up a full WordPress core development environment with zero prerequisites.

You install it, choose a directory for `wordpress-develop`, click a button, and you have:

- A cloned `wordpress-develop` repository
- A running WordPress dev server
- The ability to make code changes and generate a patch

No Git, no Node.js, no npm, no Docker needed. Everything is bundled inside the application as JS/WASM, powered by [WordPress Playground](https://wordpress.github.io/wordpress-playground/).
The [WordPress Contributor Toolkit](https://github.com/WordPress/contributor-toolkit) is a desktop Electron application (macOS on Apple Silicon, Windows, and Linux) that sets up a full WordPress core development environment with zero prerequisites — no Git, Node.js, npm or Docker on the host.

### Why

Expand All @@ -22,18 +14,12 @@ Before writing a single line of code, a first-time WordPress core contributor ty

The **WordPress Core Dev Environment Toolkit** aims to eliminate this friction entirely.

## What does it do?

Once installed, the app lets you:

- Clone `wordpress-develop` into a directory of your choice
- Run `npm install`, `npm run build`, and `npm run dev` automatically
- Start a WordPress dev server using Playground’s CLI
- Make changes to core files directly
- Generate a patch from your changes, ready to attach to a Trac ticket
- Update an existing site to the latest trunk at any time, without recreating it
## Documentation

The entire toolchain — npm, Node, Git — runs as JavaScript/WASM bundled with the app. There’s no terminal work required for the basic contributor workflow.
**The user guide lives at <https://wordpress.github.io/contributor-toolkit/>** — installing
the app, creating a site, working on a Trac ticket, applying patches and PRs, and submitting your
changes as a pull request, a Trac attachment, or a patch for a mentor. What follows here is only
what a contributor to *this repository* needs.

Here’s the full setup flow — from a fresh install to a running WordPress development environment:

Expand All @@ -51,30 +37,11 @@ Once your environment is running, generating a patch to submit to Trac takes jus

### Just using the app

1. Download the latest packaged build for your platform from the [Releases page](https://github.com/WordPress/experimental-wp-dev-env/releases/latest). Pick the file that matches your OS:
- **macOS on Apple Silicon:** Choose the `.dmg` file whose name contains `arm64`. Intel Macs are not currently supported.
- **Windows:** Choose the `.exe` installer.
- **Linux:** Choose the `.AppImage`; `.deb` and `.snap` packages may also be available.
2. Open the app
3. **macOS only:** The app is signed and notarized by Automattic. macOS should open it without issues. If Gatekeeper still blocks the app (this can happen when the file was downloaded via a browser), try either of these:
- Right-click the `.app` file and choose **Open**, then confirm in the dialog that appears.
- Or remove the quarantine attribute from the `.app` bundle itself:
```
xattr -d com.apple.quarantine "WordPress Contributor Toolkit.app"
```
> **Note:** Use `-d`, **not** `-dr`. The app is code-signed; using the recursive flag (`-r`) tries to strip attributes from files inside the sealed bundle, which macOS will reject with permission errors. Removing the attribute from the top-level bundle is sufficient.
4. Click "Create WordPress Core site" and choose a destination folder for your site.
5. Click "Install dependencies"
6. Click "Run command > npm run build"
7. Click "Start dev server"
8. A browser window should open automatically. If not, you can manually open it by clicking "Launch site".
9. Make changes in the code
10. Click "Generate patch" to create a diff of your changes.

> **Tip:** You never need to create a new site just to get newer code. **Update to latest trunk**,
> in the ☰ menu at the top right of any site, is available at any time and on any site, however old
> or new the site is: it fetches the latest trunk, reinstalls dependencies if they changed, and
> rebuilds. See [Keeping a site up to date with trunk](#keeping-a-site-up-to-date-with-trunk).
Download the latest packaged build from the
[Releases page](https://github.com/WordPress/contributor-toolkit/releases/latest) and follow
[Getting started](https://wordpress.github.io/contributor-toolkit/guide/getting-started) in
the user guide — it covers picking the right file per platform, the macOS Gatekeeper notes, and
the first-contribution walkthrough.

### Build from source

Expand Down Expand Up @@ -105,63 +72,22 @@ Electron Builder picks these up via `build` configuration in `package.json`.

## Technical notes

### How does it work?

* Git operations are handled by the `isomorphic-git` npm package. It is a pure JS implementation of Git that works in the browser and Node.js.
* Node scripts and npm commands are run using the Node.js runtime bundled with the Electron app. A small shim directory is injected into the PATH so subprocesses can find `node`, `npm`, and `npx` without requiring a system install.
* WordPress server is run using the `@wp-playground/cli` npm package from [WordPress Playground](https://w.org/playground/).
* Patches are generated using the `diff` npm package.

### Keeping a site up to date with trunk

A site is a clone of `wordpress-develop` frozen at the moment it was created, so it starts drifting
behind trunk immediately. **You never have to create a new site to get newer code.**

**Update to latest trunk**, in the ☰ menu at the top right of any site, brings an existing site up
to the current trunk: it fetches the newest commits, reinstalls dependencies if
`package-lock.json` moved, and rebuilds. **This option is always there** — on every site, at any
time, no matter how old or new the snapshot is and whether or not the app has flagged it as stale.
If nothing has moved, you simply get _Already up to date_.

The header of each site shows which snapshot it currently holds — `trunk as of 5 Aug 2026`.

The app also flags sites that have fallen behind, with a coloured dot next to the site name in the
sidebar:

- **Amber** — the snapshot is more than 14 days old. The site view also shows a notice with an
Update button.
- **Red** — a previous update moved the code but never finished installing or rebuilding, so the
built assets no longer match the source. Run the update again.

Staleness is judged **locally**, from the date of the commit your site is sitting on, and never by
asking GitHub what the tip of trunk is. That keeps the app working offline and stops it from
making a network request every time it launches. Two consequences worth knowing:

- A site created today is never marked out of date, even though trunk gets commits several times a
day and yours is already behind by a few. Flagging that would mark every site stale within hours
of creation, which makes the warning worthless.
- The only way to find out exactly how far behind you are is to run the update.
How the app works from a user's point of view — the toolchain it bundles, keeping a site up to
date with trunk, what SQLite does and doesn't cover — is documented in the
[user guide](https://wordpress.github.io/contributor-toolkit/), not here.

### Why Electron?

* WordPress core relies on Node.js, npm, and webpack for its build system. Electron is an easy way to install Node.js on all major platforms.
* It's a single, self-contained file. It's easy to distribute and install – it can be distributed on a USB sticks if everything else fails.

### Is SQLite enough for WordPress?

SQLite should suffice for most new contributors. The SQLite support is miles ahead of where it used to be (e.g. most plugins and core unit tests work, query monitor works, we track failures and missing features and, thanks to the query parser, we can improve things fairly easily).

For cases when MySQL is required, local Playground can work with MySQL. The only missing part is shipping the MySQL server with the app.

### Ideas and future work

- Integrate Playground's XDebug.
- Explore bundling MySQL server with the app.
- Built‑in SMTP catcher for local email testing.
- Migrate to the PHP Git client in https://github.com/wordpress/php-toolkit.
- Potentially integrate with Studio to benefit from PHP version selector, wp-cli integration and other Studio features.
- An ergonomic way of managing the git repository from the UI (commit, conflicts, pushes etc.) Or would it make sense to just endorse another git client?
- Integrate with Trac and GitHub to apply and submit patches directly. Related: [grunt-patch-wordpress](https://github.com/WordPress/grunt-patch-wordpress)

### Download stats

Expand Down
45 changes: 45 additions & 0 deletions docs/guide/applying-patches.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Applying patches and PRs

The **Apply a patch or PR** panel applies a pull request or a `.diff`/`.patch` file to your site's checkout and rebuilds, so you can test someone else's work before adding your own. Your own changes are left alone.

![The Apply a patch or PR panel, with a field for a pull request URL and a link to choose a patch file](/screenshots/apply-patch-panel.png)

## Choose what to apply

There are three ways to get a patch into the panel:

- Paste a pull request URL or number into the field and click **Apply PR**.
- Click **or choose a .diff / .patch file…** and pick a file from disk.
- Click **Apply…** next to a pull request or attachment in the [Trac ticket panel](trac-tickets).

## The preview

Nothing is changed yet. The panel first shows what the patch would do:

- The list of files it changes.
- A warning if you have your own edits to any of those files. The patch is applied on top of them: it succeeds if the changes do not overlap, and fails without touching anything if they do. Save a patch of your work first if you want a copy — see [Submitting your changes](submitting-changes).
- Which files are binary and will be skipped.
- Whether it changes `package-lock.json`, in which case dependencies will be installed before the rebuild.

Click **Apply and rebuild** to go ahead, or **Cancel** to back out.

## Apply and rebuild

The panel shows each step as it runs: applying the patch, installing dependencies if needed, and rebuilding. When it finishes, the panel reports what is applied — the patch's name, how many files it changed, and when.

If a step fails, the error says what went wrong and the checkout was not changed.

## Reverting an applied patch

While a patch is applied, the panel shows it in a green box with a **Revert this patch** button. Reverting removes the patch's changes and rebuilds, again leaving your own edits alone.

Very large patches cannot be undone automatically. The panel says so; use **Update to latest trunk** to reset the checkout instead — see [Staying up to date with trunk](trunk-updates).

## Your own changes

Applying and reverting patches never discards your own edits. The only risk is overlap: if a patch touches the same lines you changed, the apply fails cleanly rather than mixing the two. The preview names the files where you both have changes, so you see this before pressing anything.

## Next steps

- [Link the ticket you are testing](trac-tickets)
- [Submit your own changes](submitting-changes)
45 changes: 45 additions & 0 deletions docs/guide/creating-a-site.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Creating a site

A site is your own copy of `wordpress-develop`, the WordPress core development repository, cloned into a folder you choose. You can create as many sites as you like — each one is an independent checkout with its own working tree.

When the app starts with no sites, the main area shows a short prompt to create your first one.

![The app before any site exists: an empty main area and the Create WordPress Core site button at the bottom of the sidebar](/screenshots/empty-state.png)

## Start the creation flow

Click **Create WordPress Core site** at the bottom of the sidebar. A dialog opens with two fields.

![The Create WordPress Core site dialog, with a Site name text field and a Site location folder picker](/screenshots/create-site-modal.png)

- **Site name** — the label shown in the sidebar. It also determines the folder name: spaces and characters that are not valid in file names become hyphens, so a site named `My WordPress site` lives in a folder called `My-WordPress-site`.
- **Site location** — the parent folder where the site will be created. The app adds a new directory inside it for the project; it does not clone into the folder you pick directly.

Click **Create site** (or press Enter) to start. **Cancel** or Escape closes the dialog without creating anything.

## What happens during setup

The app clones the `wordpress-develop` repository from GitHub. Git is bundled with the app as `isomorphic-git`, a pure JavaScript implementation, so no system Git installation is involved.

While the clone runs, the site view shows a **Setting up new site…** card with the current phase and a terminal panel streaming progress output. The clone downloads the full repository, so expect it to take several minutes depending on your connection.

The clone is the first step of the [initial setup checklist](./setup-wizard); the remaining steps (installing dependencies, building, starting the dev server) stay locked until it finishes, then you drive them yourself.

If setup fails, the half-created site is removed from the list — the row simply disappears. The
reason goes to the application log rather than to a dialog, so **Help → Open App Log** is where
to look when a site never finishes.

## Where sites live on disk

Each site is an ordinary folder on your disk: the parent folder you chose in **Site location**, plus a directory named after the site. Inside is a normal `wordpress-develop` checkout — you can open it in any editor or file manager. The app only records the path and some metadata; deleting a site from the app can also delete this folder (see [Managing sites](./managing-sites)).

## The site list

Every site appears in the sidebar, newest first. Click a site to switch to it; the button for the active site is highlighted. The chevron at the top collapses the sidebar to a narrow strip showing only each site's initial.

A colored dot next to a site name warns that it has fallen behind trunk:

- **Amber** — the checkout is more than 14 days old.
- **Red** — a previous update moved the code but never finished installing or rebuilding.

Both are fixed by [updating to the latest trunk](./trunk-updates) — you never need to create a new site just to get newer code.
41 changes: 41 additions & 0 deletions docs/guide/database.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Browsing the database

The dev server runs WordPress on SQLite, and the app bundles [Adminer](https://www.adminer.org/)
so you can look inside that database from your browser.

## Open Adminer

While the dev server is running, an **Open Adminer** button appears next to the server URL in the
site view. Clicking it opens Adminer in your browser, already logged into the site's SQLite
database — no credentials to enter. From there you can browse tables, inspect rows, and run SQL,
the same way you would against a MySQL-backed install.

The database file itself lives inside the Playground environment at
`/wordpress/wp-content/database/.ht.sqlite`. It is not a file you can open directly on disk; go
through Adminer.

Adminer is only reachable while the dev server runs — the button disappears when the server
stops, and so does the page it opened.

## Is SQLite enough for core development?

For most new contributors, yes. WordPress's SQLite support has matured considerably: most plugins
and most core unit tests work, and thanks to the query parser, remaining gaps are tracked and
steadily closed.

It is not a complete substitute for MySQL, though. Be aware of the limits:

- Some queries and features behave differently on SQLite than on MySQL, and a small number do not
work at all.
- If your contribution touches the database layer itself — `wpdb`, schema changes, MySQL-specific
SQL — you should verify it against a real MySQL install before submitting. The toolkit cannot
do that for you: WordPress Playground can work with MySQL, but this app does not ship a MySQL
server.

For the typical first contribution — a fix in PHP, JavaScript, or CSS that reads and writes
ordinary posts, options, and users — the difference will not affect you.

## Related pages

- [Running the site](./running-the-site) — starting and stopping the dev server.
- [Logs and debugging](./logs-and-debugging) — where database errors surface as PHP notices.
Loading
Loading