Run.nvim is a lightweight Neovim plugin that combines
dired-do-shell-command
and compile.
Select files in a file explorer and run shell commands on them, or run from a regular buffer as a quick compile/run prompt.
You can simply select files (by placing your cursor on the line, or visual-select a list of files), call the plugin and run commands on those files
2025-05-16.00-00-42.mp4
- Why Run.nvim
- Installation
- Quick Start
- User Commands and Keymaps
- Features
- Configuration
- Using with Other File Browsers
- Command Placeholders
- Default Actions
- Documentation
- Contributing
- License
Run.nvim gives you a simple command prompt for files: select entries in a file browser, or run directly from a regular buffer like a compile command.
It helps by:
- Suggesting sensible default commands based on file type
- Executing commands without leaving your editor
- Running commands in the directory open in the browser (independent of
cwd) - Showing async output in Neovim and supporting sync runs
- Supporting placeholders for quick command entry (Command Placeholders)
Using lazy.nvim
{
"guptaanurag2106/run.nvim",
config = function()
require("run").setup({})
end,
}Using packer.nvim
use {
"guptaanurag2106/run.nvim",
config = function()
require("run").setup({})
end
}- Navigate to a file in your file browser (oil.nvim by default)
- For background execution with live output in a new buffer, use
:RunFile - Press
:RunFileSyncto run the appropriate command for that file type synchronously - Use
:RunLastto re-run the last executed command in the same cwd - Use
:RunStopto stop the current running async command - You can also run
:RunFilefrom a regular buffer as a quick compile-style prompt Note::RunFileuses a small custom input UI by default. You can fallback tovim.ui.inputby settinguse_custom_ui = falsein the setup options.
The plugin creates four user commands RunFile, RunFileSync, RunLast, RunStop. No keymaps are however
created and it's left to the user. An example keymap could be as simple as
vim.keymap.set({ "v", "n" }, "<leader>rf", ":RunFile<CR>", { desc = "(Run.nvim) Run Async" })
vim.keymap.set({ "v", "n" }, "<leader>rs", ":RunStop<CR>", { desc = "(Run.nvim) Stop job" })- Quick File Detection:
- Retrieves the full path of the file or directory under the cursor with ease.
- Predefined Commands:
- Offers a set of ready-to-use commands like tar extraction, chmod +x, xdg-open, and more.
- Custom Actions:
- The plugin suggests a default command, you can change it by typing your own command (after the
[Run (Default: <cmd>) on <file>]:and making use of (Command Placeholders).
- The plugin suggests a default command, you can change it by typing your own command (after the
- Flexible Execution:
- Choose to run commands synchronously, asynchronously and populate the qflist with the output
- Output Window
- Unbuffered output of asynchronous commands can be seen in a new popup window which opens at the bottom
- It supports
qto close,<C-c>to stop command execution, and<CR>on a highlightedfile:linespan to jump to that location - Matched
file:line:colspans are underlined to indicate they are clickable; stderr output can be highlighted full-line red (configurable) - The buffer is reused if multiple
:RunFileare started
- History
- If you provide a command other than default, it is saved to history and is suggested from then onwards for that filetype
- History is stored as JSON in your
stdpath('data')by default. The plugin keeps up to 10 entries per command key.
- Populating Quickfix List
- Based on the config, the quickfix list is automatically parsed and populated which can be opened via trouble.nvim or just
:copen. - On non-zero exit (command failure), the plugin auto-jumps to the first error via
:cfirstfor a:make-like experience. - Supports a wide range of compiler/tool output formats: generic
file:line:col,file:linepatterns, GCC, Python, Java, Lua, Go, Bash, OCaml, Valgrind, and GNU Make errors. - Filename validation rejects false positives (flags, numeric tokens, brackets, etc.) so normal output lines don't clutter the quickfix list.
- Based on the config, the quickfix list is automatically parsed and populated which can be opened via trouble.nvim or just
- CWD Fallback Scope
- If the active file browser cannot provide cwd, Run.nvim uses
cwd_fallback_scope. globaluses Neovim cwd (vim.fn.getcwd()).bufferuses the current file directory for normal file buffers and falls back toglobalfor special or temporary buffers.
- If the active file browser cannot provide cwd, Run.nvim uses
Run.nvim works out of the box, but you can customize it to fit your workflow:
require("run").setup({
-- File browser to use (default: "oil")
current_browser = "oil",
-- Ask for confirmation before executing commands
ask_confirmation = true,
-- Use custom input UI instead of vim.ui.input
use_custom_ui = true,
-- open_cmd, default is auto-detected based on OS
open_cmd = nil,
-- Auto-populate quickfix list with command output for sync commands
populate_qflist_sync = false,
-- Auto-populate quickfix list with command output for async commands
populate_qflist_async = true,
-- Auto-open quickfix list with command output for sync commands
open_qflist_sync = false,
-- Auto-open quickfix list with command output for async commands
open_qflist_async = false,
-- Focus output window after run: "never" | "on_error" | "always"
focus_output = "never",
-- Highlight full stderr lines red in the output buffer (default: false)
-- When false, only the matched file:line:col span is highlighted.
highlight_stderr_full = false,
-- Enable command history
history = {
enable = true,
history_file = vim.fn.stdpath("data") .. require("run.utils").path_separator .. "run.nvim.json"
},
-- UI settings for custom input window
ui = {
border = "none",
prompt_hl = "Constant",
},
-- Command to open the output window
output_window_cmd = "botright 15split",
-- Fallback cwd scope when browser cwd lookup fails
-- "global": use Neovim cwd (vim.fn.getcwd())
-- "buffer": use current file directory for normal file buffers
cwd_fallback_scope = "global",
-- Customize default actions for specific file types
default_actions = {
-- Example: custom Python command
[".py"] = {
command = "python %f",
description = "Run Python module"
},
-- Add your own commands here
},
action_function = function(file_list, curr_dir)
-- return <cmd>, <requires_completion>
if #file_list == 1 and file_list[1] == "Makefile" then
return "make -B", false
end
local has_go_marker = false
local only_go_project_files = #file_list > 0
for _, file in ipairs(file_list) do
if file == "go.mod" or file == "go.sum" then
has_go_marker = true
elseif not file:match("%.go$") then
only_go_project_files = false
end
end
if has_go_marker and only_go_project_files then
return "go run .", false
end
return nil, false
end
})Run.nvim works with oil.nvim by default, but you can use it with any file browser:
-- Example: Integration with nvim-tree
require("run").register("nvim-tree", "get_current_files", function(range, bufnr)
-- range is a table {line1: int, line2:int} representing range of selected text
-- range[line1]=range[line2]=current line if user in normal mode
-- bufnr is the buffer number of the file browser
-- Return list of selected file names in nvim-tree
-- Implementation depends on nvim-tree API
return {"file1.txt", "file2.py"}
end)
require("run").register("nvim-tree", "get_current_dir", function(bufnr)
-- bufnr is the buffer number of the file browser
-- Return current directory path in nvim-tree
return "/path/to/directory"
end)
-- Set nvim-tree as current browser
require("run").set_current_browser("nvim-tree")Run.nvim uses a simple placeholder system for paths:
%f- All file/folder names, space-separated%d- Current directory path%1,%2, etc. - Individual file/folder names (includes extension)%d/%f- Full paths for all files%%- Literal % character (For commands that need things like %1, sed for e.g.){open}- System-specific open command
Placeholder notes:
- Escape percent by using
%%when you need a literal%in the final command. - If no placeholder is detected, the plugin appends full file paths to the end of the command.
Run.nvim comes with sensible defaults for common file types:
-
Python (
.py):python %f -
Bash/Shell (
.sh,.bash): Executes scripts -
Archives (
.tar.gz,.zip): Extracts to current directory -
Go (
.go):go run %f -
Rust (
.rs):rustc %f -o a.out && ./a.out -
Zig (
.zig):zig run %f -
JavaScript/TypeScript (
.js,.ts): Runs with Node.js/ts-node -
Java (
.java,.jar): Compiles and runs Java files or runs JARs -
C/C++ (
.c,.cpp): Compiles source files and runsa.out -
Markdown (
.md): Converts to HTML with pandoc -
JSON/CSV: Pretty-prints JSON with
jqor displays CSV withcolumn -
Media (
.mp4,.mp3): Opens with VLC -
Web/PDF (
.html,.pdf): Opens in default viewer/browser -
Special Types
- no_extension: Default suggestion is
chmod +x %f - dir: Default suggestion is to create a
.tar.gz - exe: Runs the file (e.g.,
./%1) - multiple: Suggestion is to create a
.tar.gzfor all selected items - default: Suggestion is to open it (auto-detects
open,xdg-open, orstart)
- no_extension: Default suggestion is
You can override any of these or add your own in the configuration.
- Neovim >= 0.10 (required for
vim.system) — older versions may not support sync commands.
- Default browser integration is
oil.nvim; other file explorers require a small adapter function. - Long running commands are better handled by async mode; synchronous runs use
vim.systemand are blocking. - The quickfix parser assumes "filename:line:col:message" patterns; unusual compiler output may not parse perfectly.
- The plugin tries to auto-detect an OS-specific
opencommand (xdg-open,open,start), but behavior depends on system PATH.
For complete documentation, run :help run.nvim in Neovim after installation.
MIT