# code_runner.nvim: running and reloading code from Neovim without leaving the editor

> code_runner.nvim is a pure Lua Neovim plugin for running code by filetype, by project and by command, with output shown in a float, tab, split, terminal or quickfix list, and hot reload for long running processes. It can be configured in Lua or in JSON files that interoperate with the original VS Code code runner.

**CRAG666/code_runner.nvim** — Neovim plugin.The best code runner you could have, it is like the one in vscode but with super powers, it manages projects like in intellij but without being slow

- Repository: https://github.com/CRAG666/code_runner.nvim
- Stars: 697 · Forks: 39
- Language: Lua
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/crag666-code-runner-nvim

## Built by someone who wanted a run button in Neovim

The origin story is in the README and it explains the design. The author used VS Code in college with a single plugin that ran many programming languages, then moved to Neovim and found a pile of plugins he did not like, so he started bolting together autocommands to run code. That worked, he says, but it was lazy, and it worked only for people programming in one or three languages at most. So he wrote this plugin instead, and migrating his own commands was quick enough that it was mostly copy and paste. The pitch in the repository description is blunt, a code runner like the one in VS Code with more features, and it manages projects the way IntelliJ does without being slow. The audience is therefore narrow and specific: a Neovim user who came from a heavier editor and wants the run button back, plus the projects in that person's working life.

## Installation needs Neovim 0.10 and one of four managers

The requirement is Neovim 0.10 or newer, and the plugin is distributed for the four managers that cover almost every configuration. The native path uses the built-in package helper:

```lua
vim.pack.add("https://github.com/CRAG666/code_runner.nvim")
```

With lazy.nvim the plugin is a normal entry in the setup table:

```lua
require("lazy").setup({
  { "CRAG666/code_runner.nvim", config = true },
}
```

With packer.nvim it is a single use line:

```lua
use 'CRAG666/code_runner.nvim'
```

And with paq-nvim:

```lua
require "paq"{ 'CRAG666/code_runner.nvim'; }
```

The author also links his own configuration file, run_code.lua in his dotfiles repository, as a worked example. What matters for the choice of manager is startup cost. The README makes the point that the plugin already defers its internal modules and its JSON config, but lazy-loading on the commands and keys you actually use is described as the biggest win, and the example shows a cmd list containing RunCode, RunFile, RunProject, RunClose, CRFiletype and CRProjects.

## Filetype commands are shell snippets with $fileName placeholders

Configuration is either Lua through a setup function or JSON files, and the Lua form is the one to read first. Each filetype maps to a command string or a list of command fragments, with placeholders that the plugin substitutes:

```lua
require('code_runner').setup({
  filetype = {
    java = {
      "cd $dir &&",
      "javac $fileName &&",
      "java $fileNameWithoutExt"
    },
    python = "python3 -u",
    typescript = "deno run",
    rust = {
      "cd $dir &&",
      "rustc $fileName &&",
      "$dir/$fileNameWithoutExt"
    },
    c = "cd $dir && gcc $fileName -o /tmp/$fileNameWithoutExt && /tmp/$fileNameWithoutExt",
  },
})
```

The interesting detail is that a filetype can map to a list, which is how a compile-then-run sequence is expressed. The C entry shows the pattern in one line: compile into a temporary binary, then execute that binary. Nothing here is magic, it is a command template, and the plugin is responsible for the substitution and for choosing where to run it.

## JSON configuration for interoperability with the VS Code runner

The plugin can also be driven by JSON files, and the stated reason is interoperability with the original code runner plugin for VS Code by formulahendry. The Lua setup then points at the two files:

```lua
-- this is a config example
require('code_runner').setup {
  filetype_path = vim.fn.expand('~/.config/nvim/code_runner.json'),
  project_path = vim.fn.expand('~/.config/nvim/project_manager.json')
}
```

The warning attached to this section is the one worth remembering. A common mistake is using relative paths instead of absolute paths, and the plugin will not work in that case, so the recommendation is to use absolute paths, or something like vim.fn.expand('~/.config/nvim/project_manager.json') if you prefer short paths. The note also points out that if you want to change where the code is displayed, you have to set the mode attribute in the setup function, which is where the display style lives. The JSON route is a compatibility decision rather than a preference, and it is what lets a team share runner configuration between the two editors.

## Where the output goes: float, tab, split, terminal, tmux or quickfix

The output window is the part users argue about, and the plugin covers most of the options a Neovim user might already have. The feature list names running code in a float window, in a tab, in a split, with toggleTerm, in a split tmux pane using preservim/vimux, in a snacks.nvim terminal, and sending errors to the quickfix list like vim-dispatch does with mode set to quickfix. The toggle runner feature, which closes the previous runner and opens a new one, depends on the separate betterTerm.nvim plugin, and the README notes that this is the mode the author currently uses. Every run command allows a restart, so if a command has no hot reload you can call it again and the previous instance is closed and a new one started. That single behaviour removes the most common annoyance in this category of plugin, where a second run leaves two terminals open.

## Hot reload, hooks and project auto-detection

Three capabilities make the plugin more than a run button. Hot reload restarts a long running process when its files change, and there is a command to stop it, :CrStopHr, which the README marks as experimental and only available when hot_reload is true. Hooks let you attach behaviour to a run, for example previewing the result in a markdown file or enabling hot reload, and the feature list also covers assigning commands to projects whose files do not live in the project root. Projects are auto-detected from root files such as pom.xml, Cargo.toml and go.mod, or from a per-project .crproject.json file, and the plugin can run project commands in different modes on a per-project basis. The README also states the contribution rule plainly: if you want to implement a new feature, open an issue first to find out whether it is worth implementing and whether anyone is interested.

## The command set and the recommended mappings

The commands are few and their behaviour is documented tightly, which is what makes the plugin predictable. :RunCode runs based on the file type, first checking whether the file belongs to a project and then whether a filetype mapping exists, and it can take a key to execute a command from the current directory. :RunFile runs the current file and optionally takes a mode, :RunProject runs the current project and does nothing if you are not in one, and :RunClose closes the runner, although that does not work in better_term mode. :CRFiletype and :CRProjects open the corresponding JSON files and are only useful if you configured the plugin with JSON files. The recommended key mappings are given as Lua calls:

```lua
vim.keymap.set('n', '<leader>rr', ':RunCode<CR>', { noremap = true, silent = false })
vim.keymap.set('n', '<leader>rf', ':RunFile<CR>', { noremap = true, silent = false })
vim.keymap.set('n', '<leader>rft', ':RunFile tab<CR>', { noremap = true, silent = false })
vim.keymap.set('n', '<leader>rp', ':RunProject<CR>', { noremap = true, silent = false })
vim.keymap.set('n', '<leader>rc', ':RunClose<CR>', { noremap = true, silent = false })
```

The same operations are also exposed as Lua functions, including run_code, run_from_fn for running any command, run_filetype, run_project, run_close and get_filetype_command, which is useful when you want the command string rather than the execution.

## A small Lua codebase with no tagged releases

The repository layout is what you would expect for a single maintainer plugin, with lua, doc, tests, a .stylua.toml for formatting and an .editorconfig. The licence is MIT. What is missing is as informative as what is there: there are no GitHub releases for the repository, so there is no tagged version to pin in a plugin specification, and the last push was on 2026-08-20, a little over two months before this writing, so the work is current but unversioned. There is no changelog in the tree either. For a plugin this small that is a reasonable trade, since the surface is a handful of commands and a configuration table, but it does mean that if you depend on it you are tracking the main branch, and the way to see what changed is to read the commits or the documentation in the doc directory rather than to read release notes.

## Conclusion

code_runner.nvim fits a Neovim user who switched from an editor with a built-in run button and wants the same speed plus per-project commands, hot reload and output in whichever window style they already use. It does not fit someone who expects a debugger, a task runner with dependency graphs, or a language server integration, since it only launches commands. Before adopting it, read the configuration section, because the difference between the Lua setup and the JSON file setup is not cosmetic, and set the mode explicitly, since the default display of the output depends on that setting.

## FAQ

### How do I install code_runner.nvim?

It needs Neovim 0.10 or newer and can be installed with the native vim.pack.add, with lazy.nvim, with packer.nvim using use 'CRAG666/code_runner.nvim', or with paq-nvim. The README suggests lazy-loading on the commands you use, since the plugin already defers its internal modules.

### How do I configure a command for a filetype?

Pass a filetype table to the setup function, mapping each filetype to a command string or a list of fragments, with $dir, $fileName and $fileNameWithoutExt substituted at run time. A list is how a compile-then-run sequence is expressed.

### Where can the output of a run be displayed?

In a float window, a tab, a split, a toggleTerm terminal, a split tmux pane with vimux, a snacks.nvim terminal, or in the quickfix list for errors with mode set to quickfix. The toggle runner mode needs the betterTerm.nvim plugin.

### Does code_runner.nvim support hot reload and project detection?

Yes. Hot reload restarts long running processes and can be stopped with the :CrStopHr command, which the README marks as experimental. Projects are detected from root files such as pom.xml, Cargo.toml and go.mod, or from a per-project .crproject.json file.

## Sources

- [CRAG666/code_runner.nvim on GitHub](https://github.com/CRAG666/code_runner.nvim)
- [Issues](https://github.com/CRAG666/code_runner.nvim/issues)
- [License: MIT](https://github.com/CRAG666/code_runner.nvim/blob/main/LICENSE)
- [README](https://github.com/CRAG666/code_runner.nvim/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/crag666-code-runner-nvim
