Files
amethyst/cli/ROADMAP.md
T
Claude 3df9f831b8 feat(quartz): complete KindNames registry for every supported kind
Fill the KindNames registry from 145 to 280 entries so every event kind
quartz defines a class for has a canonical English label + NIP. Adds the
whole NIP-90 DVM request/response set, NIP-29 relay groups, NIP-60/61
Cashu wallet + nutzaps, NIP-43 relay members, WebRTC calls (NIP-AC),
marketplace (NIP-15), git PRs/state (NIP-34), CLINK, NIP-51 curation
sets, NIP-85 assertions, Marmot MLS events, and more.

For the handful of kind numbers shared by multiple classes, the registry
keeps one canonical entry (e.g. CashuToken over the deprecated nip61
TokenEvent, ExternalIdentities over GalleryList, ReleaseArtifactSet over
SoftwareRelease). Kind 1 stays "Notes" rather than the bounty value-add
helper that reuses it.

Also point `amy nip`'s Nostr fallback at quartz's canonical NipText kind
30817 (NipTextEvent) alongside the wiki and long-form kinds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011SapGdtAc1j7woifoCZ9fY
2026-06-21 21:41:52 +00:00

9.8 KiB

Amy Roadmap

The live checklist for growing amy from a Marmot test-bed into a full command-line mirror of Amethyst.

How to use this file: update it in the same PR that ships a feature. Move rows between tables, adjust ordering, add non-goals. This is the single source of truth for "what's left".


North-star goal

For every feature of the Amethyst Android app, there is a way to exercise it through amy, with byte-identical on-relay behaviour.

Why:

  • Interop tests against the ~100 other Nostr clients need a reproducible harness that does not require running Android.
  • Agents and LLMs can script real Amethyst flows without a GUI.
  • Regressions in shared logic (signing, encryption, filter building, event parsing) become shell-scriptable.
  • Power users get a command-line Amethyst for free.

Non-goal: Amy is not a second Nostr client implementation. It is a thin assembly layer over quartz + commons. Protocol and business logic in cli/ are bugs.


Parity matrix

Status legend: shipped · 📦 logic lives in commons/, needs a command · 🆕 needs extraction from amethyst/ first · ⚠️ blocked (see Notes).

Area Status Notes
Identity create / import (nsec, ncryptsec, mnemonic, npub, nprofile, hex, NIP-05) LoginCommand + Quartz NIP-05 / NIP-06 / NIP-49
Account bootstrap (nine events) commons/account/AccountBootstrapEvents.kt
Relay config + NIP-65 / NIP-10050 publish RelayCommands
MLS KeyPackage publish + fetch commons/marmot/MarmotManager
Marmot group create / add / rename / promote / demote / remove / leave commons/marmot/
Marmot message send / list commons/marmot/
await polling (KP / group / member / admin / message / rename / epoch) AwaitCommands
NIP-01 note publish (amy notes post TEXT) PostCommand — outbox via RelayCommands configured set.
NIP-01 feed read (amy notes feed [--following | --author NPUB]) FeedCommand. Hashtag / community feeds still pending.
NIP-02 follow list add / remove / list 🆕 Logic in amethyst/model/nip02FollowLists/.
NIP-09 event deletion 🆕 Builder exists in quartz.
NIP-17 DMs send / list / await DmCommands — reuses Quartz NIP17Factory + RecipientRelayFetcher; filter extracted to commons/relayClient/nip17Dm/. Plan: cli/plans/2026-04-23-nip17-dm.md.
NIP-18 reposts / quotes 🆕
NIP-25 reactions in groups · 🆕 elsewhere marmot message react covers MLS group reactions; outer-event reactions still pending.
NIP-51 lists (bookmarks, mute, follow sets) 🆕 amethyst/model/nip51Lists/
NIP-57 zaps (send + verify) 🆕 Needs LN-URL plumbing; amethyst/service/lnurl/.
NIP-65 outbox model queries 🆕
NIP-72 communities 🆕
NIP-78 app-specific data (settings sync) 🆕
Long-form (NIP-23) publish / read 🆕
Live activities / chess (NIP-53 / NIP-64) 🆕
Blossom uploads (NIP-B7) 🆕
NIP-47 Wallet Connect 🆕
NIP-46 bunker signer 🆕 Needs a signers abstraction in Amy.
Profile view (amy profile show NPUB) + edit ProfileCommands. Cache-first; --refresh forces a relay drain.
Thread view (amy thread show EVENT_ID) ⚠️ Same.
Notifications feed 🆕
Search (NIP-50) 🆕

nak parity — army-knife primitives

Tracking fiatjaf/nak's command surface. amy adapts the verbiage where its own conventions differ (req → one-shot fetch vs streaming subscribe). Stateless verbs run with no account or network.

nak command amy verb Status Notes
decode amy decode NIP-19/21 → JSON. Quartz Nip19Parser.
encode amy encode npub/nsec/note/nevent/nprofile/naddr.
verify / validate amy verify id-hash + signature, reported separately.
key amy key generate|public|encrypt|decrypt generate/derive + NIP-49 encrypt/decrypt (bidirectionally nak-verified). expand/combine/validate/default still 🆕.
event amy event build/sign an arbitrary event, optional --publish/--relay.
publish amy publish broadcast a pre-made event JSON (verified first).
req (one-shot) amy fetch filter → collect-until-EOSE, dedupe, sort, cap.
req (stream) amy subscribe filter → live NDJSON stream to stdout.
count amy count NIP-45, per-relay counts.
encrypt / decrypt amy encrypt|decrypt raw NIP-44 (default) / NIP-04.
gift amy gift wrap|unwrap NIP-59 seal+wrap / unwrap+unseal.
relay (NIP-11) amy relay info stateless NIP-11 doc fetch.
outbox amy outbox NIP-65 read/write relays, cache-first.
filter amy filter stateless — assemble + print a filter JSON.
blossom amy blossom upload/download/list/delete/check/mirror (reuses commons BlossomClient).
nip amy nip repo-first lookup + Nostr fallback (NipText kind:30817, wiki:30818, long-form:30023); nip list.
kind amy kind quartz KindNames registry (kind → English label + NIP) covering every event kind quartz defines (280 entries); number lookup + name search.
sync amy sync NIP-77 Negentropy reconcile with the local store (down/up/both).
git amy git in part NIP-34 repo announce/list/show/issue. clone/push (packfile transport) out of scope.
podcast amy podcast NIP-F4 show metadata (10154) + episode publish (54) + list.
bunker amy bunker[ connect] + amy login bunker:///--nostrconnect NIP-46 remote signer + login, both the bunker:// and nostrconnect:// flows, each direction, plus auth_url challenge handling (client surfaces the URL + keeps waiting). Interop-verified vs real nak.
serve / admin / wallet / mcp / fs / spell 🆕 (tier 2/3) larger/niche; some pull new deps.

Full nak comparison (introspected both binaries)

nak has 34 functional commands. Coverage:

  • Full / equivalent (19): event, req(→fetch+subscribe), filter, count, decode, encode, verify, relay, bunker(+nostrconnect+auth_url), encrypt, decrypt, gift, publish, sync, profile, podcast, nip, kind, blossom. Protocol-sensitive ones (bunker, sync, key NIP-49, encode/decode) are interop-verified against the real nak binary.
  • Partial / adapted (4): key (no expand/combine/validate/default), git (NIP-34 events only — no packfile transport), outbox (shows NIP-65 vs nak's hints DB), fetch (filter-based, not nip19-hint resolution).
  • Missing (11): admin (NIP-86), serve (geode is a standalone relay), dekey (NIP-4E), wallet (NIP-60 Cashu), mcp, curl (NIP-98), fs (FUSE), group/nip29 (NIP-29 — amy has MLS/Marmot instead), spell (MuSig2/FROST), validate (RoK schema).

Design differences (not gaps): amy is a stateful client (accounts, ~/.amy/, shared event store) with a stable JSON contract; nak is a stateless per-invocation tool that prints bare values for shell substitution. amy also has a large surface nak lacks: Marmot/MLS, NIP-17 DMs, zaps, CLINK offer/debit, NIP-02 follow, NIP-50 search, napplets, profile edit, store management, account management.

Cheap remaining wins: the key expand/combine/validate/default sub-verbs.


Order of operations

Proposed sequencing. Each step is one PR. Each step should extract at least one file from amethyst/ into commons/; if it doesn't move anything, re-audit — you're probably duplicating logic.

  1. Event rendering core in commons/commonMain/.../rendering/ with renderers for kinds 0 / 1 / 3 / 6 / 7 / 10002 / 10050. Unblocks all the 🆕 and ⚠️ read-path rows below. Design: commons/plans/2026-04-21-event-renderer.md.
  2. amy notes post / amy notes show / amy notes react — smallest end-to-end write+read loop outside Marmot. Post + feed shipped; notes show and outer-event react still pending.
  3. amy notes feed home|profile|hashtag|thread reading through the renderer. --following and --author NPUB ; hashtag/thread variants still pending.
  4. amy follow add|remove|list (NIP-02) — proves extraction of list-building logic from amethyst/model/.
  5. amy dm send|list (NIP-17) — shipped. Reuses the gift-wrap path also exercised by Marmot.
  6. amy list bookmarks|mute|pin … (NIP-51).
  7. amy zap send|verify (NIP-57).
  8. Distribution — Homebrew + Scoop + .deb in the same release pipeline as desktop. Plan: cli/plans/2026-04-21-cli-distribution.md.
  9. Test suite — end-to-end against a local relay. Marmot interop is covered by cli/tests/marmot/marmot-interop-headless.sh; NIP-17 DM interop between two amy clients is covered by cli/tests/dm/dm-interop-headless.sh (text + file + strict 10050 + fallback + cursor-advance). Neither runs in CI yet (both need Rust + ~3 min cold relay build).
  10. Everything else in the matrix.

Non-goals

  • Interactive TUI or REPL.
  • Native image (GraalVM) until Quartz has a pure-Kotlin signer fallback — secp256k1-kmp-jni-* needs JNI today.
  • A Gradle dependency on :amethyst or :desktopApp. Ever.
  • Re-implementing any Nostr protocol piece that's already in quartz/ or in another client's library.