How to get started developing plug-ins

• May 30, 2024 - 19:28

I browsed to the developer's page and the plug-in chapter it mentions but these are either completely unhelpful or starting from a point beyond where I am. The section on plug-ins for version 4 is all but empty; the section for version 3 is not useful for a version 4 user (for example, it suggests looking at the "Plug-in Creator" which doesn't (appear to?) exist in 4.

Can someone point me to an absolute beginner's starting point. I haven't programmed seriously in many years and can't figure out where to start.


FYI, MuseScore 4.4 (currently nightly master) does plugins slightly differently. It uses qt 6.2.4. I’ll look for the link, but some things done in prior versions no longer work.

In reply to by TDYama

But not only that.
Also QtQuick.controls and various other changes prevent most plugins to work.
e.g. for the "title" problem

title: "TITLE_HELLO 4.4"
// note: title="TITLE" doesn't work and causes menu to say "Run plugin ()", but the plugin does run.
// also, make sure the ":" after "title" is connected, as in "title:". "title : " doesn't work.

When 4.4 will be released, we will be in the same situation as when 4.0 was released: most plugins will not work anymore.

In reply to by graffesmusic

That some qtquick.controls will not work seems to mean most old plugins will need to be rewritten.

Soon , there will be more advanced plugins that are called extensions. When that happens, plugins likely will not be backward compatible. I don’t know when that will happen, though.

The workaround for “title” is at the bottom of the post. It allows a plug-in to be used by 3.6, 4.2 and 4.4, but requires changing the plugin with conditional logic.

3.6 doesn’t like “title” and causes the plug-in to not work. If no title is given, it’s hard to know which plug-in to run in the plugins menu in 4.4. The solution works but shows how supporting all the versions is not straightforward.

In reply to by TheHutch

4.4 is available as a nightly “master” build. I currently use one about a week old for daily composition, and download new ones regularly (and report bugs). There is some risk but that’s OK for me. I also tested out 4.4 plugins a while back and worked out some issues. Using ubuntu linux and the appimage method, multiple versions are easy to keep around.

Which OS do you use? The nightly pages are here:

Which OS you use determines how you see the “console.” Running musescore 4.x with a “-d” switch in debug mode will show “console.log” messages. This lets you see stuff that you print out and also error messages. A syntax error message indicates the line number of the error. This is pretty helpful - sometimes. MS 3’s plug-in builder is much better but if you want to use 4.2, we can base info on 4.2.

There are some plugins that show the contents of the data structure and structures that are “linked” to it. You will want to use one.

Once we know which OS you use, we can discuss how to run in debug mode and see console messages. Then, run a plug-in that shows the contents of the data structures “in the console”. Then, discuss how to view the contents of the structures and method to get there. There are multiple methods needed. Just to mention it, getting access to structures is slightly different when in a “selected” range vs. using “measure” access.

In reply to by TDYama

I'm on Windows 11 at this point. I'd like to move to Unix, but I'd need a second computer, which is not an option at this time. (I thought about setting up a dual-boot, but decided I don't want to take any chances.)

I'm very much at the "Hello world" point, so it will be a long journey. Hopefully past experience with other languages can make the journey shorter. :-)

In reply to by graffesmusic

I should clarify. I don’t “think” they will be useless but new plugins using advanced features (referred to as “extensions” on GitHub) likely won’t be usable on older musescore versions. Unfortunately no real details are available so I am speculating.

There will “likely” be a drift away from trying to be compatible to just using new capabilities. I’m surprised on the number of current 3.x users. Trying to be compatible in MS 3.x and 4.2 is nice. Making a new 4.4 plugin work in 3.6 seems “mostly” possible since the API hasn’t changed.

When the new “extensions” are added (unknown time frame, unknown capabilities), there is “likely” to be something new that can’t be used in MS 4.2 and 3.6. We will have to wait and see.

It is supposed to be advanced. It is “progress” that we have to work with.

The plug-in creator in version 3 (!) is pretty useful. I would suggest loading musescore 3.7 and using the creator in it to get used to plugins. They can’t all be transferred but you will have learned quite a bit.

I’ll edit a plug-in that has a basic structure. You can then type it in a text editor, save it in the plugs in directory, restart musescore to find it, go to manage plugins to add it into musescore, and then run it from the menu.

It will probably take a couple of days to get to it.

In reply to by TDYama

Yes, those two pages were among the pages I looked at ... that didn't seem helpful. Looking at one of the "boilerplate" pages, I see now that I must not have gone far enough down in that second link.

Where can I find info about Plug-Ins for version 4? I no longer have v.3 installed (I think! :-) and I want to write stuff for what I'm actually working on: namely 4.2.1 (at this time!)

The very basic “idea” of a plug-in is to A) load additional capabilities (like import MuseScore 3.0, import QtQuick.Controls 2.2, etc. )
B) set up “global” variables
C) have user interface definitions to build buttons, check boxes, etc.
D) have an optional “on load” section, which can set up things when musescore starts up and initially loads the plug-in into memory and E) “on run”, which is executed when the plug in is run from the menu and F) commands and functions that are linked to structures (like buttons) that run when the button is pressed, that act on and change musescore data structures (by setting values, running built in functions, navigating within the structure, etc.).

There are more capabilities but that is the general idea. Maybe someone can refine the explanation and post their version.

Plug-ins use a limited version of QML. If you see a QML function on a website, don’t be surprised when it doesn’t work. This QML “mostly” uses an object-oriented “variant” data type. Variables are “mostly” of a type based on usage but will sometimes surprise you. Console.log output helps show you what you are looking at. (There are some advance capabilities as well.)

Some data structure are a “fraction” (time signature numerator and denominator for example) and need a method to separate them, a “function” that returns a value (a parameter may be needed to run the function), and arrays and lists (like annotations). Arrays and lists have a “.length”, which will tell how many objects are in them.

Some big structures are staffs. There is a staff index since a score can have multiple staffs. Each staff can have 4 voices. The voice number is set to allow you to work on a particular voice. Inside the staff are measures, etc.

The parent of the staffs is the score. There are variables and functions related to the overall score here. The parent CurScore allows you to navigate through staffs, measures, etc. Then, you can act on them. Navigation can be done multiple - somewhat independent - ways. For instance, go to the next measure, go to a certain “tick” in the score, go to start, go to selection point and access data through the selection, etc.

Looking at the API that I posted earlier gives a better idea of the structures and the related functions.

In reply to by TDYama

Re: Variables are “mostly” of a type based on usage but will sometimes surprise you.

Variables in QML have a dynamic data type since QML uses javascript. You can use a variable as an integer in one statement then use it as text in another. If you ever need to know a variable's current datatype you can use typeof. (I have not needed to use this yet in any plugin).…

The parent of staffs is not CurScore; it is curScore - the lowercase "c" is important. Variable names and function names are all case sensitive in javascript; so are Musescore objects and their property names.

There is a post somewhere which tells how to view the console in a Windows system. If you don't have a console view, you don't have error messages and console output. It would seem almost impossible to develop a plugin (without MS 3.x plugin creator) without the console.

In any case, use a text editor and enter the plugin below, and name the file 'test.qml'.
Then, use the standard plugin info. For MS3, you want the "Plugins." prefix to the menuPath, or your plugin name won't be in the plugins folder to run plugins. The plugin runs on MS 3.6, 4.2 and 4.4 versions. (sorry, posting removed all indentation).

Run the executable using the "-d" switch (in MS 4+).

// plugin start...
import MuseScore 3.0
import QtQuick 2.1
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2

MuseScore {
version: "1.0"
id: window
menuPath: "Plugins.MS3MenuName"
description: "My Description-a"

requiresScore: false
pluginType: "dialog"

width: 200
height: 300
visible: true

property int globalVariable: 10
property var globalVar: 5

Component.onCompleted: { // optional for 4.2, but useful to test in all versions
console.log ("plugin loading completed");
if (mscoreMajorVersion >= 4) {
if (mscoreMinorVersion >= 4) {
// VERY STRICT syntax: "title:", with no space between 'title' and ':'
title: "Title for MS4.4+ "
} else {
var tString = "Title for MS4.0 to 4.3x "
} else {



function myFun(a,b) {
return (a+b)

// console log doesn't show in the application, only on the terminal when
// using -d option.
console.log ("We're running");
globalVar = globalVar + "A";
globalVariable += 3;
myFun (1,3); // Oh, didn't look at return value
console.log ("myFun test #1: " + myFun(11,43));
console.log ("myFun test #2: " + myFun("AB","CD"));
for (var i = 1; i < 4; i++) {
console.log ("var i is: " + i);

Column {
Text {
id: refText;
font.pixelSize: 14
text: "hello world!";

Button {
id: button4Text;
text: 'Add text'
visible: true
onClicked: {
refText.text = "goodbye!"
Button {
id: button4Number;
text: 'Show number +1'
visible: true
onClicked: {
globalVariable += 1;
refText.text = globalVariable;
Button {
id: button4TShowHide;
text: 'Hide/Show buttons'
visible: true
onClicked: {
button4Text.visible = !button4Text.visible;
button4Number.visible = !button4Number.visible;
Button {
text: 'close';
visible: true;
onClicked: {
(typeof(quit)==='undefined' ? Qt.quit(): quit());
} // end MuseScore

In reply to by TDYama

I have several simple ideas to implement. I doubt any of them would be of any actual use to anyone. They're more to get me used to creating these plug-ins.

TDYama: I have several questions about your post above:

view the console in a Windows system
I'm under the impression that there are (or, at least, can be) several different things that could be referred to as "console". Even if there's only one, I don't know where to find it. What/which are you referring to?

name the file 'test.qml'
... and save it where?

standard plugin info
No idea what this means?

you want the "Plugins." prefix to the menuPath
Nor any idea what this means?

Run the executable using the "-d" switch
Which executable? And exactly what is this switch supposed to do with that executable?

In addition, it looks like (???) the code you gave me has unmatched curly braces? I'm inspecting that closer; I could easily have missed something.

If I'm reading this code correctly,...
* It initializes globalVar to "A" and globalVariable to 3.
* It writes several messages to console.log. This is presumably the "console" that you talked about and that I asked about. Again, what/which console?
* It counts from 1 to 4 in the console.
* It creates a dialog (???) with a title of "hello world" and four (?) buttons.
* * The first button is labeled "Add text" and, when clicked shows "Goodbye" somewhere
* * The second button is lebeled "Show number +1". It adds one to globalVariable ... and display it?
* * The third button is labeled "Hide/Show buttons" and toggles ... all (???) the buttons between visible and not. How does it toggle it back to visible from not? Usually you can't click on an invisible button???
* * The fourth button is labeled "close" and it looks like it's supposed to exit the dialog, but it has the "qt.quit()" command in it that you said above makes MuS 4 crash.

In reply to by TheHutch

The console issue is the most important. It is like running on the MSDOS command line. If you run cmd in windows, you get a C prompt. If you type the full path of the musesscore program, you maybe can run the musescore program although maybe you’d have to know it’s full path. Right clicking the desktop icon could get you to the place that shows the full path. If the program was called MuseScore-4.2.1-12345, you would type the full name and put a -d (space then -d) at the end and run the program. Hopefully you can alt-tab between the windows command line, which hopefully shows a lot of messages and the gui interface of musescore.

I have to run, but the curly brace is there. It does look funny on the post. Copy and paste into a text file. That should clean it up or I can add an attachment tonight.

It goes into the directory found in your preferences - folders directory. Maybe edit/preferences/folders.

MS 3 is easier. MS 3.7 is better if you have a GitHub account and can download it from Jojo’s site.

MS 3.7 has the creator and console built in.

Your thinking on what the program does is generally correct. Once you see it work, you will understand it.

Please work on the dos command line issue or try MS 3.7. You need a console view or you’ll never know where to find syntax errors in the plugin, or see helpful console messages.

In reply to by TDYama

Ahh, simply the MuseScore executable. What is the "-d" flag supposed to do? ... and it hits him: oh, of course: "debug".

It wasn't a case of a missing curly brace, but additional ones. I did put the code into a text editor and tried to re-add the appropriate indentation, but it still looks like there are either one or two extra, unmatched curly braces (right brace or "close brace", however you call them) at the end. I assume I'm missing something somewhere.

Yes, please, if you can find that other thread about this, I would really appreciate it!!!

In reply to by TDYama

And the indentation makes it obvious where I miscounted the braces. Thanks!!

Now to see if I can figure this out!!!

Oh, a (very minor!!!) question: Is any "white space" available for indentation? Specifically, can I use tab as well as space?

Do you still have an unanswered question? Please log in first to post your question.