account-state
Account state and in-memory event store patterns in Amethyst. Use when working with `Account.kt` (per-user state objects — `kind3FollowList`, `nip65RelayList`,…
Nostr protocol implementation patterns in Quartz (AmethystMultiplatform's KMP Nostr library). Use when working with: (1) Nostr events (creating, parsing, signing), (2) Event kinds and tags, (3) NIP implementations (80+ NIP packages in quartz/), (4) Event builders and
$ npx -y skills add vitorpamplona/amethyst --skill nostr-expert --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/nostr-expertContext preview
The summary Claude sees to decide when to auto-load this skill.
Nostr protocol implementation patterns in Quartz (AmethystMultiplatform's KMP Nostr library). Use when working with: (1) Nostr events (creating, parsing, signing), (2) Event kinds and tags, (3) NIP implementations (80+ NIP packages in quartz/), (4) Event builders and
name: nostr-expert description: Nostr protocol implementation patterns in Quartz (AmethystMultiplatform's KMP Nostr library). Use when working with: (1) Nostr events (creating, parsing, signing), (2) Event kinds and tags, (3) NIP implementations (80+ NIP packages in quartz/), (4) Event builders and TagArrayBuilder DSL, (5) Nostr cryptography (secp256k1, NIP-44 encryption), (6) Relay communication patterns, (7) Bech32 encoding (npub, nsec, note, nevent), (8) Resolving user input (hex, npub, nprofile, or NIP-05 `name@domain` internet identifiers) to a pubkey. Complements nostr-protocol agent (NIP specs) - this skill provides Quartz codebase patterns and implementation details.
Practical patterns for working with Nostr in Quartz, AmethystMultiplatform's KMP Nostr library.
**For NIP specifications** → Use `nostr-protocol` agent **For Quartz implementation** → Use this skill
Quartz organizes code by NIP number:
quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/ ├── nip01Core/ # Core protocol (Event, Kind, Tags) ├── nip04Dm/ # Legacy DMs (deprecated) ├── nip10Notes/ # Text notes with threading ├── nip17Dm/ # Private DMs (gift wrap) ├── nip19Bech32/ # Bech32 encoding ├── nip44Encryption/ # Modern encryption (ChaCha20) ├── nip57Zaps/ # Lightning zaps ├── ... (57 NIPs total) └── experimental/ # Draft NIPs
**Pattern**: `nip##<Name>/` directories contain event classes, tags, and utilities for that NIP.
**Find implementations**: Use `scripts/nip-lookup.sh <nip-number>` or see `references/nip-catalog.md`.
@Immutable
open class Event(
val id: HexKey, // SHA-256 hash of serialized event
val pubKey: HexKey, // Author's public key (32 bytes hex)
val createdAt: Long, // Unix timestamp
val kind: Kind, // Event kind (Int typealias)
val tags: TagArray, // Array of tag arrays
val content: String, // Event content
val sig: HexKey, // Schnorr signature (64 bytes hex)
) : IEvent**Key insight**: `Event` is the base class. Specific event types (TextNoteEvent, ReactionEvent) extend it and add parsing/helper methods.
typealias Kind = Int fun Kind.isEphemeral() = this in 20000..29999 // Not stored fun Kind.isReplaceable() = this == 0 || this == 3 || this in 10000..19999 fun Kind.isAddressable() = this in 30000..39999 // Replaceable + has d-tag fun Kind.isRegular() = this in 1000..9999 // Stored, not replaced
**Pattern**: Kind determines event lifecycle and replaceability.
fun eventTemplate(
kind: Kind,
content: String,
tags: TagArray = emptyArray()
): EventTemplate**Usage**:
val template = eventTemplate(
kind = 1, // Text note
content = "Hello Nostr!",
tags = tagArray {
add(arrayOf("subject", "Greeting"))
}
)
// Sign with a signer
val signedEvent = signer.sign(template)**Why templates?** Separates event data from signing. Templates can be signed by different signers (local keys, remote signers, hardware wallets).
fun <T : Event> tagArray(
initializer: TagArrayBuilder<T>.() -> Unit
): TagArray**Methods**:
**Example**:
val tags = tagArray<TextNoteEvent> {
add(arrayOf("e", replyToEventId, "", "reply"))
add(arrayOf("p", authorPubkey))
addUnique(arrayOf("subject", "Re: Hello"))
add(arrayOf("content-warning", "spoilers"))
}**Pattern**: Fluent DSL for building tag arrays with validation and deduplication.
class TextNoteEvent : BaseThreadedEvent
**Creating**:
val note = eventTemplate(
kind = 1,
content = "Hello world!",
tags = tagArray {
add(arrayOf("subject", "First post"))
}
)**Parsing**:
val event: TextNoteEvent = ... val subject = event.subject() // Extension from nip14Subject val mentions = event.mentions() // List of p-tags val quotedEvents = event.quotes() // List of q-tags
fun createReaction(
targetEvent: Event,
emoji: String = "+"
): EventTemplate {
return eventTemplate(
kind = 7,
content = emoji,
tags = tagArray {
add(arrayOf("e", targetEvent.id))
add(arrayOf("p", targetEvent.pubKey))
}
)
}data class UserMetadata(
val name: String?,
val displayName: String?,
val picture: String?,
val banner: String?,
val about: String?,
// ... more fields
)
fun createMetadata(metadata: UserMetadata): EventTemplate {
return eventTemplate(
kind = 0,
content = metadata.toJson() // Serialize to JSON
)
}fun createArticle(
slug: String,
title: String,
content: String
): EventTemplate {
return eventTemplate(
kind = 30023,
content = content,
tags = tagArray {
addUnique(arrayOf("d", slug)) // UniAccount state and in-memory event store patterns in Amethyst. Use when working with `Account.kt` (per-user state objects — `kind3FollowList`, `nip65RelayList`,…
Patterns for extending `amy`, the Amethyst CLI in `cli/`. Use when adding an `amy <verb>` command, touching files under `cli/src/main/kotlin/…/cli/`, wiring a…
Android platform patterns for the `amethyst/` module. Use when working with (1) Android navigation (Navigation Compose, type-safe routes, bottom nav), (2)…
Signer abstraction patterns in Amethyst. Use when working with event signing, choosing between a local keypair (`NostrSignerInternal`), a remote NIP-46 bunker…
Advanced Compose Multiplatform UI patterns for shared composables. Use when working with visual UI components, state management patterns (remember,…
Use when writing or reviewing Jetpack Compose layout APIs, modifier parameters, modifier chain construction, hardcoded root layout decisions, or layout…