Library / SDK
Vigemus/iron.nvim avatar
Vigemus/iron.nvim

iron.nvim, where every Lua example after the install snippet stops mid-statement

Interactive Repl Over Neovim. What is iron.nvim Iron allows you to quickly interact with the repl without having to leave your work buffer It both a plugin and a library, allowing for better user experience and extensibility at the same time.

1,373 stars110 forksLuaBSD-3-Clause

At a glance

What is it?
A Neovim plugin and library for talking to a REPL without leaving the work buffer. Its three configuration examples are all syntactically incomplete, and its Makefile has a single target that runs nvim with no config at all.
Who is it for?
iron.nvim fits a Neovim user who wants a REPL reachable without leaving the current buffer and who is willing to reconstruct the closing braces that the examples leave off. It does not fit someone who needs copy-pasteable configuration, an alternative plugin-manager path, or a test suite that exercises a real editor setup.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Lua, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • Vigemus/iron.nvim1,373 ★ · +17
Star history
Repository2026-07-282026-11-13
Vigemus/iron.nvim1.4k1.4k

17 Stars in the last 108 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The GitHub description is the README opening, typo included

The repository's one-line description was not written for search results. It is the README heading followed by its first two paragraphs, run together: What is iron.nvim, then Iron allows you to quickly interact with the repl without having to leave your work buffer, then It both a plugin and a library, allowing for better user experience and extensibility at the same time.

The third fragment has no verb in it, which is the sort of error that only appears when text has been copied rather than composed. That is what sits in the repository header and in every search result quoting it.

The other metadata fields are thinner. There is no homepage value and there are no GitHub releases. The default branch is master rather than main, which matters if you write a fetch rule or pin against it. The project was last pushed to on 2026-09-15, with 1364 stars, 111 forks, and 55 open issues.

Every Lua fence after the install snippet stops mid-construct

The install snippet is complete. Everything after it is not. The configuration example opens iron.setup, descends through config and repl_definition into a python entry, sets command, format, and block_dividers, and then the fence closes with the table still open:

lua
local iron = require("iron.core")
local view = require("iron.view")
local common = require("iron.fts.common")

iron.setup {
  config = {
    -- Whether a repl should be discarded or not
    scratch_repl = true,

The splits example ends on a comment fragment, -- They'l. The floats example ends after return 20 with no end keyword. Three consecutive examples, three different stopping points, and no closing braces, no end, and no balanced table anywhere after the install block.

The practical effect is that the names are the documentation. You can see which functions exist, which keys exist, and what shape their arguments take, and you cannot paste any of the three. Copying the first into a config file gives you a syntax error at the end of the file rather than at the line you got wrong.

vim.pack is the only install path and no minimum version is given

One install command is offered, and it uses Neovim's built-in package manager:

lua
vim.pack.add({
  {
    src = "https://github.com/Vigemus/iron.nvim",
  }
}
)

Beside it, the text adds that you can use the plugin manager of your choice. No other manager is named and no snippet for one appears. There is no lazy.nvim block, no packer configuration, no rockspec, and no luarocks line anywhere on the page.

So the single concrete recipe depends on vim.pack existing in your Neovim build, and no minimum Neovim version is stated in the repository metadata, on the page, or in the files available here. If your editor predates vim.pack, there is no fallback to read, and the phrase plugin manager of your choice leaves the wiring entirely to you.

scratch_repl decides whether a repl is discarded, and its default is unstated

Settings sit under a config table inside iron.setup, not at the top level. The first key shown is scratch_repl, set to true, carrying the comment Whether a repl should be discarded or not. One boolean decides whether starting a repl throws the old one away, and the example turns it on.

The page does not say what the value is when the key is absent, so the behaviour of an unconfigured install is something you find out by trying. Depth is part of what the examples teach too: every one of them repeats the config level before the individual keys, rather than placing them beside it.

The second key is repl_definition, and that is where the repls live. Two are shown. sh runs zsh. python runs python3, or ipython with --no-autoindent, and adds two more fields: a format function taken from iron.fts.common, and block_dividers listing both spellings of the Python cell marker, "# %%" and "#%%".

command can be a function, which is how a repl reads the current buffer

A repl command is normally a table of arguments. It can also be a function, and that form receives a meta table:

lua
iron.setup{
  config = {
    repl_definition = {
      -- custom repl that loads the current file
      haskell = {
        command = function(meta)
          local filename = vim.api.nvim_buf_get_name(meta.current_bufnr)
          return { 'cabal', 'v2-repl', filename}
        end
      }
    }
  },
}

The example uses it to build a Haskell repl that loads the file being edited. It reads the buffer name out of meta.current_bufnr with vim.api.nvim_buf_get_name and appends it after cabal and v2-repl, so the arguments are decided at the moment the repl starts, from the buffer you are standing in.

Which makes the function form more than a convenience for assembling argument lists. It is the hook that lets a repl definition depend on editor state, and this is the only field of meta the page shows.

view.center with a function gets called twice, once per dimension

Window placement goes through one key, repl_open_cmd. For splits the page shows a plain Vim command as its value, vertical botright 80 split, and notes that the default Vim commands can always be used directly. Around that sits a fluent style built on a metatable, accepting vertical, leftabove or aboveleft, rightbelow or belowright, topleft, and botright, written the way you would write the command itself.

Floats get three functions: view.top with a percentage, view.center with either one or two arguments, and view.center with a function. One argument sets both dimensions, two set them separately:

lua
repl_open_cmd = view.center(function(vertical)
-- Useless function, but it will be called twice,
-- once for each dimension (width, height)
  if vertical then
    return 50
  end
  return 20

That last shape is the one to watch. The callback is handed a boolean saying which axis it is being asked about, and it runs once per dimension, so anything with a side effect happens twice. The example says so in its own comment, and the block stops after return 20 without the end that would close it.

The Makefile has one target and it runs nvim with no config

The root listing is .github/, .gitignore, .luarc.json, LICENSE, Makefile, README.md, doc/, lua/, and tests/. The Makefile holds a single phony target:

make
.PHONY: test

test:
	NVIM_APPNAME=nvim-iron-test \
	nvim --headless \
		-u NONE \
		-l tests/init.lua

One verb, test. There is no lint target, no build target, no documentation target, and no way to run the suite against a chosen editor version or a chosen configuration. The recipe sets NVIM_APPNAME to nvim-iron-test, launches nvim headless, passes -u NONE so that no configuration file is loaded, and hands control to tests/init.lua through -l.

So the test path cannot tell you how iron behaves inside your own setup. A .luarc.json sits at the root for the Lua language server, but there is no formatter configuration in the tree and no lint command in the Makefile to use it.

Editorial conclusion

iron.nvim fits a Neovim user who wants a REPL reachable without leaving the current buffer and who is willing to reconstruct the closing braces that the examples leave off. It does not fit someone who needs copy-pasteable configuration, an alternative plugin-manager path, or a test suite that exercises a real editor setup. Before you commit, open the three lua fences and finish them yourself, find out what scratch_repl defaults to when you do not set it, and read your own configuration for the keys the page shows, because nothing in the repository tells you what happens when they are missing.

Frequently asked questions

What is iron.nvim and what does it do in Neovim?

It is a Neovim plugin and library for interacting with a REPL without leaving the work buffer. Repl definitions go under config.repl_definition inside iron.setup, and window placement is set through the repl_open_cmd key.

How do I install iron.nvim?

With vim.pack.add, passing src set to the GitHub URL for Vigemus/iron.nvim. The page adds that the plugin manager of your choice also works, but names no other manager and states no minimum Neovim version.

How do I run the iron.nvim tests?

Through the single test target in the Makefile, which sets NVIM_APPNAME to nvim-iron-test and runs nvim headless with -u NONE and -l tests/init.lua. Because of -u NONE no user configuration is loaded, so the recipe cannot exercise your own setup.

How do I open an iron.nvim REPL in a floating window?

Set repl_open_cmd to view.top with a percentage, or to view.center with one or two arguments. A function passed to view.center is called once per dimension with a boolean telling it which axis it is sizing, so it runs twice.

Official sources

  1. Official README
  2. Project repository
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vigemus-iron-nvim.svg)](https://hysenlabs.com/projects/vigemus-iron-nvim)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/vigemus-iron-nvim.svg)](https://hysenlabs.com/projects/vigemus-iron-nvim)

Was this useful?