Open-source project
iebb/NekokoLPA avatar
iebb/NekokoLPA

NekokoLPA is an open source eSIM manager for phones and card readers

Open-source LPA Software for Android and iOS

596 stars77 forksTypeScriptNOASSERTION

At a glance

What is it?
NekokoLPA is a React Native application for downloading and managing eSIM profiles on Android and iOS, talking to card readers over OMAPI, USB CCID or Bluetooth and talking to the phone's own modem over OMAPI or the Telephony API on rooted devices. A second generation, NekokoLPA 2, adds Windows, macOS and Linux but is not yet open source.
Who is it for?
NekokoLPA 1 fits a developer or technically inclined user who wants to manage eSIM profiles without a vendor application, and who is willing to build the app from source with yarn and Xcode or Android Studio, and it fits a hardware hacker who needs the 9eSIM legacy Bluetooth reader or an ESTKme-RED unit supported.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 66 days ago.
What is it written in?
Mainly TypeScript, 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

Two projects with different licences at different stages

The README opens with the state of play, and it matters for anyone deciding what to build on.

NekokoLPA 2 is now available, and the new version does support the Telephony API in addition to OMAPI on rooted devices, and now also works on Windows, macOS and Linux. The plan stated in the README is that it will be open source in the same MIT licence in late 2026, pending codebase improvements. Its website is n.lpa.ee, and downloads are hosted as GitHub releases of the separate NekokoLPA2 repository.

Everything below the banner describes NekokoLPA 1, the Android and iOS application, which is the open source repository you are looking at. The primary language is TypeScript, and the project licence is recorded as a custom one that GitHub cannot classify, with the terms in the LICENSE file.

The last push was on 2026-08-18, and the release history shows v1.14.401 and v1.14.400 on the same day and v1.13.373 two days earlier. The version numbering in package.json is a buildVersion of 401 against a version string of 1.14.401, which is how the two release numbers in the tags relate.

So there are two code bases, one open and one not yet, and a plan to converge them on an MIT licence later in 2026.

The card reader support list decides whether it works for you

NekokoLPA 1 is an Android and iOS LPA app, and the hardware it can talk to is enumerated in the README under currently supported card readers.

On Android there is the internal OMAPI slot on the device, which means an eSIM capable phone with no extra hardware, and USD CCID readers over USB. On iOS there are USD CCID readers through CryptoTokenKit, plus two specific products. The first is the ESTKme-RED dual mode card reader, and the second is the 9eSIM legacy Bluetooth card reader, with the firmware requirement of greater than 2.3.1 noted alongside it.

That Bluetooth entry is the interesting one. A reader that speaks to the phone wirelessly over Bluetooth needs no cable or dock, which makes it a convenient route to a physical card reader on an iPhone, alongside the USB CCID route through CryptoTokenKit that the README also lists.

The list is a closed set, though. If your reader is a USB CCID device and you are on iOS, you need CryptoTokenKit support for it to appear, and if your reader is not on the list, the application has no way to talk to it.

Two Google Play flavours for two different eSIM ecosystems

The app is published on Google Play in two variants, and the difference is about which ecosystem of removable eSIM cards the build targets.

The NekokoLPA App, with the package id ee.nekoko.nlpa, is for the Community Key of ShiinaSekiu. The 9eSIM App, with the package id ee.nekoko.nlpa.flavor1, is for 9eSIM removable cards.

This is the same distinction the card reader list hints at. The 9eSIM legacy Bluetooth reader is supported, which makes sense in a build aimed at 9eSIM removable cards, while the Community Key is a different provisioning approach that does not depend on a particular reader.

The build system supports these as variants rather than as one binary with a runtime switch. The repository contains a variants directory, an apply_variant.sh script that generates the per flavour configuration, a generate_variant.sh, and build_variant.sh and build_all_variants.sh. The README notes that src/assets/config.json and src/assets/images/logo.png are generated per build flavour by apply_variant.sh and are intentionally not tracked in git, so those two files are outputs of a build rather than source.

The naming convention throughout the repository uses the NekokoLPA prefix, for example the Android package ids above and the iOS bundle at ios/NekokoLPA, and the release build paths follow the same convention with build_aab.sh and build_all_aabs.sh.

Building from source with yarn, and the checks that run

The development section gives the three commands that get a working environment:

bash
yarn install
yarn pod-install   # iOS only
yarn android       # or: yarn ios

The pod-install step is the iOS specific one, and package.json shows it as cd ios && pod install && cd .., which is why it exists as a script rather than something you type. The project uses Yarn with a checked in .yarn directory and a .yarnrc.yml, and a Gemfile with Gemfile.lock is present for the Ruby side of the iOS tooling.

The quality gates are the usual set for a React Native codebase, and they are all separate scripts:

| Command | Purpose | | --- | --- | | `yarn type-check` | TypeScript, no emit | | `yarn lint` / `yarn lint:fix` | ESLint | | `yarn format` / `yarn format:check` | Prettier | | `yarn build` | Build a variant (see `build_variant.sh`) |

The type-check script is worth a second look, because it is not just tsc. In package.json it is node scripts/check-module-collisions.js && tsc --noEmit, and there is a separate check:collisions script for the first half. In a project with this many platform specific native modules and patched dependencies, a script that fails the build on a module name collision before the type check runs is a deliberate guard against one of the classic React Native native module mistakes.

The project also carries a patches directory and a postinstall script running patch-package, plus a jest config and a test script, an .eslintrc.js, a .prettierrc.js, a babel.config.js, a metro.config.js, a react-native.config.js and a tamagui.config.ts.

Mac Catalyst and the entitlements that decide reader access

The iOS target also builds and runs as a Mac Catalyst app, including USB CCID readers via CryptoTokenKit, and there is a yarn macos script for it that runs bash scripts/run-macos.sh. A separate macos:release script sets CONFIGURATION=Release for the same runner, and a macos:logs script streams the process log with log stream and a predicate on the process name.

The Catalyst detail in the README is the part to know. Catalyst apps are always sandboxed, so every capability has to be declared in ios/NekokoLPA/NekokoLPA.entitlements, and the documentation names com.apple.security.smartcard specifically as the one without which no reader is ever found. A reader that works on an iPad will silently not appear on a Catalyst build if that entitlement is missing.

The build is ad-hoc signed, so no developer certificate is needed, which removes the usual cost of getting a local build onto a Mac.

One dependency conflict is documented in detail. ML Kit ships fat frameworks whose arm64 slice is device-only, and no Catalyst slice at all, which makes the aggregate Pods target unbuildable for an arm64 simulator with a linker error about the Pods-NekokoLPA library not being found, and breaks Catalyst linking outright. The response is to exclude it from iOS builds by default, and the cost is stated: the only feature lost is decoding a QR code from a saved image, the button hides itself, and live camera scanning is unaffected. Android keeps the feature.

To include it for an iOS device or a release build, the README gives one command:

bash
cd ios && RN_WITH_MLKIT=1 pod install

The architecture is a device adapter layer over a wasm bridge

The source tree is laid out by domain, and the lpa directory is where the eSIM logic lives.

code
src/
  app/         App root, navigation, and context providers
  features/    One folder per screen (main, profile, download, settings, …)
  lpa/         eSIM domain: device adapters, wasm bridge, native modules, types
  shared/      Reusable UI, hooks, storage, theme, and utilities
  store/       Redux store and slices
  data/        Static datasets (PLMN, MCC, profile sizes)
  i18n/        Translations
  assets/      Images and flags

The lpa folder contains device adapters, a wasm bridge, native modules and types, and the extension mechanism is explicit. Device support is added by implementing the Device interface in src/lpa/adapters and registering it in src/lpa/deviceManager.ts.

That is the part of the design worth understanding. Adding a new card reader is not a patch to a device specific code path; it is a new implementation of one interface plus a registration, and the device manager dispatches to it. The wasm bridge is what carries the eSIM protocol work into the JavaScript layer, and the data directory holds static datasets covering PLMN, MCC and profile sizes, which are the lookup tables an LPA needs to describe a profile and the mobile networks it belongs to.

The rest of the tree is conventional. Screens are one folder each under features, shared holds reusable UI, hooks, storage, theme and utilities, the Redux store and slices live in store, translations in i18n, and a Japanese README sits alongside the English one.

The README warns about unofficial forks

There is a section on other cards, and it is a short one with a practical point in it.

The project is aware that several other eSIM brands have released applications derived from or modified versions of NekokoLPA. The response is a disclaimer rather than a takedown: these are unofficial builds, the project is not affiliated with and not responsible for any third party modifications, and it cannot provide support for them.

Then there is a licence reminder, and this is the part a developer should not skip. While the licence permits use, copying, modification, merging, publication, distribution, sublicensing and sale of the Software without limitation, the copyright notice and this permission notice must still be included in all copies or substantial portions of the Software.

That is a permissive MIT style term with an attribution obligation, and it is compatible with the MIT licence NekokoLPA 2 is expected to be released under. The obligation matters in the common case of a fork that is rebranded and shipped on a store, because the notice has to travel with it.

The combination of permissive terms, a licence classification that GitHub cannot classify, and a project that explicitly asks that the notice be retained is worth checking against the LICENSE file itself before you build a business on top of it. That file is where the actual terms are.

Where NekokoLPA is the wrong choice

Four situations rule it out.

The first is if you need a working eSIM app today. This is a source distribution that you build with yarn, with Xcode for the iOS target and Android Studio for the Android target. The Play Store builds exist, but they are branded for two specific ecosystems, the Community Key and 9eSIM removable cards, so a general purpose eSIM manager is not what you get from the store.

The second is if you need the cross platform future. The version that works on Windows, macOS and Linux is NekokoLPA 2, which is not open source yet, with the plan being an MIT release in late 2026 pending codebase improvements. Depending on it today means depending on a binary, and depending on a licence that has not been published.

The third is if your hardware is not on the list. A USB CCID reader on iOS needs CryptoTokenKit support, and a reader outside the enumerated list simply will not be detected. There is no generic fallback.

The fourth is if you need features this app does not have. The documented scope is downloading and managing eSIM profiles, with the domain code organised around that, and the list of features beyond it is thin. An operator tool, a business eSIM fleet manager, or a multi device provisioning console is a different product.

The alternative is the vendor application for your eSIM provider, or a generic eSIM manager from the app store, both of which are installed rather than built. The real reason to choose NekokoLPA is a specific one: you have a 9eSIM legacy Bluetooth reader, or a Community Key card, or you want to see exactly what the LPA protocol calls look like in an application whose source you can read. That is a genuine reason, but it is a narrow one.

Editorial conclusion

NekokoLPA 1 fits a developer or technically inclined user who wants to manage eSIM profiles without a vendor application, and who is willing to build the app from source with yarn and Xcode or Android Studio, and it fits a hardware hacker who needs the 9eSIM legacy Bluetooth reader or an ESTKme-RED unit supported. It is the wrong choice if you need an app today on your phone, since the Google Play variants are separate builds for the Community Key and for 9eSIM removable cards, and the cross platform successor is not yet open source. Before adopting it, check three things: that your card reader is on the supported list, which names the internal OMAPI slot on Android, USD CCID readers on Android, USD CCID readers through CryptoTokenKit on iOS, the ESTKme-RED dual mode reader and the 9eSIM legacy Bluetooth reader with firmware above 2.3.1, that you can build and run the app, and that the licence terms in LICENSE match your use, since the project records a custom licence that GitHub cannot classify and asks that the copyright and permission notice travel with copies and substantial portions.

Frequently asked questions

What is NekokoLPA and what does it do?

NekokoLPA is an open source eSIM LPA app for Android and iOS that downloads and manages eSIM profiles. It talks to the device's own eSIM over OMAPI, to USB CCID readers, to an ESTKme-RED reader and to the 9eSIM legacy Bluetooth card reader, and it is built with React Native and TypeScript.

Which card readers does NekokoLPA support?

The supported list covers the internal OMAPI slot on Android, USD CCID readers on Android, USD CCID readers through CryptoTokenKit on iOS, the ESTKme-RED dual mode card reader, and the 9eSIM legacy Bluetooth card reader with firmware greater than 2.3.1.

How do I build NekokoLPA from source?

Run yarn install, then yarn pod-install for iOS only, then yarn android or yarn ios. The project also has a yarn macos script for the Mac Catalyst build, and the build is ad-hoc signed so no developer certificate is required.

What is the difference between NekokoLPA and NekokoLPA 2?

NekokoLPA 2 additionally supports the Telephony API on rooted devices and runs on Windows, macOS and Linux, but it is not yet open source. The plan stated in the README is that it will be open sourced under the same MIT licence in late 2026, pending codebase improvements.

How do I add support for a new eSIM device?

Implement the Device interface in src/lpa/adapters and register the implementation in src/lpa/deviceManager.ts. The eSIM domain code lives in src/lpa, which also holds the wasm bridge, the native modules and the types.

Official sources

  1. iebb/NekokoLPA on GitHub
  2. Issues
  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/iebb-nekokolpa.svg)](https://hysenlabs.com/projects/iebb-nekokolpa)

Was this useful?