using-nostr

Post notes, send encrypted messages, and interact with relays using the Nostr protocol.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "using-nostr" with this command: npx skills add besoeasy/open-skills/besoeasy-open-skills-using-nostr

NOSTR Posting Skill

Using nostr-sdk library

Source: https://github.com/besoeasy/nostr-sdk

Overview

Post messages, send encrypted DMs, and interact with the Nostr decentralized social protocol using minimal direct exports from the nostr-sdk module.

Installation:

npm install nostr-sdk

Key Concepts:

  • nsec: Private key in bech32 format (starts with nsec1)
  • npub: Public key in bech32 format (starts with npub1)
  • Relays: WebSocket servers that propagate Nostr events
  • Events: Signed JSON objects representing posts, DMs, etc.
  • POW: Proof of Work (mining) to reduce spam

Default Relays:

  • wss://relay.damus.io
  • wss://nos.lol
  • wss://relay.snort.social
  • wss://nostr-pub.wellorder.net
  • wss://nostr.oxtr.dev
  • And 9+ more for maximum reach

Skills

post_public_note

Post a public text note to Nostr.

Usage:

const { posttoNostr } = require("nostr-sdk");

const result = await posttoNostr("Hello Nostr! #introduction", {
  nsec: "nsec1...your-private-key",
  tags: [],
  relays: null,
  powDifficulty: 4
});
console.log(result);

Parameters:

  • message: Text content to post
  • tags: Optional array of tags (e.g., [['t', 'topic']])
  • relays: Optional custom relay list (uses defaults if null)
  • powDifficulty: Proof of work difficulty (default: 4, 0 to disable)

Auto-extracted Tags:

  • Hashtags: #nostr["t", "nostr"]
  • Mentions: @npub1...["p", <pubkey>]
  • Links: URLs automatically preserved
  • Notes: note1... references → ["e", <event-id>]

Response:

{
  success: true,
  eventId: "abc123...",
  published: 12,      // Successfully published to 12 relays
  failed: 2,          // Failed on 2 relays
  totalRelays: 14,
  powDifficulty: 4,
  errors: []
}

When to use:

  • User wants to post a public message
  • Sharing content with hashtags
  • Broadcasting announcements

reply_to_post

Reply to an existing Nostr post.

Usage:

const { replyToPost } = require("nostr-sdk");

const result = await replyToPost(
  "note1...event-id",           // Event ID (note or hex format)
  "Great post! @npub1...author", // Reply message
  "npub1...author-pubkey",      // Author's public key
  [],                           // Additional tags
  null,                         // Use default relays
  4                             // POW difficulty
);

When to use:

  • Responding to a specific post
  • Thread conversations
  • Engaging with content

send_encrypted_dm (NIP-4)

Send encrypted direct message using legacy NIP-4 standard.

Usage:

const { sendmessage } = require("nostr-sdk");

const result = await sendmessage(
  "npub1...recipient",    // Recipient's public key
  "Secret message here",  // Message content
  { nsec: "nsec1...your-private-key" }
);

When to use:

  • Compatibility with older Nostr clients
  • Basic encrypted messaging
  • Wide client support

Limitations:

  • Sender/recipient metadata visible
  • Older encryption (NIP-04)

send_encrypted_dm_modern (NIP-17)

Send gift-wrapped encrypted message using NIP-17 (recommended).

Usage:

const { sendMessageNIP17 } = require("nostr-sdk");

const result = await sendMessageNIP17(
  "npub1...recipient",    // Recipient's public key
  "Private message!",     // Message content
  { nsec: "nsec1...your-private-key" }
);

Benefits:

  • Sealed sender (hides who sent the message)
  • Better metadata protection
  • Modern NIP-44 encryption
  • Ephemeral keys for each message

When to use:

  • Maximum privacy needed
  • Modern applications
  • Hiding sender identity

receive_messages (NIP-4)

Listen for incoming direct messages.

Usage:

const { getmessage } = require("nostr-sdk");

const unsubscribe = getmessage((message) => {
  console.log("From:", message.senderNpub);
  console.log("Message:", message.content);
  console.log("Time:", new Date(message.timestamp * 1000));
}, {
  nsec: "nsec1...your-private-key",
  since: Math.floor(Date.now() / 1000) - 3600  // Last hour
});

// Stop listening:
// unsubscribe();

Message Object:

{
  id: "event-id",
  sender: "hex-pubkey",
  senderNpub: "npub1...",
  content: "decrypted message",
  timestamp: 1234567890,
  event: { /* full event */ }
}

When to use:

  • Building a chat bot
  • Receiving DMs
  • Monitoring for messages

receive_messages_modern (NIP-17)

Listen for incoming NIP-17 gift-wrapped messages.

Usage:

const { getMessageNIP17 } = require("nostr-sdk");

const unsubscribe = getMessageNIP17((message) => {
  console.log("From:", message.senderNpub);
  console.log("Content:", message.content);
  console.log("Wrapped ID:", message.wrappedEventId);
}, {
  nsec: "nsec1...your-private-key",
  since: Math.floor(Date.now() / 1000) - 300  // Last 5 minutes
});

// Stop listening:
// unsubscribe();

When to use:

  • Receiving modern private messages
  • Maximum privacy for incoming DMs
  • Supporting NIP-17 protocol

get_global_feed

Fetch recent posts from the global Nostr feed.

Usage:

const { getGlobalFeed } = require("nostr-sdk");

const events = await getGlobalFeed({
  limit: 50,                                    // Max 50 posts
  since: Math.floor(Date.now() / 1000) - 3600, // Last hour
  until: null,                                  // Up to now
  kinds: [1],                                   // Text notes only
  authors: null,                                // All authors
  relays: null                                  // Use defaults
});

events.forEach(event => {
  console.log("Author:", event.authorNpub);
  console.log("Content:", event.content);
  console.log("Note ID:", event.noteId);
  console.log("Posted:", event.createdAtDate);
});

When to use:

  • Building a feed reader
  • Monitoring public posts
  • Trending content analysis

generate_keys

Generate new Nostr key pair.

Usage:

const { generateNewKey } = require("nostr-sdk");

const keys = generateNewKey();
console.log(keys);
// {
//   privateKey: "hex-private-key",
//   publicKey: "hex-public-key",
//   nsec: "nsec1...",
//   npub: "npub1..."
// }

Quick Generate:

const { generateRandomNsec } = require("nostr-sdk");
const nsec = generateRandomNsec();
console.log(nsec); // nsec1...

convert_keys

Convert between key formats.

Usage:

const { nsecToPublic } = require("nostr-sdk");

const publicInfo = nsecToPublic("nsec1...your-key");
console.log(publicInfo);
// {
//   publicKey: "hex-public-key",
//   npub: "npub1..."
// }

Quick Start Examples

Example 1: Post a Message

const { posttoNostr } = require("nostr-sdk");

async function postHello() {
  const result = await posttoNostr("Hello from my bot! #nostr #automation", {
    nsec: "nsec1...your-private-key"
  });
  
  console.log("Posted:", result.eventId);
}

postHello();

Example 2: Send Private DM

const { sendMessageNIP17 } = require("nostr-sdk");

async function sendPrivateMessage() {
  const result = await sendMessageNIP17(
    "npub1...recipient",
    "This is a secret message!",
    { nsec: "nsec1...your-private-key" }
  );
  
  console.log("Sent:", result.success ? "Yes" : "No");
}

sendPrivateMessage();

Example 3: Listen for DMs

const { getMessageNIP17 } = require("nostr-sdk");

console.log("Listening for messages...");

const unsubscribe = getMessageNIP17((msg) => {
  console.log(`Message from ${msg.senderNpub}: ${msg.content}`);
}, {
  nsec: "nsec1...your-private-key"
});

// Keep running or call unsubscribe() to stop

Example 4: Quick Post (No Setup)

const { posttoNostr } = require("nostr-sdk");

// Auto-generates keys if not provided
const result = await posttoNostr("Quick post!", {
  nsec: "nsec1...your-key"  // Optional - generates new if omitted
});

Decision Tree

User wants to post to Nostr?
├─ Is it a public post?
│  ├─ Is it a reply to another post?
│  │  ├─ YES → Use replyToPost()
│  │  └─ NO → Use posttoNostr()
│  └─ Need spam protection?
│     ├─ YES → Set powDifficulty to 4+
│     └─ NO → Set powDifficulty to 0
│
├─ Is it a private message?
│  ├─ Maximum privacy needed?
│  │  ├─ YES → Use sendMessageNIP17()
│  │  └─ NO → Use sendmessage()
│  │
│  └─ Need to receive messages?
│     ├─ Use NIP-17 → getMessageNIP17()
│     └─ Use NIP-4 (legacy) → getmessage()
│
└─ Need to read posts?
   └─ Use getGlobalFeed()

Key Management

Security Best Practices:

  • Never commit nsec keys to git
  • Store keys in environment variables or secure vaults
  • Generate new keys for testing
  • Use different keys for different purposes

Environment Variables:

export NOSTR_NSEC="nsec1...your-private-key"
const { posttoNostr } = require("nostr-sdk");

await posttoNostr("Health check log", {
  nsec: process.env.NOSTR_NSEC
});

Error Handling

Common Errors:

  • Private key not set → Provide nsec or generate keys
  • Invalid nsec format → Check bech32 encoding
  • Failed to post to Nostr → Check relay connections
  • Failed to decrypt message → Wrong private key for recipient

Best Practice:

const { posttoNostr } = require("nostr-sdk");

try {
  const result = await posttoNostr("Hello", {
    nsec: process.env.NOSTR_NSEC
  });
  if (!result.success) {
    console.error("Failed to publish:", result.errors);
  }
} catch (error) {
  console.error("Error:", error.message);
}

Cleanup

Direct-export functions do not require a class instance, so there is no client cleanup step.


Resources

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

news-aggregation

No summary provided by upstream source.

Repository SourceNeeds Review
General

anonymous-file-upload

No summary provided by upstream source.

Repository SourceNeeds Review
General

free-geocoding-and-maps

No summary provided by upstream source.

Repository SourceNeeds Review
General

trading-indicators-from-price-data

No summary provided by upstream source.

Repository SourceNeeds Review