A Neovim plugin that brings Nostr (Notes and Other Stuff Transmitted by Relays) to your editor.
nostr.nvim connects Neovim to the Nostr protocol, allowing you to interact with Nostr relays directly from your editor. Built using Neovim's remote plugin system with TypeScript and nostr-tools.
- π Key Management - Generate, import, and manage Nostr keys
- π Notes - Post kind 1 notes directly from Neovim
- π¬ Direct Messages - Send and receive encrypted DMs (NIP-17)
- π» Code Snippets - Share code with syntax highlighting (NIP-C0)
- π Long-form Content - Publish markdown articles (NIP-23)
- π·οΈ Frontmatter Support - YAML frontmatter for article metadata
- π Multi-relay Support - Publish to multiple relays simultaneously
- β‘ Buffer Integration - Post buffer contents as notes, snippets, or articles
- Neovim 0.11.2+
- Node.js 20+
- Global neovim npm package:
npm install -g neovim
Using lazy.nvim
{
"nodetec/nostr.nvim",
build = "npm install && npm run build",
config = function()
-- Optional: set up keymaps
vim.keymap.set('n', '<leader>np', ':NostrPostNote ', { desc = 'Post Nostr note' })
vim.keymap.set('n', '<leader>nb', ':NostrPostBuffer<CR>', { desc = 'Post buffer as note' })
vim.keymap.set('n', '<leader>ns', ':NostrPostSnippet<CR>', { desc = 'Post code snippet' })
vim.keymap.set('n', '<leader>nl', ':NostrPostLongform<CR>', { desc = 'Post long-form article' })
vim.keymap.set('n', '<leader>nm', ':NostrSendDM ', { desc = 'Send Nostr DM' })
vim.keymap.set('n', '<leader>nM', ':NostrCheckDMs<CR>', { desc = 'Check Nostr DMs' })
end,
}Using packer.nvim
use {
'nodetec/nostr.nvim',
run = 'npm install && npm run build',
}After installation, run:
:UpdateRemotePluginsThen restart Neovim.
-
Initialize your configuration:
:NostrInit
This generates keys and sets up a default relay (wss://relay.damus.io).
-
Post your first note:
:NostrPostNote Hello Nostr from Neovim! -
Check your public key:
:NostrShowPubkey
Initialize Nostr configuration with new keys and default relay.
Generate a new keypair and save to config.
Import an existing private key from nsec format.
:NostrImportKey nsec1...Display your public key in both hex and npub format.
Copy your npub to the system clipboard.
Configure default relay (wss://relay.damus.io).
Post a simple text note (kind 1).
:NostrPostNote This is my note from Neovim!Post the entire current buffer content as a kind 1 note. Shows confirmation before posting.
Post current buffer as a code snippet (kind 1337, NIP-C0).
Features:
- Auto-detects language from filetype and extension
- Prompts for description
- Shows confirmation with snippet details
- Supports syntax highlighting metadata
Example workflow:
" Open a code file
:e hello.js
" Write some code...
" Post as snippet
:NostrPostSnippetPost current buffer as a long-form article (kind 30023, NIP-23).
Features:
- Extracts YAML frontmatter for metadata
- Uses
# Titleheader if no frontmatter exists - Prompts for title, summary, and topics
- Auto-generates or uses custom identifier
- Updates frontmatter with identifier after posting
- Auto-saves file after posting
Frontmatter example:
---
title: My Article Title
identifier: my-custom-slug
summary: A brief description
image: https://example.com/image.jpg
tags: nostr, neovim, programming
---
# Article content starts here...Add YAML frontmatter to current markdown buffer. Prompts for:
- Title (auto-detected from
# Headerif present) - Identifier (optional, auto-generated if empty)
- Summary (optional)
- Image URL (optional)
- Topics/tags (comma-separated, optional)
Send an encrypted direct message (NIP-17).
:NostrSendDM npub1... Hello from Neovim!Fetch and display recent direct messages in a popup window.
- Shows sender, timestamp, and message content
- Press
qto close the window - Displays last 20 messages
Fetch and display notes from a specific user.
:NostrGetNotes npub1...Shows the last 20 notes in a popup window.
Configuration is stored in ~/.config/nostr.nvim/config.json:
{
"privateKey": "hex-format-private-key",
"publicKey": "hex-format-public-key",
"relays": [
{ "url": "wss://relay.damus.io", "read": true, "write": true },
{ "url": "wss://relay.notebin.io", "read": true, "write": true }
]
}Each relay can be configured for reading, writing, or both:
Read + Write (default):
{ "url": "wss://relay.damus.io", "read": true, "write": true }Read-only (great for following content from popular relays):
{ "url": "wss://relay.nostr.band", "read": true, "write": false }Write-only (good for paid or personal relays):
{ "url": "wss://my-paid-relay.com", "read": false, "write": true }Backward Compatibility: The old string array format is still supported and will be automatically migrated:
{
"relays": ["wss://relay.damus.io", "wss://nos.lol"]
}Strings are converted to relays with both read and write enabled.
You can manually edit this file to:
- Add multiple relays with different read/write permissions
- Change keys
- Configure other settings
Warning: Keep your private key secure! The config file contains your private key in plaintext.
- NIP-01: Basic protocol flow
- NIP-17: Private Direct Messages (encrypted DMs)
- NIP-19: bech32-encoded entities (npub, nsec)
- NIP-23: Long-form Content (kind 30023 articles)
- NIP-C0: Code Snippets (kind 1337)
- Write your article in markdown
- Add frontmatter with
:NostrAddFrontmatter - Edit and refine your content
- Post with
:NostrPostLongform - The identifier is saved to frontmatter automatically
- Future posts with the same identifier will update the article
- Open or create a code file
- Write your code
- Run
:NostrPostSnippet - Add a description
- Confirm and post
Edit ~/.config/nostr.nvim/config.json to configure multiple relays with different permissions:
{
"relays": [
{ "url": "wss://relay.damus.io", "read": true, "write": true },
{ "url": "wss://relay.notebin.io", "read": true, "write": true },
{ "url": "wss://relay.nostr.band", "read": true, "write": false },
{ "url": "wss://my-paid-relay.com", "read": false, "write": true }
]
}How it works:
- Write operations (posting notes, snippets, articles, DMs) use relays with
write: true - Read operations (checking DMs, fetching notes) use relays with
read: true - The plugin attempts to publish to all write-enabled relays simultaneously
- The plugin queries all read-enabled relays for fetching content
Make sure you've run :UpdateRemotePlugins and restarted Neovim.
Install the global neovim package:
npm install -g neovimEnsure you have Node.js 16+ installed:
node --version
npm install
npm run buildCheck Neovim's health:
:checkhealthVerify the plugin is installed:
:scriptnames- Check your internet connection
- Verify relay URLs in
~/.config/nostr.nvim/config.json - Try using well-known relays like
wss://relay.damus.io
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Search and filter notes
- Profile management
- Reaction support (kind 7)
- Repost/quote support
- Custom relay configuration per command
- Threading/replies support
- Zap support (Lightning payments)
- Media uploads via blossom
- Note templates
- Vim motions for navigating notes
To develop the plugin locally using lazy.nvim:
-
Clone the repository:
git clone https://github.com/nodetec/nostr.nvim.git ~/path/to/nostr.nvim cd ~/path/to/nostr.nvim
-
Install dependencies:
npm install
-
Configure lazy.nvim to use your local clone:
-- In your Neovim config (e.g., ~/.config/nvim/lua/plugins/nostr.lua) return { dir = "~/path/to/nostr.nvim", -- Use local directory instead of GitHub build = "npm run build", -- Build on install/update config = function() -- Optional: set up keymaps or other config end, }
-
Build the plugin:
npm run build
-
Update remote plugins in Neovim:
:UpdateRemotePlugins
-
Restart Neovim to load the plugin.
After making changes to the TypeScript source:
# Rebuild the plugin
npm run build
# Or use watch mode for automatic rebuilds
npm run devThen in Neovim:
:UpdateRemotePlugins
:restartNote: The plugin requires Node.js and the global neovim package:
npm install -g neovimnostr.nvim/
βββ lua/nostr/ # Lua plugin interface
βββ src/ # TypeScript source code
β βββ index.ts # Main plugin entry point
β βββ lib/ # Library functions
β βββ config.ts # Configuration management
β βββ keys.ts # Key generation and management
β βββ message.ts # Direct messaging (NIP-17)
β βββ note.ts # Note posting (kind 1)
β βββ snippet.ts # Code snippets (NIP-C0)
β βββ longform.ts # Long-form content (NIP-23)
βββ rplugin/node/nostr/ # Compiled JavaScript output
βββ package.json # Node.js dependencies
MIT
Made with π for the Nostr community