Transform Learning with a Powerful Enterprise LMS

Learn more
Moodle

Moodle Plugin Types Explained: Every Type and Its Directory

A reference to every Moodle plugin type in 5.3: the frankenstyle prefix, the directory, the subplugin types core plugins declare, what changed from 4.5 to 5.3 and how to choose the right type.

Learn more about this topic with AI

Gemini opens with the prompt copied - paste it into the chat to start.

Illustration of the Moodle plugin type tree, mapping frankenstyle prefixes such as mod, block and local to their directories

Moodle plugin types are the fixed categories of extension that Moodle core knows how to load: each type has a short frankenstyle prefix (such as mod, block or local) and one directory where every plugin of that type lives. Moodle 5.3 defines 45 plugin types in lib/components.json, keeps one more (mnetservice) in a deprecated list, and core plugins declare a further 18 subplugin types of their own. Pick the wrong type and your code either never loads or fights the APIs it needs.

This reference lists every type with its directory, explains how subplugins work, shows which types arrived or left in recent releases, and gives a short rule set for choosing the right one. Checked against the Moodle 5.3.0 source (lib/components.json, every core db/subplugins.json, core_component and core_plugin_manager) and the Moodle developer docs on plugin types, October 2026.

How Moodle knows which plugin types exist

Moodle does not scan the disk for anything that looks like a plugin. It reads a registry, then looks only in the directories that registry names:

  • lib/components.json at the project root holds three objects: plugintypes (type to directory), subsystems (core areas such as core_course) and, when needed, deprecatedplugintypes or deletedplugintypes.
  • db/subplugins.json inside a plugin declares that plugin's own subplugin types under a subplugintypes object, with directories relative to the parent plugin.
  • core_component loads both, then caches the result. core_component::get_plugin_types() returns every type and its full path, get_plugin_list($plugintype) returns the installed plugins of one type, and get_subplugins($component) returns a parent's subplugin types.

A new plugin folder is installed when an administrator visits the Notifications page or runs admin/cli/upgrade.php. If you need the exact list for your own site rather than this article, the developer docs give a short CLI script that loops over core_plugin_manager::instance()->get_plugin_types() and prints each type, its plural name from plugintype_name_plural() and its directory.

From Moodle 5.1 the web-accessible code moved into public/, so every directory below sits under public/ on 5.1, 5.2 and 5.3. On 5.0 and earlier, drop that prefix. components.json in 5.3 stores the paths with the prefix, for example "local": "public/local".

The plugin types most projects actually use

Most custom work lands in about a dozen types. This table maps the common needs to the type that fits.

You want toPlugin typeDirectory (under public/)
Add a new activity teachers place in a course, with its own grades and completionmodmod
Show a panel on course, dashboard or site pagesblockblocks
Add site-wide behaviour, event observers, web services or pages that fit no other typelocallocal
Log users in against an external identity sourceauthauth
Control how users get into courses (sync, payment, keys)enrolenrol
Change the look of the sitethemetheme
Change how a course page lays out sections and activitiesformatcourse/format
Add a site or course reportreportreport
Add an admin utility under Site administrationtooladmin/tool
Add a new question type for quizzesqtypequestion/type
Transform text as it is displayedfilterfilter
Add a new "Restrict access" conditionavailabilityavailability/condition

Every Moodle plugin type and its directory in Moodle 5.3

This is the full plugintypes object from the 5.3.0 lib/components.json, grouped by area. Directories are relative to public/.

AreaFrankenstyle type and directory
Courses and activitiesmod mod; block blocks; format course/format; availability availability/condition; customfield customfield/field
Questionsqtype question/type; qbehaviour question/behaviour; qformat question/format; qbank question/bank
Gradesgradeexport grade/export; gradeimport grade/import; gradereport grade/report; gradingform grade/grading/form; gradepenalty grade/penalty
Users and accessauth auth; enrol enrol; profilefield user/profile/field
Reports and adminreport report; coursereport course/report; tool admin/tool
Look and contenttheme theme; filter filter; editor lib/editor; media media/player; contenttype contentbank/contenttype; h5plib h5p/h5plib
Files and exportsrepository repository; portfolio portfolio; fileconverter files/converter; dataformat dataformat
Integration and messagingwebservice webservice; message message/output; communication communication/provider; paygw payment/gateway; smsgateway sms/gateway; plagiarism plagiarism; calendartype calendar/type
AI and analyticsaiprovider ai/provider; aiplacement ai/placement; mlbackend lib/mlbackend
Infrastructurecachestore cache/stores; cachelock cache/locks; search search/engine; antivirus lib/antivirus
Everything elselocal local

A few of these surprise people. coursereport is still registered, but 5.3 ships no plugins in course/report; new course-level reports belong in report. editor covers whole text editors (TinyMCE and the plain textarea in 5.3), not editor buttons. h5plib holds versions of the H5P integration library, not H5P content.

Subplugin types: plugins inside plugins

Some plugins expose their own extension points. The parent declares them in db/subplugins.json, and the subplugin's component name uses the subplugin type as its prefix, for example assignsubmission_file. These are the 18 subplugin types declared by core plugins in 5.3.0:

ParentSubplugin typeDirectory (under public/)
Assignmentassignsubmission, assignfeedbackmod/assign/submission, mod/assign/feedback
Quizquiz (reports), quizaccessmod/quiz/report, mod/quiz/accessrule
Workshopworkshopform, workshopallocation, workshopevalmod/workshop/form, mod/workshop/allocation, mod/workshop/eval
Databasedatafield, datapresetmod/data/field, mod/data/preset
External tool (LTI)ltisource, ltiservicemod/lti/source, mod/lti/service
Bookbooktoolmod/book/tool
SCORMscormreportmod/scorm/report
Forumforumreportmod/forum/report
BigBlueButtonbbbextmod/bigbluebuttonbn/extension
Logging (tool_log)logstoreadmin/tool/log/store
Multi-factor authentication (tool_mfa)factoradmin/tool/mfa/factor
TinyMCE editortinylib/editor/tiny/plugins

Third-party plugins can declare subplugin types too, so a site with contributed plugins will show more than this list. Subplugin type names are global: each subplugin type name must be unique across the site, because Moodle maps the prefix alone, such as quizaccess, to one directory.

A subplugin is usually the cleaner choice when you extend one activity. A new quiz access rule belongs in quizaccess, not in a local plugin that hooks into quiz pages, because the quiz then calls your rule through its own API.

Plugin types added, deprecated and removed in recent releases

If you maintain plugins across several Moodle branches, these changes matter more than the full list:

ReleaseChange
3.10Payment subsystem with the paygw gateway type (MDL-69166)
4.0qbank question bank plugins
4.3Communication subsystem with Matrix and custom link providers in communication/provider (MDL-77576, MDL-78619)
4.5AI subsystem with aiprovider and aiplacement (MDL-82627); SMS subsystem with the smsgateway type (MDL-80960)
5.0gradepenalty for generic grade penalties, shipped with gradepenalty_duedate (MDL-80984); Atto editor removed, so the atto subplugin type is gone (MDL-83282); MNet plugins removed (MDL-84652); plugin type deprecation mechanism added (MDL-79843)
5.1Web code moved into public/; plugin types must define type_<type> and type_<type>_plural language strings (MDL-84948)

In 5.3.0, mnetservice (public/mnet/service) is the only entry in deprecatedplugintypes, and there is no deletedplugintypes object. Deprecation is staged: in the first stage core stops calling plugins of that type through hooks, callbacks and events, though their classes and strings still load; in the second (deleted) stage, any installed plugin of that type blocks the site upgrade until it is uninstalled. Subplugin owners use the same stages through deprecatedsubplugintypes and deletedsubplugintypes. If you hit that block, our guide to an upgrade blocked by a deprecated plugin type walks through the fix.

Naming rules and frankenstyle component names

Every plugin has a frankenstyle component name: the type, an underscore, then the plugin's machine name, as in local_hrsync or block_myoverview. The machine name is checked by core_component::is_valid_plugin_name():

  • It must start with a lowercase letter, end with a lowercase letter or digit, and contain only lowercase letters, digits and single underscores. The pattern is /^[a-z](?:[a-z0-9_](?!__))*[a-z0-9]+$/.
  • Activity modules (mod) may not contain underscores at all (the check is /^[a-z][a-z0-9]*$/), and a module may not share its name with a core subsystem.
  • qtype_random is reserved and rejected.
  • Hyphens are never allowed. A plugin that fails these checks is silently ignored, which is a common reason a freshly copied plugin never appears on the upgrade screen.

The folder name must match the machine name, and the component name drives the class namespace (\local_hrsync\...), the language file (lang/en/local_hrsync.php) and configuration rows. One quirk: activity modules keep a bare language file name (lang/en/forum.php for mod_forum).

How to choose the right plugin type

A few rules settle most debates on a project:

  1. Use the most specific type that has an API for your job. A new login method is auth, a new payment provider is paygw, a new AI model connector is aiprovider. The specific type plugs into the admin screens and callbacks core already has for that job.
  2. Extend an activity through its subplugin type when one exists, rather than patching the activity or hooking into it from outside.
  3. Reach for local when nothing else fits: integrations, scheduled sync jobs, event observers, web service functions and site-wide hooks. Do not use it to add a learner-facing course activity; that needs mod so it appears in the activity chooser, backup and restore, the gradebook and completion.
  4. Use tool for admin-only utilities that live under Site administration, and report for read-only reporting screens.
  5. Never edit core plugins. If a core plugin almost fits, look for a hook, a subplugin type or a theme override first, then a local plugin.

Some features span types. A typical HR integration is a local plugin for the sync and web services plus an auth plugin for login. Ship each as its own plugin, declare the dependency in version.php, and keep shared code in one of them.

To see what a site already has, open Site administration, Plugins, Plugins overview, or run php admin/cli/uninstall_plugins.php --show-contrib from the project root to list third-party plugins only. Our Moodle guide covers the rest of the development and administration topics, and the plugin compatibility guide explains what to check before a major upgrade.

How we can help

We build and maintain Moodle plugins of every common type, from local integrations and auth connectors to full activity modules and quiz access rules, and we audit contributed plugins before upgrades. See our Moodle plugin development service or the wider Moodle platform page.

Frequently asked questions

How many plugin types does Moodle have?

Moodle 5.3.0 lists 45 plugin types in the plugintypes object of lib/components.json, plus mnetservice in the deprecated list. Core plugins add 18 subplugin types, and contributed plugins can declare more.

What is the difference between a local plugin and an admin tool?

A tool plugin lives in admin/tool and is meant for admin utilities under Site administration. A local plugin lives in local and is the general home for site-wide customisations, integrations, event observers and web services that fit no other type.

Where do plugins go in Moodle 5.1 and later?

Under the public/ directory, for example public/local/myplugin or public/blocks/myblock. On Moodle 5.0 and earlier the same paths sit directly in the web root.

Why does my Moodle plugin not show up after I copy it to the server?

Common reasons are a folder name that breaks the naming rules (hyphens, uppercase, or underscores in an activity module name), the wrong parent directory for its type, or a version.php component name that does not match the folder. Invalid names are silently ignored.

Free 30-minute consultation

Not sure where to start? Talk to an LMS engineer.

Tell us what platform you run and what you need. You’ll get honest, practical advice - even if the answer is that you don’t need us.

Sources & references

  1. Plugin types - Moodle HQ
  2. lib/components.json (Moodle 5.3.0) - Moodle HQ
  3. lib/classes/component.php (Moodle 5.3.0) - Moodle HQ
  4. Frankenstyle component names - Moodle HQ
  5. Moodle 4.5 release notes - Moodle HQ
  6. Moodle 5.0 release notes - Moodle HQ
Add as a preferred source on Google

Add All-in-One LMS as a preferred source to see more of our articles in Google’s Top Stories.

Learn more about this topic with AI

Gemini opens with the prompt copied - paste it into the chat to start.

Keep reading

Before you go - get a free LMS audit

Tell us which LMS you use and what is not working. An engineer replies within one business day.

Choose which optional cookies we may use. You can change this at any time from "Cookie preferences" in the footer. Cookie policy · Privacy policy