Edit remote files in Neovim with full LSP and TreeSitter support. This plugin runs language servers directly on remote machines while keeping your editing experience completely local, giving you the best of both worlds: responsive editing with full language features.
Note
Why this approach wins: You get instant keystrokes and cursor movement (local editing) combined with accurate code intelligence that understands your entire remote project (remote LSP). No more choosing between responsiveness and functionality.
The key insight: Instead of running language servers locally (which lack remote project context) or editing remotely (which has network latency), this plugin runs language servers on the remote machine while keeping file editing completely local.
Local Neovim ←→ SSH ←→ Remote Language Server
(fast editing) (full project context)
Here's what happens when you open a remote file:
- Fetch once: Download the remote file to a local buffer for instant editing
- Connect LSP: Start the language server on the remote machine with full project access
- Bridge communication: Translate LSP messages between your local Neovim and remote server
- Save asynchronously: File changes sync back to the remote machine in the background
- Enable TreeSitter: Syntax highlighting works immediately on the local buffer
This gives you zero-latency editing with full LSP features like code completion, go-to-definition, and error checking.
- Passwordless SSH access to your remote server:
ssh user@host
(should work without password) - Plugin installed and configured (see Installation section below)
-
Open a remote file:
:RemoteOpen rsync://user@host//path/to/file.cpp
-
Or browse remote directories:
:RemoteTreeBrowser rsync://user@host//path/to/folder/
Use
j/k
to navigate,Enter
to open files,q
to quit. -
Verify it works:
- You should see syntax highlighting immediately
- LSP features (completion, hover, go-to-definition) should work within seconds
- File saves happen automatically in the background
-
Run TUI applications remotely:
:RemoteTui htop " System monitor :RemoteTui lazygit " Git interface (https://github.com/jesseduffield/lazygit) :RemoteTui "tail -f app.log" " Log monitoring
Use
Ctrl+H
to hide sessions,:RemoteTui
(no args) to restore them.
That's it! The plugin handles the rest automatically.
- 🧠 Full LSP Support - Code completion, go-to-definition, hover documentation, and error checking work seamlessly
- ⚡ Zero-latency Editing - All keystrokes and cursor movements happen instantly on local buffers
- 🎨 TreeSitter Syntax Highlighting - Immediate syntax highlighting without network delays
- 💾 Smart Auto-save - Files sync to remote machines asynchronously without blocking your workflow
- 👁️ File Change Detection - Automatically detects when remote files are modified by others with conflict resolution
- 📁 Remote File Explorer - Tree-based directory browsing with familiar navigation
- 🔍 Enhanced Search - Telescope integration for searching remote buffers and file history
- 📚 Session History - Track and quickly reopen recently used remote files and directories
Ready-to-use configurations for popular language servers:
✅ Fully Supported & Tested:
- C/C++ (clangd) - Code completion, diagnostics, go-to-definition
- Python (pylsp) - Full IntelliSense with linting and formatting
- Rust (rust-analyzer) - Advanced Rust language features
- Lua (lua_ls) - Neovim configuration and scripting support
- CMake (cmake-language-server) - Build system integration
- XML (lemminx) - Markup language support
🟡 Available But Not Tested:
- Zig (zls), Go (gopls), Java (jdtls)
- JavaScript/TypeScript (tsserver), C# (omnisharp)
- Python (pyright), Bash (bashls)
Note
If you find that desired LSP is not listed here, try testing it out, if it works (or not), open a GitHub issue and we can get it added to this list with the correct status
- Automatic Server Management - Language servers start automatically on remote machines
- Smart Path Translation - Seamless handling of local vs remote file paths for LSP
- Robust Error Recovery - Graceful handling of network issues and connection problems
- Neovim >= 0.10.0
- nvim-lspconfig
- OpenSSH client
- Python 3
- rsync
- SSH server
- Language servers for your programming languages
- Python 3
- rsync
- find (for directory browsing)
- grep (for remote file searching)
Platform | Support |
---|---|
Linux | ✅ Full |
macOS | ✅ Full |
Windows | 🟡 WSL recommended |
Using lazy.nvim
{
"inhesrom/remote-ssh.nvim",
branch = "master",
dependencies = {
"inhesrom/telescope-remote-buffer", --See https://github.com/inhesrom/telescope-remote-buffer for features
"nvim-telescope/telescope.nvim",
"nvim-lua/plenary.nvim",
"neovim/nvim-lspconfig",
-- nvim-notify is recommended, but not necessarily required into order to get notifcations during operations - https://github.com/rcarriga/nvim-notify
"rcarriga/nvim-notify",
},
config = function ()
require('telescope-remote-buffer').setup(
-- Default keymaps to open telescope and search open buffers including "remote" open buffers
--fzf = "<leader>fz",
--match = "<leader>gb",
--oldfiles = "<leader>rb"
)
-- setup lsp_config here or import from part of neovim config that sets up LSP
require('remote-ssh').setup({
on_attach = lsp_config.on_attach,
capabilities = lsp_config.capabilities,
filetype_to_server = lsp_config.filetype_to_server
})
end
}
Using packer.nvim
use {
'inhesrom/remote-ssh.nvim',
branch = "master",
requires = {
"inhesrom/telescope-remote-buffer",
"nvim-telescope/telescope.nvim",
"nvim-lua/plenary.nvim",
'neovim/nvim-lspconfig',
},
config = function()
require('telescope-remote-buffer').setup()
-- setup lsp_config here or import from part of neovim config that sets up LSP
require('remote-ssh').setup({
on_attach = lsp_config.on_attach,
capabilities = lsp_config.capabilities,
filetype_to_server = lsp_config.filetype_to_server
})
end
}
For seamless remote development, you need passwordless SSH access to your remote servers:
# Generate SSH key if you don't have one
ssh-keygen -t ed25519 -C "[email protected]"
# Copy key to remote server
ssh-copy-id user@remote-server
# Test passwordless connection
ssh user@remote-server
You'll need to configure LSP servers for the plugin to work properly. Here's a basic setup:
- Create an LSP utility file (e.g.,
lsp_util.lua
):
-- lsp_util.lua
local M = {}
-- LSP on_attach function with key mappings
M.on_attach = function(client, bufnr)
local nmap = function(keys, func, desc)
vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc })
end
-- Key mappings
nmap('gd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition')
nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
nmap('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation')
nmap('K', vim.lsp.buf.hover, 'Hover Documentation')
nmap('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
nmap('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction')
end
-- LSP capabilities
local capabilities = vim.lsp.protocol.make_client_capabilities()
M.capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
-- Server definitions
M.servers = {
clangd = {}, -- C/C++
rust_analyzer = {}, -- Rust
pylsp = {}, -- Python
lua_ls = {}, -- Lua
-- Add more servers as needed
}
-- Generate filetype to server mapping
M.filetype_to_server = {}
for server_name, _ in pairs(M.servers) do
local filetypes = require('lspconfig')[server_name].document_config.default_config.filetypes or {}
for _, ft in ipairs(filetypes) do
M.filetype_to_server[ft] = server_name
end
end
return M
- Use Mason for automatic local LSP management/installation:
Note
You will need to manually ensure that the corresponding remote LSP is installed on the remote host
-- In your plugin configuration
{
'williamboman/mason.nvim',
dependencies = { 'williamboman/mason-lspconfig.nvim' },
config = function()
require('mason').setup()
require('mason-lspconfig').setup({
ensure_installed = vim.tbl_keys(require('lsp_util').servers),
})
end
}
Install the required language servers on your remote development machines:
# On remote server
pip3 install python-lsp-server[all]
# Optional: for better performance
pip3 install python-lsp-ruff # Fast linting
# Ubuntu/Debian
sudo apt install clangd
# CentOS/RHEL/Rocky
sudo dnf install clang-tools-extra
# macOS
brew install llvm
# Arch Linux
sudo pacman -S clang
# Install via rustup (recommended)
rustup component add rust-analyzer
# Or via package manager
# Ubuntu 22.04+: sudo apt install rust-analyzer
# macOS: brew install rust-analyzer
# Arch: sudo pacman -S rust-analyzer
# Ubuntu/Debian (if available in repos)
sudo apt install lua-language-server
# macOS
brew install lua-language-server
# Or install manually from releases:
# https://github.com/LuaLS/lua-language-server/releases
# Install Java first
sudo apt install openjdk-17-jdk # Ubuntu
brew install openjdk@17 # macOS
# jdtls will be automatically downloaded by Mason
# Install via pip
pip3 install cmake-language-server
# Or via package manager
sudo apt install cmake-language-server # Ubuntu 22.04+
Ensure your remote systems have the following:
# Check Python 3 availability
python3 --version
# Check rsync availability
rsync --version
# Verify SSH server is running
systemctl status ssh # Ubuntu/Debian
systemctl status sshd # CentOS/RHEL
# Test SSH access
ssh user@remote-server "echo 'SSH working'"
Here's a default configuration with comments explaining each option:
require('remote-ssh').setup({
-- Optional: Custom on_attach function for LSP clients
on_attach = function(client, bufnr)
-- Your LSP keybindings and setup
end,
-- Optional: Custom capabilities for LSP clients
capabilities = vim.lsp.protocol.make_client_capabilities(),
-- Custom mapping from filetype to LSP server name
filetype_to_server = {
-- Example: Use pylsp for Python (default and recommended)
python = "pylsp",
-- More customizations...
},
-- Custom server configurations
server_configs = {
-- Custom config for clangd
clangd = {
filetypes = { "c", "cpp", "objc", "objcpp" },
root_patterns = { ".git", "compile_commands.json" },
init_options = {
usePlaceholders = true,
completeUnimported = true
}
},
-- More server configs...
},
-- Async write configuration
async_write_opts = {
timeout = 30, -- Timeout in seconds for write operations
debug = false, -- Enable debug logging
log_level = vim.log.levels.INFO,
autosave = true, -- Enable automatic saving on text changes (default: true)
-- Set to false to disable auto-save while keeping manual saves (:w) working
save_debounce_ms = 3000 -- Delay before initiating auto-save to handle rapid editing (default: 3000)
}
})
The plugin includes an intelligent autosave feature that automatically saves remote files as you edit them. This feature is enabled by default but can be customized or disabled:
Enable autosave (default behavior):
require('remote-ssh').setup({
async_write_opts = {
autosave = true, -- Auto-save on text changes
save_debounce_ms = 3000 -- Wait 3 seconds after editing before saving
}
})
Disable autosave while keeping manual saves working:
require('remote-ssh').setup({
async_write_opts = {
autosave = false -- Disable auto-save, but `:w` still works
}
})
Note: Manual saves (:w
, :write
) always work regardless of the autosave setting. When autosave is disabled, you'll need to manually save your changes using :w
or similar commands.
# In your terminal
nvim rsync://user@remote-host/path/to/file.cpp
Or from within Neovim:
:e rsync://user@remote-host/path/to/file.cpp
:RemoteOpen rsync://user@remote-host/path/to/file.cpp
:RemoteTreeBrowser rsync://user@remote-host/path/to/directory
With telescope-remote-buffer, you get additional commands for managing remote buffers:
Default keymaps (configurable during setup as shown above):
<leader>fz
- Fuzzy search remote buffers<leader>gb
- Browse remote buffers<leader>rb
- Browse remote oldfiles
The plugin includes an intelligent file watching system that monitors remote files for changes made by other users or processes. This helps prevent conflicts and keeps your local buffer synchronized with the remote file state.
- Automatic Detection: When you open a remote file, the file watcher automatically starts monitoring it
- Change Detection: Uses SSH to periodically check the remote file's modification time (mtime)
- Smart Conflict Resolution: Distinguishes between changes from your own saves vs. external changes
- Conflict Handling: When conflicts are detected, you'll be notified and can choose how to resolve them
- No Conflict: Remote file hasn't changed since your last interaction
- Safe to Pull: Remote file changed, but you have no unsaved local changes - automatically pulls the remote content
- Conflict Detected: Both local and remote files have changes - requires manual resolution
You can configure the file watcher behavior for each buffer, if you find the defaults are not working for you:
" Set poll interval to 10 seconds
:RemoteWatchConfigure poll_interval 10000
" Enable auto-refresh (automatically pull non-conflicting changes)
:RemoteWatchConfigure auto_refresh true
" Disable file watching for current buffer
:RemoteWatchConfigure enabled false
The file watcher supports SSH config aliases, allowing you to use simplified hostnames:
# ~/.ssh/config
Host myserver
HostName server.example.com
User myuser
Port 2222
Then use in Neovim:
:RemoteOpen rsync://myserver-alias//path/to/file.cpp
Note the double slash (//
) format which is automatically detected and handled.
The plugin includes a comprehensive session history feature that tracks all your remote file and directory access, providing quick navigation to recently used items.
- 🎨 File Type Icons: Shows proper file type icons with colors (using nvim-web-devicons if available)
- 📌 Pin Favorites: Pin frequently used sessions to keep them at the top
- 🔍 Smart Filtering: Filter sessions by filename or hostname
- 💾 Persistent Storage: History persists across Neovim sessions
- 📁 Mixed Content: Tracks both individual files and directory browsing sessions
- ⚡ Fast Navigation: Quickly jump to any previously accessed remote location
:RemoteHistory
Opens a floating window with your session history where you can:
- Navigate: Use
j/k
or arrow keys to move through sessions - Open: Press
Enter
orSpace
to open the selected session - Pin/Unpin: Press
p
to pin or unpin sessions - Filter: Press
/
to enter filter mode, then type to search - Exit: Press
q
orEsc
to close the picker
Each session shows: [PIN] [TIME] [HOST] [ICON] [PATH] [(pinned)]
Example:
▶ 📌 12/04 14:30 myserver /home/user/config.lua (pinned)
12/04 14:25 myserver 📁 /home/user/project
12/04 14:20 devbox 🐍 /app/main.py
12/04 14:15 myserver 📝 /home/user/README.md
Sessions are automatically tracked when you:
- Open remote files using
:RemoteOpen
or:e rsync://...
- Browse remote directories using
:RemoteTreeBrowser
- Use any command that opens remote content
- Storage: Sessions saved to
~/.local/share/nvim/remote-ssh-sessions.json
- History Limit: Default 100 entries (configurable)
- Window Size: Dynamically sized to fit content (minimum 60x10, maximum available screen space)
- Auto-save: Changes saved immediately and on Neovim exit
Benefits: Run and manage multiple TUI applications (htop, lazygit, yazi, even nvim) on remote machines with session persistence and instant switching. Hide/restore sessions without losing state, perfect for multitasking across different remote tools.
The plugin includes a powerful TUI session management system that lets you run terminal applications on remote servers with full session control - think tmux-like functionality integrated directly into Neovim.
- 🎯 Session Multiplexing: Run multiple TUI apps per remote host simultaneously
- ⚡ Hide/Restore: Use
Ctrl+H
to hide sessions, restore instantly from picker - 🎨 Visual Session Picker: Colorful interface showing app, host, directory, and timestamp
- 💾 State Preservation: Hidden sessions maintain their full state and scrollback
- 🗑️ Session Cleanup: Delete unwanted sessions with confirmation
Create a TUI session:
:RemoteTui htop " Run htop on current remote host
:RemoteTui lazygit " Run lazygit for git operations
:RemoteTui "tail -f app.log" " Monitor log files
Manage sessions:
- Hide current session: Press
Ctrl+H
while in any TUI session - Open session picker: Run
:RemoteTui
(no arguments) - Navigate picker: Use
j/k
or arrow keys to select sessions - Restore session: Press
Enter
orSpace
on selected session - Delete session: Press
d
theny
to confirm deletion
The picker shows sessions in this format: [TIME] APP @ HOST:DIRECTORY
Example display:
▶ [12/25 14:30] htop @ myserver.com:~/projects
[12/25 14:25] lazygit @ devbox:~/repo
[12/25 14:20] tail @ production:/var/log
With remote buffer open: Automatically uses the current buffer's connection info Without remote buffer: Prompts for connection details:
- Enter
user@host
format (e.g.,[email protected]
) - Specify remote directory (defaults to
~
)
" Monitor system resources
:RemoteTui htop
" Work with git (hide when done)
:RemoteTui lazygit
<Ctrl+H>
" Check logs while coding
:RemoteTui "tail -f /var/log/app.log"
<Ctrl+H>
" Switch between sessions
:RemoteTui
" Use picker to restore any session
💡 Pro tip: Each remote host can run multiple concurrent TUI sessions. Use descriptive commands like :RemoteTui "htop -d 1"
to distinguish similar tools with different options.
Primary Commands | What does it do? |
---|---|
:RemoteOpen |
Open a remote file with scp:// or rsync:// protocol |
:RemoteTreeBrowser |
Browse a remote directory with tree-based file explorer |
:RemoteTreeBrowserHide |
Hide the remote file browser |
:RemoteTreeBrowserShow |
Show the remote file browser |
:RemoteTui [app] |
Run TUI application on remote host (with args) or show session picker (no args) |
:RemoteHistory |
Open remote session history picker with pinned items and filtering |
:RemoteGrep |
Search for text in remote files using grep |
:RemoteRefresh |
Refresh a remote buffer by re-fetching its content |
:RemoteRefreshAll |
Refresh all remote buffers |
Remote History Commands | What does it do? |
---|---|
:RemoteHistory |
Open session history picker with pinned items and filtering |
:RemoteHistoryClear |
Clear remote session history |
:RemoteHistoryClearPinned |
Clear pinned remote sessions |
:RemoteHistoryStats |
Show remote session history statistics |
File Watcher Commands | What does it do? |
---|---|
:RemoteWatchStart |
Start file watching for current buffer (monitors remote changes) |
:RemoteWatchStop |
Stop file watching for current buffer |
:RemoteWatchStatus |
Show file watching status for current buffer |
:RemoteWatchRefresh |
Force refresh from remote (overwrite local changes) |
:RemoteWatchConfigure |
Configure file watcher settings (enabled, poll_interval, auto_refresh) |
:RemoteWatchDebug |
Debug file watcher SSH connection and commands |
Debug Commands | What does it do? |
---|---|
:RemoteLspStart |
Manually start LSP for the current remote buffer |
:RemoteLspStop |
Stop all remote LSP servers and kill remote processes |
:RemoteLspRestart |
Restart LSP server for the current buffer |
:RemoteLspSetRoot |
Manually set the root directory for the remote LSP server, override automatic discovery |
:RemoteLspServers |
List available remote LSP servers |
:RemoteLspDebug |
Print debug information about remote LSP clients |
:RemoteLspDebugTraffic |
Enable/disable LSP traffic debugging |
:RemoteFileStatus |
Show status of remote file operations |
:AsyncWriteCancel |
Cancel ongoing asynchronous write operation |
:AsyncWriteStatus |
Show status of active asynchronous write operations |
:AsyncWriteForceComplete |
Force complete a stuck write operation |
:AsyncWriteDebug |
Toggle debugging for async write operations |
:AsyncWriteLogLevel |
Set the logging level (DEBUG, INFO, WARN, ERROR) |
:AsyncWriteReregister |
Reregister buffer-specific autocommands for current buffer |
:RemoteDependencyCheck |
Check all plugin dependencies (local tools, Neovim, Lua modules, SSH hosts) |
:RemoteDependencyQuickCheck |
Quick dependency status overview with summary |
:TSRemoteHighlight |
Manually enable TreeSitter highlighting for remote buffers |
The plugin includes a comprehensive dependency checking system to help diagnose setup issues and ensure all required components are properly installed and configured.
For a rapid overview of your system status:
:RemoteDependencyQuickCheck
This provides a simple ✅/
For detailed diagnostics and troubleshooting:
:RemoteDependencyCheck
This performs a thorough check of:
Local Machine:
- ✅ System Tools:
ssh
,scp
,rsync
,python3
,stat
- ✅ Neovim Version: >= 0.10.0 requirement
- ✅ Lua Dependencies:
plenary.nvim
,nvim-lspconfig
,telescope.nvim
(optional),nvim-notify
(optional)
Remote Hosts:
- 🔗 SSH Connectivity: Tests passwordless SSH access and response times
- 🛠️ Remote Tools:
python3
,rsync
,find
,grep
,stat
,ls
- 📡 Auto-discovery: Automatically finds hosts from
~/.ssh/config
You can check specific hosts instead of auto-discovery:
" Single host
:RemoteDependencyCheck myserver
" Multiple hosts
:RemoteDependencyCheck server1,server2,server3
The dependency checker provides color-coded results:
- ✅ Green: Component is properly installed and working
⚠️ Yellow: Optional component missing or minor issues- ❌ Red: Critical dependency missing - plugin won't work properly
Each failed dependency includes:
- Detailed error messages
- Version information where available
- Specific recommendations for fixing the issue
The dependency checker will identify issues like:
- Missing
rsync
(prevents RemoteOpen from working) - SSH connectivity problems (timeouts, authentication failures)
- Missing Neovim plugins (
plenary.nvim
,nvim-lspconfig
) - Outdated Neovim version
- Missing remote tools needed for directory browsing
- SSH configuration problems
💡 Pro tip: Run :RemoteDependencyCheck
after initial setup to ensure everything is configured correctly, and whenever you encounter issues with RemoteOpen or RemoteTreeBrowser.
Before diving into specific troubleshooting steps, always start with the dependency checker:
:RemoteDependencyCheck
This will identify most common setup issues including missing dependencies, SSH configuration problems, and plugin installation issues.
Symptoms: No LSP features (completion, hover, etc.) in remote files
Solutions:
-
Check if language server is installed on remote:
ssh user@server "which clangd" # Example for clangd ssh user@server "which rust-analyzer" # Example for rust-analyzer
-
Verify Mason installation locally:
:Mason :MasonLog
-
Check LSP client status:
:LspInfo :RemoteLspDebug
-
Enable LSP debug logging:
:RemoteLspDebugTraffic on :LspLog
Symptoms: "Connection refused", "Permission denied", or timeout errors
Solutions:
-
Test basic SSH connectivity:
ssh user@server
-
Check SSH key authentication:
ssh-add -l # List loaded keys ssh user@server "echo SSH key auth working"
-
Verify SSH config:
# Add to ~/.ssh/config Host myserver HostName server.example.com User myuser IdentityFile ~/.ssh/id_ed25519
-
Check remote SSH server status:
ssh user@server "systemctl status sshd"
Symptoms: Files won't open, save, or refresh
Solutions:
-
Check file permissions:
ssh user@server "ls -la /path/to/file"
-
Verify rsync availability:
ssh user@server "rsync --version"
-
Test file operations manually:
rsync user@server:/path/to/file /tmp/test-file
-
Check async write status:
:AsyncWriteStatus :RemoteFileStatus
Symptoms: "Python not found" or proxy connection errors
Solutions:
-
Check Python 3 on remote:
ssh user@server "python3 --version" ssh user@server "which python3"
-
Verify proxy script permissions:
ls -la ~/.local/share/nvim/lazy/remote-ssh.nvim/lua/remote-lsp/proxy.py
-
Check proxy logs:
ls -la ~/.cache/nvim/remote_lsp_logs/
Symptoms: No autocomplete suggestions in remote files
Solutions:
-
Check nvim-cmp configuration:
:lua print(vim.inspect(require('cmp').get_config()))
-
Verify LSP client attachment:
:LspInfo
-
Check LSP server capabilities:
:lua print(vim.inspect(vim.lsp.get_clients()[1].server_capabilities))
Symptoms: File watcher shows "not a remote buffer" or doesn't detect changes
Solutions:
-
Check if file watcher is running:
:RemoteWatchStatus
-
Test SSH connection manually:
:RemoteWatchDebug
-
Verify SSH config alias setup:
# Test SSH config alias ssh myserver "echo 'SSH alias working'"
-
Check file watcher logs:
:AsyncWriteDebug # Enable debug logging :AsyncWriteLogLevel DEBUG
-
Restart file watcher:
:RemoteWatchStop :RemoteWatchStart
Symptoms: File watcher causing UI blocking or performance issues
Solutions:
-
Increase poll interval:
:RemoteWatchConfigure poll_interval 10000 # 10 seconds
-
Check for SSH connection multiplexing:
# Add to ~/.ssh/config Host * ControlMaster auto ControlPath ~/.ssh/control-%r@%h:%p ControlPersist 10m
# LSP Debugging
:RemoteLspDebug # Show remote LSP client information
:RemoteLspServers # List available LSP servers
:RemoteLspDebugTraffic on # Enable LSP traffic debugging
:LspInfo # Show LSP client information
:LspLog # View LSP logs
# File Operation Debugging
:RemoteFileStatus # Show remote file operation status
:AsyncWriteStatus # Show async write operation status
:AsyncWriteDebug # Toggle async write debugging
# File Watcher Debugging
:RemoteWatchStatus # Show file watcher status for current buffer
:RemoteWatchDebug # Test SSH connection and debug file watcher
:RemoteWatchStart # Start file watching for current buffer
:RemoteWatchStop # Stop file watching for current buffer
# Dependency Checking
:RemoteDependencyCheck # Comprehensive dependency check with detailed report
:RemoteDependencyQuickCheck # Quick dependency status check
# General Debugging
:checkhealth # General Neovim health check
:Mason # Open Mason UI for server management
:MasonLog # View Mason installation logs
-
Use SSH connection multiplexing:
# Add to ~/.ssh/config Host * ControlMaster auto ControlPath ~/.ssh/control-%r@%h:%p ControlPersist 10m
-
Configure SSH keep-alive:
# Add to ~/.ssh/config Host * ServerAliveInterval 60 ServerAliveCountMax 3
-
Optimize rsync transfers:
# For large files, consider compression Host myserver Compression yes
- Language servers must be installed on the remote machine
- SSH access to the remote machine is required
- Performance depends on network connection quality
- For very large projects, initial LSP startup may take longer
- SSH Config: Using SSH config file entries can simplify working with remote hosts
- Language Servers: Ensure language servers are properly installed on remote systems
- Project Structure: For best results, work with proper project structures that language servers can recognize
- Network: A stable network connection improves the overall experience
While mounting remote directories (via SSHFS, etc.) is a valid approach, it has several drawbacks:
- Network latency affects every file operation
- Syncing large projects can be time-consuming
- Language servers running locally might not have access to the full project context
This plugin runs language servers directly on the remote machine where your code lives, providing a more responsive experience with full access to project context.
Neovim's built-in remote file editing doesn't provide LSP support. This plugin extends the built-in functionality by:
- Enabling LSP features for remote files
- Providing asynchronous file saving
- Handling the complexities of remote path translation for LSP
- Adding TreeSitter support for syntax highlighting
- Providing commands for browsing and searching remote directories
-
remote-nvim.nvim (https://github.com/amitds1997/remote-nvim.nvim) - The most VS Code Remote SSH-like solution:
- Automatically installs and launches Neovim on remote machines
- Launches headless server on remote and connects TUI locally
- Can copy over and sync your local Neovim configuration to remote
- Supports SSH (password, key, ssh_config) and devcontainers
- Limitations: Plugin has not yet reached maturity with breaking changes expected
- Network latency inherent to the headless server + TUI approach
- Remote server may not be able to access generic internet content in some controlled developement environments
-
distant.nvim (https://github.com/chipsenkbeil/distant.nvim) - Theoretically addresses latency:
- Alpha stage software in rapid development and may break or change frequently
- Requires distant 0.20.x binary installation on both local and remote machines
- Requires neovim 0.8+
- Limitations: Limited documentation and setup complexity; experimental status makes it unreliable for production use
-
This remote-ssh.nvim (https://github.com/inhesrom/remote-ssh.nvim):
- Uses SSH for all file operations
- Syncs buffer contents locally to eliminate editing lag
- Only requires language server installation on remote (supports clangd for C++, pylsp for Python)
- Includes tree-based remote file browser (
:RemoteTreeBrowser
) - Focused on simplicity and immediate usability
- Limitations: Plugin has not yet reached maturity with breaking changes expected
The key trade-off is between feature completeness (remote-nvim.nvim) and responsiveness (this plugin's local buffer approach).
Contributions are welcome! Please read CONTRIBUTING.md for guidelines.
- Report bugs via GitHub Issues
- Submit feature requests
- Contribute code via Pull Requests
- Improve documentation
If you feel so inclined, out of appreciation for this work, send a coffee my way! Buy Me a Coffee Link
This project is licensed under the MIT License - see the LICENSE file for details.