NickelMenu: a launcher and settings menu for Kobo e-readers, delivered as a KoboRoot archive
The easiest way to launch scripts, change settings, and run actions on Kobo e-readers.
At a glance
- What is it?
- NickelMenu adds a menu system to Kobo e-readers so you can run scripts, change hidden firmware settings and trigger actions from a touch interface, and it is installed by copying a single KoboRoot.tgz into the .kobo folder. It is a shared library injected into the Kobo Qt firmware, it does not yet support firmware 5.x, and the build runs against a Nickel toolchain.
- Who is it for?
- NickelMenu fits a Kobo owner who wants a touch menu for launching scripts and reaching firmware settings the stock interface hides, and who is content to sideload an archive and can read log output over telnet when something breaks. It is the wrong choice if your reader is on firmware 5.x, which the project does not support yet, and the wrong choice if you are not willing to run a modified, unsigned binary on the device.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 133 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What NickelMenu adds to a Kobo, and how it is delivered
NickelMenu is the easiest way to launch scripts, change settings and run actions on Kobo e-readers, and the README is even more direct about it being the easiest way to launch custom scripts, change hidden settings and run actions.
The delivery method is the first thing to understand, because it explains the whole shape of the project. You download a pre-built package of the latest stable release from the releases page, or a bleeding-edge build of each commit from the GitHub Actions page. After downloading the package, you copy KoboRoot.tgz into the .kobo folder of your eReader and then eject it.
Copying a single archive and ejecting is the Kobo sideload mechanism, and it means the whole installation is one file and one eject. There is no installer, no flashing and no bootloader modification, and that is what makes the tool usable on a device that was not designed to be modified.
After it installs, you find a new menu item named NickelMenu with further instructions, which the README says you can also read in the res/doc directory of the repository. That is the arrangement: the on-device menu is the entry point, and the documentation is shipped on the device alongside it, so the instructions are available even without a computer to hand.
Uninstalling is symmetric and deliberately easy. You create a new file named uninstall in .adds/nm/, or you trigger the failsafe mechanism by immediately powering off the Kobo after it starts booting. The second option is the interesting one, since a device that will not boot past a broken launcher is a device you would otherwise have to recover over USB, and this way the power button is enough.
The primary language is C++, the licence is MIT, and the homepage is pgaskin.net/NickelMenu, with a MobileRead thread linked for screenshots and detail. The repository is not archived, the last push was on 2026-06-12, and the recent releases are v0.6.0 from 2025-12-07, v0.5.4 from 2022-01-22 and v0.5.3 from 2022-01-21. The three year gap between 0.5.4 and 0.6.0 is the project catching up after a long pause, and the fact that 0.5.3 and 0.5.4 landed a day apart in January 2022 shows what a burst of fixes looks like.
One line in the README is the hard constraint: firmware 5.x is not supported yet.
The library, the config directory and the shared config warning
The Makefile is where the architecture becomes visible, and it is short enough to read in full.
The output is a shared library, src/libnm.so, built from a fixed list of sources: action.c, action_c.c, action_cc.cc, config.c, generator.c, generator_c.c, kfmon.c, nickelmenu.cc and util.c. The library is named libnm, which is the abbreviation the whole project uses.
The build pulls in NickelHook, with the Makefile including NickelHook/NickelHook.mk at the top and again further down, which is the integration layer that gets a menu into the Kobo firmware. The package config adds Qt5Widgets to PKGCONF, so the code links against the Qt widget toolkit the firmware itself uses, and the C++ flags include -isystemlib, which is a project-specific include path for that library.
The compiler flags are strict in a way that suggests the author cares about the code being clean: -Wall -Wextra -Werror for both C and C++, plus -fvisibility=hidden, so the shared library does not export symbols it does not intend to. The C++ flags add -fvisibility-inlines-hidden, and the C flags do not, which is the right asymmetry since inline functions are a C++ specific leak.
The configuration directory is the part with a warning attached. NM_CONFIG_DIR defaults to /mnt/onboard/.adds/nm, which is the on-device path, and the Makefile emits an explicit message if it is set to anything else: NM_CONFIG_DIR is set to a non-default value, this will cause issues with other mods using it. The warning is compile time, so a developer who changes it finds out immediately, and the reason given is that another mod uses the same directory.
That is worth pausing on, because it is the only place in the build that acknowledges other software on the device. NickelMenu is not a privileged system component, it is one mod among several on a device where the config space is shared, and the project is being explicit that taking a different directory is possible but will collide. The same variable appears twice in the compile flags, once as NM_CONFIG_DIR and once as NM_CONFIG_DIR_DISP, and the second is derived by substituting the mount path with KOBOeReader, which suggests the path is presented differently in the UI than it exists on the filesystem, since the on-board storage is mounted at /mnt/onboard and appears to the firmware under a device-flavoured name.
There is also a build option for the uninstall path, NM_UNINSTALL_CONFIGDIR, which when set to 1 adds a -DNM_UNINSTALL_CONFIGDIR define. And the build produces a stripped library, with a strip target running --strip-unneeded on src/libnm.so, and SKIPCONFIGURE including strip so the configuration step does not try to strip it first.
Compiling it, and the cross-compilation setup that makes it work
NickelMenu is designed to be compiled with NickelTC, a separate toolchain project by the same author, and the two ways to build are the interesting part.
The host build is a single make invocation with a cross-compile prefix:
make CROSS_COMPILE=/path/to/nickeltc/bin/arm-nickel-linux-gnueabihf-The prefix names the target triple, and the important part is in it. arm-nickel means the ARM processor as NickelDbus and the firmware's own components are built, nickel-linux is the target platform the Kobo firmware uses for its own userspace, and gnueabihf is the ARM 32-bit hardware floating point ABI, so EABI with hardware floating point, which is what the Kobo hardware has. Getting the ABI wrong is the kind of thing that produces a library that links and then crashes, so NickelTC exists to package a known good combination.
The containerised build avoids the host setup entirely:
docker run --volume="$PWD:$PWD" --user="$(id --user):$(id --group)" --workdir="$PWD" --env=HOME --entrypoint=make --rm -it ghcr.io/pgaskin/nickeltc:1.0 all koborootThe image is pinned to version 1.0 of the toolchain, and the flags carry the details. The volume mount maps the working directory to itself so the build output lands in your checkout rather than inside the container, and the user flag passes your host uid and gid so the files you get back are owned by you rather than by root, which is the difference between a build you can clean up and one that needs sudo.
The --env=HOME is the subtle one, and it is not optional decoration. The build is a cross-compilation, and cross-compilers reach for host tools and caches, several of which assume a writable home directory. If HOME is not set or points somewhere unwritable inside the container, the build fails in a way that looks like a compiler problem.
The entrypoint is make and the arguments are all and koboroot, so the container is running the build rather than a shell, and the --rm flag means the container is removed when the build finishes, which keeps the image from accumulating state. The target names in the Makefile match: koboroot is the target that produces the KoboRoot package you copy into the .kobo folder, and all is the full build.
The repository listing supports the picture. There is a NickelHook/ directory for the firmware integration, src/ for the library, res/ for the resources including the doc directory, test/ for the test suite, a Makefile, a .gitmodules file for the NickelHook submodule, and a .github/ directory for the workflows that produce the bleeding-edge per-commit builds and the Docker image.
What the NickelHook integration actually does
The repository listing has a NickelHook/ directory and a .gitmodules file, and the Makefile includes NickelHook/NickelHook.mk twice, so NickelHook is a separate component brought in as a submodule rather than code living in this tree. Understanding that split explains how a menu gets into firmware that was never designed to have one.
A Kobo e-reader's interface is a Qt application, the same Qt that the build links against through Qt5Widgets. To add a menu to it, something has to run alongside that application and be able to draw on top of it and receive input. That is what a hook layer is for: it provides the mechanism to inject a library into the running process and intercept the events the firmware's own code handles.
The Makefile shows the contract between the two halves. The library NickelMenu itself is src/libnm.so, built from the source files in src/, and the NickelHook.mk include is what sets up the flags, the install targets and the packaging that put that library in the right place inside the KoboRoot package. The res/ directory holds the resources, and KOBOROOT is extended with res/doc mapped to the config directory's doc subdirectory, which is the mechanism by which the on-device documentation is installed alongside the menu.
The config directory handling follows the same pattern. NM_CONFIG_DIR is a compile-time define baked into the library, so the path is fixed at build time rather than being looked up at run time, and NM_CONFIG_DIR_DISP is the second, presentational variant of the same path. The derivation in the Makefile is worth reading, because it is a small piece of knowledge about the device rather than about the code: the substitution turns the /mnt/onboard/ prefix into KOBOeReader/, which tells you the firmware sees the on-board storage under a different name than the Linux userspace mount does. Anything a user-facing menu shows has to use the display form, while anything that touches the filesystem has to use the real one, and having two compile-time constants for one path keeps that distinction from being an error.
The NM_UNINSTALL_CONFIGDIR option ties the uninstall story into the build. Setting it to 1 adds a define that tells the code the configuration lives in a directory that is removed on uninstall, which is what makes the uninstall file approach work without leaving stray state behind. The whole design is consistent: everything the tool needs is placed in one directory that can be pointed at, and that can be removed.
Debugging on a device, and what firmware 5.x means for you
Two practical notes from the README deserve to be read as instructions rather than as caveats.
The first is about errors. Most errors, if any, are displayed as a menu item in the main menu. If no new menu entries appear after a reboot, the advice is to try reinstalling NickelMenu, and if that still does not work, to connect over telnet or SSH and check the output of logread.
That is a sensible escalation order, and the logread step is the important one. On a Linux based device like the Kobo, logread is the standard way to see what the kernel and userspace logged, and since NickelMenu injects itself into the firmware's startup path, a failure there is a boot-time failure that would be invisible without log access. The escalation from a menu item to a reinstall to a shell is a sensible order because each step is more invasive than the last, and by the time you need logread you have already established that the friendly diagnostics are not appearing, which usually means the launcher itself did not start.
The telnet or SSH route also means the device has to be reachable, which for many Kobo users means enabling that over the USB connection rather than over the network, and that is a step with its own consequences. It is worth knowing before you need it.
The second note is the firmware constraint. Firmware 5.x is not supported yet.
That is a single sentence in the README and it determines whether the project is usable for you at all, because the menu injection works by hooking into the firmware's Qt application, and a major firmware version is very likely to have changed the internals the hook relies on. The 0.5.3 and 0.5.4 releases landing a day apart in January 2022, then nothing until 0.6.0 in December 2025, is consistent with a project waiting for firmware support to become possible rather than one that had abandoned it, but the README does not explain the gap, so anyone waiting on 5.x support should ask the MobileRead thread or the repository rather than assume it is imminent.
The 0.6.0 release is a major version bump, and for a project with this shape that usually means the interface or the configuration changed in a way that affects add-ons built against it. The README does not detail the changes, so the changelog or the release notes are where to look, and the res/doc directory that ships on the device is the version-matched documentation, which is the version to read rather than whatever the website happens to show.
Editorial conclusion
NickelMenu fits a Kobo owner who wants a touch menu for launching scripts and reaching firmware settings the stock interface hides, and who is content to sideload an archive and can read log output over telnet when something breaks. It is the wrong choice if your reader is on firmware 5.x, which the project does not support yet, and the wrong choice if you are not willing to run a modified, unsigned binary on the device. Before installing, check your firmware version against the support statement, copy the archive into the .kobo folder rather than unpacking it yourself, and read the res/doc instructions that the installed menu item points at, since those are the authoritative usage documentation.
Frequently asked questions
How do I install NickelMenu on a Kobo?
Download the pre-built package from the releases page, or a per-commit build from the GitHub Actions page, then copy KoboRoot.tgz into the .kobo folder of the eReader and eject it. After it installs, a new menu item named NickelMenu appears with further instructions, which are also in the res/doc directory of the repository.
How do I uninstall NickelMenu?
Create a new file named uninstall in the .adds/nm/ folder, or trigger the failsafe mechanism by immediately powering off the Kobo after it starts booting. The second option means a launcher that breaks the boot does not require a USB recovery.
What does NickelMenu support and what does it not?
It runs scripts, exposes hidden firmware settings and triggers actions from a touch menu on Kobo e-readers, but firmware 5.x is not supported yet. The README also notes that most errors appear as a menu item in the main menu, and that if no menu entries appear after a reboot you should reinstall, then check logread over telnet or SSH.
How is NickelMenu compiled?
It is designed to be compiled with NickelTC. On the host, run make CROSS_COMPILE=/path/to/nickeltc/bin/arm-nickel-linux-gnueabihf-. To build in a container instead, run the published nickeltc:1.0 image with the working directory mounted, your own uid and gid, and HOME passed through, invoking make with the all and koboroot targets.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pgaskin-nickelmenu)Was this useful?