ndr
CLI for encrypted Nostr messaging using the double ratchet protocol.
Designed for humans, AI agents, and automation. Compatible with chat.iris.to.
Installation
Or build from source:
Quick Start
# Login with a private key (hex or nsec)
# Check identity
# Create an invite
# Publish a device invite (default device id = your identity pubkey hex)
# Join someone's invite
# Send a message
# Read messages
# Listen for new messages in real-time
JSON Mode
Use --json flag for machine-readable output (for scripts and AI agents):
Commands
Identity
Invites
Notes:
ndr invite publishdefaults to device id = your identity pubkey (hex), matching Iris multi-device expectations.- Re-run
ndr invite publishto refresh the device invite. - If you want a single "public" invite per identity across devices, use
--device-id public.
Link Devices
# On the device to be linked
# On the owner device
# Back on the device to be linked
Chats
Messages
Groups
Configuration
Default data directory: ~/.local/share/ndr/ (Linux) or platform equivalent.
Override with --data-dir flag or NDR_DATA_DIR environment variable.
Create config.json in data directory to configure relays:
Examples
Create an invite and wait for response
# Alice creates invite
# Output: invite URL
# Alice listens for responses
# Bob joins (on his machine)
# Alice sees session created, can now send messages
Send to npub using a public invite
# Bob publishes a public invite
# Alice can send directly to Bob's npub
AI Agent Integration
# Agent receives message event from relay
event='{"kind":1060,"content":"...",...}'
# Decrypt and process
# Output: {"status":"ok","data":{"chat_id":"...","content":"Hello!"}}
# Reply
Security Notes
- Outer events are signature-verified; sender attribution is resolved from authenticated session context plus owner/device mapping.
ownerPubkeyclaims are checked against AppKeys in multi-device flows.- Inner rumor
pubkeyis not treated as trusted sender identity. - Inner message payloads are unsigned and deniable; do not treat them as non-repudiable signatures.