Matthias J Mair

The InvenTree ecosystem: Plugins


In the spring of this year (2026), I thought I should write a short article about the InvenTree ecosystem after having told people at FOSDEM about it. Then I lacked any simple reference that I could look things up in. a simple article would be the perfect solution.

It is not spring anymore and this article is not done but I have to start publishing this as I have written talks that reference data from it.

Main insights

My current data set contains 112 publicly visible and 63 private plugins. All following statements are only about the public plugins. Public plugins are ones where there is some form of public, unauthenticated access to the plugin. Might it be a source code repository, a Python wheel, a sdist or a zip folder (yes there is at least on author publishing plugins to a public FTP server as zip archives1).

                       Plugins by license            
           ┌                                        ┐ 
    (none) ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 54   
       MIT ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 54   
   GPL-3.0 ┤■■ 3                                      
    Apache ┤■ 1                                       
           └                                        ┘
                      Plugins per source              
          ┌                                        ┐ 
   GitHub ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 90   
     PyPI ┤■■■■■■■■■■■■■■■■■ 43                      
          └                                        ┘
                   Plugins grouped by source combination  
                ┌                                        ┐ 
         GitHub ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 69   
           PyPI ┤■■■■■■■■■■■ 22                            
   GitHub; PyPI ┤■■■■■■■■■■■ 21                            
                └                                        ┘
                         Plugins per author (3 or more)      
                   ┌                                        ┐ 
   SchrodingersGat ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 14   
           matmair ┤■■■■■■■■■■■■■■■ 6                         
          wolflu05 ┤■■■■■■■■■■■■■■■ 6                         
            gunstr ┤■■■■■■■■■■■■■ 5                           
      SergeoLacruz ┤■■■■■■■■■■■■■ 5                           
         invenhost ┤■■■■■■■■■■ 4                              
          tekktrik ┤■■■■■■■■■■ 4                              
           0neShot ┤■■■■■■■■ 3                                
   james-b-collins ┤■■■■■■■■ 3                                
                   └                                        ┘
                                 Plugins per import group         
                        ┌                                        ┐ 
       UI modifications ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 18   
       printing plugins ┤■■■■■■■■■■■■■■■■ 8                        
            Linked Data ┤■■■■ 2                                    
   Notification plugins ┤■■ 1                                      
                        └                                        ┘

(unstructured) data collection beginnings

Ever since I got involved with InvenTree in March 2021 and submitted the plugin framework (still not sure this was the best of ideas) I have collected data on usage in various ways.

First I had a spreadsheet in which I recorded every encounter in which someone mentioned the plugin interface.
After a while I extended the error reporting template and matching in-platform dialog with some metadata on plugin usage. This was a happy side-effect of restructuring the report / feature request flow. This manual process of recording events by hand continued.
During a discussion with a valued coworker about InvenTree they inquired about what ETL pipeline/tool I was using for my statistics and I was amazed about my oversight. Never had this possibility occurred to me. That evening I added a simple scraper script (in Python obviously) that I scheduled in a weekly GitHub action and some simple on-demand analytics on my homelab cluster.

Trying to use the data

This still pretty simple setup kept humming along till autumn 2025. Around August of that year, I started thinking about breaking the plugin API and doing a major overhaul of the way plugins are registered. This would help to fix some long standing efficiency issues. It also could help with isolating plugins from core context for a nicer threat model and less potential for unintended information disclosure.

After building a prototype I rewrote some of my private plugins to work with the new system. There would be quite a bit of work to update all existing plugins. Just to be sure the amount of required work for plugin authors was somewhat realistic I took a look at some of Oliver Walter's plugins. The required time shot up, he laid things out other than I did. Then I tested with wolfu05's work and had to recognise: the ecosystem is just too unknown to me to make this kind of decisions. I buried the idea and never published my work as it was not to my standards. This is usual, maybe half of my experiments ever make it into upstream.

I recognised that I needed more and much more detailed data on plugins. So I got "us" a trove classifier. These are used in the Python ecosystem to describe packages. I documented that a bit on this blog in 2025. With this new capability available a few days later (the Python community can be very fast), I updated internal and public tools, crawled GitHub and Gitlab and submitted a bunch of PRs to get adoption up. Then I decided to work on other stuff for 39c3 and promptly stopped working on this for a few months.

On my way back from FOSDEM in February 2026 I took nearly the full ride from Brussels to Innsbruck to look at all tagged packages and analyse the source code. The classifier worked but PyPI was not the correct catalog as only 1/3 of the packages ever made it there. A more structured tool was needed.

Writing a "proper" tool

For another data collection effort around security I wrote a small web tool for scanning InvenTree instances in 2024. In July 2025 it was restructured to generate SBOMs and in September of that year I rewrote it to use Django as I feel more comfortable with it.

So I had a django-codebase just waiting to be blown up with more functions in classic monolithic fashion. In march 2026 I started moving the scraper logic and data modelling into that app. I added PyPI, GitHub and Gitlab discovery based on topics and tags, the trove classifier and some distinctive code patterns that plugins must include to work. Then I let it rot till a larger holiday in July 2026, during which I needed some of the data for a small talk and discussions about InvenTree.

With help from some AI tooling I vastly reduced the resource usage on external resources (PyPI mainly, the great people at the PSF really do not need any more load than necessary on their infra).

Plugin detail screenshot

That brings me to today where the tool crawls the internet every day, classifies and correlates the data (most plugins on PyPI are also on some forge), then adds it to the database and runs extensive analytics on it. Amongst some basic statistics I:

This data then feeds into a human review and ends up in a few (for now internal) dashboards. At some point I hope to find the time to make at least the cleaned list of plugins publicly available.

Using the AST for better tagging

Running and persisting AST analysis on the source code of all available plugins allows me to use structural information rather than the tags on the official plugin list which seems to be not too popular amongst developers.

For example here are the matching patterns I use for printer plugins.

Printer plugin matching patterns

With these insights I can base future refactors on much better data. It would be much better if people provided more structured data to the official plugin list or we had some telemetry (I already knew we needd that in 2023 but this will probably lead to very energy intensive discussions).


  1. I have decided to not include their plugins in the dataset due to them probably being a honeypot ↩


Previous / Next Articles