Free tool · MIT licensed

Drupal 7 migration inventory scanner

Point it at a Drupal 7 codebase. It tells you what is in there that forces a migration decision, and files every finding under the decision it belongs to. One file, no dependencies, no signup, no network access.

Download d7-scan.mjs

Or fetch and run it in one go:

curl -O https://practicalmodules.com/tools/d7-scan.mjs
node d7-scan.mjs /path/to/drupal7

What it tells you

The hard part of a Drupal 7 migration is not the import. It is knowing what you are carrying. The scanner answers that in two halves.

Your own code. It finds the constructs that no longer exist in Drupal 10 or 11 — variable_get(), direct db_query() calls, hook_menu() page callbacks, block hooks, theme functions, .tpl.php templates, custom field types, custom entity types, Views exported to code, URL alter hooks, hook_update_N() and the rest — and reports each one with the files and line numbers it lives at, plus one sentence on why it forces a decision.

Everybody else's code. For every contributed module in the codebase, it reports whether a Drupal 10 or 11 release actually exists. That is measured, not remembered: the verdicts come from drupal.org's own release-history feed, the same one your site's update checker reads. Modules whose job was taken over by core — strongarm, date, entityreference, views, and about thirty more — carry a note saying so, because "no Drupal 8+ release" and "core does this now" are very different problems.

What the output looks like

Decision 5 — Give every contributed module a verdict
  https://practicalmodules.com/guide/drupal-7-migration-kickoff-checklist/#modules

  5 of 6 projects need a decision before you start:

    strongarm     no Drupal 8+ release [unsupported on drupal.org]
                  → Superseded by the core configuration system.
    mollom        stopped at Drupal 8/9 [unsupported on drupal.org]
                  → The Mollom service shut down in 2018. Pick a different spam defence.
    acme_widgets  not in this tool's table
                  → check https://www.drupal.org/project/acme_widgets

Decision 4 — Resolve every field that has no obvious destination
  https://practicalmodules.com/guide/drupal-7-migration-kickoff-checklist/#fields

  Custom field types — 1 in 1 file
    A custom field type has no destination until you write one; this is the
    classic migration blocker.
      sites/all/modules/custom/acme_reports/acme_reports.module:34

Add --markdown to get a version you can paste straight into a ticket, or --json for the full structured report.

It maps to the ten decisions, not to a score

Every finding is filed under one of the ten decisions in our free Drupal 7 migration kickoff checklist, and links to it. The scanner deliberately does not produce an effort estimate or a readiness percentage — it has no way to know your content volume, your team, or your deadline, and a made-up number would be worse than none.

One of the ten decisions — naming the decision owners — has no code signal at all. The report says so instead of quietly dropping it.

What it does not do

After the scan

The scanner tells you what has to be decided. The kickoff checklist is free and tells you how to know when each decision is genuinely settled rather than merely discussed. If you then want that same structure as a working record — inventory, field map, module plan, redirect map, and release QA, connected and formula-driven — that is the Drupal 7 to Drupal 11 Migration Workbook, $29 once.

You do not need the workbook for the scanner to be useful. It is free, it is MIT licensed, and it stands on its own.