This is the documentation for developing and distributing plugins for SkyTemple. The documentation on how to install and use plugins, as well as general information, can be found on our wiki.
A SkyTemple plugin is a Python distribution package that contains
at least one entry point for the group skytemple.module
.
Entries in the entry point can use an arbitrary key and the value must point to a class that subclasses AbstractModule.
Modules can then modify SkyTemple's behaviour and add their own views to the main item tree (the tree on the left side of the UI when a ROM is loaded). Since they are Python packages, pretty much everything is theoretically possible.
Depending on how SkyTemple is installed, there are two ways plugins are discovered and loaded. Understanding these mechanisms is important.
If SkyTemple is installed as a regular Python package using tools like
pip
, then you can just install your plugin as a regular Python
package. You can do this by using pip
. The editable mode (pip -e
)
is also supported for ease of development.
Note that this is also referred to sometimes as the "development setup". End-users of SkyTemple are unlikely to install SkyTemple this way, and will probably install it via the Flatpak or PyInstaller distributions, see below.
No matter how SkyTemple is installed, it also has a built-in plugin loader
that loads wheels placed in the plugins
directory of SkyTemple's
configuration directory.
This directory should be at the following location:
- Linux:
~/.config/skytemple/plugins
($XDG_CONFIG_HOME
is used) - MacOS:
~/Library/Application Support/skytemple/plugins
- Windows:
C:\Users\<username>\AppData\Local\skytemple\plugins
You can open the configuration directory from SkyTemple ("Open config directory...").
A plugin wheel placed in these directories is automatically loaded after the user confirms it on start. This is the primary way to distribute plugins. The section "Distribution" will go into more details on how to create these wheels.
A SkyTemple plugin is usually at least made up of the following files and
directories (where name_of_your_package
is the name of your package):
name_of_your_package/
__init__.py
module.py
LICENSE
MANIFEST.in
pyproject.toml
SkyTemple is licensed under GPLv3+. As such your plugin must be licensed under the same license or a newer version.
The pyproject.toml file is the new standard for defining Python packages. It contains the following minimal contents:
# The build system, see documentation for info.
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "name_of_your_package"
requires-python = ">=3.10"
keywords = ["skytemple", "skytemple-plugin"]
license = {text = "GPL-3.0-or-later"}
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
]
dependencies = [
# See the `Dependencies` section.
'skytemple >= 1.6.0',
'skytemple-files >= 1.6.0',
'pmdsky-debug-py',
'range-typed-integers >= 1.0.0',
'pygobject >= 3.26.0'
]
# This is the entry point definition for your plugin.
[project.entry-points."skytemple.module"]
# Replace the key with a name describing your plugin and the value with
# the path to your module class.
name_of_your_package = "name_of_your_package.module:ExampleModule"
This file contains a definition of additional non-Python files that are included in your package, see the example plugin.
This is your package's code. It must contain a __init__.py
(all sub-packages also),
it can be empty. In this example the module.py
contains the module:
from __future__ import annotations
from typing import List
from skytemple.core.abstract_module import AbstractModule
from skytemple.core.item_tree import ItemTree
from skytemple.core.rom_project import RomProject
class ExamplePlugin(AbstractModule):
def __init__(self, rom_project: RomProject):
"""
Your plugin gets passed in the RomProject when it is created.
This is your primary way to interact with the game and other modules.
Note that `__init__` is called to create an instance of your module whenever a ROM
is loaded. If you want to perform one-time initialization when SkyTemple starts
use the classmethod load.
"""
@classmethod
def depends_on(cls) -> List[str]:
"""
This returns a list of modules that your plugin needs. This can be another plugin module
or one of the built-in modules, which are listed in SkyTemple's pyproject.toml.
You can reference these other modules and rely on functionality in them.
"""
return []
@classmethod
def sort_order(cls) -> int:
"""
A number that is used to sort all of the items in the main item tree of the SkyTemple UI.
Experiment with this until you find a value you are happy with.
"""
return 0
def load_tree_items(self, item_tree: ItemTree):
"""
This is the heart of your plugin (if your plugin's purpose is to show views in the UI.
You can add new views to the main item tree on the left of SkyTemple's UI here.
You must implement this, but you can also do just nothing,
if your UI does not actually provide new views.
You can also manipulate other items in the item tree, but this is not recommended, since
it could easily break with updates.
"""
pass
Your plugin can not pull in any dependencies not bundled with SkyTemple, if you intend
to distribute it via the plugins
directory (see "Via SkyTemple's plugin loader").
You can rely on the following dependencies being bundled with SkyTemple.
- GTK 3.24 (Note: SkyTemple will eventually switch to GTK 4. Try to only use GTK 4 compatible widgets).
- ndspy 3
- skytemple-files 1.6
- pmdsky-debug-py in the same version skytemple-files requires
- skytemple-dtef 1.6
- skytemple-icons 1.3
- explorerscript 0.1
- skytemple-rust 1.6
- dungeon_eos 0.0.5+
- range-typed-integers 1
- pygobject 3.40.0+
- pycairo 1.18+
- tilequant 1
- skytemple-ssb-debugger 1.6
- CairoSVG 2.7
- packaging
- wheel
- importlib_metadata on Python < 3.10
- importlib_resources on Python < 3.9
An example plugin that also shows a lot of the APIs you can use and how to build custom views can be found at:
https://github.com/SkyTemple/skytemple-example-plugin/
Additionally you can reference built-in modules.
In order to distribute your plugin you need to create a Wheel for it.
To do this, install the wheel
package on your system via pip
.
After this run the following command:
pip wheel --no-deps <path to your package>
If you used the basic examples this will usually produce a file with the
.whl
file extension and the string py3-none-any
in its name.
This is a "Pure Python wheel" and can be installed on any platform. You
can give this your users and they can place it in the plugins directory.
If the string py3-none-any
is not in the wheel filename, you have
built a "Platform Wheel". Continue reading below.
By default Python distributions produce "Pure Python wheels". These wheels only contain Python source code and no binaries.
If your package links against binary code, eg. C/Rust it will become a
"Platform Wheel". It does not matter if your binary code is a
Python module (a CPython extension) or if you just use it dynamically
via ctypes
.
A "Platform Wheel" is always bound to a specific Python release, architecture and operating system. Linux Wheels must be built using the manylinux Docker images in order to be distributable.
Please provide wheels for all Python versions and platforms supported by SkyTemple. This is currently:
- Python 3.10 - 3.13
- Architecture x86_64 for Windows 10+, MacOS 11+, Linux (
manylinux2014
). - Architecture aarch64: Linux (
manylinux2014
).
To make integration easier, you can use setuptools
plugins:
- setuptools_rust can be used to bundle Rust code in your package.
You can either use different bindings if you want to create real
Python modules written in Rust, or set the binding to
NoBinding
if you plan to load it viactypes
(example repository for the latter). - setuptools_dso can be used to bundle C libraries that will be used via ctypes.
Tilequant is an example on a Python package using "setuptools_dso" and skytemple-rust for a package using "setuptools_rust".
You need to build a wheel for each platform and prompt your users to use the correct one depending on their platform.
The PyInstaller/Flatpak distributions of SkyTemple currently use the following Python versions:
- Linux Flatpak: 3.10
- MacOS PyInstaller: 3.11
- Windows PyInstaller: 3.11