CRITICAL: This is a public repository. Never include private WordPress.com URLs (e.g., *.wordpress.com internal sites) in PR descriptions, commit messages, code comments, or any public-facing text. Use the p2 shorthand syntax instead (e.g., peKye1-1Z1-p2).
projects/plugins/— WordPress pluginsprojects/packages/— Composer/PHP packagesprojects/js-packages/— JavaScript/npm packagesprojects/github-actions/— GitHub Actionstools/— Monorepo toolingdocs/— Documentation
Projects define build steps in composer.json:
.scripts.build-production— Production build (setNODE_ENV=production).scripts.build-development— Development build.scripts.test-php— PHP tests.scripts.test-js— JavaScript tests
FORCE_PULL=1— Force pull latest Docker imageBUILD_LOCAL=1— Build Docker image locallyDEBUG=1— Enable debug output
The jp command runs pnpm jetpack inside the monorepo Docker container. Install globally: npm install -g @automattic/jetpack-cli (this is a global install, safe to run even inside a Jetpack checkout). jp commands work from git worktrees — the CLI resolves to the monorepo root automatically.
jp build plugins/jetpack # Build a project
jp build plugins/jetpack --deps # Build with dependencies
jp watch plugins/jetpack # Watch and rebuild on changes
jp test php packages/connection # Run PHP tests (packages)
jp test js packages/connection # Run JS tests
jp changelog add # Add changelog entry (interactive)
jp generate # Create new project (interactive wizard)
jp install plugins/jetpack # Install project dependencies
jp clean plugins/jetpack # Clean build artifacts
jp docker up -d # Start Docker environment
jp docker install # Install WordPress in Docker
jp phan # Run PHP static analysisUse jp generate to create new projects:
- Plugins:
jp generate plugin --name my-plugin(choose "Starter plugin" for React admin page example, or "Blank plugin" for minimal scaffolding) - Packages:
jp generate package --name my-package - JS Packages:
jp generate js-package --name my-js-package - GitHub Actions:
jp generate github-action --name my-action
Detailed guidelines are in docs/coding-guidelines.md.
- Use WordPress naming conventions for functions and classes
- Prefix global PHP functions and hooks with
jetpack_ - Use lowercase with underscores for PHP functions
- Follow WordPress React component naming patterns
- Use BEM-like naming for SCSS
- Follow WordPress PHP Coding Standards
- Use proper WordPress prefix for functions and classes
- Implement WordPress nonce verification for form handling and AJAX
- Follow WordPress database operations best practices (
$wpdbprepared statements) - Structure plugin hooks logically
When adding a version number in a DocBlock, MUST use $$next-version$$:
@since $$next-version$$@deprecated $$next-version$$@deprecated since $$next-version$$_deprecated_function( __METHOD__, 'package-$$next-version$$' );
The $$next-version$$ placeholder is automatically replaced with the correct version at release time. Do NOT replace these with actual version numbers.
- Write modern ES6+ code following WordPress JS standards
- Importing from
reactdirectly is fine.@wordpress/elementalso works but is no longer required — follow the convention used in the package you're working in - Use WordPress data stores (
@wordpress/data) for state management - Use
@wordpress/i18nfor translations with an appropriate unique text domain - Follow WordPress component lifecycle patterns and accessibility guidelines
- When using TypeScript with Webpack, use
@babel/preset-typescriptrather thants-loader
- Use BEM-like naming conventions
- Use CSS logical properties instead of physical direction/dimension mappings to make styles RTL-aware by default (reference: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties)
jp test php <project> -v # PHPUnit tests (verbose)
jp test js <project> # Jest tests
jp test coverage <project> # Generate coverage report- Packages (
jp test php packages/...,jp test js packages/...): Work immediately with no extra setup. The monorepo Docker container handles everything. - Plugins: Some plugins use mocked WordPress environments (WorDBless/Brain Monkey) and their tests work immediately via
jp test php. Others (notablyplugins/jetpack,plugins/crm,plugins/wpcomsh) require a full WordPress test environment:jp docker up -d— Start Docker WordPress containersjp docker install— Install WordPress in Docker Then run:jp docker phpunit <target>where<target>can bejetpack,jp-multisite,crm,wpcomsh, orjp-wpcomsh(seejp docker phpunit --helpfor the full list).
- If you've modified package versions or dependencies between monorepo packages, run
tools/fixup-project-versions.shto update lock files before testing. - If a project's
composer.jsondoesn't definetest-js, the JS test step is skipped automatically — this is normal, not an error.
After modifying a project, run its tests and static analysis:
jp test php <project> # PHP tests
jp test js <project> # JS tests (skipped if not defined)
jp phan <project> # Static analysis
jp test coverage <project> # Generate coverage report (optional)jp test phpworks for most projects. A few plugins that require a full WordPress copy (plugins/jetpack,plugins/crm,plugins/wpcomsh) usejp docker phpunitinstead.- PHP version matrix: CI runs PHP tests against every supported version from 7.2 to 8.5 (see
.github/versions.shfor current values). When fixing an issue on one PHP version, ensure the fix is compatible with all supported versions — don't use syntax or functions unavailable in PHP 7.2 unless the project'scomposer.jsonrequires a higher minimum. jp test phpdoes not support passthrough options like--filter. To filter tests in Docker-based projects, use:jp docker phpunit jetpack -- --filter=Jetpack_Sync_Post_Testorjp docker phpunit jetpack -- --group jetpack-sync- PHP testing approaches vary by project:
- Some packages use basic PHPUnit with
yoast/phpunit-polyfills(no WordPress-specific testing) - Some use
brain/monkeyfor basic WordPress mocking - Some use WorDBless (via
automattic/jetpack-test-environment) for a lightweight WordPress environment - A few plugins use an actual copy of WordPress (these are the
jp docker phpunitprojects)
- Some packages use basic PHPUnit with
- For WorDBless-based tests: test classes extend
WorDBless\BaseTestCase. Theself::factory()helper is available for creating posts and other objects. For users specifically, preferwp_insert_user()+get_userdata()as user factory support varies by project. - Test class names MUST end in "Test"
- Every test class MUST be in a file with a matching name (e.g., class
My_Unit_TestinMy_Unit_Test.php) - See
projects/packages/connection/tests/php/sso/Helpers_Test.phpfor an example of a WorDBless-based test.
See docs/automated-testing.md for full testing guidelines.
- Use Jest with
@testing-library/react - Follow WordPress testing patterns for async testing and mocking
See projects/packages/my-jetpack/_inc/components/connection-status-card/test/component.tsx for a representative example.
Every PR touching /projects MUST include a changelog file in the project's changelog/ directory. Changes outside /projects (e.g., tools/, docs/, .github/) do NOT need changelog entries.
The PR template includes a checkbox: "Generate changelog entries for this PR (using AI)." When checked, a CI workflow uses AI to generate and commit changelog entries automatically. This workflow only runs for pull requests from branches in this repository (not from forks).
When filling out a PR description:
- Do NOT check this box if changelog files already exist in
changelog/directories for the affected projects. - Do NOT check this box if you have already created changelog entries (e.g., via
jp changelog add). - Only check this box if the PR needs changelog entries and you want them auto-generated.
- When in doubt, leave it unchecked -- the bot will flag missing entries.
Run jp changelog add and follow the prompts.
jp changelog add <project> -s <significance> -t <type> -e "<entry>" [-f <filename>]Parameters:
-s, --significance:patch|minor|major-t, --type:security|added|changed|deprecated|removed|fixed-e, --entry: Changelog entry text-f, --file: Filename (defaults to git branch name)-c, --comment: For trivial changes with empty entry, explain why no entry needed
Examples:
# Standard changelog entry
jp changelog add packages/connection -s patch -t fixed -e "Connection: Fix issue with site registration."
# Jetpack plugin (uses different types: major, enhancement, compat, bugfix, other)
jp changelog add plugins/jetpack -s patch -t bugfix -e "Connection: Fix issue with site registration."
# Trivial change (no user-facing entry needed)
jp changelog add packages/connection -s patch -t changed -e "" -c "Update internal documentation"Note: Jetpack plugin uses custom changelog types defined in projects/plugins/jetpack/composer.json at .extra.changelogger.types.
Significance: patch
Type: fixed
Connection: Fix issue with site registration.
Entries MUST:
- Be grammatically correct and free of typos
- Start with a capital letter and end with a period
- Use imperative mood (e.g., "Add feature." not "Added feature" or "Adds feature")
- Use a component/feature prefix when the change is specific to a component (e.g., "Connection: Fix timeout issue with site registration.")
- NOT use the package/project name as a prefix within that same package
- Describe the change from a user's perspective, not the implementation details
PR descriptions MUST follow the template in .github/PULL_REQUEST_TEMPLATE.md — CI checks expect the metadata format defined there.
gh pr create --title "Title" --body-file pr-body.md --label "[Status] Needs Review" --label "Enhancement" --assignee @meWhen reviewing code, check for:
- Adherence to
docs/coding-guidelines.md - Inconsistent naming conventions and typos
- Missing documentation for public APIs
- Missing explanations for complex or non-obvious logic
- Inefficient algorithms
- CSS/SCSS files not using logical properties for RTL
Do NOT suggest modifying $$next-version$$ placeholders — these are intentionally used and replaced during release.
Before introducing new dependencies:
- Survey existing packages within the monorepo for similar functionality
- Check for reusable components, utilities, or hooks in shared packages
- Review existing WordPress core and Jetpack APIs
- Prioritize internal packages and APIs over external dependencies
- Do NOT edit WordPress core files — all changes must be in plugins/packages
- Do NOT modify
$$next-version$$placeholders — they are replaced automatically at release time - Reuse monorepo packages before adding external dependencies — check
projects/packages/andprojects/js-packages/first - Git merge conflicts: after resolving, use
git commit --no-edit --no-verify— pre-commit hooks can make unintended changes to merge commit files
If you discover a pattern or pitfall not covered here, mention it to the developer so they can decide whether to update this file.