Wisp

Wisp
Photo by Thomas Stephan / Unsplash

Wisp is an open-source Android client for the Nostr protocol. Built with Kotlin and Jetpack Compose, it focuses on intelligent relay routing, lightweight performance, and native wallet integration. The project is developed by Barry Deen, an independent developer who also maintains several Nostr relay implementations including Haven, wot-relay, and algo-relay.

The app is currently in early access beta at v0.3.0 (github.com/barrydeen/wisp). It is MIT licensed and has 291 commits across 15 releases to date.

The outbox problem

Most Nostr clients treat relays as interchangeable infrastructure. They connect to a hardcoded list and pull events from wherever they can find them. This works, but it ignores a basic property of how Nostr is designed. Users choose where they publish, and the people who want to read those posts need to look in the right places.

The outbox/inbox model (defined in NIP-65) addresses this by letting users declare their relay preferences: a set of write relays where they publish, and a set of read relays where they expect to receive messages. A client that respects this model fetches a user's posts from their write relays and delivers replies to their read relays. The result is more reliable event delivery and less wasted bandwidth from querying relays that do not have the content being requested.

Wisp implements this model from the ground up. It tracks relay reliability and author coverage through a scoring system, selects relay hints that overlap between the sender's outbox and the recipient's inbox, and opens ephemeral relay connections dynamically (up to 30 at a time) with automatic cleanup after five minutes of inactivity. When a user has not published a relay list, Wisp falls back to broadcast mode rather than failing silently.

Architecture

source

Wisp makes an unusual design choice for a mobile client: it does not use a local database. All state is held in memory through LRU caches (5,000 events, plus separate caches for profiles, reactions, reposts, and zaps) or in Android's EncryptedSharedPreferences. Events are fetched from relays on each session. The rationale, as stated in the project documentation, is that this keeps the app simple and fast while aligning with how Nostr was designed to work, with relays as the persistent storage layer.

The codebase follows MVVM architecture with a clear layer separation: UI (Jetpack Compose), ViewModels, Repositories, Protocol implementations, and a Relay layer. Each NIP is implemented as a Kotlin object with static helper functions, making the protocol layer modular. All relay communication and event parsing runs on background dispatchers, and feed updates are debounced to one per 16ms frame to prevent excessive UI recomposition from rapid relay events.

Private keys are stored using AES-256-GCM via Android's EncryptedSharedPreferences and never touch plain storage. The app supports multiple accounts with per-account encrypted storage and biometric authentication for key access.

NIP support

Wisp currently implements 16 Nostr Implementation Possibilities. The core set covers the basic protocol flow (NIP-01), follow lists (NIP-02), reply threading (NIP-10), and relay list metadata (NIP-65). For messaging, it supports NIP-17 gift wrap encryption (the three-layer rumor, seal, gift wrap model with timestamp randomisation) backed by NIP-44 modern encryption (ECDH + HKDF + XChaCha20 + HMAC-SHA256), with legacy NIP-04 as a fallback. Users can configure separate DM relay sets (NIP-51 kind 10050) to isolate private messaging traffic from their main relay infrastructure.

On the payments side, Wisp implements full NIP-47 Nostr Wallet Connect support, allowing users to link any NWC-compatible Lightning wallet via a connection URI. Balance checks, invoice payments, invoice creation, and Lightning zaps (NIP-57) with optional messages all work from within the app. The app also supports NIP-51 lists for mute lists, bookmarks, pins, relay blocking, and custom follow sets that can serve as alternative feed sources.

Media uploads go through Blossom, the decentralised media storage protocol, rather than centralised CDNs. Users manage their own server list (kind 10063) and the app tries each configured server in sequence until one accepts the upload. Nostr event-based authentication (kind 24242) handles the upload credentials.

Additional features

Wisp includes a relay console for debugging relay communication, NIP-05 DNS verification with caching, bech32 encoding support for npub/nsec/note/nevent/nprofile identifiers, QR code display for sharing keys and profiles, and an onboarding flow with follow suggestions for new users. Content safety controls include mute lists for blocking pubkeys, keyword muting, and relay blocking, all synced across clients via published Nostr events.

Roadmap

The project's published roadmap lists local database support (Room or SQLDelight) for offline access, image and video previews, hashtag following, and push notifications via UnifiedPush as near-term priorities. Medium-term plans include NIP-42 relay authentication, NIP-96 file storage, long-form content support (NIP-23), and community/group features (NIP-72). Longer-term goals include Tor/proxy support for enhanced privacy, an offline-first architecture with background sync, and a Wear OS companion app.

Current status

Wisp is Android only, requires Android 8.0 (API 26) or higher, and is built with Kotlin 2.0, Jetpack Compose with Material 3, OkHttp 4 for WebSocket connections, and secp256k1-kmp for Schnorr signatures. The repository lists two contributors: Barry Deen and Claude (indicating the use of AI-assisted development via Claude Code). APK downloads are available on the GitHub releases page.

The source code and release downloads are at github.com/barrydeen/wisp.


Source: Wisp GitHub repository (github.com/barrydeen/wisp), wisp.mobile project website, and Barry Deen's GitHub profile (github.com/barrydeen).