Self-hosted library for your own Nintendo Switch dumps. Scan folders of NSP, NSZ, XCI, XCZ, and homebrew NRO files, fill in metadata, spot missing or duplicate content, and send titles to a modded Switch over LAN.
TypeScript
0
2 commits
updated Sep 19, 2026
Self-hosted library for your own Nintendo Switch dumps. Scan folders of NSP, NSZ, XCI, XCZ, and homebrew NRO files, fill in metadata, spot missing or duplicate content, and send titles to a modded Switch over LAN.
There are no download sources, no shop scraping, and no title keys handed out. Keys (prod.keys) come from your own console, stay on the server, and are optional.

This project is for content you dumped yourself, from your own console and your own cartridges. It will not help you obtain games, keys, or firmware, and requests to add that are out of scope permanently. See CONTRIBUTING.md.
prod.keys dumped from your console. Optional titledb (a URL or file you supply, refreshed daily if it's a URL) fills in names, which game DLC belongs to, and latest-version numbers only.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.NSLU frames. Transfers time out so cancel and unplug can interrupt a job.The Switch homebrew client (C++ / Borealis) streams NSP, NSZ, XCI, and XCZ installs into SD or NAND without copying the whole file to the SD card first. Connect over LAN HTTP or USB.

Borealis is a submodule, so clone recursively (git submodule update --init --recursive if you already cloned):
git clone --recursive https://github.com/tuckerwales/nslibrary.git
cd nslibrary
Docker (Node 22 image, linux/amd64 and linux/arm64, port 8465):
docker compose up --build
Open http://localhost:8465 and create the admin account. The first run asks for a setup token, which the server prints to its log on boot (docker compose logs nslibrary):
Setup token: K7M2X-9PQRT-4WHJN-6DFYB
Set NSLIB_SETUP_TOKEN to choose your own. Then browse the demo library, mount your dumps read-only as /library/games, and add that path under Folders.
Without Docker (Node ≥ 22.15, pnpm 12):
pnpm install
pnpm seed
NSLIB_SEED=true \
NSLIB_SEED_DIR="$PWD/data/demo-library" \
NSLIB_SEED_KEYS="$PWD/data/keys/prod.keys" \
pnpm start
Then pnpm --filter @nslib/web build so the server can serve the UI, or run pnpm dev:web alongside pnpm start / pnpm dev:server and use the Vite proxy on http://localhost:5173.
Production deploys (Coolify, volumes, PUID/PGID) are in docs/deploy.md.
pnpm workspaces. Shared types live in @nslib/shared; parsers never write into library folders.
| Path | Package | Role |
|---|---|---|
packages/shared | @nslib/shared | Zod schemas, error codes, USB frame constants, golden protocol files |
packages/formats | @nslib/formats | PFS0, HFS0/XCI, NCA, CNMT, NACP, ticket, NCZ, NRO, keyset |
packages/fixtures | @nslib/fixtures | Synthetic containers encrypted with a generated fake keyset |
packages/server | @nslib/server | HTTP APIs, scanner, SQLite (Drizzle), keys, titledb, UDP discovery |
packages/web | @nslib/web | React + Vite + TanStack Query UI |
packages/device-sim | @nslib/device-sim | CLI fake Switch for the device API (nslib-sim) |
packages/usb-host | @nslib/usb-host | USB frame session and node-usb attach |
packages/electron | @nslib/desktop | Electron window, tray, USB on the desktop |
switch/ | — | libnx + Borealis client, host-native C++ tests |
docker/ | — | Image entrypoint and compose overlay |
docs/ | — | Device API, USB frames, keys, deploy |
pnpm install
pnpm test # Vitest across packages
pnpm typecheck
pnpm lint
pnpm format
pnpm dev:server # API + scanner on :8465
pnpm dev:web # UI on :5173, proxies /api to the server
nslib-sim talks to a running server the way a Switch would:
pnpm --filter @nslib/device-sim start -- pair --code 123456
pnpm --filter @nslib/device-sim start -- hello --token <token>
Host-native tests (no devkitPro) cover PFS0, HFS0/XCI, NCZ, CNMT, tickets, JSON, the device-API codec, USB frames, and the install pipeline against the same golden files as TypeScript:
pnpm test:switch
The .nro needs devkitPro (switch-curl, switch-libzstd). From the repo root:
./scripts/build-switch.sh
See docs/switch.md for pairing, USB, nxlink -s, and NSP/NSZ/XCI installs to SD or NAND. Host tests need libzstd-dev. Desktop: pnpm dev:desktop (see docs/desktop.md).
| Variable | Default | Meaning |
|---|---|---|
NSLIB_HOST | 0.0.0.0 | Bind address |
NSLIB_PORT / PORT | 8465 | HTTP (web UI, /api/v1, /api/device/v1) |
NSLIB_DATA_DIR | data | SQLite, keys, icon cache. Docker: /data |
NSLIB_WEB_DIR | packages/server/public or packages/web/dist | Built UI; unset serves API only |
NSLIB_TRUST_PROXY | off | Set true behind Coolify / Traefik |
NSLIB_POLLING | off | Poll library folders (NFS/SMB) instead of inotify |
NSLIB_DISCOVERY | on | 0 / false disables UDP discovery and mDNS advertising |
NSLIB_DISCOVERY_PORT | 8466 | UDP port for NSLIB?1 |
NSLIB_SETUP_TOKEN | generated | Creating the admin account asks for this value. Unset, the server generates one per boot and logs it, so a server reachable before you've signed up can't be claimed by whoever opens it first |
NSLIB_SERVER_NAME | NSLibrary | Shown in hello and discovery |
NSLIB_SEED | off (on in the image) | Attach the demo library on first boot if no folders exist |
NSLIB_SEED_DIR / NSLIB_SEED_KEYS | — | Demo library path and matching fake prod.keys |
PUID / PGID | 1000 | Docker user that owns /data |
NSLIB_LOG_LEVEL | info | Fastify log level |
NSLIB_TLS_KEY / NSLIB_TLS_CERT | — | PEM files for optional HTTPS (LAN without a reverse proxy) |
NSLIB_NRO_PATH | data/update/nslibrary.nro if present | A signed release mirrored here, so consoles without internet can update (needs update.json and update.json.sig beside it) |
NSLIB_FORWARDER_MAIN | data/forwarder/main if present | ExeFS main for the HOME-menu NSP |
The server never writes into library folders. Missing files are marked, then purged after 30 days.
Upload prod.keys in Settings (or PUT /api/v1/keys). Stored at <dataDir>/keys/prod.keys with mode 0600. The API reports which names are present; key material is never returned, logged, or sent to a device.
Without keys the library still lists files from containers, tickets, and filenames, and labels that metadata as unverified. Details: docs/keys.md.
prod.keys and filename mode.nro releases, fetched from GitHub or mirrored on your serverIssues and pull requests are welcome — start with CONTRIBUTING.md, which covers setup, house style, and the things this project will not accept. Security vulnerabilities go through SECURITY.md rather than the issue tracker.
Apache License 2.0. Third-party components, including Borealis, TweetNaCl, libnx, the devkitPro portlibs, and the bundled Archivo font, are listed in THIRD-PARTY.md.
NSLibrary is an independent, unofficial project. It is not affiliated with, endorsed by, or associated with Nintendo. Nintendo Switch is a trademark of Nintendo. All product names, logos, and brands are the property of their respective owners, and are used only to describe what this software interoperates with.
NSLibrary is a file manager and a transfer tool. It ships no games, no keys, no firmware, and no
copyrighted Nintendo material of any kind; every test fixture in this repository is synthetic and
generated from scratch. It provides no way to obtain content, and does not circumvent any protection
measure — prod.keys must already be extracted from a console you own, and is optional.
What you do with it is your responsibility. Dumping content you own is treated differently in different countries; downloading or sharing content you do not own is not something this project supports, and running modified system software may violate Nintendo's terms of service and can get a console banned from online services.
2 commits
TypeScript
57.2%
C++
35.7%
C
3.2%
JavaScript
1.9%
Self-hosted library for your own Nintendo Switch dumps. Scan folders of NSP, NSZ, XCI, XCZ, and homebrew NRO files, fill in metadata, spot missing or duplicate content, and send titles to a modded Switch over LAN.
TypeScript
0
2 commits
updated Sep 19, 2026
Self-hosted library for your own Nintendo Switch dumps. Scan folders of NSP, NSZ, XCI, XCZ, and homebrew NRO files, fill in metadata, spot missing or duplicate content, and send titles to a modded Switch over LAN.
There are no download sources, no shop scraping, and no title keys handed out. Keys (prod.keys) come from your own console, stay on the server, and are optional.

This project is for content you dumped yourself, from your own console and your own cartridges. It will not help you obtain games, keys, or firmware, and requests to add that are out of scope permanently. See CONTRIBUTING.md.
prod.keys dumped from your console. Optional titledb (a URL or file you supply, refreshed daily if it's a URL) fills in names, which game DLC belongs to, and latest-version numbers only.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.NSLU frames. Transfers time out so cancel and unplug can interrupt a job.The Switch homebrew client (C++ / Borealis) streams NSP, NSZ, XCI, and XCZ installs into SD or NAND without copying the whole file to the SD card first. Connect over LAN HTTP or USB.

Borealis is a submodule, so clone recursively (git submodule update --init --recursive if you already cloned):
git clone --recursive https://github.com/tuckerwales/nslibrary.git
cd nslibrary
Docker (Node 22 image, linux/amd64 and linux/arm64, port 8465):
docker compose up --build
Open http://localhost:8465 and create the admin account. The first run asks for a setup token, which the server prints to its log on boot (docker compose logs nslibrary):
Setup token: K7M2X-9PQRT-4WHJN-6DFYB
Set NSLIB_SETUP_TOKEN to choose your own. Then browse the demo library, mount your dumps read-only as /library/games, and add that path under Folders.
Without Docker (Node ≥ 22.15, pnpm 12):
pnpm install
pnpm seed
NSLIB_SEED=true \
NSLIB_SEED_DIR="$PWD/data/demo-library" \
NSLIB_SEED_KEYS="$PWD/data/keys/prod.keys" \
pnpm start
Then pnpm --filter @nslib/web build so the server can serve the UI, or run pnpm dev:web alongside pnpm start / pnpm dev:server and use the Vite proxy on http://localhost:5173.
Production deploys (Coolify, volumes, PUID/PGID) are in docs/deploy.md.
pnpm workspaces. Shared types live in @nslib/shared; parsers never write into library folders.
| Path | Package | Role |
|---|---|---|
packages/shared | @nslib/shared | Zod schemas, error codes, USB frame constants, golden protocol files |
packages/formats | @nslib/formats | PFS0, HFS0/XCI, NCA, CNMT, NACP, ticket, NCZ, NRO, keyset |
packages/fixtures | @nslib/fixtures | Synthetic containers encrypted with a generated fake keyset |
packages/server | @nslib/server | HTTP APIs, scanner, SQLite (Drizzle), keys, titledb, UDP discovery |
packages/web | @nslib/web | React + Vite + TanStack Query UI |
packages/device-sim | @nslib/device-sim | CLI fake Switch for the device API (nslib-sim) |
packages/usb-host | @nslib/usb-host | USB frame session and node-usb attach |
packages/electron | @nslib/desktop | Electron window, tray, USB on the desktop |
switch/ | — | libnx + Borealis client, host-native C++ tests |
docker/ | — | Image entrypoint and compose overlay |
docs/ | — | Device API, USB frames, keys, deploy |
pnpm install
pnpm test # Vitest across packages
pnpm typecheck
pnpm lint
pnpm format
pnpm dev:server # API + scanner on :8465
pnpm dev:web # UI on :5173, proxies /api to the server
nslib-sim talks to a running server the way a Switch would:
pnpm --filter @nslib/device-sim start -- pair --code 123456
pnpm --filter @nslib/device-sim start -- hello --token <token>
Host-native tests (no devkitPro) cover PFS0, HFS0/XCI, NCZ, CNMT, tickets, JSON, the device-API codec, USB frames, and the install pipeline against the same golden files as TypeScript:
pnpm test:switch
The .nro needs devkitPro (switch-curl, switch-libzstd). From the repo root:
./scripts/build-switch.sh
See docs/switch.md for pairing, USB, nxlink -s, and NSP/NSZ/XCI installs to SD or NAND. Host tests need libzstd-dev. Desktop: pnpm dev:desktop (see docs/desktop.md).
| Variable | Default | Meaning |
|---|---|---|
NSLIB_HOST | 0.0.0.0 | Bind address |
NSLIB_PORT / PORT | 8465 | HTTP (web UI, /api/v1, /api/device/v1) |
NSLIB_DATA_DIR | data | SQLite, keys, icon cache. Docker: /data |
NSLIB_WEB_DIR | packages/server/public or packages/web/dist | Built UI; unset serves API only |
NSLIB_TRUST_PROXY | off | Set true behind Coolify / Traefik |
NSLIB_POLLING | off | Poll library folders (NFS/SMB) instead of inotify |
NSLIB_DISCOVERY | on | 0 / false disables UDP discovery and mDNS advertising |
NSLIB_DISCOVERY_PORT | 8466 | UDP port for NSLIB?1 |
NSLIB_SETUP_TOKEN | generated | Creating the admin account asks for this value. Unset, the server generates one per boot and logs it, so a server reachable before you've signed up can't be claimed by whoever opens it first |
NSLIB_SERVER_NAME | NSLibrary | Shown in hello and discovery |
NSLIB_SEED | off (on in the image) | Attach the demo library on first boot if no folders exist |
NSLIB_SEED_DIR / NSLIB_SEED_KEYS | — | Demo library path and matching fake prod.keys |
PUID / PGID | 1000 | Docker user that owns /data |
NSLIB_LOG_LEVEL | info | Fastify log level |
NSLIB_TLS_KEY / NSLIB_TLS_CERT | — | PEM files for optional HTTPS (LAN without a reverse proxy) |
NSLIB_NRO_PATH | data/update/nslibrary.nro if present | A signed release mirrored here, so consoles without internet can update (needs update.json and update.json.sig beside it) |
NSLIB_FORWARDER_MAIN | data/forwarder/main if present | ExeFS main for the HOME-menu NSP |
The server never writes into library folders. Missing files are marked, then purged after 30 days.
Upload prod.keys in Settings (or PUT /api/v1/keys). Stored at <dataDir>/keys/prod.keys with mode 0600. The API reports which names are present; key material is never returned, logged, or sent to a device.
Without keys the library still lists files from containers, tickets, and filenames, and labels that metadata as unverified. Details: docs/keys.md.
prod.keys and filename mode.nro releases, fetched from GitHub or mirrored on your serverIssues and pull requests are welcome — start with CONTRIBUTING.md, which covers setup, house style, and the things this project will not accept. Security vulnerabilities go through SECURITY.md rather than the issue tracker.
Apache License 2.0. Third-party components, including Borealis, TweetNaCl, libnx, the devkitPro portlibs, and the bundled Archivo font, are listed in THIRD-PARTY.md.
NSLibrary is an independent, unofficial project. It is not affiliated with, endorsed by, or associated with Nintendo. Nintendo Switch is a trademark of Nintendo. All product names, logos, and brands are the property of their respective owners, and are used only to describe what this software interoperates with.
NSLibrary is a file manager and a transfer tool. It ships no games, no keys, no firmware, and no
copyrighted Nintendo material of any kind; every test fixture in this repository is synthetic and
generated from scratch. It provides no way to obtain content, and does not circumvent any protection
measure — prod.keys must already be extracted from a console you own, and is optional.
What you do with it is your responsibility. Dumping content you own is treated differently in different countries; downloading or sharing content you do not own is not something this project supports, and running modified system software may violate Nintendo's terms of service and can get a console banned from online services.
2 commits
TypeScript
57.2%
C++
35.7%
C
3.2%
JavaScript
1.9%