A Magisk module is a folder placed in
/data/adb/modules with a structure below:
/data/adb/modules ├── . ├── . | ├── $MODID <--- The folder is named with the ID of the module │ │ │ │ *** Module Identity *** │ │ │ ├── module.prop <--- This files stores the metadata of the module │ │ │ │ *** Status files *** │ │ │ ├── skip_mount <--- If exists, Magisk will NOT mount your files │ ├── disable <--- If exists, the module will be disabled │ ├── remove <--- If exists, the module will be removed next reboot │ │ │ │ *** Scripts *** │ │ │ ├── post-fs-data.sh <--- This script will be executed in post-fs-data │ ├── service.sh <--- This script will be executed in late_start service | ├── uninstall.sh <--- This script will be executed when Magisk removes your module │ │ │ │ *** Resetprop Files *** │ │ │ ├── system.prop <--- This file will be loaded as system properties by resetprop │ │ │ │ *** Module contents *** │ │ │ ├── system <--- This folder will be Magic Mounted if skip_mount does not exists │ │ ├── . │ │ ├── . │ │ └── . │ ├── vendor <--- Auto generated. A symlink to $MODID/system/vendor │ │ │ │ *** Others *** │ │ │ ├── . <--- Any additional files / folders are allowed │ └── . | ├── another_module │ ├── . │ └── . ├── . ├── .
As long as a folder follows the structure above, it will be recognized as a module.
Here is the strict format of
id=<string> name=<string> version=<string> versionCode=<int> author=<string> description=<string>
idhas to match this regular expression:
a module, ✗
versionCodehas to be an integer. This is used to compare versions
The official Magisk Module installer is hosted here.
That repo is a starting point for creating a Magisk module installer zip. Here are some details:
META-INF/com/google/android/update-binaryis a dummy file. If you are creating a module locally for personal usage or testing, download the latest installer
update-binarywith the script
module.propto provide information about your module
install.shto fit your need. The script is heavily documented so you should know what to do.
uninstall.shto the root of the installer
You can submit a module to Magisk-Module-Repo so users can download your module directly in Magisk Manager. Before submitting, follow the instructions in the previous section to create a valid installer for your module. You can then create a request for submission via this link: submission.
META-INF/com/google/android/update-binarywill be forcefully replaced with the latest
module_installer.shto make sure all installation uses the latest scripts.
update-binarywill be replaced, this means that all modules in the repo are expected to follow how the installation framework works: the installation framework will load your
install.shscript and run the corresponding callbacks.
update-binaryas they will simply be ignored.
AUTO_MOUNT, but instead uses
SKIP_MOUNT. In a nutshell,
AUTO_MOUNT=truebehaves exactly the same as
SKIP_MOUNT=false, and 99% of the time you should NOT touch this flag.
On modern Android,
/system/vendor is moved out from the system partition into its own separate
vendor partition. For module developers, Magisk will handle these different configurations transparently so you do not need to worry anything about it. If you want to modify files in
vendor, place the modified files under
/system/vendor and you’re good to go!
Starting in Android Q and some devices on older Android versions, a separate partition
platform is available. Support for
platform will come soon in upcoming Magisk versions, please stay tuned!
In Magisk, you can run boot scripts in 2 different modes: post-fs-data and late_start service mode.
In Magisk, there are also 2 kinds of scripts: general scripts and module scripts.
chmod +x script.sh)
post-fs-data.druns in post-fs-data mode, and scripts in
service.druns in late_start service mode.
post-fs-data.shruns in post-fs-data mode, and
service.shruns in late_start service mode.
Magisk’s internal busybox’s path
$BBPATH is always prepended in
PATH. This means all commands you call in scripts are always using busybox unless the applet is not included. This makes sure that your script always run in a predictable environment and always have the full suite of commands regardless of which Android version it is running on.
How to remove a file systemless-ly? To actually make the file disappear is complicated (possible, not worth the effort). Replacing it with a dummy file should be good enough! Create an empty file with the same name and place it in the same path within a module, it shall replace your target file with a dummy file.
Same as mentioned above, actually making the folder disappear is not worth the effort. Replacing it with an empty folder should be good enough! A handy trick for module developers is to add the folder you want to remove into the
REPLACE list within
install.sh. If your module doesn’t provide a corresponding folder, it will create an empty folder, and automatically add
.replace into the empty folder so the dummy folder will properly replace the one in