Lua Script Extension and menu API

I have a suggestion for the Lua API.
I use Lua scripts a lot, but I find it a bit inconvenient.

  1. Call from the Script menu.
    If I make the directory structure easy to see in Aseprite, it is troublesome to manage the download source.
    If the directory structure is easy for the download source to manage, the provided functions and menu structure in Aseprite conflict.
    (And, one script is one menu, the number of files tends to increase.)

  2. Call from the shortcut key.
    Unnecessarily, the number of shortcut keys increases.I forget the scripts only used occasionally.

Therefore, I want to support Lua Script Extension and adding menu Lua API.
What does everyone think?

I made a sample that works in Windows 10.

Screenshot Image

Lua Script

Sample extension is here.

The Aseprite source is here.

The fix commit is here.

I’m sorry for poor English.
thank you for reading!

1 Like

Hi @msk-k, actually I had some plans to register actions in different menu items (even items in the main menu bar but different locations, not only File > Extensions). I’ve found my incomplete patch.

Some notes about your changes:

  • As in issue 1949, we have plans to register several things from extension scripts (commands, file formats, inks, etc.), so maybe app.register() is too much, or we should need app.registerMenu() or something like app.register{ menu="..." } (my original API use names like app.newCommand and app.newMenu).
  • There should be a way to unload a extension/script (remove all registered items)
  • I would prefer other word for "context" (to avoid confusion with keyboard shortcuts “context”), but still not sure.

I think some design work is still needed for the exact API that we want for extension scripts. Something like this might be a possibility:

  load=function() ... end,
  unload=function() ... end

Or other example:

function init() -- or load() or activate()

function exit() -- or unload() or deactivate()

Some ideas from VSCode.

Another good thing would be to have all registered items automatically unloaded:

function init(plugin)
  plugin.register{ menu="edit.myMenu", ... }

So there is no need to create a exit() function.

1 Like

@dacap Thank you for your reply and reading my commit!

I haven’t seen the above issue, sorry.
I understand that my suggestion is included in the V1.2.X milestone (and it is still under design).

The plugin load / unload design was too difficult for me…I couldn’t get an idea.

I will post again if I come up with an idea that could contribute.

I look forward to the V1.2.X release.

Thank you!


I was working on this issue and making some progress with the final API:

This is an example:

function init(plugin)
  print('foo init')

  if plugin.preferences.count == nil then
    plugin.preferences.count = 0

    title="Foo First Command",
      plugin.preferences.count = plugin.preferences.count+1

function exit(plugin)
  print("foo exit - count=" .. plugin.preferences.count)

Both functions init() and exit() will be optional. The "group" attribute should indicate the exact menu where to put the new command (anyway if no group is specified, the command will be available for keyboard shortcuts anyway). (All commands are deleted/unregistered automatically when the extension is disabled/uninstalled or at exit, so generally there will no need to define an exit() function).


That is awesome! How do I paint over the user drawing?
And how to publish/install a plugin?

Welcome @melanke, we still need to write the documentation to create plugins, anyway about your points:

  1. to draw in the canvas you can use the app.useTool() function
  2. you can create a .zip with a package.json file similar to other extensions like palettes but instead of "palettes" section you have to include a scripts section, for example:
      "name": "dacap-scripts",
      "displayName": "dacap scripts",
      "description": "dacap scripts",
      "version": "0.1",
      "author": { "name": "dacap scripts",
                  "email": "",
                  "url": "" },
      "contributors": [ ],
      "publisher": "aseprite",
      "license": "CC-BY-4.0",
      "categories": [ "Scripts" ],
      "contributes": {
        "scripts": [
            { "path": "./my-script.lua" },

The my-script.lua can be something like the given example above. After that you compress both files (package.json and my-script.lua) in a .zip, and rename the .zip to .aseprite-extension. To install the extension just double-clicking just be enough on Windows or macOS.


I tried a new feature!

The sample is working perfectly just by rewriting the third argument (group) of the newCommand function to the group in gui.xml.

gui.xml here:

I will try various things!

Thank you very much!


Great @dacap! I am very happy with this update.
I believe there will be a lot of amazing new possibilities for Aseprite now.

Thank you all for creating and improving this great tool Aseprite is :wink:

1 Like