Build a plugin that displays every note as it plays β from zero to running in under ten minutes.
Lua 5.1 is built in. You don't need to install anything extra.
The standard base,
table,
string, and
math
libraries are available. File-system access (os,
io) is intentionally restricted for security.
Each plugin lives in its own subdirectory inside the Tabatura plugins folder.
Tabatura discovers and loads every subdirectory that contains a valid
plugin.toml manifest on startup.
~/tabatura/plugins/
βββ note-display/ β your plugin folder
βββ plugin.toml β metadata & entry point
βββ main.lua β plugin code
The Lua runtime calls plugin.on_init() once at load time.
From there your plugin subscribes to events and builds UI using the
plugin.* global table provided by the host.
When Tabatura quits, plugin.on_shutdown() is called so your plugin can clean up.
In Tabatura, open the Plugins menu and click
Open Plugin Folder. This opens the plugins directory in your file manager.
Inside that folder, create a new subfolder called note-display.
~/Library/Application Support/tabatura/plugins/ %AppData%\tabatura\plugins\ ~/.config/tabatura/plugins/ The folder is created automatically the first time Tabatura runs. If it doesn't exist yet, just create it.
Inside the note-display folder,
create a new file named plugin.toml
(make sure your editor saves it as plain text, not rich text or .txt).
This is the manifest Tabatura reads to discover your plugin.
name = "Note Display" version = "1.0.0" description = "Shows each note as it plays during playback." author = "Your Name" entry = "main.lua"
See the Manifest reference for all available fields.
In the same note-display folder,
create a file named main.lua.
The plugin opens a small floating window and listens for the
note event,
which fires for every note that plays during playback.
local win
local note_label
local pos_label
function plugin.on_init()
-- Create two labels: one for pitch, one for position.
note_label = plugin.new_label("Open a file and press βΆ to startβ¦")
pos_label = plugin.new_label("")
-- Pack them into a floating window.
win = plugin.new_window("Note Display")
plugin.window_set_content(win, plugin.new_vbox(note_label, pos_label))
plugin.window_show(win)
-- Add a toolbar button so the window can be reopened if closed.
plugin.add_toolbar_item("Note Display", function()
plugin.window_show(win)
end)
-- Update the display whenever a note fires during playback.
plugin.on("note", function(e)
plugin.set_label_text(note_label,
string.format("String %d Β· Fret %d", e.string, e.fret))
plugin.set_label_text(pos_label,
string.format("Track %d Β· Measure %d Β· Beat %d",
e.track + 1, e.measure, e.beat))
end)
-- Reset when the file is closed.
plugin.on("file.close", function(_)
plugin.set_label_text(note_label, "Open a file and press βΆ to startβ¦")
plugin.set_label_text(pos_label, "")
end)
end
function plugin.on_shutdown()
print("[Note Display] shutting down")
end plugin.on_init() Called once when Tabatura loads the plugin. All setup β UI creation, event subscriptions, toolbar items β happens here. plugin.new_label(text) Creates a text widget. Returns a handle you can pass to set_label_text() later to update its content. plugin.new_window(title) Creates a floating window. Not visible until you call plugin.window_show(win). plugin.new_vbox(...) Stacks widgets vertically. Pass any number of widget handles as arguments. plugin.add_toolbar_item(tooltip, fn) Adds a button to the plugin toolbar strip. Useful for reopening windows the user may have closed. plugin.on("note", fn) Subscribes to the note event. The handler receives a table with string, fret, track, measure, beat, and effect fields for every note that plays. plugin.on_shutdown() Called when Tabatura is quitting. Windows are closed automatically β use this for any extra teardown. note-display/ βββ plugin.toml βββ main.lua
Tabatura loads plugins on startup. Quit the app fully and reopen it β plugins are not hot-reloaded.
Open the Plugins menu. You should see "Note Display" listed. If it's missing, double-check that both files are saved as plain text (not .txt or .rtf) and that they are directly inside the note-display folder.
The Note Display window should update in real time, showing the string and fret of each note as it plays.
You have a working plugin. Here's what to explore next:
Full payload shapes for file, playback, and note events β file.open, playback.start, beat, note, and more.
Buttons, entries, selects, sliders, windows, toolbar items, preferences, and song data.
Load a SoundFont or WAV sample and synthesise notes or click sounds in real time.
Every field in plugin.toml, including licensing for paid plugins.