Skip to content

TryDying/RemoteMirror.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

remote_mirror

remote_mirror is a minimal Neovim plugin for editing remote files through a local mirror backed by rsync over ssh.

Features

  • Mirror root under: stdpath('cache') .. '/remote-mirror/<target_id>/rootfs'
  • Session state under: stdpath('data') .. '/remote-mirror'
  • Pseudo-root mapping:
    • Remote /home/u/p/a.lua
    • Local <rootfs>/home/u/p/a.lua
  • Sync entire project on :RemoteMirrorConnect via rsync
  • Open a remote file via :RemoteMirrorEdit (after project sync it should be local already; fallback pull still exists)
  • Auto-push on BufWritePost with debounce and serialized rsync execution
  • Optional URI input: rssh://host//abs/path

Install

Place this repository in your runtimepath (or install with your plugin manager).

Then call setup:

require("remote_mirror").setup({
  debounce_ms = 400,
  -- By default we DO NOT expose legacy aliases (:RemoteConnect/:RemoteEdit/...)
  -- enable_legacy_commands = true,

  -- Ignore rules for project sync (rsync exclude patterns)
  -- These required ignores are ALWAYS applied:
  --   .git/  .root/  .opencode/  .sisyphus/
  -- `ignore` adds more patterns on top (union).
  -- ignore = { "build/" },
  -- use_gitignore = true,

  -- Pull behavior
  -- pull_mode = "full",      -- "full" | "lazy"
  -- lazy_pull_mode = "dir",  -- "dir" | "file" (used when pull_mode="lazy")

  -- Lazy mode UX
  -- When enabled (default), remote_mirror will build a placeholder tree on connect
  -- so file explorers can show the full project structure without pulling contents.
  -- lazy_index = true,

  -- Bidirectional sync
  -- When true, pushes do not overwrite newer remote files.
  -- bidirectional = true,

  -- Optional periodic pull (off by default)
  -- auto_pull = false,
  -- auto_pull_interval_ms = 5000,

  -- Skip transferring files larger than this (human readable)
  -- max_file_size = "50m",   -- e.g. "2k", "1m", "10g", "off"

  -- Rsync tuning
  -- rsync_compress = false,        -- adds: -z
  -- rsync_bwlimit = nil,           -- adds: --bwlimit=<rate> (number or string)
  -- rsync_resume = false,          -- adds: --partial/--partial-dir/--delay-updates (pull+push)

  -- Progress UI for long-running pull operations.
  -- When enabled, remote_mirror streams rsync stderr and uses `--info=progress2`.
  -- A small spinner is shown until the first progress update arrives.
  -- progress_ui = true,

  -- ssh_args defaults to key-based auth and a short timeout:
  -- { "-o", "BatchMode=yes", "-o", "ConnectTimeout=5" }
  -- ssh_args = { "-o", "BatchMode=yes", "-o", "ConnectTimeout=10" },
})

Vimscript globals (g:RMC_*)

All of the options above can also be configured via vim.g variables set before setup(). Globals have lower precedence than setup({ ... }) options.

let g:RMC_IgnoreFiles = ["build/"]
let g:RMC_UseGitignore = 1
let g:RMC_MaxFileSize = "50m"      " case-insensitive, supports k/m/g/t
let g:RMC_PullMode = "lazy"        " full|lazy
let g:RMC_LazyPullMode = "dir"     " dir|file
let g:RMC_LazyIndex = 1            " build placeholder tree on connect (lazy mode)
let g:RMC_Bidirectional = 1
let g:RMC_AutoPull = 0
let g:RMC_AutoPullIntervalMs = 5000
let g:RMC_RsyncCompress = 0
let g:RMC_RsyncBwlimit = "5m"       " or a number (KB/s)
let g:RMC_RsyncResume = 0
let g:RMC_ProgressUI = 1

Commands

  • :RemoteMirrorConnect {host} {remote_root} [target_id] (remote_root should be a directory; if you pass a file path, it will connect to its parent dir and open that file)
  • :RemoteMirrorEdit {/abs/path | rel/path | rssh://host//abs/path}
  • :RemoteMirrorStatus
  • :RemoteMirrorExec {remote shell command}
  • :RemoteMirrorPull (pull entire project)
  • :RemoteMirrorPullDir {/abs/dir|rel/dir} (pull a directory subtree)
  • :RemoteMirrorIndex (index remote tree; creates placeholder files/dirs in local mirror)
  • :RemoteMirrorBrowse (browse remote files; uses telescope.nvim if available)
  • :RemoteMirrorDiff [/abs/path|rel/path] (diff local mirror vs remote content)

Legacy aliases (:RemoteConnect, :RemoteEdit, :RemoteStatus, :RemoteExec) are kept for backwards compatibility but disabled by default.

Example

:RemoteMirrorConnect devbox /home/u/project
:RemoteMirrorEdit lua/main.lua
" Or: :RemoteMirrorEdit /home/u/project/lua/main.lua

After saving the buffer, the file is pushed back to devbox automatically.

Notes

  • :RemoteMirrorConnect validates connectivity by running ssh and checking that rsync, tar, and remote_root exist on the remote.
  • The default ssh_args uses BatchMode=yes (no interactive password prompts). Set up SSH keys or override ssh_args.
  • rsync is invoked with argument vectors (no local shell) and --protect-args.
  • For push, remote parent directories are created using:
    • --rsync-path=mkdir -p '<escaped-dir>' && rsync
    • When rsync_resume=true, remote partial dirs are also created:
      • --rsync-path=mkdir -p '<escaped-dir>' '<escaped-dir>/.rsync-partial' && rsync
  • Remote paths with NUL or newline are rejected.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages