Skip to main content
drupalreleases

Use direct release data with your AI assistant.

Learn more

Adaptive Updates Info

No security coverage Under active development 70 sites

This module provides Drush commands and a PHP service to report available updates for Drupal core, modules, and themes. It can output this information as plain text, JSON, or YAML, making it suitable for command-line use, scripting, and integration into monitoring or deployment pipelines. The report prioritizes security updates and includes details like installed and recommended versions, release dates, and links to release notes.

Adaptive Updates Info reports which of your site's projects (Drupal core, modules and themes) have updates available, and which parts of the site are deprecated, unsupported or waiting on a core upgrade. It also lists every module and theme on the site with its path, and whether it is core, contrib or custom. It works from the command line or from your own code, and outputs readable text, JSON or YAML.

If you are new to Drupal: Drupal already checks drupal.org for new releases of everything you have installed, and shows the result on a page in the admin interface at Reports › Available updates. It also warns about deprecated modules on the status report. Those pages are built for a person sitting in front of a browser. The moment you want the same information anywhere else (in a nightly email, on a monitoring dashboard, in a check that stops a deployment while a security release is outstanding, or in a spreadsheet of versions across a dozen sites) there is nothing to call. You either read the page by eye or write code against Drupal's internals.

This module fills that gap. It adds four Drush commands that print the reports at your terminal or emit it as JSON or YAML for a script, and documented services so your own module can ask the same questions in PHP. It reads the data Drupal already collects: it changes nothing, installs nothing, and stores nothing.

Features

  • Four Drush commands. drush aui:updates reports every project that needs attention. drush aui:security reports only projects with a security release. drush aui:deprecations reports deprecated and obsolete modules and themes, and projects that are revoked, unsupported or blocked by core. Those two exit with a non-zero status when they find something, so they can fail a build or block a deploy. drush aui:pmlx (or just drush pmlx) lists every module and theme, like drush pm:list, with more detail.
  • Know where every module comes from. pmlx adds three columns to the familiar pm:list output: the source (core, contrib or custom), the parent project of a submodule (so ai_search is shown as part of ai), and the lifecycle (stable, experimental, deprecated or obsolete). The path is shown by default, and Drush's own --format, --fields and --filter options all work.
  • Output for people and for machines. --format=table (the default) is written for the terminal; --format=json and --format=yaml emit the full report for scripts, dashboards and monitoring tools.
  • Most urgent first. Security releases come first, then revoked releases, then unsupported ones, then ordinary updates, alphabetically within each group, so what matters is always at the top of the output.
  • Detail the admin page does not give you in a usable form. For each project: installed and recommended versions, release date, release notes link, release type, core compatibility (including whether the release can be installed on your version of core), and the modules the project covers, so a project name can be traced back to what is actually installed.
  • Upgrade blockers, not just updates. The deprecations report picks out the updates you cannot take yet because the recommended release needs a newer Drupal core, alongside the modules and themes core has marked deprecated or obsolete. That is your list of what has to be replaced or upgraded before the next core version.
  • A site-wide summary. Counts of security, revoked, unsupported, pending and unknown projects (or, for deprecations, of deprecated, obsolete, unsupported and core-blocked items), plus the timestamp of the last check, in every machine readable response.
  • A full inventory on demand. --all adds the projects that are already up to date, turning the report into a complete version inventory of the site.
  • Fast mode. --skip-refresh reports the data Drupal has already stored, with no network requests, for checks that run often.
  • Reusable services. adaptive_updates_info.updates_info, adaptive_updates_info.deprecations_info and adaptive_updates_info.extensions_info do all of the work behind interfaces, so a custom module, a REST resource, a cron hook or your own Drush command can produce the same reports without duplicating any of it.
  • Read-only and quiet. No configuration, no user interface, no permissions, no database writes, and no data sent anywhere beyond the update check Drupal core already performs.

When would you use it?

  • A nightly job that posts pending updates to Slack, Teams or email.
  • A CI or deployment pipeline that refuses to ship while a security release is outstanding.
  • Planning a core upgrade: a list of the deprecated modules to remove and the contrib updates waiting on the new core version.
  • An agency or hosting dashboard that tracks update status across many sites from one place.
  • Maintenance reporting: a per-site record of exactly which versions were installed at the time of a release.
  • Auditing a site you have inherited: which modules are core, contrib, contrib submodules or custom code, and where each one lives.
  • Any custom module that needs to know whether the site is up to date, without re-implementing the logic.

Post-Installation

There is nothing to configure. The module has no settings page, no permissions, no content types and no blocks; enabling it simply makes the commands and the services available. Drupal core's Update Status module is installed with it automatically.

Check that the commands are registered:

drush list

You should see an aui: section listing aui:deprecations, aui:pmlx, aui:security and aui:updates. If it is not there, or you have just updated from 1.0.x, rebuild the caches with drush cr. Under DDEV or Lando, prefix the commands as usual (ddev drush aui:updates).

Reporting available updates

drush aui:updates

The command refreshes the release data from drupal.org, then reports only the projects that need attention: a security release, a revoked release, an unsupported release, or simply a newer release available. Projects that are up to date are left out, so a healthy site prints a single line:

 [OK] All projects are up to date.

Otherwise you get a section per project, worst first, followed by a summary of the whole site:

Entity API (module)
-------------------

 Status: SECURITY UPDATE
 Installed: 8.x-1.6
 Recommended: 8.x-1.8 (2026-08-26 https://www.drupal.org/project/entity/releases/8.x-1.8)
 Includes: Entity

Session Entity (module)
-----------------------

 Status: NOT SUPPORTED
 Installed: 8.x-1.0-beta2+1-dev
 Recommended: 2.0.1 (2024-01-23 https://www.drupal.org/project/session_entity/releases/2.0.1)
 Includes: Session Entity

 [ERROR] 1 security update(s) available!

 ! [WARNING] 1 unsupported release(s) installed.

 ! [WARNING] 14 update(s) available.

aui-updates works as an alias, and drush aui:updates --help lists everything below at the terminal.

Options

  • --all: also report the projects that are already up to date. They are listed last, after everything that needs work. The security, revoked, unsupported and pending counters in the summary are the same either way, because an up-to-date project never adds to them; what changes is total, which becomes the number of installed projects rather than the number needing attention. Use it when you want a full inventory rather than a to-do list. On a large site this produces a long report, so it pairs best with --format=json or --format=yaml. (aui:updates only.)
  • --format=table|json|yaml: how the report is rendered; defaults to table. Any other value is rejected with an error listing the supported formats.
  • --skip-refresh: report the release data Drupal has already stored instead of fetching fresh data. It returns immediately and makes no network requests, at the cost of being as old as the last check; the last_checked value in the JSON and YAML output tells you how old that is. Use it for checks that run often, and leave it off when the answer has to be current, such as before a deployment.

Output formats

Table is the default and is meant for a person: a section per project, then a colour-coded summary, as shown above.

JSON gives the complete report, pretty-printed:

drush aui:updates --format=json
drush aui:updates --all --format=json
{
  "projects": [
    {
      "name": "entity",
      "title": "Entity API",
      "type": "module",
      "installed": "8.x-1.6",
      "installed_release": [],
      "recommended": "8.x-1.8",
      "recommended_release": {
        "version": "8.x-1.8",
        "release_link": "https://www.drupal.org/project/entity/releases/8.x-1.8",
        "date": "2026-08-26",
        "core_compatibility": "^10.1 || ^11",
        "core_compatibility_message": "Requires Drupal core: 11.3.14 to 11.4.6",
        "core_compatible": true,
        "release_type": ["Security update"]
      },
      "also_available": [],
      "includes": ["Entity"],
      "status": "SECURITY UPDATE",
      "status_code": 1,
      "has_update": true,
      "is_security_update": true
    }
  ],
  "summary": {
    "security": 1,
    "updates": 14,
    "revoked": 0,
    "not_supported": 1,
    "unknown": 0,
    "total": 16
  },
  "last_checked": "2026-09-04T14:01:25+00:00"
}

Progress notices, warnings and errors are written to stderr, so stdout stays valid JSON and can be piped straight into another tool:

# The projects with a security release, as a list of names.
drush aui:updates --format=json | jq -r '.projects[] | select(.is_security_update) | .name'

# How many updates are pending.
drush aui:updates --format=json | jq '.summary.updates'

# A file for a dashboard to pick up.
drush aui:updates --all --format=json > /var/www/reports/updates.json

YAML carries exactly the same structure, which is easier to read by eye when you still want every field:

drush aui:updates --format=yaml

A release details value holds version and, when drupal.org provides them, release_link, date, core_compatibility, core_compatibility_message, core_compatible and release_type. core_compatible is true when the release can be installed on the site's version of Drupal core and false when it needs a different one. A release details value is empty when drupal.org no longer lists that release, which is common for the installed version of an older project.

Security updates only, and failing a build

drush aui:security
drush aui:security --format=json

aui:security lists only the projects with a security release available and exits with a non-zero status when there is one, which is what makes it useful in a pipeline:

drush aui:security --skip-refresh --format=json > security.json \
  || echo 'Security updates are pending.'

It takes the same --skip-refresh and --format options, and aui-security is an alias. Its summary is calculated before the security filter is applied, so the other pending updates stay visible even though they are not listed.

Deprecations and upgrade blockers

drush aui:deprecations
drush aui:deprecations --format=json

aui:deprecations reports the parts of the site that need replacing rather than simply updating:

  • installed modules and themes whose .info.yml file marks them lifecycle: deprecated or lifecycle: obsolete, the same ones core warns about on the status report;
  • projects whose installed release has been revoked;
  • projects whose installed release is no longer supported;
  • projects whose recommended release needs a newer version of Drupal core than the site runs, so the update cannot be installed until core is upgraded.
Statistics (module)
-------------------

 Lifecycle: deprecated
 Project: drupal
 More information: https://www.drupal.org/node/3223395#s-statistics

Search API Solr (module)
------------------------

 Status: Update available
 Installed: 4.3.14
 Recommended: 4.4.0 (2026-07-28 https://www.drupal.org/project/search_api_solr/releases/4.4.0)
 Includes: Search API Solr
 Reasons: Recommended release needs a newer Drupal core
 Recommended release: Requires Drupal core: 11.3.0 to 11.4.8

 ! [WARNING] 1 deprecated extension(s) installed.

 ! [WARNING] 1 update(s) need a newer Drupal core.

Like aui:security, it exits with a non-zero status when it reports anything, and takes the same --skip-refresh and --format options; aui-deprecations is an alias. The JSON and YAML output has four parts:

{
  "extensions": [
    {
      "name": "statistics",
      "title": "Statistics",
      "type": "module",
      "project": "drupal",
      "lifecycle": "deprecated",
      "lifecycle_link": "https://www.drupal.org/node/3223395#s-statistics"
    }
  ],
  "projects": [
    {
      "name": "search_api_solr",
      "...": "the same fields as in the update report",
      "reasons": ["core_incompatible"]
    }
  ],
  "summary": {
    "deprecated": 1,
    "obsolete": 0,
    "revoked": 0,
    "not_supported": 0,
    "core_incompatible": 1,
    "total": 2
  },
  "last_checked": "2026-10-01T15:08:19+00:00"
}

Each project carries every field of the update report plus reasons: one or more of revoked, not_supported and core_incompatible. A project can have more than one reason, so total is the number of extensions plus the number of projects rather than the sum of the other counters.

Listing modules and themes with pmlx

drush pmlx
drush pmlx --status=enabled --source=contrib,custom
drush pmlx --status=enabled --lifecycle=deprecated,obsolete
drush pmlx --fields=name,source,parent_project,path --format=csv
drush pmlx --fields=* --format=json

aui:pmlx lists the same modules and themes as drush pm:list, and adds:

  • source: core, contrib, custom or unknown. A contrib or custom folder in the path decides it; otherwise an extension carrying the project key that drupal.org adds when it packages a release counts as contrib. Anything else, such as a module placed directly in modules/ without a project key, is unknown.
  • parent_project: for a submodule or subtheme, the project it is part of, for example ai for ai_search. It is empty for top level extensions and for core.
  • lifecycle: the lifecycle key from the .info.yml file, or stable when it is not set.
 ----------------------- -------- ---------- --------- --------- ---------------- -------------- --------------------------------------
  Name                    Type     Status     Version   Source    Parent project   Lifecycle      Path
 ----------------------- -------- ---------- --------- --------- ---------------- -------------- --------------------------------------
  Ban (ban)               module   Disabled   11.4.8    core                       deprecated     core/modules/ban
  AI Core (ai)            module   Enabled    1.5.0     contrib                    stable         modules/contrib/ai
  AI Search (ai_search)   module   Enabled    1.5.0     contrib   ai               experimental   modules/contrib/ai/modules/ai_search
  Site core (site_core)   module   Enabled              custom                     stable         modules/custom/site_core
 ----------------------- -------- ---------- --------- --------- ---------------- -------------- --------------------------------------

Options, each taking a comma separated list: --type (module, theme), --status (enabled, disabled), --source, --lifecycle and --package. The output is built the same way as pm:list, so --format accepts table, json, yaml, csv and the rest, and --fields and --filter work as usual. --fields=* adds the package, project, name and lifecycle_link fields. Test modules and themes are left out, as they are by pm:list. pmlx and aui-pmlx are aliases.

Because it is a normal Drush command, it works through Terminus or any other remote Drush too:

terminus drush <site>.<env> -- pmlx --fields=* --format=json

Exit codes

0 means the report was produced and, for aui:security and aui:deprecations, that nothing was found. 1 means aui:security found at least one security update, aui:deprecations found at least one deprecation, or an unsupported --format value was given. aui:updates and aui:pmlx return 0 whatever the report contains, so use aui:security, aui:deprecations or the summary in the JSON output to fail a build.

Status values

  • SECURITY UPDATE (code 1): a security release is available.
  • REVOKED (2): the installed release has been revoked.
  • NOT SUPPORTED (3): the installed release is no longer supported.
  • Update available (4): a newer release is available.
  • Up to date (5): the installed version is the recommended one.
  • Not checked (-1), Unknown (-2), Not fetched (-3), Fetch pending (-4): no usable update data for that project yet.

The labels are deliberately not translated, so that scripts can rely on them; status_code is there for machine comparison.

Using the services in your own code

/** @var \Drupal\adaptive_updates_info\UpdatesInfoInterface $updates_info */
$updates_info = \Drupal::service('adaptive_updates_info.updates_info');

// The projects that need attention, using the stored release data.
$projects = $updates_info->getProjects();

// Every project, after refreshing the release data, plus the summary.
$report = $updates_info->getReport(TRUE, TRUE);

// Just refresh the stored data, for example from a cron hook.
$updates_info->refresh();

/** @var \Drupal\adaptive_updates_info\DeprecationsInfoInterface $deprecations_info */
$deprecations_info = \Drupal::service('adaptive_updates_info.deprecations_info');

// Installed modules and themes marked deprecated or obsolete.
$extensions = $deprecations_info->getExtensions();

// The whole deprecations report, after refreshing the release data.
$deprecations = $deprecations_info->getReport(TRUE);

/** @var \Drupal\adaptive_updates_info\ExtensionsInfoInterface $extensions_info */
$extensions_info = \Drupal::service('adaptive_updates_info.extensions_info');

// Every module and theme with its path, source, parent project and lifecycle.
$all = $extensions_info->getExtensions();

In your own services, type hint \Drupal\adaptive_updates_info\UpdatesInfoInterface, \Drupal\adaptive_updates_info\DeprecationsInfoInterface or \Drupal\adaptive_updates_info\ExtensionsInfoInterface and let autowiring inject it. getProjects() and getReport() on the updates service take $include_current (the equivalent of --all) and $refresh (the opposite of --skip-refresh, and off by default); the deprecations service takes $refresh only. The extensions service reads the code base only and makes no network requests. Refreshing performs network requests to the update servers, so leave it off when the stored data is good enough.

Things worth knowing

  • The report is only as good as the update data Drupal can fetch, so the site needs outbound HTTPS access to the update servers unless you always pass --skip-refresh.
  • Refreshing contacts the update servers for every project. On a large site the command can take a while; that is why --skip-refresh exists.
  • Everything is per site, so on a multisite installation run the commands with the usual Drush site selector (drush @site aui:updates or -l).
  • The module reports updates; it never applies them. See the recommended modules below for that.

Additional Requirements

  • Drupal 10.3 or Drupal 11.
  • PHP 8.1 or newer.
  • Drupal core's Update Status (update) module. It is a dependency, so it is installed automatically.
  • Drush 12 or newer for the aui:updates, aui:security, aui:deprecations and aui:pmlx commands. The commands are attribute based and live in src/Drush/Commands, which Drush discovers from version 12 on; Drush 11 and earlier will not see them. The services themselves have no Drush dependency and work without it.
  • Outbound HTTPS access to the update servers (updates.drupal.org by default), unless the commands are always run with --skip-refresh.

No third-party libraries, no API keys and no external services are involved.

  • Automatic Updates (and core's Package Manager): this module tells you what needs updating; those apply the update.
  • Drupal core's Update Status settings at /admin/reports/updates/settings: turn on email notifications so a person is told as well as a script.
  • Upgrade Status: for the different question of whether your own code uses deprecated APIs and is ready for the next major version of Drupal. aui:deprecations covers deprecated modules, themes and releases, not deprecated code.

Similar projects

  • Drupal core's Update Status report (Reports › Available updates) and status report (Reports › Status report) use the same underlying data, and are the right tools when a person is looking at the site in a browser. They have no command line or programmatic equivalent, which is exactly what this module adds.
  • drush pm:security was removed in Drush 13 and now points users at composer audit, so there is no longer a built-in Drush command reporting Drupal project update status.
  • composer audit and composer outdated work at the Composer package level. composer audit reports security advisories only; composer outdated knows nothing about Drupal core compatibility, release types, module lifecycles or projects that are not managed by Composer. This module reports what Drupal itself thinks about every installed project, including whether a release is revoked, unsupported or blocked by core.
  • drush pm:list lists modules and themes, and can show their path with --fields, but does not say whether each one is core, contrib or custom, which project a submodule belongs to, or whether it is deprecated. aui:pmlx keeps the same output and options and adds those.
  • Site Audit runs a broad best-practice review of a site. Its scope is much wider; this module does one thing and gives you the structured output to build on.

Supporting this Module

This module is maintained by Adaptive. Issues, patches and merge requests are very welcome in the issue queue. Bug reports with the output of drush aui:updates --format=json or drush aui:deprecations --format=json are especially useful.

Community Documentation

The README in the repository documents every command, option, output format and report field in full.

Drupal 10–11 PHP >=8.1

Ask your assistant about Adaptive Updates Info

Check compatibility with your Drupal and PHP version, maintenance and security coverage, from current release data. How it works

Depends on

Dependencies of the latest stable release

  • update Drupal core

Required by

Tracked projects that depend on this one

No tracked projects depend on this one yet.

Activity

Tracked releases
6
Tracked since
Sep 2026
Latest release
2 weeks ago
Releases (12 mo)
6 ▲ from 0
Maintenance
Active

Release Timeline

Releases

Version Type Core PHP Release date
1.2.1 Stable 10–11 PHP >=8.1 Oct 3, 2026
1.2.0 Stable 10–11 PHP >=8.1 Oct 2, 2026
1.2.x-dev Dev 10–11 PHP >=8.1 Oct 2, 2026
1.1.1 Stable 10–11 PHP >=8.1 Oct 1, 2026
1.1.0 Stable 10–11 PHP >=8.1 Oct 1, 2026
1.0.0 Stable 10–11 PHP >=8.1 Sep 4, 2026