Phase 3a of the Clubhouse/nests integration. Adds a new KMP module
`nestsClient` (Android + JVM targets) that owns the HTTP control plane
for talking to a nests audio-room backend. No transport/audio yet —
that arrives in 3b with WebTransport + MoQ.
Surface:
- `NestsAuth.header(signer, url, method)` signs a kind 27235 event via
Quartz's existing HTTPAuthorizationEvent and returns a ready-to-use
`Authorization: Nostr <base64>` header value.
- `NestsRoomInfo` data class + tolerant JSON parser (ignores unknown
fields so newer nests server revisions don't break older clients).
- `NestsClient.resolveRoom(serviceBase, roomId, signer)` calls
`<serviceBase>/<roomId>` with the signed NIP-98 header and returns
the MoQ endpoint + token the audio layer will need.
- `OkHttpNestsClient` (jvmAndroid) is the default implementation
shared between Android and desktop JVM.
Tests:
- `NestsRoomInfoTest` (commonTest) covers full/minimal payloads,
unknown-field tolerance, missing-endpoint rejection, and URL
construction edge cases.
- `NestsAuthTest` (jvmTest) signs a real 27235 event, decodes the
base64 back through Quartz's JacksonMapper, and asserts the
signature verifies and the url+method tags bind correctly.
https://claude.ai/code/session_013nVLALALKaHVgHm9u5Cg8D
New :cli JVM module producing an `amy` binary that drives Amethyst
functionality headlessly. Identity and relay configuration sit at the
root (`amy init`, `amy whoami`, `amy relay …`); Marmot/MLS lives under
`amy marmot …` so future verbs (dm, feed, profile) can slot in cleanly.
Marmot surface covered:
- key-package publish / check
- group create / list / show / members / admins / add / rename /
promote / demote / remove / leave
- message send / list (kind:9 inner events)
- await key-package / group / member / admin / message / rename / epoch
(non-interactive polling with --timeout; exit 124 on timeout)
Wiring:
- NostrClient + BasicOkHttpWebSocket.Builder, reusing the existing
publishAndConfirmDetailed and fetchFirst accessories
- MarmotManager from :commons with file-backed MlsGroupStateStore,
KeyPackageBundleStore, and MarmotMessageStore (unencrypted — scratch
harness use only)
- each invocation is one-shot: prepare → syncIncoming → run command →
persist → disconnect
All commands emit one JSON object on stdout; diagnostics on stderr.
Designed so shell harnesses can pipe through jq without bespoke parsing.
https://claude.ai/code/session_01M6dCKAF5Y1VyHGZPjzwDXq
- Add desktopApp module with JVM entry point and sidebar navigation
- Add Claude specs for AI-assisted development:
- Agent definitions: nostr-protocol, kotlin-multiplatform, compose-ui, kotlin-coroutines
- Skills: quartz-kmp conversion, compose-desktop patterns
- Commands: desktop-run, nip, extract
- Update Gradle configuration with Compose Multiplatform 1.7.1 plugin
- Add coroutines and secp256k1 JVM dependencies to version catalog
Next steps:
- Convert Quartz library to full KMP (expect/actual for crypto)
- Implement relay connections in desktop app
- Share UI components between Android and Desktop
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Creates a Benchmark Module to test Performance
- Migrates from GSon to Jackson for Performance Gains, adapts all serializers accordingly
- Recreates Hex encoding/decoding classes for Performance.
- Migrates NIP24 to the new ByteArray Concat encoding.
- Removes support for Lenient choices in the. events.
- Reorganizes Nostr Events dependencies.
- Refactors TLV's and NIP-19 dependencies.
- Adds a Large DB for signature checks.