Production-Ready Obsidian-style Markdown Link Navigation for Neovim
Transform your Neovim into a powerful knowledge management system with wiki-style links and intelligent completion.
- π Wiki-style Links: Navigate using
[[file-name]]syntax with automatic file creation - π§ Intelligent Completion: Ultra-fast tag (
#), wiki link ([[), and markdown link completion - π Interactive Graph View: Visualize your markdown link network with telescope integration
- β‘ Performance Optimized: Sub-second file discovery with ripgrep, intelligent caching, async processing
- π¨ Syntax Highlighting: Automatic highlighting for tags (
#tag) and HTTPS/HTTP links - π·οΈ Tag Management: Add, view, and search tags across your knowledge base with telescope integration
- π Link Management: Create links from selected text with smart filename cleaning
- π Navigation History: Seamless back/forward navigation through your knowledge base
- βοΈ Production Ready: Comprehensive error handling, diagnostics, and emergency recovery options
Major Performance & Completion Overhaul
- 10-20x faster file discovery and completion with ripgrep integration
- Production-grade stability with comprehensive testing and error handling
- Intelligent auto-configuration that adapts to your repository size
- Emergency safety commands for troubleshooting and recovery
- Enhanced completion system with tag and wiki link support
- Required: telescope.nvim - Used for graph functionality
- Required: ripgrep - Fast file search for completion and search features
- Optional: nvim-treesitter - Enhanced syntax highlighting
- Optional: nvim-cmp - Completion framework support
- Optional: blink.cmp - Alternative completion framework support
macOS (via Homebrew):
brew install ripgrepUbuntu/Debian:
sudo apt install ripgrepFedora:
sudo dnf install ripgrepArch Linux:
sudo pacman -S ripgrepWindows (via Chocolatey):
choco install ripgrepCargo (cross-platform):
cargo install ripgrepProduction-Ready Setup (Recommended):
{
"saravenpi/pebble.nvim",
dependencies = {
"nvim-telescope/telescope.nvim",
"hrsh7th/nvim-cmp", -- Optional: for completion support
-- "Saghen/blink.cmp", -- Alternative: blink.cmp support
},
ft = "markdown", -- Load only for markdown files
config = function()
-- Auto-configure based on your repository size
require('PRODUCTION_CONFIG').auto()
end
}Manual Setup (Advanced Users):
{
"saravenpi/pebble.nvim",
dependencies = {
"nvim-telescope/telescope.nvim",
"hrsh7th/nvim-cmp",
},
config = function()
require('pebble').setup({
auto_setup_keymaps = true,
global_keymaps = false,
completion = {
nvim_cmp = true, -- Enable nvim-cmp integration
blink_cmp = false, -- Disable blink.cmp (or true to enable)
},
search = {
ripgrep_path = "rg", -- Path to ripgrep executable
},
})
-- Add pebble completion sources to nvim-cmp
local cmp = require('cmp')
cmp.setup({
sources = cmp.config.sources({
{ name = "pebble_wiki_links", priority = 1000 }, -- Wiki links [[
{ name = "pebble_tags", priority = 950 }, -- Tags #
{ name = 'nvim_lsp' },
{ name = 'buffer' },
{ name = 'path' },
})
})
end
}Advanced setup with detailed configuration:
{
"saravenpi/pebble.nvim",
dependencies = {
"nvim-telescope/telescope.nvim",
"hrsh7th/nvim-cmp",
},
config = function()
require('pebble').setup({
auto_setup_keymaps = true,
global_keymaps = false,
completion = {
nvim_cmp = {
enabled = true,
priority = 100,
max_item_count = 50,
trigger_characters = { "[", "#" },
},
blink_cmp = {
enabled = false,
priority = 100,
max_item_count = 50,
},
cache_ttl = 30000, -- Cache TTL in milliseconds
cache_max_size = 2000, -- Maximum cached items
},
search = {
ripgrep_path = "rg",
max_results = 1000,
timeout_ms = 5000,
}
})
-- Configure nvim-cmp with pebble sources
local cmp = require('cmp')
cmp.setup({
sources = cmp.config.sources({
{ name = "pebble_wiki_links", priority = 1000 },
{ name = "pebble_tags", priority = 950 },
{ name = 'nvim_lsp' },
{ name = 'luasnip' },
{ name = 'buffer' },
{ name = 'path' },
})
})
end
}With blink.cmp:
{
"saravenpi/pebble.nvim",
dependencies = {
"nvim-telescope/telescope.nvim",
"Saghen/blink.cmp",
},
config = function()
require('pebble').setup({
completion = {
blink_cmp = {
priority = 100,
max_item_count = 50,
}
}
})
end
}Minimal setup (no completion):
{
"saravenpi/pebble.nvim",
dependencies = {
"nvim-telescope/telescope.nvim",
},
config = function()
require('pebble').setup({
completion = false -- Disable completion features
})
end
}use {
'saravenpi/pebble.nvim',
requires = {
'nvim-telescope/telescope.nvim',
'hrsh7th/nvim-cmp', -- Optional
},
config = function()
require('pebble').setup()
-- Setup nvim-cmp source if using nvim-cmp
local cmp = require('cmp')
cmp.setup({
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
{ name = 'pebble' },
{ name = 'buffer' },
})
})
end
}- Open a markdown file
- Create links using
[[file-name]]syntax - Place cursor on a link and press
<CR>to follow it - Use
<Tab>and<S-Tab>to jump between all types of links (wiki, markdown, HTTP/HTTPS) - Use
<leader>mpand<leader>mnto navigate history - Use the graph view to explore your link network
- Select text in visual mode
- Press
<leader>mcto create a link, create the file, and navigate to it - Press
<leader>mlto create a link and create the file without navigation
- Press
<leader>mgto open the interactive graph - Press
<leader>mvto open the enhanced visual graph with ASCII art - Use
j/kor arrow keys to navigate - Press
<CR>to open a file - Press
qor<Esc>to close
Pebble provides three types of intelligent completion:
- Trigger: Type
[[in any markdown file - Features:
- Advanced fuzzy matching against filenames, titles, and aliases
- YAML frontmatter title and alias support
- Supports both
[[Note Name]]and[[Note Name|Display Text]]formats - Ultra-fast ripgrep-powered file discovery
- Intelligent caching with 30-second TTL
- Trigger: Type
#in any markdown file - Features:
- Extracts tags from both inline (
#tag) and YAML frontmatter - Supports nested tags (
#category/subcategory) - Frequency-based ranking with fuzzy matching
- Immediate response with intelligent caching
- Extracts tags from both inline (
- Trigger: Type
](for markdown links - Features:
- Relative file path completion
- Title extraction from YAML frontmatter and headers
- Context-aware suggestions prioritizing nearby files
-
Ripgrep Integration: Sub-second file discovery for large repositories
-
Intelligent Caching: 30-second TTL with automatic invalidation
-
Async Processing: Non-blocking UI with batch processing
-
Scalability: Efficiently handles 2000+ markdown files
-
Fallback Support: Works without ripgrep using vim.fs.find
-
Navigate with
j/k,β/β,G/gg -
Press
<CR>to open selected file -
Press
rto refresh the cache -
Press
qor<Esc>to close
| Command | Description |
|---|---|
:PebbleFollow |
Follow link under cursor |
:PebbleNext |
Next link in buffer |
:PebblePrev |
Previous link in buffer |
:PebbleBack |
Go back in history |
:PebbleForward |
Go forward in history |
:PebbleGraph |
Toggle graph view |
:PebbleVisualGraph |
Toggle enhanced visual graph view |
:PebbleHistory |
Show navigation history |
:PebbleStats |
Show cache statistics |
:PebbleToggleChecklist |
Toggle markdown checklist/todo item |
:PebbleCreateLinkAndNavigate |
Create link, file and navigate (visual mode) |
:PebbleCreateLinkAndFile |
Create link and file without navigation (visual mode) |
:PebbleInitHeader |
Initialize YAML header if not present |
:PebbleIncreaseHeading |
Increase markdown heading level |
:PebbleDecreaseHeading |
Decrease markdown heading level |
:PebbleSearch <pattern> |
Search in markdown files using ripgrep |
:PebbleComplete |
Test wiki link completion in current context |
:PebbleCompletionStats |
Show completion cache statistics |
:PebbleCompletionRefresh |
Refresh completion cache |
:PebbleDiagnose |
Run comprehensive system diagnostics |
:PebbleReset |
Reset all caches and internal state |
:PebbleBuildCache |
Build file cache with progress notification |
:PebbleAddTag [tag] |
Add tag to current file (interactive if no tag provided) |
:PebbleShowTags |
Show tags in current file with telescope UI |
:PebbleFindTag [tag] |
Find all files containing a specific tag |
:PebbleLiveSearchTags [tag] |
Live search tags using telescope's live_grep (ultra-fast) |
:AddTag [tag] |
Short alias for PebbleAddTag |
:Tags |
Short alias for PebbleShowTags |
:FindTag [tag] |
Short alias for PebbleFindTag |
:LiveTags [tag] |
Short alias for PebbleLiveSearchTags |
<CR>- Follow link under cursor (opens HTTP/HTTPS links in browser, navigates to files for wiki/markdown links)<Tab>- Next link in buffer (supports all link types)<S-Tab>- Previous link in buffer (supports all link types)<Ctrl+t>or<leader>mx- Toggle markdown checklist/todo item<leader>mg- Toggle graph view<leader>mv- Toggle visual graph view<leader>mc- Create link, file and navigate (visual mode)<leader>ml- Create link and file without navigation (visual mode)<leader>mh- Initialize YAML header<leader>mta- Add tag to current file<leader>mts- Show tags in current file<leader>mtf- Find files with tag+- Increase heading level-- Decrease heading level
<leader>bo- Open current base view
When viewing a base:
j/korβ/β- Navigate rowsG- Go to last itemgg- Go to first item<CR>- Open selected filer- Refresh cacheqor<Esc>- Close view
Set global_keymaps = true in setup to enable:
<leader>mg- Toggle graph view<leader>mv- Toggle visual graph view<leader>mp- Go to previous in navigation history<leader>mn- Go to next in navigation history<leader>mB- List available bases<leader>mb- Open current base view
require('pebble').setup({
-- Automatically set up keymaps for markdown files
auto_setup_keymaps = true,
-- Set up global keymaps (disabled by default)
global_keymaps = false,
-- Completion configuration
completion = {
-- Enable nvim-cmp integration (auto-detected if not specified)
nvim_cmp = {
priority = 100,
max_item_count = 50,
trigger_characters = { "[", "(" },
},
-- Enable blink.cmp integration (auto-detected if not specified)
blink_cmp = {
priority = 100,
max_item_count = 50,
trigger_characters = { "[", "(" },
},
}
})Pebble provides intelligent completion for markdown files with three types of completions:
-
Wiki Link Completion (
[[file-name]])- Auto-completes file names when typing
[[ - Shows available markdown files in your project
- Uses ripgrep for fast file discovery
- Auto-completes file names when typing
-
File Path Completion (
[text](path))- Auto-completes file paths when typing
]( - Provides relative paths to markdown files
- Optimized for current directory context
- Auto-completes file paths when typing
-
Text Search Completion
- Searches content across all markdown files using ripgrep
- Triggered when typing 2+ character words
- Shows matching text with file context
- Fast File Discovery: Uses ripgrep for sub-second file enumeration
- Intelligent Caching: 30-second TTL cache for file lists and completions
- Context-Aware: Only activates in markdown files
- Minimal Resource Usage: Lazy-loaded modules and efficient search patterns
- Async Processing: Non-blocking operations for large repositories
- Smart Fallbacks: Graceful degradation when ripgrep is unavailable
- π Major Performance Improvements: 10-20x faster file discovery and bases loading
- β¨ Enhanced Completion System: Ultra-fast tag (
#), wiki link ([[), and markdown link ([) completion - β‘ Ripgrep Integration: All search operations now use ripgrep for maximum speed
- π§ Async Processing: Bases now load asynchronously with smart caching
- π οΈ Better Error Handling: Comprehensive diagnostics and recovery mechanisms
- π Monitoring Tools: Added diagnostic commands and performance monitoring
- π Configuration Flexibility: Support for both boolean and detailed table configurations
The plugin now supports both simple boolean and detailed table configurations:
-- Simple configuration (recommended)
completion = {
nvim_cmp = true, -- Enable nvim-cmp integration
blink_cmp = false, -- Disable blink.cmp
}
-- Advanced configuration (optional)
completion = {
nvim_cmp = {
enabled = true,
priority = 100,
max_item_count = 50,
},
blink_cmp = {
enabled = false,
},
}To disable automatic keymaps and set your own:
require('pebble').setup({
auto_setup_keymaps = false
})
-- Set custom keymaps
vim.keymap.set('n', 'gf', require('pebble').follow_link, { desc = 'Follow link' })
vim.keymap.set('n', '<leader>gg', require('pebble').toggle_graph, { desc = 'Toggle graph' })
vim.keymap.set('n', '<leader>gv', require('pebble').toggle_visual_graph, { desc = 'Toggle visual graph' })
vim.keymap.set('v', '<leader>cl', require('pebble').create_link_and_navigate, { desc = 'Create link and navigate' })
vim.keymap.set('v', '<leader>cf', require('pebble').create_link_and_file, { desc = 'Create link and file' })Enable global keymaps for non-markdown files:
require('pebble').setup({
global_keymaps = true -- Enables global keymaps for all file types
})[[wiki-style]]- Obsidian-style links[text](file.md)- Standard markdown links[text](https://url.com)- External URLs (opens in browser)
Pebble works excellently with markview.nvim and other markdown rendering plugins. The link navigation functionality is completely independent of how markdown is displayed, so you can enjoy beautiful rendered markdown while still having full Obsidian-style linking capabilities.
Create Obsidian-compatible database views from your markdown files using .base files. Fully compatible with Obsidian's bases feature introduced in 2025.
Note: Bases functionality uses Telescope for the UI. Make sure telescope.nvim is installed and configured.
Example base file (tasks.base):
# Filter which files to include
filters:
and:
- status != "done"
- status != "cancelled"
# Create computed properties
formulas:
days_until_due: 'due and tonumber(os.difftime(date(due), os.time()) / 86400) or nil'
priority_level: 'priority == "high" and "π΄" or priority == "medium" and "π‘" or "π’"'
status_icon: 'status == "todo" and "β³" or status == "in-progress" and "π" or "β
"'
# Display names for columns
display:
name:
displayName: "Task"
formula.status_icon:
displayName: "π"
formula.days_until_due:
displayName: "Days Left"
# Define views
views:
- type: table
name: "Active Tasks"
filters:
and:
- status != "done"
order:
- priority
- due
limit: 50Supported Features:
- Filters: Complex logical operations (
and,or,not) - Formulas: Dynamic computed properties with date math, conditionals, string operations
- Display Names: Custom column headers for better readability
- Views: Table view with sorting, filtering, and limits
- Functions:
date(),now(),if(),concat(),length(), and more - Obsidian Compatibility: Supports both old and new Obsidian filter syntax
- Create and Navigate: Select text, press
<leader>mcto create a[[link]], create the file, and navigate to it - Create Only: Select text, press
<leader>mlto create a[[link]]and the file without navigation - Smart Filename Cleaning: Removes invalid characters while preserving spaces and accents
- Duplicate Prevention: Checks for existing files before creating new ones
- History Tracking: Automatic back/forward navigation with
<leader>mp(previous) and<leader>mn(next) - Smart Link Jumping: Use
<Tab>and<Shift-Tab>to move between all link types (wiki, markdown, HTTP/HTTPS) - Fallback Behavior:
<CR>falls back to default behavior when not on a link
- Add Tags: Press
<leader>mtato add tags to the current file with autocompletion - View File Tags: Press
<leader>mtsto see all tags in the current file with telescope UI - Search by Tag: Press
<leader>mtfto find all files containing a specific tag - Live Search Tags: Use
:LiveTagsfor ultra-fast live search using telescope's live_grep - Smart Integration: Works with both frontmatter tags and inline
#tags - Ripgrep Optimization: Lightning-fast tag search across large repositories
- Short Commands: Use
:AddTag,:Tags,:FindTag, and:LiveTagsfor quick access
- Real-time Search: Type and see results instantly as you search
- Telescope Integration: Leverages your existing telescope live_grep configuration
- Context Preview: See tag occurrences in context with file previews
- Performance Optimized: Uses all CPU threads with memory mapping for speed
- Smart Case: Automatically handles case-sensitive/insensitive searching
- Visual Network: See all connected files in a clean, interactive interface
- Keyboard Navigation: Use
j/kor arrows to navigate,Enterto open files - Missing File Detection: Clearly shows which links point to non-existent files
- Performance Optimized: Cached results with smart invalidation
- Intelligent Caching: File discovery results are cached and invalidated automatically
- Git-Aware: Uses git root as the search base when available
- Limited Scanning: Prevents performance issues in large repositories (200 file limit)
- Graph Caching: Graph view results are cached with 5-second TTL
- Base Caching: Base queries are cached for fast repeated access
- Lazy Loading: Caches are built only when needed, not on startup
MIT