I have a folder of Switch dumps I made myself, and for a long time that folder was the library. Filenames I half-trusted. Updates I wasn’t sure I had. DLC that may or may not belong to the game next to it. Homebrew NROs mixed in with everything else. Getting a title onto the console meant copying files around by hand, or relying on tools that wanted to be more of a shop than a file manager.

So I built NSLibrary. It’s a self-hosted library for content you already dumped from your own console and your own cartridges. Point it at your folders, open the web UI, and it groups base games, updates, DLC, and homebrew — then lets a paired Switch claim install jobs over the LAN (or USB).

There are no download sources. No shop scraping. No title keys handed out. Keys (prod.keys) come from your own console, stay on the server, and are optional.

The pitch

Run the server (Docker is the fastest path), open http://localhost:8465, create the admin account, and add a library folder. NSLibrary walks that folder read-only, watches for changes, and builds a catalog. The web UI shows the library, homebrew, problems (missing updates, duplicates, orphans), paired devices, folders, and settings.

On the Switch side, a small homebrew client (C++ / Borealis) browses the same catalog and installs NSP, NSZ, XCI, and XCZ straight to SD or NAND — streaming the file rather than copying the whole thing to the SD card first. You can connect over LAN HTTP or USB.

“Send to Switch” from the web UI doesn’t push. It queues a job. The console always initiates; it picks the job up with a long poll. Same device API over HTTP and USB, so the install engine doesn’t care which transport you used.

Why self-hosted

Most of the tools in this space want to be a shop, a scraper, or a mirror. I wanted the opposite: something that treats a directory of files you already own as the source of truth, runs on your machine (or your NAS), and never phones home.

Library roots are read-only. The server never writes into them. Remove a file and it’s marked missing, then purged after 30 days. Identity is (root, rel_path, size, mtime) — a file is re-parsed only when one of those changes. You can force polling for NFS/SMB mounts where inotify is unreliable.

Docker image covers linux/amd64 and linux/arm64. There’s an Electron desktop build too (tray, native folder picker, USB), and signed releases for macOS, Windows, and Linux if you’d rather not compose anything.

Metadata without the drama

Container listings and tickets need no keys. Names, icons, firmware requirements, and NCA hashes need prod.keys dumped from a console you own. Without keys the library still lists files from containers, tickets, and filenames — it just labels that metadata as unverified.

Optional titledb (a URL or file you supply) fills in names, which game DLC belongs to, and latest-version numbers. It’s off by default; you bring your own source.

Key material is never returned by the API, never logged, and never sent to a device. The server reports which key names are present. That’s it.

Finding the gaps

Once the catalog is built, the useful part is what it tells you about the gaps. Latest update missing. Duplicate (title id, version). Superseded update. Orphan update or DLC. Firmware newer than a paired device. Not present on a given console. Verify state — quick (headers only) or full (NCA hashes), with streaming NCZ decode so a large title doesn’t have to be materialised first.

That’s the difference between a folder of files and a library.

How the Switch finds you

Discovery is UDP NSLIB?1 on port 8466, plus mDNS _nslibrary._tcp so the server shows up in Bonjour/Avahi browsers. You can always type an IP by hand. Pairing is a short-lived 6-digit code from the web UI; the device gets a bearer token that can read the catalog and its own jobs, and nothing else — no settings, no key upload, no library writes. Tokens are revocable.

Technically

It’s a pnpm monorepo. Shared Zod schemas in @nslib/shared. Pure format parsers in @nslib/formats (PFS0, HFS0/XCI, NCA, CNMT, NACP, ticket, NCZ, NRO, keyset) that read through a RandomAccessReader and never write. Fastify + SQLite (Drizzle, WAL) for the server. React + Vite + TanStack Query for the web UI. A CLI device simulator (nslib-sim) that talks to a running server the way a Switch would. Host-native C++ tests for the Switch client against the same golden fixtures as TypeScript.

The constraint I care about most: the Switch always sends the requests. HTTP and USB carry identical messages behind one DeviceApiService. Preserve that, and the install path stays honest.

Demo data ships with synthetic containers and a fake keyset, so the UI is usable without real dumps. No copyrighted content in the repo.

What it isn’t

NSLibrary is not a shop. It will not help you obtain games, keys, or firmware, and requests to add that are out of scope permanently. It is a file manager and a transfer tool for dumps you already made.

It is also an independent, unofficial project — not affiliated with Nintendo. Dumping content you own is treated differently in different countries; downloading or sharing content you do not own is not something this project supports. Running modified system software can get a console banned from online services. What you do with it is your responsibility.

Try it

Source, docs, and releases are on github.com/tuckerwales/nslibrary. Latest release is v0.4.0.

Docker:

git clone --recursive https://github.com/tuckerwales/nslibrary.git
cd nslibrary
docker compose up --build

Open http://localhost:8465. The first run asks for a setup token, which the server prints to its log. Mount your dumps read-only, add the path under Folders, and pair a Switch when you’re ready.

If you try it — and especially if you try it with a real library of your own dumps — I’d love to hear how it went.