Is your WordPress site ready for the next PHP or WordPress version? Scan the whole installed stack and find out before you upgrade.
Every plugin · every theme · every mu-plugin — not just your own code
Upgrading PHP or WordPress on a site with dozens of third-party plugins is a gamble. There is no way to know what breaks until it breaks — in production. Pressready changes that.
Scans every plugin, theme, and mu-plugin in wp-content — not just your own code. Third-party code breaks too.
Two engines, one command. PHPCompatibility handles the PHP axis; a custom sniff handles the WordPress deprecation axis.
Fatals (white screen) are separated from risky behaviour changes and mere deprecations — no false alarms, no hiding real problems.
Findings group by the plugin or theme that owns them, sorted fatals-first, so you know exactly which package to fix or replace.
Snapshot today's known issues and fail CI only on new findings — adopt on a site with pre-existing tech debt without drowning in noise.
Run wp pressready scan from the WordPress root on a live site. No database needed — readiness scanning is entirely static.
One scan, two engines. Pressready runs PHPCompatibility and its own WordPress sniff in a single PHP_CodeSniffer pass.
The battle-tested community standard. Catches removed functions, deprecated language features, and behavioural changes for any PHP version from 5.3 to 8.4. Runs via the phpcompatibility/phpcompatibility-wp wrapper that skips functions WordPress itself polyfills — no false positives.
A custom PHPCS sniff driven by an authoritative, regenerable JSON dataset of every WordPress core deprecation — extracted straight from core's own _deprecated_* annotations and @deprecated docblocks. Hundreds of unique entries covering functions, methods, classes, hooks, and files back to WordPress 1.5.
The dataset is regenerable against any wordpress-develop checkout: php bin/gen-wp-deprecations.php --src=/path/to/wordpress-develop/src --out=data/wp-deprecations.json. Re-run each WordPress release to refresh for free.
Every finding is classified into one tier. The verdict and --fail-on key on true fatals only, so the report never cries wolf.
| Level | Meaning | Source |
|---|---|---|
| fatal | A symbol removed by the target version — a PHP symbol gone, or a WordPress core API removed by the target WP version → call to undefined → white screen | PHPCompatibility · Pressready sniff (message says "removed since") |
| risky | Behavioural / correctness change that still runs but may produce wrong results | Other PHPCompatibility errors |
| php | PHP feature deprecated (not yet removed) by the target version | PHPCompatibility warnings |
| wp | WordPress core API deprecated (but still shimmed) by the target WP version | Pressready sniff |
The WP dataset records the WordPress version it was generated from. Target a --wp newer than the dataset and Pressready warns on stderr (results may be incomplete — regenerate) rather than imply a clean bill of health. Point a run at a custom or newer dataset with PRESSREADY_DATASET=/path/to/wp-deprecations.json.
Run the single-file PHAR for zero-setup use anywhere, or install via Composer to pin it per project.
A single self-contained file that bundles the whole PHPCS toolchain — nothing to composer install, and no chance of clashing with a project's own pinned squizlabs/php_codesniffer. Ideal for CI, a server, or a project you don't want to add a dev dependency to.
# Download the latest release and run it curl -L https://github.com/itzmekhokan/pressready/releases/latest/download/pressready.phar -o pressready.phar chmod +x pressready.phar ./pressready.phar --php=8.4 --wp=6.9 --path=wp-content
On first run it extracts its bundled toolchain to a cache dir; later runs reuse it. Every flag works exactly as the Composer-installed CLI.
Installs the released PHAR and runs it with a Homebrew-managed php (pulled in as a dependency) — nothing else to set up. Upgrade with brew upgrade pressready.
brew tap itzmekhokan/pressready
brew install pressready
pressready --php=8.4 --wp=6.9 --path=wp-content
Installs the Pressready PHPCS standard automatically via dealerdirect/phpcodesniffer-composer-installer, in two tiers depending on how new a PHP version you need to target.
The standard install needs no stability config. It pulls the stable PHPCompatibility engine, which detects everything up to PHP 8.1 plus the full WordPress deprecations axis. Most sites can stop here.
# Add to your project as a dev dependency
composer require --dev itzmekhokan/pressready
PHP 8.2–8.4 detection needs the pre-release PHPCompatibility 10 engine. Allow dev stability and request the pre-release engine explicitly (Composer prefers stable otherwise, so you must name it):
# Configure your project once composer config minimum-stability dev composer config prefer-stable true composer config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true composer config --no-plugins allow-plugins.phpcsstandards/phpcsutils true # Add Pressready and pin the pre-release engine composer require --dev itzmekhokan/pressready phpcompatibility/phpcompatibility-wp:3.0.0-alpha2 # Verify the standards registered vendor/bin/phpcs -i # lists "Pressready" and "PHPCompatibilityWP"
Requires PHP 7.4+. The PHP 8.2–8.4 engine (PHPCompatibility 10.x) is pre-release — this opt-in step goes away once it ships stable.
Prefer one shared install for ad-hoc scans across all your local sites? Install it globally. Configure global Composer once (same stability rules — drop the minimum-stability/prefer-stable lines if you only target PHP ≤ 8.1), then require it:
# Configure global Composer once (the dev-stability lines are only needed for PHP 8.2–8.4) composer global config minimum-stability dev composer global config prefer-stable true composer global config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true composer global config --no-plugins allow-plugins.phpcsstandards/phpcsutils true # Install globally (drop the explicit engine pin if you only target PHP ≤ 8.1) composer global require itzmekhokan/pressready phpcompatibility/phpcompatibility-wp:3.0.0-alpha2 # Put the global bin on your PATH (zsh; use ~/.bashrc for bash) echo 'export PATH="$PATH:$(composer global config home)/vendor/bin"' >> ~/.zshrc && source ~/.zshrc # Verify, then scan any site by path pressready --php=8.2 --path=/path/to/site/wp-content
Global is ideal for a developer's local sweeps across many sites. For CI and team reproducibility, still use composer require --dev per project so the engine version is pinned in each composer.lock.
Run the standalone CLI directly after composer install.
# Both axes — the headline question. vendor/bin/pressready --php=8.4 --wp=6.9 --path=wp-content # One axis at a time. vendor/bin/pressready --php=8.4 --path=. vendor/bin/pressready --wp=6.9 --path=. # Scan just your own code — repeat --path (theme + brand mu-plugins). vendor/bin/pressready --php=8.4 --wp=6.9 --path=wp-content/themes/acme --path=wp-content/mu-plugins/acme # Delta: only what newly breaks upgrading FROM 6.4 TO 6.9. vendor/bin/pressready --wp=6.9 --since=6.4 --path=. # CI gate: fail the build only on real fatals. vendor/bin/pressready --php=8.4 --wp=6.9 --fail-on=fatal --path=. # Machine-readable output. vendor/bin/pressready --php=8.4 --wp=6.9 --format=json --path=. # GitHub PR inline annotations. vendor/bin/pressready --php=8.4 --wp=6.9 --format=github --path=. # SARIF for code-scanning dashboards (GitHub Advanced Security). vendor/bin/pressready --php=8.4 --wp=6.9 --format=sarif --path=. > pressready.sarif # GitLab Code Quality report — inline MR annotations. vendor/bin/pressready --php=8.4 --wp=6.9 --format=gitlab --path=. > gl-code-quality-report.json # A PHP upgrade path — everything that breaks across 8.1 → 8.4. vendor/bin/pressready --php=8.1-8.4 --path=. # Compatibility matrix — how far can I safely upgrade, and what breaks first? vendor/bin/pressready --php=7.4-8.4 --matrix --path=. # Deprecations are hidden by default — add --all to list the full tail. vendor/bin/pressready --php=8.4 --wp=6.9 --all --path=. # Drop deprecations from the report and exit code entirely. vendor/bin/pressready --php=8.4 --wp=6.9 --ignore-on=deprecated --path=.
--format: grouped (default) · table · summary · json · sarif · github · gitlab
--fail-on: fatal · risky · deprecated · --ignore-on: hide findings at/below a level (the inverse)
--path is repeatable (or a comma list) to scan several targets in one pass · -h/--help prints the full flag reference · -V/--version prints the version.
Exit codes: 0 clean · 1 findings at/above --fail-on · 2 usage/config error (bad flag, missing path, or zero files scanned — a gate fails loudly instead of passing vacuously).
Instead of "does this one target break my site?", --matrix answers the question every site owner actually has — how far can I safely upgrade, and what's the first thing that breaks? It grades each version in the requested span from a single scan.
vendor/bin/pressready --php=7.4-8.4 --matrix --path=wp-content Pressready — compatibility matrix — PHP 7.4–8.4 Scanned: wp-content PHP 7.4 ✓ clear 8.0 ✗ 1 fatal 8.1 ✗ 1 fatal 8.2 ✗ 1 fatal 8.3 ✗ 1 fatal 8.4 ✗ 1 fatal ✓ Safe through PHP 7.4. ✗ First break: PHP 8.0 (1 fatal).
Pass a range (--php=7.4-8.4) to grade across it; a single --php=8.4 grades just that version.
--format=json emits the per-version grid plus safe_through / first_break for each axis, so CI can consume the ceiling.
--fail-on is honoured — a span containing a fatal exits non-zero. The WordPress axis is graded too, and lights up as the dataset gains removal data.
Built to scan a full enterprise wp-content — hundreds of plugins, tens of thousands of files — without crawling.
Speed
# Parallel is ON by default (auto-detects CPU cores). vendor/bin/pressready --php=8.4 --wp=6.9 \ --path=wp-content --parallel=8 # Cache results — re-scans only reprocess changed files. vendor/bin/pressready --php=8.4 --wp=6.9 \ --path=wp-content --cache
Focus & signal
# The 10 worst components, or just one. vendor/bin/pressready --php=8.4 --wp=6.9 \ --path=wp-content --top=10 vendor/bin/pressready --php=8.4 --wp=6.9 \ --path=wp-content --only=woocommerce
Un-fixable / generated code is skipped by default (vendor, node_modules, build, dist, *.min.php, tests, *.blade.php). Add your own with --ignore=<patterns> or turn the built-ins off with --no-default-ignore. Repeated identical findings collapse into one line with an (×N) count. The long deprecation tail is hidden by default — each component header keeps its deprecation count, and --all lists them in full.
Commit shared defaults to a .pressready.json in your project root — CLI flags always win.
{
"php": "8.4",
"wp": "6.9",
"fail-on": "fatal",
"paths": ["wp-content/themes/acme", "wp-content/mu-plugins/acme"],
"ignore": ["*/cache/*", "*/languages/*"],
"top": 20
}
Use paths: [] for multiple scan targets. Unknown keys are reported as a warning so a typo never silently changes your scan scope. Any --path on the command line replaces the file's path/paths entirely.
wp pressready scanSame engine, run from the WordPress root. Defaults to the site's wp-content. Runs before WordPress boots — no database required.
Add to your project's wp-cli.yml:
require: - vendor/itzmekhokan/pressready/wp-cli.php
Or pass --require inline:
wp --require=vendor/itzmekhokan/pressready/wp-cli.php pressready scan --php=8.4 --wp=6.9
# Scan with both axes — the main question. wp pressready scan --php=8.4 --wp=6.9 # Scan a specific directory instead of the default wp-content. wp pressready scan wp-content/plugins --php=8.4 # WordPress axis only, JSON output. wp pressready scan --wp=6.9 --format=json # CI gate: exit non-zero when fatals are present. wp pressready scan --php=8.4 --wp=6.9 --fail-on=fatal # Delta: only what newly deprecates upgrading from 6.4. wp pressready scan --wp=6.9 --since=6.4 # Compatibility matrix: how far can I upgrade, and what breaks first? wp pressready scan --php=7.4-8.4 --matrix # Table format (default), summary, CSV, or count. wp pressready scan --php=8.4 --format=table wp pressready scan --php=8.4 --format=summary wp pressready scan --php=8.4 --format=csv
Options
scan [<path>] | Directory to scan. Default: this site's wp-content. Positional — WP-CLI reserves --path for the install dir. |
--php=<ver> | Target PHP version (e.g. 8.4). Reports removed/deprecated PHP features. |
--wp=<ver> | Target WordPress version (e.g. 6.9). Reports deprecated core APIs. |
--since=<ver> | With --wp, only what newly deprecates upgrading from this version. |
--format=<fmt> | table (default) · summary · json · csv · yaml · count |
--fail-on=<lvl> | Exit non-zero when findings at/above this level exist: fatal · risky · deprecated |
--ignore-on=<lvl> | Hide findings at/below this level (the inverse of --fail-on). |
--parallel=<n> | phpcs worker processes. Default: auto (CPU cores); 1 to disable. |
--cache[=<file>] | Cache results so re-scans only reprocess changed files. |
--ignore=<patterns> | Extra comma-separated path patterns to skip (--no-default-ignore drops the built-ins). |
--only / --top | Focus the report: one component by name, or the N worst. |
--all | List every deprecation inline. By default the tail is hidden so fatals/risky stay scannable (--verbose is an alias). |
--config=<file> | Load defaults from a JSON config file (CLI flags still win). |
Adopt Pressready on a legacy site without drowning in pre-existing findings — snapshot today's known issues, then fail CI only on new ones.
GitHub Action recommended
The published Docker action bakes Pressready and its PHPCS 4.x toolchain into the image, so your repo carries no Composer boilerplate and can't clash with a project's own squizlabs/php_codesniffer ^3.x pin. A whole CI gate becomes two lines — .pressready.json and the baseline stay repo-local.
- uses: actions/checkout@v4 - uses: itzmekhokan/pressready@v1 with: baseline: .pressready-baseline.json fail-on: fatal format: github
Inputs: config (default .pressready.json) · baseline · fail-on (fatal·risky·deprecated) · format · php · wp · working-directory. Output: exit-code. Pin @v1 for the moving major tag or @v1.6.0 for an immutable release; the image is pulled pre-built from ghcr.io/itzmekhokan/pressready.
Run anywhere with Docker
The image is dual-mode: a GitHub Action when GitHub runs it, a plain CLI runner everywhere else — no Composer, no local PHP, no toolchain clash. Mirrored to Docker Hub (docker.io/itzmekhokan/pressready) for environments that can't pull GHCR.
docker run --rm -v "$PWD":/src -w /src ghcr.io/itzmekhokan/pressready:1 \
--php=8.4 --wp=6.9 --path=wp-content
GitLab CI
--format=gitlab emits a Code Quality (Code Climate JSON) report — publish it as a codequality artifact and GitLab annotates every finding inline on the merge request.
pressready: image: ghcr.io/itzmekhokan/pressready:1 variables: { GITHUB_ACTIONS: "" } script: - pressready --php=8.4 --wp=6.9 --path=wp-content --format=gitlab > gl-code-quality-report.json artifacts: reports: { codequality: gl-code-quality-report.json }
Other CI & your editor
Any runner that can pull the image gates the same way — Bitbucket Pipelines (image: ghcr.io/itzmekhokan/pressready:1) and Jenkins (agent { docker { image '…' } }) both run pressready … --fail-on=fatal and honour the exit codes. Pressready is also a phpcs standard, so VS Code / PhpStorm can surface findings inline — point the phpcs inspection at Pressready/ruleset.xml. See the README for copy-paste recipes.
Pre-commit hook optional
Entirely opt-in — a project adds it to its own .pre-commit-config.yaml to scan staged PHP before each commit. Runs via the image (Docker only) or a repo: local hook pointing at vendor/bin/pressready / pressready.phar (no Docker).
repos: - repo: https://github.com/itzmekhokan/pressready rev: v1.6.0 hooks: - id: pressready args: [--php=8.4, --wp=6.9, --path=wp-content]
Or run the binary yourself
Standalone CLI
# Snapshot existing findings. vendor/bin/pressready \ --php=8.4 --wp=6.9 \ --generate-baseline # From now on, fail only on NEW findings. vendor/bin/pressready \ --php=8.4 --wp=6.9 \ --baseline --fail-on=fatal
GitHub Actions
- name: Pressready scan run: | php bin/pressready \ --php=8.4 --wp=6.9 \ --baseline \ --fail-on=fatal \ --format=github \ --path=wp-content
Findings are keyed by path → signature (sniff code + message with line numbers neutralised), so the baseline survives line shifts and reordering. Paths normalise relative to the directory you run from (your repo root), so a baseline generated locally matches one generated in CI regardless of whether --path was absolute, relative, or scoped to a subdirectory. --baseline=<file> / --generate-baseline=<file> accept a custom path.
Uses native PHPCS inline comments — no custom syntax to learn.
// Suppress everything on this line. create_function( '$x', 'return $x;' ); // phpcs:ignore // Suppress a specific sniff. get_postdata( 1 ); // phpcs:ignore Pressready.WordPress.Deprecated.DeprecatedFunction
The core scanning engine and WP-CLI integration are complete and production-ready.
| Phase | Scope | Status |
|---|---|---|
| 1 | WP-deprecations dataset generator + authoritative JSON dataset | done |
| 2 | Custom PHPCS sniff + reporter (grouped / summary / json), version gate, exit codes | done |
| 3 | --php= via bundled PHPCompatibility; unified severity model (fatal / risky / php / wp) | done |
| 4 | Per-component attribution, baseline, --format=github, inline suppression | done |
| 5 | wp pressready scan WP-CLI command (before_wp_load, all formats, --fail-on) | done |
| 6 | Enterprise scale: parallel scanning, result cache, path ignores, duplicate collapsing, --only/--top, .pressready.json config, SARIF output, PHP version ranges, docblock-driven dataset coverage | done |
| 7 | Docker GitHub Action (ghcr.io image, @v1) — one-line CI adoption with the PHPCS toolchain baked into the image | done |
| 8 | v1.5: compatibility matrix (--matrix); WordPress removed-by-target findings are fatal + dataset-version awareness; single-file pressready.phar distributable | done |
| 9 | Integration tooling: docker run CLI mode, opt-in pre-commit hook & GitLab CI Code Quality report (--format=gitlab) | done |
| 10+ | Cross-version removed data; DataViews admin report; WP.org distribution | planned |
Found Pressready useful? A ⭐ helps other WordPress teams find it before their next upgrade — and shapes what ships next.
★ Star on GitHub