#Amethyst v1.17.0: Cordn, Geocaching, a New QR Scanner, and One UI
Highlights:
- Adds **Cordn** group chats: MLS groups over an MCP coordinator, with the
full chat experience, device migration and encrypted backups.
- Adds **Geocaching** (NIP-CC): a hub, a map, hunts, and QR-verified finds.
- Rebuilds the **QR scanner** on CameraX + zxing-cpp. It reads off-axis, blurry
and low-contrast codes the old one could not.
- Brings **Concord** up to spec: pins, Direct Invites, private channels with key
rotation, disappearing messages, kick and dissolve.
- Brings the **in-app browser** close to an installed Chrome PWA, with a new
omnibox and a search-engine setting.
- Shows **Ultra HDR** photos, plays **audio posts** as cards with
picture-in-picture, and shares what you listen to as **Now Playing**.
- Asks before another app's version of your **backed-up lists** drops items.
- Moves ~200 screens into shared UI on the way to **one UI** for Android and
Desktop.
## New Features
### Cordn
- Adds Cordn group chats to the Messages inbox, beside DMs, Marmot and Concord.
Messages never enter the event cache, so they are never searchable.
- Builds the chat on the shared components: bubbles, gestures, reactions,
quoted replies, day and unread dividers, and the rich text renderer.
- Adds replies, reactions, edits, deletions and pins, interoperable with the
reference client. Pins sit in a one-line carousel above the chat.
- Uses the shared composer: @-mentions, emoji shortcodes, GIF keyboard and paste.
- Adds encrypted attachments over Blossom and encrypted voice notes, with the
shared upload dialog and media viewer.
- Keeps drafts, unread counts and messages on disk, so rooms no longer open
empty after a relaunch.
- Redesigns New group as four steps: name, people, coordinator, and who can
add and remove. Shows how many of your people each coordinator can reach.
- Invites the whole roster in one commit, so one failed invite cannot fork the
group. People without a key package get a share link instead.
- Finds coordinators from their ContextVM announcements and names them by
profile, instead of asking for a 64-character key.
- Adds member management: add by name, npub or NIP-05, remove, rename, and admin
mode. Enforces admin rights like the reference client.
- Adds a metadata-exposure card explaining what each coordinator can learn.
- Shares groups as `cordn1…` links and QR codes, and adds an invitations screen
with Join and Decline.
- Adds join requests, coordinator health and management, and a key-package
screen that keeps your pool topped up.
- Adds device migration: the old phone shows a handoff code, the new phone scans
it and restores every group with its history. Keys are never in the code.
- Adds encrypted backup and restore of groups and their messages.
- Groups all Cordn settings under one entry, and adds Cordn Groups to the drawer
and the bottom-bar catalog.
### Geocaching (NIP-CC)
- Renders geocache listings and found logs as cards, with a photo hero, map
inset, rating, distance and badges.
- Adds a Geocaches hub (Nearby, Map, Hunts, Finds, Mine), cache details with
their log thread, and composers for caches, hunts and logs.
- Verifies a find by scanning the cache's QR code. The secret signs once and is
never stored.
- Hides hints behind a tap, and detects whether each was written in plaintext
or ROT13.
- Sorts Nearby by distance only when you ask.
- Opens caches and hunts from feeds, notifications, `naddr` links, QR scans and
search.
### QR Codes
- Rebuilds the scanner on CameraX + zxing-cpp, with autofocus, tap-to-focus,
pinch zoom and a torch. The old decoder read 31 of 48 test codes.
- Lets you pick when several codes are in frame or in a picture, and reassembles
multi-part codes.
- Reads codes from the gallery, the clipboard and the share sheet, and adds a
"Scan QR code" launcher shortcut.
- Explains a code it cannot open instead of closing, and keeps private keys off
the result screen and out of the logs.
- Keeps the screen bright while showing your own QR code.
### Concord
- Adds pinned messages, with a pin badge in the channel header and
jump-to-message.
- Adds Direct Invites: invite by npub, and accept or decline from the hub,
Notifications or Messages.
- Adds Public and Private community modes. A ban in a Private community rotates
the keys.
- Adds private channels, with Make private, Make public and Rotate key.
- Adds disappearing messages, with a timer from 1 day to 1 year.
- Adds cooperative Kick and community dissolution.
- Moves the Community List to the fragmented kind 33302, migrating the old list.
- Lets you edit your own thread replies and retract a reaction by tapping it
again.
- Shows the community description at the top of the channel list.
### Marmot
- Adds editing your own messages, compatible with White Noise edits.
- Detects a group this device has fallen out of sync with, and offers a Reset
that keeps history.
- Names unnamed groups after their members, and hides names on bubbles in
two-person groups, like DMs.
- Commits a member's leave automatically when you are an admin.
- Applies White Noise admin deletions.
- Adds Marmot Groups to the drawer, and makes the list read like the DM list.
- Warns when another device of yours is receiving your invites, and offers to
move them here.
### Buzz
- Brings Buzz to parity with upstream: artifacts, huddle liveness, team catalog,
projects and thread windows.
- Writes channel messages as kind 9, as Buzz's own clients do, and lets you edit
them.
- Labels agents as "Agent · managed by Alice", and tells apart members with the
same name.
### Browser
- Brings the in-app browser close to an installed Chrome PWA: new windows,
Tor-aware downloads, fullscreen, find in page, text size, desktop site and
crash recovery.
- Redraws every browser surface with one shared pill.
- Reworks the address field into an omnibox with paste-and-go and completions.
- Adds a search-engine setting: DuckDuckGo, Brave, Startpage, Mojeek, Qwant,
Ecosia, Kagi, Google or Bing.
- Adds per-site camera, microphone and location permissions, with "Only this
time".
- Adds "Add to Home screen". Shortcuts open in Amethyst and wait for Tor.
- Shows page alerts and prompts, which used to be silently cancelled.
- Replaces the WebView error page with a readable one, with Try again and Try
without Tor.
- Asks before every download, with the real name, size and source, and blocks
files pretending to be another type.
### Media
- Shows Ultra HDR photos in HDR, capped at 2x in the feed.
- Plays audio files in posts as a waveform or cover card, with
picture-in-picture.
- Shares what you are listening to as a NIP-38 music status, from Amethyst,
other apps or desktop players. Off by default.
- Adds captions to NIP-71 videos, with a CC toggle in the player.
- Shows video credits, and checks collaborators who accepted.
- Plays divine.video's adaptive HLS streams.
- Adds Cast on Android 17, and names the format a receiver refuses.
### Backups
- Asks before another app's version of your follows, mutes, relays, profile,
wallets or settings drops items you backed up.
- Shows a card on Home for each conflict, with one-tap Accept.
- Adds a review screen per conflict that lists every removed, added and changed
entry.
- Keeps open conflicts across restarts, and closes them when the other app puts
the items back.
### Key Backup
- Shows the nsec as a numbered, grouped grid you can copy onto paper. It hides
again when the app goes to the background.
- Adds a confirm-then-encrypt flow for the ncryptsec backup.
- Requires passwords of at least 12 characters for new ncryptsecs. Old ones
still open.
- Accepts hand-typed keys at login, with uppercase letters, spaces or dashes.
### Profiles
- Reads NIP-92 `imeta` for profile pictures and banners, trying the declared
fallback URLs when the main one fails.
- Shows the banner's blurhash while it loads.
- Publishes an `imeta` for freshly uploaded pictures and banners, on Android and
Desktop.
### Signing
- Shows a relay login (kind 22242) as a login card in signing prompts, naming
each relay exactly as signed. Odd-looking addresses get a "check before
signing" warning.
- Makes the event preview in signing prompts read-only, so you can no longer
react, zap, vote or RSVP on an event that does not exist yet.
### Notifications
- Shows DMs, Marmot groups and Buzz rooms as Android conversations, with
per-chat priority and launcher shortcuts.
- Shows inline-reply progress, with a Retry that keeps your text.
### Calendar
- Shows follows' "Going" RSVPs on Home, with a toggle in Settings.
- Adds a "Friends going" lens of upcoming events your list attends.
### Feeds and Lists
- Renders 3D Simple Nostr Objects, shards and cyberspace avatars, with a
full-screen viewer.
- Opens cyberspace region bags, showing how long the search will take.
- Renders every NIP-51 list kind as a card, instead of encrypted text.
- Adds favorite follow sets: star any follow set to use it as a feed.
- Shows prediction markets and ballots as their own cards, and hides kind-38000
spam.
- Shows Zapstore app curation sets, NIP-34 git status events and video curation
lists as cards.
- Shows a compact link preview for pages without an OpenGraph image.
- Shows follow-list petnames as a display-name fallback.
- Adds Cash App, Nano, Revolut, silent payments and BIP-353 payment targets.
### Messages
- Redesigns the Messages list: unread drives emphasis, and previews show @Name or
"Photo" instead of raw links.
- Redesigns the chat screen: softer bubbles, clock times and the avatar outside
the bubble.
- Shows sent messages immediately with a sending state, and retries a failed
send on tap.
- Plays voice messages and encrypted audio in the waveform player.
- Shows a DM rename as "Alice renamed the conversation".
### Uploads
- Falls back through your Blossom servers when an upload fails. The signer is
asked once.
- Shows why an upload failed, and lets you remove a failed attachment.
### Relays
- Adds an event allow list, roles and claims to relay management (NIP-86).
- Detects when a NIP-29 group has moved to another relay, and supports group
banners and `a` pins.
### Android
- Enables ARM Memory Tagging on supporting devices to catch native memory bugs.
## Performance
- Loads My Fitness progressively instead of behind a 2–3s spinner.
- Cuts the DEX from 31.1 MB to 29.9 MB by dropping kotlin-reflect.
- Confirms a Marmot group change at the first relay that accepts it, so creating
a group no longer waits for the slowest relay.
- Stops the Marmot key-package lookup shortly after the first package arrives, so
adding a member no longer takes most of a minute.
- Stops rewriting the whole Marmot message log and group state on every send.
- Removes a duplicate encryption on every Marmot send.
- Loads cached Blossom images straight from disk, also offline.
- Remembers missing Blossom files for 30s, so videos no longer stall 10s per
retry.
- Makes the audio visualizer smooth: 46 frames a second instead of 5.
- Speeds up the 3D renderer 4x and cuts its GC from 51% of a core to 7.7%.
- Speeds up the event cache's list observers 1.3–4x.
- Stops calendar screens rescanning the cache on every event.
- Stops the fullscreen image dialog recomposing on every frame of a swipe.
- Stops rebuilding Notifications and Messages on every Concord update.
## Improvements and Bug fixes
- Shows Tor status in the drawer. The icon hides when Tor is off and opens Tor
settings on tap.
- Fixes devices stuck on "Loading account" forever because they reject the
AES/GCM/PKCS7Padding cipher.
- Fixes encrypted stores that could write but not read back.
- Moves settings and account data from SharedPreferences to DataStore, and keys
off the deprecated androidx.security. Old files stay for downgrades.
- Fixes Tor never working on 32-bit ARM and x86 devices, which shipped without
the Tor library.
- Fixes notifications opening on a black screen after a cold start.
- Opens DM and private reply notifications in their conversation, under the
right account.
- Fixes kind-5 deletions matching any author: one user could hide another's
note.
- Decrypts private zaps for the zapped user, showing the real zapper.
- Fixes zap goals reading only 0% or 100%.
- Saves Cashu counters before using them, so a crash cannot lock funds at the
mint.
- Keeps proof-of-work posts mining in the background, and saves the draft first.
- Fetches your own profile and lists from inbox relays when you have no write
relays.
- Fits subscriptions under a relay's filter cap instead of losing the whole REQ.
- Keeps a subscription alive when a relay refuses one kind by name.
- Splits large profile requests, so relays that cap results do not leave authors
unnamed.
- Fixes quoted notes stuck on "Loading quoted note...".
- Sends calendar RSVPs to the host's and every invitee's inbox relays.
- Keeps the calendar's view and scroll when you come back to it, and stops
appointments flickering.
- Fixes Marmot groups forking on relay echoes, simultaneous commits, and
commits that leave you alone.
- Sends Marmot reactions and deletions inside the group, so White Noise sees
them.
- Fixes Concord messages being invisible in Accordion and other applesauce
clients.
- Fixes Concord joins: channels show at once, and failures are reported.
- Keeps a private channel's old keys, so history survives a rotation.
- Lets a banned Concord member return when re-invited after an unban.
- Fixes Direct Invites that never arrived.
- Fixes Buzz Desktop interop: uploads, mentions, profile, and relay refusal
reasons.
- Shows Buzz Join only to non-members and Leave only to members.
- Keeps browser pages on Tor whenever any surface uses Tor, and fails closed
when Tor cannot be applied.
- Keeps NIP-07 replies with the page that asked, and holds signing and payments
from tabs you are not looking at.
- Brings back black browser tabs and restores the page after Android reclaims
memory.
- Stops deleting a private DM from publishing a public NIP-09.
- Fixes NIP-49 rejecting some valid keys and crashing on very high scrypt costs.
- Plays videos from a local Blossom cache over Tor, and falls back to the server
when the cache is closed.
- Restores YouTube link previews.
- Stops the keyboard staying up after leaving a text field.
- Keeps the bottom bar on every pinnable tab.
- Returns a tablet rail tap to that tab's root.
- Makes all floating action buttons circular.
- Fixes amounts rounding wrongly, such as 12,500 showing as "12k".
- Fixes "100%%" in relay uptime labels.
- Fixes NWC notifications for wallets on the new NIP-47 extensions spec.
- Shows the bunker's error when a NIP-46 signer refuses.
- Encrypts every private relay entry, including ones other clients left in
plain text.
- Uses plurals for counts, so Czech and Polish read correctly.
- Fixes two release-only crashes on launch in the minified build.
## Desktop
- Stops offline users being stuck on "Connecting to Tor...": after 10s it offers
a regular connection.
- Reads now-playing from Linux MPRIS, macOS Spotify and Music, and Windows media
controls.
- Shows names and avatars for thread replies, and stops holding every note in
memory.
- Shows the nsec in the hand-copyable grid, and requires 12-character passwords.
- Uses the shared report dialog, which now also mutes the author.
- Renames the AppImage to `amethyst-desktop-<ver>-<arch>.AppImage`.
## Cli
- Adds `amy cordn` for refs, exposure, coordinators, key packages, groups,
invites, sending, `watch` and `migrate`.
- Adds `amy sno` to validate 3D objects and avatar proof of work.
- Adds `amy cyberspace`, which matches the reference cyberspace-cli.
- Adds `amy concord` pins, invites, private channels, kick, dissolve and timer.
- Adds `amy admin` commands for NIP-86 allow lists, roles and claims.
- Adds `amy relaygroup pin/unpin` and joins from invite links.
- Catches up correctly on Marmot groups after being offline.
- Accepts hand-copied keys in `amy login` and `amy key decrypt`.
## Quartz
- Adds ContextVM (MCP over Nostr) with all 12 CEPs, and the Cordn protocol.
- Moves the MLS engine to `quartz/mls/`, shared by Marmot and Cordn, with
several RFC 9420 interop fixes.
- Adds NIP-CC geocaching, Simple Nostr Objects, cyberspace region bags and
Tapestry Decentralized Lists.
- Adds NIP-FE relay commands over HTTP, with a client and a server.
- Adds NIP-67 EOSE completeness hints and a NIP-43 membership engine.
- Follows the latest NIP-29, NIP-47, NIP-51, NIP-86 and NIP-A3.
- Fixes NIP-44 padding above 16 MB and rejects non-canonical lengths.
- Fixes NIP-49 to check the AEAD tag and zero derived keys.
- Fixes NIP-88 rejecting every spec-conformant `polltype` tag.
- Fixes NIP-62 vanish requests for relays without a trailing slash.
- Stops page limits truncating NIP-77 negentropy reconciles.
- Answers a superseded replaceable with `OK false replaced:`.
- Indexes every natural-language tag on Decentralized Lists, so authors and
subjects become searchable, while skipping URLs and ids. Indexed text drops
from 105 MB to 75 MB on 1.5M events. Existing databases need
`reindexFullTextSearch()`.
- Makes local search match a searchable kind only by what it indexes, so local
and store search agree.
- Adds typed diffs between versions of replaceable events.
- Fixes many tag readers and bounds checks on hostile tags.
- Renames event classes to their NIP names, keeping deprecated aliases.
- Breaking: removes `ForkTag`. Use `experimental.forks.parseForkedAddress`.
- Fixes iOS ConcurrentModificationException crashes in LargeCache.
## Geode
- Serves NIP-FE relay commands over HTTP, with limits, CORS and NIP-98 sign-in.
- Adds NIP-43 membership: members-only writes, invites and roles.
## Build & Documentation
- Enables R8 obfuscation, and publishes mapping files with each release.
- Adds `scripts/retrace.sh` to deobfuscate a crash report in one command.
- Checks at release time that every reflected class survived R8.
- Builds Arti and zxing-cpp reproducibly for all four ABIs.
- Moves 1,906 strings to shared Compose resources.
- Moves the event cache, Account, AccountViewModel and most screens into
`commons`/`commonsUI`. 204 of 252 screens are now shared.
- Makes `./gradlew test` run every KMP module's JVM tests: 11,690 instead of
3,567.
- Updates AGP to 9.4.1, Gradle to 9.8.0, Compose Multiplatform to 1.12.1, Ktor
to 3.6.0, Coil to 3.6.3 and zoomable to 2.16.0.
- Runs Android Lint in its own CI job.
- Bumps `appCode` to 462.
## Contributors
- @nprofile…vhl6
- @nprofile…m3sx
- @nprofile…7nrg
- @nprofile…xxx2
- atesfurkan
## Translations
- Czech, German, Swedish, and Brazilian Portuguese by @nprofile…m3sx
- Polish by @nprofile…8c53
- Hungarian by @nprofile…ns2l
- Hindi by @nprofile…z0lu
- Russian by Anton Zhao
- Slovenian by @nprofile…3gag