Files
Vitor PamplonaandClaude Opus 5.5 395af4dc9c chore(skills): consolidate 33 skills into 14, verified against the tree
The 33 descriptions (~16k chars, ~19k with paths) overran Codex's skill-list
budget (2% of the context window, or 8,000 chars when unknown), and a review
found most bodies stale: paths from before the commons/commonsUI moves, the
deleted legacy desktop app, a callback signer API that no longer exists, and
example APIs that were never in the tree.

Kept, rewritten and checked against the code (every path, class and command):
account-state (+feeds), amy-expert, android-expert, auth-signers,
compose-expert (+API style, Navigation 3 back stacks), desktop-expert
(+run/package), event-store-semantics (+NIP-50 search), find-missing-
translations, kotlin-coroutines (+structured concurrency, flow modeling),
kotlin-multiplatform (+Gradle, composable extraction), ngit-pr,
nip85-trusted-assertions, nostr-expert (+NIP lookup, generated NIP catalog),
relay-client.

Dropped: textbook Compose/Kotlin technique skills, kotlin-expert,
kotlin-types-value-class, gradle-expert, quartz-integration (external-facing;
see the Quartz docs commit), find-non-lambda-logs (audit finished; the rule is
now in AGENTS.md Kotlin Style), and the /nip, /desktop-run, /extract commands.
The skill list is now ~4k chars. Also drops .claude/core-skills-plan.md
(stale history) and repoints SearchableEvent's KDoc to event-store-semantics.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:21:01 -04:00

50 lines
2.7 KiB
Markdown

# NIP-19 bech32 in Quartz
All under `quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip19Bech32/`.
| File | Holds |
|---|---|
| `Nip19Parser.kt` | `object Nip19Parser`: `uriToRoute(uri): ParseReturn?` (`entity`, `nip19raw`, `additionalChars`), `tryParseAndClean(uri): String?` (bare `npub1…` out of dirty input), `parseAll(content)`, `parseAllStandalone`, `parseAllEvents`, `hasAny`. Top-level `decodePublicKey`, `decodePublicKeyAsHexOrNull`, `decodePrivateKeyAsHexOrNull`, `decodeEventIdAsHexOrNull`. |
| `ByteArrayExt.kt` | `toNpub()`, `toNsec()`, `toNote()`, `toNEvent()`, `toNProfile()`, `toNAddress()`, `toNEmbed()`, `toLnUrl()` on raw bytes |
| `entities/` | `Entity` (plain interface) and `NPub`, `NSec`, `NNote`, `NEvent`, `NProfile`, `NAddress`, `NRelay`, `NEmbed`; each has `parse(bytes)` and a companion `create(...)` that returns the bech32 string |
| `EventExt.kt` | `Event.toNIP19(relayHint)` — `naddr` for addressable events, `nevent` otherwise |
| `ATagExt.kt` | `ATag.toNAddr()`, `ATag.parseAny`, `ATag.parseNAddr`, `ATag.isATag` |
| `ListEntityExt.kt` | `List<Entity>.eventHints()/eventIds()/addressHints()/pubKeys()…` for parsed content |
| `tlv/`, `TlvTypes.kt` | `TlvBuilder` (`addHex`, `addString`, `addInt`, `…IfNotNull`), `TlvTypes { SPECIAL, RELAY, AUTHOR, KIND }` |
| `bech32/Bech32Util.kt` | `object Bech32` (`encodeBytes`, `decodeBytes`), `String.bechToBytes()` |
## Encoding
```kotlin
val npub = pubkeyBytes.toNpub() // or NPub.create(hex)
val nevent = NEvent.create(idHex, authorHex, kind, relays) // relays: List<NormalizedRelayUrl> (or one, nullable)
val nprofile = NProfile.create(pubkeyHex, relays)
val link = event.toNIP19(relayHint)
```
Entities have no `toBech32()`/`toNostrUri()` methods; use `create(...)`, the `ByteArray`
extensions, or `toNIP19`.
## Decoding
```kotlin
when (val entity = Nip19Parser.uriToRoute(input)?.entity) { // accepts nostr: URIs
is NPub -> entity.hex
is NEvent -> entity.hex to entity.relay // relay: List<NormalizedRelayUrl>
is NAddress -> entity.aTag() // or entity.address()
null -> /* not bech32 */
}
```
Just need a pubkey from hex/npub/nprofile/nsec? `decodePublicKeyAsHexOrNull(input)`, or
`resolveUserHexOrNull` to also accept NIP-05 (see `nip05-identifiers.md`).
## Gotchas
- Relay hints in `nevent`/`nprofile`/`naddr` are hints; the outbox model decides where to
fetch.
- `NEmbed` is a gzip-compressed full event (`NEmbed.create(event)`), an Amethyst extension
beyond NIP-19.
- Never log an `NSec` or the input string it came from. `PubKeysNeverLeakNsecTest`
(commonTest `nip19Bech32/`) guards the decode helpers.