Fixes #4547 The Nostr plugin was calling runtime.channel.reply.handleInboundMessage(), which doesn't exist in the PluginRuntime API. This caused DM processing to fail with 'handleInboundMessage is not a function'. Changed to use the correct message dispatch pattern: 1. Build proper MsgContext with finalizeInboundContext() 2. Create reply dispatcher with createReplyDispatcherWithTyping() 3. Dispatch replies with dispatchReplyFromConfig() This matches the pattern used by other channel extensions like Matrix and Discord. The fix ensures: - DMs are properly routed through the agent pipeline - Session state is recorded correctly - Reply text is formatted with markdown table conversion - Human delay and typing indicators work as expected |
||
|---|---|---|
| .. | ||
| src | ||
| test | ||
| CHANGELOG.md | ||
| index.ts | ||
| openclaw.plugin.json | ||
| package.json | ||
| README.md | ||
@openclaw/nostr
Nostr DM channel plugin for OpenClaw using NIP-04 encrypted direct messages.
Overview
This extension adds Nostr as a messaging channel to OpenClaw. It enables your bot to:
- Receive encrypted DMs from Nostr users
- Send encrypted responses back
- Work with any NIP-04 compatible Nostr client (Damus, Amethyst, etc.)
Installation
openclaw plugins install @openclaw/nostr
Quick Setup
-
Generate a Nostr keypair (if you don't have one):
# Using nak CLI nak key generate # Or use any Nostr key generator -
Add to your config:
{ "channels": { "nostr": { "privateKey": "${NOSTR_PRIVATE_KEY}", "relays": ["wss://relay.damus.io", "wss://nos.lol"] } } } -
Set the environment variable:
export NOSTR_PRIVATE_KEY="nsec1..." # or hex format -
Restart the gateway
Configuration
| Key | Type | Default | Description |
|---|---|---|---|
privateKey |
string | required | Bot's private key (nsec or hex format) |
relays |
string[] | ["wss://relay.damus.io", "wss://nos.lol"] |
WebSocket relay URLs |
dmPolicy |
string | "pairing" |
Access control: pairing, allowlist, open, disabled |
allowFrom |
string[] | [] |
Allowed sender pubkeys (npub or hex) |
enabled |
boolean | true |
Enable/disable the channel |
name |
string | - | Display name for the account |
Access Control
DM Policies
- pairing (default): Unknown senders receive a pairing code to request access
- allowlist: Only pubkeys in
allowFromcan message the bot - open: Anyone can message the bot (use with caution)
- disabled: DMs are disabled
Example: Allowlist Mode
{
"channels": {
"nostr": {
"privateKey": "${NOSTR_PRIVATE_KEY}",
"dmPolicy": "allowlist",
"allowFrom": [
"npub1abc...",
"0123456789abcdef..."
]
}
}
}
Testing
Local Relay (Recommended)
# Using strfry
docker run -p 7777:7777 ghcr.io/hoytech/strfry
# Configure openclaw to use local relay
"relays": ["ws://localhost:7777"]
Manual Test
- Start the gateway with Nostr configured
- Open Damus, Amethyst, or another Nostr client
- Send a DM to your bot's npub
- Verify the bot responds
Protocol Support
| NIP | Status | Notes |
|---|---|---|
| NIP-01 | Supported | Basic event structure |
| NIP-04 | Supported | Encrypted DMs (kind:4) |
| NIP-17 | Planned | Gift-wrapped DMs (v2) |
Security Notes
- Private keys are never logged
- Event signatures are verified before processing
- Use environment variables for keys, never commit to config files
- Consider using
allowlistmode in production
Troubleshooting
Bot not receiving messages
- Verify private key is correctly configured
- Check relay connectivity
- Ensure
enabledis not set tofalse - Check the bot's public key matches what you're sending to
Messages not being delivered
- Check relay URLs are correct (must use
wss://) - Verify relays are online and accepting connections
- Check for rate limiting (reduce message frequency)
License
MIT