I contribute to WordPress core, and for the last while I have done it with an AI coding assistant, Claude Code, working next to me. This post is the workflow I settled on: how a ticket is picked, how the fix is checked, and what I do myself.
It is not a way to produce patches in bulk. Core has reviewers with limited time, and a pull request that nobody tested costs them more than it gives. Everything below is built around sending a small number of changes that are correct.
The workflow in one list
- Find an easy ticket that nobody has claimed.
- Reproduce the problem on a local copy of WordPress and measure it.
- Make the smallest change that fixes it.
- Verify the fix in a real browser, with the same measurement as before.
- I read the diff and test it by hand.
- Open the pull request, say that AI was used, and link it on the Trac ticket.
The assistant does most of steps 1 to 4. Steps 5 and 6 are decisions, and those stay with me.
Writing the workflow down once
Claude Code has a feature called skills: a Markdown file of instructions that it loads when a task matches. I wrote one for core contributions. It holds my preferences, the local setup and the things learned from earlier attempts, so I do not explain them again in every session.
These are the rules at the top of it:
- Current WordPress only. No tickets for old default themes or legacy-only features.
- Easy tickets, minimal changes. The smallest diff that fixes the ticket, with no extra fixes along the way. A related problem is mentioned as a possible follow-up and left out of the patch.
- A short pull request description. One sentence on what changed, testing instructions, and what the template requires.
- Ask before anything public. No commit, push or pull request without my go-ahead.
The skill also keeps a history: which tickets were done, which were rejected and why. That list stops the same unsuitable ticket from being suggested twice.
Picking a ticket
This is the step where most of the time goes, and where I am strictest. I focus on accessibility tickets outside the editor.
A ticket is rejected if any of these is true:
- It has an owner, or someone commented that they will open a pull request.
- A pull request is already linked, or it carries the
has-patchkeyword. - It carries
needs-design,2nd-opinion,dev-feedbackorclose. - A committer disputes it or raises backward compatibility.
- It needs a discussion or a decision before any code.
- It is a tracking ticket for work that happens in Gutenberg.
Two things I learned here. The good-first-bug keyword is not a reliable source, because those tickets almost always have a patch already. The best source is recently filed tickets from the accessibility team, which are often small, clear pieces split off from bigger work.
Before any code is written, a search on GitHub confirms there is no open pull request for the ticket. Then the assistant shows me the pick, why it is easy and which files it touches, and I say yes or no. I say no often.
Reproduce first, then fix
The local setup is the standard wordpress-develop checkout with its Docker environment. Every ticket gets a fresh branch from current trunk.
The rule that matters most is to measure before changing anything. For a focus style, that means loading the real admin screen in a browser with Playwright, moving focus to the element and reading its computed styles. The same script runs again after the fix, and the two results are compared. This shows that the bug existed, that the fix changed it, and that nothing else changed.
For CSS in wp-admin, the check runs under several admin color schemes and not just the default one. A fix that looks right in one scheme can be wrong in another.
Then the project’s own checks have to pass: the build, the linters and the relevant tests.
Two examples
Both of these are open for review as I write this.
A focus ring that disappeared. Buttons marked aria-disabled="true" stay focusable, which is the point of that attribute. When such a button also had the .disabled class, a box-shadow: none !important rule removed its focus ring, so keyboard users could not see where they were. The fix is a small CSS change in one file. It is ticket #66271 and pull request #14158.
Uploads where uploading makes no sense. In the media modal, dropping a file started an upload even in states such as cropping or editing an image, where there is nothing to upload to. This one is JavaScript and was harder to verify, because a drop made by a script does not behave like a real one. It is ticket #47130 and pull request #14159.
There is a third one that never became a pull request. A fix for pausing video headers was written and working when I dropped it, because the feature is legacy and I had decided not to spend reviewers’ time there. That decision is now a rule in the skill.
Saying that AI was used
The core pull request template has a section for AI tools, and I fill it in every time:
## Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: Drafting the CSS change and verifying it with Playwright; reviewed and tested by me.
The last part is the important one. My name is on the pull request, so I have read every line and tested it myself. If a reviewer asks why the change is written that way, I can answer.
Commits carry no AI co-author line. I am the author, and the disclosure belongs in the pull request, where the project asks for it.
What I keep for myself
- Choosing the ticket. The assistant proposes, and I decide whether it is worth a reviewer’s time.
- Reading the diff. Every line, before it is committed.
- Testing by hand. The automated check is evidence. I still open the screen and try it.
- Everything public. Commits, pushes, the pull request and the comment on Trac.
- The discussion. Review feedback is a conversation between people, and I take part in it myself.
What I would tell another contributor
- Start with the rejection rules. An assistant will happily fix a ticket that someone else is already working on. Tell it what to skip.
- Demand a before and after. A fix without a measurement is a guess.
- Keep the diff small. Small changes get reviewed, and large ones wait.
- Write your rules down. Each correction I made became a line in the skill, and the next session started from there.
- Disclose it. The project asks for it, and it costs nothing.
AI did not change what a good core contribution is. It is still a clear ticket, a small change and proof that it works. What changed is how long the searching, setting up and measuring take.
Leave a Reply