As various topics have mentioned, the 2.0 release will bring with it an overhaul of the plugin framework. Two components of this are a new Avogadro-plugin API, and a new way for plugins to specify metadata for Avogadro (in TOML files). These have been previously discussed, and are pretty much implemented.
The third and final component of the plugin framework is the broader infrastructure that provides plugins to users. This is currently handled by a combination of the Avogadro/plugins GitHub repository and the plugin index at https://avogadro.cc/plugins.json. Since the infrastructure is designed to work with the current plugins and the current metadata format, it needs adjusting, which Iâve been working on doing.
This post is to:
- summarize the current state of affairs;
- summarize the work done and decisions made so far;
- pose a few remaining questions.
Hopefully this means those interested are kept abreast of the development progress. Anyone is welcome to contribute opinions and perspectives if they like!
Current state
The infrastructure is currently set up as follows:
- The
Avogadro/pluginsrepository currently comprises a register of plugins, calledrepositories.txt, and a Python script,cachedetails.py - The register contains a list of plugin repository URLs and nothing more.
- A plugin author can apply for their plugin to be made available to Avogadro users in the plugin downloader dialog by requesting that the pluginâs repo is added to the register.
- The script is responsible for processing the register, fetching information from each pluginâs source, and compiling an index file,
plugins.json, from that information. - The generated index is uploaded to https://avogadro.cc/plugins.json; this file at this URL is then the actual index, and is accessed by Avogadro to get information on the available plugins.
- When installing a plugin, Avogadro does not download the pluginâs code from some central repository that the project maintains, it downloads the code directly from the pluginâs own repo â all Avogadro gets from the index is some metadata and the URL for the source repo.
- The information in the index includes the pluginâs name and version, the type of plugin, and the date and time of the last update.
- Which version of a plugin to use is not specified in the register. Avogadro simply downloads the latest source code of the
mainormasterbranch, unless the plugin uses GitHubâs Releases feature, in which case Avogadro downloads the most recent release instead. - To collect the metadata for the index, the script combines information from each pluginâs metadata file (which until now was called
plugin.json) as well as the GitHub repoâs metadata. If the same thing is specified differently in several places it picks one to use preferentially: for example, the plugin name, authors, and description are taken preferentially fromplugin.json, but the version number is taken preferentially from the release name (but only if there is a release, of course). - The different sources of metadata, and correct metadata not being enforced, leads to problems like the the PyPept plugin being listed in the plugin downloader with the name
commandsand the same description as the actualcommandsplugin - The index is generated by the script, but the script is run manually, and the upload of the index file to https://avogadro.cc/plugins.json is also manual.
- When a new version of a plugin is created, the plugin index becomes outdated and inaccurate. After making a new version, plugin authors have to request that the index is regenerated. The plugin register is not changed.
- If a plugin does not use GH releases, Avogadro always fetches the latest code, so any changes to the code of the plugin are automatically given to anyone who subsequently downloads the plugin, even if the index hasnât been updated. If the version number doesnât get updated, different users can have different versions of the same plugin while each still has the same version number.
Changes and decisions already made
Updates to all this (register, script, and index) are necessary anyway for the new API and metadata format, but various aspects of the above are also unsatisfactory.
The current state of work on the Avogadro/plugins repository can be seen in my branch for the purpose at GitHub - matterhorn103/plugins at api2.
Some general principles
- The old register and script are to be retained for now.
- Information that is necessary for Avogadro to handle plugins properly prior to download is to be stored in the plugin index, which means plugin authors must specify it either in
repositories.tomlor the pluginâs metadata TOML, and it is now mandatory to provide it. This way, Avogadro does not have to inspect the pluginâs code prior to download- This applies to the download/installation mechanisms and to the main area of the plugin downloader dialog; things like the README of a plugin are not intended
- In future, we might want to allow sources other than GitHub; as such, plugin metadata should be, as far as possible, independent from the structure or metadata of the Git(Hub) repo itself.
- All pieces of information put into the index should come from a single source, never selected from amongst multiple possibilities. Conflicts and inconsistencies are thus avoided. From now on, for example, the pluginâs description is optional, but if one is provided it must be specified in the pluginâs metadata TOML, and is never taken from the GH repo description any more.
- The code of plugins made available to Avogadro users via the Avogadro infrastructure should never change without the knowledge and approval of the Avogadro team.
Changes so far
- Everything has been updated to reflect the changes to the API and plugin metadata file (which is now contained in either
pyproject.tomloravogadro.toml). - The register for new (>=2.0) plugins is in a
repositories.tomlfile. - There is a new script,
generate_index.py, for generating the new index. - Plugin authors are required to specify more information in the register than before:
- The plugin name
- The name is the key of the pluginâs table in the TOML â this is a convenient way to prevent two plugins ever having the same name
- The URL of the git repository of the pluginâs source
- This is basically the same as before, but because itâs separate to the name, it allows the name of the plugin to differ from the name of the GH repository (e.g. Iâd like the xtb plugin to just be called
xtbwithin Avogadro, but the repo is calledavo_xtbto distinguish it from the actual xtb program)
- This is basically the same as before, but because itâs separate to the name, it allows the name of the plugin to differ from the name of the GH repository (e.g. Iâd like the xtb plugin to just be called
- An optional path to the plugin relative to the top of the git repo
- This allows for a project to make an Avogadro plugin for the project and keep it with the rest of the projectâs code, but not have to have it at top level. This would allow the PyPept plugin to be merged into the parent PyPept project, for example. Would also have meant I wouldnât have had to split
easyxtbandavo_xtbacross two separate repos.
- This allows for a project to make an Avogadro plugin for the project and keep it with the rest of the projectâs code, but not have to have it at top level. This would allow the PyPept plugin to be merged into the parent PyPept project, for example. Would also have meant I wouldnât have had to split
- The plugin metadata file being used
- Makes the script much simpler if itâs known in advance
- The type of the plugin
- This could be removed, but is the only source of the information and might be useful for the plugin downloader to have without having to work it out
- A specific git commit
- The plugin name
- The script combines information for each plugin from
repositories.toml, the pluginâs metadata file, and the GitHub metadata of the repository.
name,version,authors, andlicenseare now mandatory keys in the plugin metadata file. - The script now validates some aspects of the metadata it collects e.g. that version numbers are strings rather than floats. If the script errors due to bad metadata, the responsible plugin wonât be accepted into the index.
- GitHub releases are no longer a source of information. However, if releases are in use for the pluginâs repository, the script will check that the commit indicated in
repositories.tomlcorresponds to a release, and that the version numbers match. This is to prevent the code that users install in Avogadro for versionxbeing different from the code in the pluginâs repo released as versionx, which would be deceiving. This will result in a warning, not an error, so as not to prevent the âproject provides an Avogadro plugin in a subdirectory rather than a separate repoâ setup. - A plugin will always be downloaded by Avogadro by reference to a specific commit, not to a release. This is because releases can be deleted or changed, so the release might not have the same code in future, whereas a commit hash is essentially unique and unchangeable.
- Plugins are in future to be made available to users by changing
repositories.tomlvia a pull request, which the Avogadro team will merge. A mixture of manual and automatic vetting of plugins will likely be applied. Importantly, updates to existing plugins are also released via the same pull request mechanism. - Index generation and upload remains manual for now but will likely be automated as a GitHub action that is triggered by the merge of a PR. Since in future all changes to plugins will require a PR, this will work nicely to keep the index always up-to-date.
The resulting index
All this affords an index file that looks like this (indentation added to make it more readable here â the version online wouldnât have it):
[
{
"name": "pypkg-demo",
"version": "6.0.2",
"authors": [
{
"name": "Amedeo Avogadro",
"email": "[email protected]"
}
],
"license": "BSD-3-Clause",
"description": "An example Python package plugin for Avogadro 2 to demonstrate the revamped plugin API in v2.0 onwards",
"minimum-avogadro-version": "1.103",
"feature-types": [
"electrostatic-models",
"energy-models",
"file-formats",
"input-generators",
"menu-commands"
],
"git": "https://github.com/matterhorn103/avo-plugin-demo.git",
"path": "pypkg-demo",
"metadata": "pyproject.toml",
"commit": "dbbc4d49396ac2b7746abb0bec0af6e577d8c0c5",
"plugin-type": "pypkg",
"last-update": "2026-02-16T02:18:19Z",
"commit-timestamp": "2026-02-16T02:18:14Z",
"has-release": false
},
{
"name": "avogenerators",
"version": "2.0",
"authors": [
{
"name": "Allison Vacanti",
"email": "[email protected]"
},
{
"name": "Kyle Lutz",
"email": "[email protected]"
},
{
"name": "Marcus D. Hanwell",
"email": "[email protected]"
},
{
"name": "Geoffrey Hutchison",
"email": "[email protected]"
},
{
"name": "Eric Berquist",
"email": "[email protected]"
},
{
"name": "Shiv Upadhyay",
"email": "[email protected]"
},
{
"name": "Amanda E. Dumi",
"email": "[email protected]"
},
{
"name": "Adrea Snow",
"email": "[email protected]"
},
{
"name": "Christian Clauss",
"email": "[email protected]"
},
{
"name": "Ty Balduf",
"email": "[email protected]"
},
{
"name": "Javier Cerezo",
"email": "[email protected]"
},
{
"name": "Matthew Milner",
"email": "[email protected]"
}
],
"license": "BSD-3-Clause",
"description": "Scripts for generating input files for computational chemistry packages",
"minimum-avogadro-version": "1.103",
"feature-types": [
"input-generators"
],
"git": "https://github.com/OpenChemistry/avogenerators.git",
"metadata": "pyproject.toml",
"commit": "9843e35d4009040847dab2f49cd108a1c5391e0a",
"plugin-type": "pypkg",
"last-update": "2026-02-21T19:59:00Z",
"commit-timestamp": "2026-02-21T19:58:56Z",
"has-release": false
}
]
If a plugin has GH releases, the index would additionally contain release-tag and release-version.
@ghutchis Are you happy with this? Would you like to see any other information included in the index, or is this enough for the plugin downloader to do everything it needs to do without downloading the whole pluginâs code?
Remaining questions
- Does the new index contain all necessary information?
- Where should the new index be put?
- The intention is to put it at a different URL e.g. https://avogadro.cc/plugins2.json, so that the old index can remain online and people using Avogadro versions <2.0 can still get plugins the same way they do now
- Might it be an idea to have a copy of the index in the plugins repo as well as on the website, and have the plugin downloader in Avogadro check both in case one or the other is unavailable? In case the Avogadro code moves to GitLab, for example, or for any times when the website is down.
- Should the
pluginsrepo move to theOpenChemistryorganization to sit alongside the other Avogadro repos? (The same question could apply to the documentation/website, which is atAvogadro/two.avogadro.cc.) - When should the old infrastructure be retired? (Note that if any plugins that donât use GitHub releases choose to update for the new API, those plugins will stop working with Avogadro <2.0, because the code downloaded is always the latest for release-less plugin repos.)
All feedback welcome!


