Files
Amber/desktop/README.md
T
Claudeandgreenart7c3 5af0afdd45 Add desktop app (Windows/macOS/Linux) as Compose for Desktop module
New :desktop Gradle module turns a computer into a NIP-46 signer with the
same accounts, permission model and bunker flows as the Android app, built
on the quartz-jvm artifact and Compose Multiplatform.

- BunkerEngine ports NotificationSubscription + EventNotificationConsumer +
  BunkerRequestUtils: per-connection localKey subscriptions (kind 24133),
  auto-accept/auto-reject via the rememberType/acceptUntil rules, approval
  queue for everything else, and relay responses with retry/backoff
- All NIP-46 methods supported: connect, sign_event, get_public_key, ping,
  nip04/nip44 encrypt/decrypt, nip44v3 encrypt/decrypt, decrypt_zap_event,
  sign_psbt, switch_relays, logout (NIP-55 is Android-only IPC and is
  intentionally out of scope)
- Keys are AES-256-GCM encrypted at rest with the key held in a PKCS12
  Java KeyStore; keystore + password files are owner-only permissions
- Connections via pasted nostrconnect:// URIs or generated bunker:// URIs
  with QR code; per-app permissions, activity history and logs persisted
  as JSON per account
- UI mirrors mobile: same theme/colors, bottom navigation (Incoming
  request / Applications / Relays / Settings), login/create-key with
  NIP-06 seed words, ncryptsec backup, multi-account switching
- Packaging via compose nativeDistributions: dmg, msi, exe, deb, rpm
- Tests: unit tests plus an opt-in (AMBER_E2E=1) end-to-end NIP-46
  round-trip against a public relay

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YQTVwy8RBj7spdEK3aEc3i
2026-09-28 10:12:09 -03:00

2.9 KiB

Amber Desktop (Windows, macOS, Linux)

A Compose for Desktop port of Amber that turns your computer into a NIP-46 remote signer ("bunker"). It shares the same Nostr stack as the Android app (the Quartz library, published for the JVM) and mirrors the mobile UI and permission model.

Features

  • Multiple accounts: create a new key (NIP-06 seed words) or import an nsec, ncryptsec (NIP-49), raw hex key, or mnemonic
  • NIP-46 signing over relays: connect, sign_event, get_public_key, ping, nip04_encrypt/decrypt, nip44_encrypt/decrypt, nip44v3_encrypt/decrypt, decrypt_zap_event, sign_psbt, switch_relays, logout
  • Connect applications with a nostrconnect:// URI or by generating a bunker:// URI (with QR code) — each connection gets its own local key
  • The same permission model as mobile: auto-accept / auto-reject rules per request type and event kind, time-bound grants (5 minutes … always), and per-application sign policies (basic / manual / sign everything)
  • Per-application activity history and relay logs
  • Default bunker relays management
  • Light/dark theme following the mobile look

Not included: NIP-55 (nostrsigner: intents and the content provider) — that is Android IPC and does not exist on desktop. Web apps and other clients connect through NIP-46 instead.

Key storage

Private keys are encrypted at rest with AES-256-GCM. The AES key is held in a Java KeyStore (PKCS12) file under the application data directory:

  • Windows: %APPDATA%\Amber
  • macOS: ~/Library/Application Support/Amber
  • Linux: $XDG_DATA_HOME/amber (or ~/.local/share/amber)

Desktop platforms have no universal hardware-backed keystore, so the keystore password is a per-install random secret stored next to the keystore with owner-only permissions. Anyone with access to your OS user account can read your keys — use full-disk encryption and OS login protection.

Run and build

./gradlew :desktop:run                                # run from source
./gradlew :desktop:createDistributable                # runnable app image
./gradlew :desktop:packageDeb                         # Linux .deb
./gradlew :desktop:packageRpm                         # Linux .rpm
./gradlew :desktop:packageMsi                         # Windows .msi (build on Windows)
./gradlew :desktop:packageExe                         # Windows .exe (build on Windows)
./gradlew :desktop:packageDmg                         # macOS .dmg (build on macOS)
./gradlew :desktop:packageDistributionForCurrentOs    # whatever fits the host

jpackage can only produce installers for the OS it runs on, so release builds are made per-platform. Linux packaging needs fakeroot (deb) or rpm-build (rpm) installed.

Tests

./gradlew :desktop:test              # unit tests
AMBER_E2E=1 ./gradlew :desktop:test  # + a NIP-46 round-trip over a public relay