A nostr-native app for reading and highlighting. Paste a URL, share one from the browser, or open an http/https/nostr: link (articles, notes, npub/nprofile). You get a calm article view, your marks, swarm highlights from friends and the rest of the nostrverse, and listen with on-device TTS. Bookmarks and RSS live in the library.
No ads, no trackers, no paywalls, no subscriptions. Nostr is the backend, so your highlights travel with your npub. Pair a local relay like Citrine and keep reading in airplane mode.
Login is optional. Amber or a bunker can sign events. Boris never holds an nsec.
Light mode. An article on cream paper, a mark in the text, Boris reading it aloud.
Dark mode. Cover on the article, other people's marks on the same passage, a profile, TTS.
Home, library, feeds, search. You is the fifth tab; I left it off so the row stays four wide.
Settings, highlight colors, airplane mode, About.
In Reader's account profile, choose Export Library as CSV (export instructions). In Boris, open Settings → Library → Import from Readwise Reader, choose the CSV, then tap Import articles.
Boris downloads readable article text and saves device-local copies in the Web shelf. Source URLs and exported titles are preserved. Existing URLs in the library already loaded on this device and repeated CSV rows are skipped, using Boris's usual URL matching. If private bookmarks are locked, unlock them in Library first. Refresh Library before importing to include your latest synced bookmarks in the duplicate check.
Import requires internet access. Successfully imported text survives restarts and cache eviction; images may still need a connection. Failed downloads are reported and can be retried by running the import again. Completed copies are kept if you stop the import or leave Settings. After an app restart, select the same CSV again to continue, skipping completed copies.
The first version imports web articles from CSV, without a Readwise API token. It does not import highlights, tags, PDFs, EPUBs, or Reader's full-content ZIP export, and it does not publish imported copies to Nostr. Remove imported copies in the same settings section removes these local library entries and their saved text.
Open Settings → Library → Import from Pocket and select a Pocket CSV export you already saved. If it is inside a ZIP, extract the CSV first. The first version targets the CSV export described in Pocket's export documentation; legacy HTML exports are not supported.
Pocket and Readwise share the same import preview, progress, retry, duplicate detection, and device-local storage. Article URLs and titles are preserved, and successfully downloaded text is available offline in the Web shelf. Pocket rows from Saves, Archive, and Favorites are all imported as saved articles; status, tags, and highlights are not transferred. Import needs internet access to retrieve readable text from the original websites; unavailable pages are reported as failures. Images may need a connection.
Duplicate checks include prior imports from either service and the library already loaded on this device. Remove imported copies removes local copies from both services, while keeping Nostr bookmarks.
Boris is free and open source and always will be. Fork it, change it, send a pull request, or just use it.
Come say hi on Nostr. Report a bug or suggest a feature. Pull requests run lint and unit tests; same commands as under Build.
If you like the work, you can zap the Boris account directly or send sats to the author.
./gradlew :app:assembleDebugPull requests run Android Lint (debug) and JVM unit tests. Same checks locally:
./gradlew :app:lintDebug :app:testDebugUnitTestFatal lint errors fail the job. Warnings are reported and do not fail the build.
Signing uses a local upload keystore. Put these in gitignored local.properties:
OEM_STORE_FILE=/absolute/path/to/upload.jks
OEM_STORE_PASSWORD=…
OEM_KEY_ALIAS=upload
OEM_KEY_PASSWORD=…Then:
./gradlew :app:assembleReleaseConfig lives in zapstore.yaml (includes publisher pubkey). Releases are published with zsp.
- Install
zspfrom zsp releases (orgo install github.com/zapstore/zsp@latest). - Cut a GitHub release that includes the signed APK (or build
assembleReleaselocally). - Publish with your Nostr key for
npub1dergggklka99wwrs92yz8wdjs952h2ux2ha2ed598ngwu9w7a6fsh9xzpc:
export SIGN_WITH='nsec1…' # or bunker://… or browser
./scripts/zapstore-publish.shSIGN_WITH can also live in a gitignored .env file at the repo root.
The script publishes through zapstore.yaml (not a bare APK path) so release_notes from CHANGELOG.md are included. Use ZSP_EXTRA_ARGS='--overwrite-release' to replace an already-published version.
First publish links the APK signing certificate to your Nostr identity (NIP-C1) and whitelists the repo via zapstore.yaml.
MIT. Versions are in CHANGELOG.md.
















