Open-source project
omer-faruq/appstore.koplugin avatar
omer-faruq/appstore.koplugin

appstore.koplugin: a plugin store that lives inside KOReader

Discover, install, and update community-created KOReader plugins and user patches without leaving your device.

627 stars29 forksLuaGPL-3.0

At a glance

What is it?
The KOReader add-on turns GitHub into a browsable app store for community plugins and user patches, with an offline cache and update tracking, but it leans on the GitHub search API and asks for a personal access token to work properly.
Who is it for?
appstore.koplugin is the right tool for a KOReader user on a Kobo, a Kindle or an Android device who installs community plugins by copying files over USB and wants installation, updating and removal to happen from the device instead.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Lua, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What problem this solves for an e-ink reader

KOReader is an e-ink reading system, and the devices it runs on are deliberately awkward to work with. There is no package manager, no app store and no browser that can reach a download page and unpack a file. The usual way to add a community plugin is to find its source on GitHub, download an archive on a computer, connect the device by USB and copy files into the plugins directory by hand.

The App Store plugin removes that loop. It discovers, installs and updates community created KOReader plugins and user patches without leaving the device, and the documentation is explicit that the flows are designed to feel native on e-ink hardware, which means dialogs, toolbars and lists that work with a slow refresh and a limited screen.

The audience is therefore the reader who already has a community plugin habit, not a developer. The plugin is a Lua add-on that lives in the KOReader plugins directory and is reached from Tools, then App Store.

It is worth being clear about one thing at the start. This is a client for GitHub, not a hosted store. There is no vendor behind it, no catalogue on a server, and no signing or review of what it installs. It searches GitHub and then runs the code it finds, which is the single most important fact for anyone deciding whether to use it.

Discovery is GitHub search plus a naming convention

The mechanism is simpler than the feature list suggests, and understanding it tells you what the store will and will not find.

The plugin searches two GitHub topics, koreader-plugin and koreader-user-patch, and it also searches repositories whose names follow patterns like KOReader.patches or [NAME].plugins. So a community plugin is discoverable if the author tagged it correctly, and a patch repository is discoverable if it followed a naming convention. Both are conventions rather than a registry, which means the catalogue is exactly as good as the tagging discipline of the community.

On top of the raw search sit the standard owner, topic and description filters, plus sorting and paging, and the plugins browser toolbar offers search text, an owner filter, a minimum stars filter, and sorting by stars descending or ascending, by last update or by name.

The patches browser works differently from the plugins browser, because a patch repository is not the unit of installation. It enumerates files matching the pattern ^[number]-*.lua inside a repository and treats each numbered file as a separate patch, which is how KOReader user patches are versioned, with each numbered file being a later revision.

That is the key difference between the two halves of the store. A plugin is a repository, and a patch is a file in a repository, so the update tracking, the install pipeline and the ignore list have to work at two different granularities.

Installing the plugin and reaching the four screens

Installation is a copy, and the documentation gives the exact directories for each platform.

The steps are to download the latest release from the releases page or clone the repository, copy the appstore.koplugin folder into the KOReader plugins directory, restart KOReader, and then open the tool from the menu.

The plugins directory differs by platform: koreader/plugins/ on Kobo and Kindle, /sdcard/koreader/plugins/ on Android, and ~/.config/koreader/plugins/ on desktop Linux.

From there the interface is four dialogs. The Plugins Browser lists repositories tagged as KOReader plugins and offers Install, Update, Remove and View README per entry, with a detail dialog showing the description, the star count, the last updated timestamp and the repository owner. The Patches Browser lists patch repositories and, per patch, lets you install it, retry a failed download or open the repository README for the full instructions. The Installed Plugins screen summarises what is on the device, both plugins matched to a repository and ones with no repository, and offers Check all updates, a toggle between Only outdated and Show all plugins, and per plugin Disable, Delete, Update and Reinstall. A fourth screen covers the installed patches, with a matching patch banner when reconciling local files against remote entries.

A gear icon in each browser opens settings, including Install plugin from URL and Install patch from URL for entering a GitHub owner and repository by hand.

The cache under data/cache/AppStore is what makes it usable

On an e-ink device, a network round trip to GitHub is slow, and a reader on a train or a plane may have no signal at all. The plugin is built around that constraint rather than treating it as an edge case.

The cache is stored under data/cache/AppStore, so existing results stay accessible when connectivity is lost, and the browsers keep persistent filters and paging across a session. The per entry README viewer fetches README.md directly from GitHub and opens it in the KOReader document renderer, which means a plugin's own documentation is readable on the device with the same gestures as a book.

Update tracking is the part with the most moving pieces. For installed plugins and for numbered patch files alike, the plugin compares SHA values and keeps refreshable summaries, and each row in the installed list shows the local version, the cached remote version and SHA for linked plugins, and the last checked timestamp, with Update and Reinstall buttons appearing when a difference is detected. An ignore release feature can hide a specific plugin update until a newer version appears, which handles the common case of a release that is worse for your device.

The install pipeline itself handles .koplugin archives, verifies metadata, and copies files to data/plugins or to data/patches as appropriate. Verification and checksum comparison are what make auto updating safe enough to leave switched on.

The personal access token is a search API constraint, not a nicety

The token requirement is the part of the documentation that most directly affects whether the plugin works, and the reason is technical.

The plugin relies on GitHub's search API to discover plugins and patches, and GitHub's search API does not support fine grained personal access tokens at all. Requests carrying a fine grained token fail regardless of the permissions granted, so the documentation is emphatic that a classic token must be used. The configuration file is a Lua table with a token field.

lua
return {
    auth = {
        github = {
            type = "github",
            token = "ghp_your_token_here",
        },
    },
}

The file lives at plugins/appstore.koplugin/appstore_configuration.lua, and it can be created from the appstore_configuration.sample.lua that ships in the repository. The documentation walks through creating a classic token, granting at least the public_repo scope, pasting it in and restarting KOReader.

The reason to bother is the rate limit. Unauthenticated, the quota is around ten requests per minute shared across the device, which a browser session can exhaust quickly. The token is included automatically in API requests, which raises the quota to the standard authenticated limits.

The trade is a credential on a device that travels in a bag. A classic token with public_repo scope is read only against public repositories, but it is still a token that can be used against anything else in the account it belongs to, so it should belong to an account used for exactly this.

Where the App Store plugin is the wrong choice

Four situations argue against it.

The first is a device that is offline. The cache makes previously seen results available, and the offline friendly cache is a genuine design point, but a fresh search, a README that has not been fetched, or an update check all need the network. A reader with no connectivity gets a smaller catalogue, not a full one.

The second is a reader who will not put a GitHub token on the device. Without it, the plugin still works, but it lives under an unauthenticated rate limit of roughly ten requests per minute shared across the device, and a browsing session can hit that wall.

The third is a device running an older KOReader. The requirement is a nightly build or 2024.12 or newer, with LuaSocket, Archiver, SHA2 and SQLite dependencies, which the default releases bundle. On an older reader the plugin simply will not have what it needs.

The fourth is a security sensitive setup. There is no review, no signature check on the repository contents and no allow list of authors. The install pipeline verifies metadata and compares checksums, which tells you the download arrived intact and unchanged, but it does not tell you the code is safe. For a device that holds a reader's library and account credentials, installing whatever public search returns is a decision you have to make deliberately.

GPL-3.0, a steady release line, and a flat Lua layout

The licence is GPL-3.0, with a LICENSE file at the root of the repository. For a personal device add-on that is a non issue, and for anyone who wants to bundle or redistribute the plugin the copyleft obligations are the usual ones and are worth a legal review rather than an assumption. This is not legal advice.

The release line is regular. Version 1.12.0 was published on 2026-08-01, 1.13.0 on 2026-08-24 and 1.14.0 on 2026-09-11, and the last push to the default branch was on 2026-10-02. The repository is not archived, and a monthly minor cadence on a 1.x line is a good sign for a plugin that has to keep up with a nightly build of its host application.

The source layout is flat and self explanatory, and it reads as a description of the plugin's jobs. There is main.lua, an _meta.lua for the plugin metadata, and then one file per concern: appstore_cache for the offline cache, appstore_net and appstore_net_github for the network layer, appstore_install_helpers, appstore_installs and appstore_updates for the install and update pipeline, appstore_plugin_paths for the path resolution rules, appstore_repo_content for reading repository contents, appstore_mirror, appstore_progress and appstore_settings, plus appstore_gettext for translations. A l10n directory holds the localisation files and a tests directory holds the test suite.

That layout also explains the extra_plugin_paths behaviour, since appstore_plugin_paths is where the resolution rules live, and why a hidden folder is skipped only when choosing where to install a new plugin while KOReader still loads plugins from it normally.

Editorial conclusion

appstore.koplugin is the right tool for a KOReader user on a Kobo, a Kindle or an Android device who installs community plugins by copying files over USB and wants installation, updating and removal to happen from the device instead. It is the wrong choice for a reader on an e-ink device that is permanently offline, for anyone unwilling to store a GitHub personal access token on the device, and for a setup where plugins come from a trusted private source rather than from public repositories. Before adopting, confirm your KOReader build is nightly or 2024.12 or newer, read the plugin paths section to understand where new plugins will land when extra_plugin_paths is set, and decide up front whether the classic token with the public_repo scope is acceptable on the device.

Frequently asked questions

How do I install the appstore.koplugin plugin for KOReader?

Download the latest release or clone the repository, copy the appstore.koplugin folder into the KOReader plugins directory, which is koreader/plugins/ on Kobo and Kindle, /sdcard/koreader/plugins/ on Android and ~/.config/koreader/plugins/ on desktop Linux, then restart KOReader and open it from Tools and App Store.

How does the appstore.koplugin find plugins and patches?

It searches GitHub topics, both koreader-plugin and koreader-user-patch, and also repositories whose names follow patterns like KOReader.patches or [NAME].plugins. Patches are then enumerated as numbered files matching the pattern ^[number]-*.lua inside each repository.

Why does appstore.koplugin need a classic GitHub token?

The plugin relies on GitHub's search API, which does not support fine grained personal access tokens at all, so requests with one fail regardless of permissions. A classic token with at least the public_repo scope raises the quota from the unauthenticated limit of around ten requests per minute shared across the device.

Does appstore.koplugin work without an internet connection?

Partly. The offline friendly cache is stored under data/cache/AppStore so existing results remain accessible when connectivity is lost, but refreshing caches, fetching README files and downloading plugin or patch archives all require network connectivity.

What are the requirements for running the KOReader App Store plugin?

You need a KOReader nightly build or 2024.12 or newer, with the LuaSocket, Archiver, SHA2 and SQLite dependencies that the default releases bundle, and network connectivity. A GitHub personal access token is optional but recommended to avoid the unauthenticated rate limits.

Official sources

  1. License: GPL-3.0
  2. omer-faruq/appstore.koplugin on GitHub
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/omer-faruq-appstore-koplugin.svg)](https://hysenlabs.com/projects/omer-faruq-appstore-koplugin)

Was this useful?