# Firenvim: Turn Chrome and Firefox Textareas Into Neovim Buffers

> Firenvim is a browser extension plus Neovim plugin that replaces any focused textarea with a real Neovim instance. It is powerful for people who already live in Neovim, and awkward for everyone else.

**glacambre/firenvim** — Embed Neovim in Chrome, Firefox & others.

- Repository: https://github.com/glacambre/firenvim
- Stars: 6,140 · Forks: 159
- Language: TypeScript
- License: GPL-3.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/glacambre-firenvim

## The problem Firenvim solves: editing long text in a textarea

Browser textareas are the worst place to write anything long. You get no modal editing, no macros, no registers, and whatever keybindings the site itself has installed. Firenvim's answer is not to emulate Vim in JavaScript. It hides the textarea and mounts a Neovim instance inside an iframe appended to the page's DOM. The README describes the interaction in three steps: click a textarea, the textarea is replaced by Firenvim, and `:w` writes the Neovim buffer back into the now hidden textarea. `:q` closes the overlay and returns you to the page.

The target user is narrow and specific. If your init.lua is already tuned, if you know which of your plugins behave in a small frame, and if the text you write in a browser is worth more than the friction of an overlay, Firenvim is a direct fit. If you use Vim occasionally, or you want the site's own editor to keep working, the trade is bad: you lose the page's editor entirely for as long as the overlay is open. The README's own framing is blunt about scope. Firefox and Chrome are specifically supported; Brave, Vivaldi, Opera and Arc should work but are not specifically tested; Safari does not, because it does not support WebExtensions.

## How Firenvim connects a browser iframe to a real Neovim process

The architecture is visible in the repository layout and package.json. The extension side is TypeScript under src/, bundled by webpack, with msgpack-lite in the dependency list for the wire format and ws for a WebSocket transport. The Neovim side is Lua and VimScript under autoload/, lua/ and plugin/. A browser extension cannot spawn a process directly, so the extension talks to something running on the machine, and the README's permission list confirms the mechanism: it asks to exchange messages with programs other than Firefox, which it says is "necessary in order to be able to start Neovim instances."

Each buffer gets a generated name built from the page, not from a file on disk. The README points at the toFileName function in src/utils/utils.ts and gives the shape as `domainname_page_selector.txt`. That naming is the hook for per-site configuration: an autocmd matching `github.com_*.txt` can set the filetype for GitHub buffers, and `:buffers` shows you the current name. Firenvim also signals its presence in two ways. It sets `g:started_by_firenvim`, and it fires the `UIEnter` autocmd, whose event carries a channel you can inspect with `nvim_get_chan_info` and match on a client named "Firenvim". `UILeave` fires on disconnect. Those two hooks are the clean way to change options only inside the embedded instance.

The practical consequence of this design is that Firenvim is not a sandbox. Your real configuration loads, your real plugins run, and anything slow in your init.lua delays the overlay. That is the point, and it is also the cost.

## Installing Firenvim and editing your first textarea

Firenvim installs in two halves: a Neovim plugin, then a browser addon. The README says to read SECURITY.md before installing anything. With lazy.nvim, the plugin spec carries a build step that runs the post-install script:

```lua
{ 'glacambre/firenvim', build = ":call firenvim#install(0)" }
```

With vim-plug, the same call goes in the `do` key:

```vim
Plug 'glacambre/firenvim', { 'do': { _ -> firenvim#install(0) } }
```

If you manage plugins some other way, install it as usual and then run the headless command the README gives:

```sh
nvim --headless "+call firenvim#install(0) | q"
```

What that call does is register the native messaging manifests so the browser can reach Neovim. The repository's package.json exposes the same step as an npm script, `install_manifests`, which runs `nvim --headless -u NORC -i NONE -n -c ":set rtp+=." -c "call firenvim#install(1)" -c "quit"`; the argument differs from the user-facing instructions, so treat the README as the source of truth for normal installs. There is also a Dockerfile that builds the extension in a `node:lts-alpine` stage and exports `/firenvim/target`, which is aimed at building rather than at day-to-day use.

The second half is the addon: Mozilla's store or Google's, per the README. After that, click any textarea. If nothing appears where you expected, the README says to press `<C-e>`, the default manual trigger. That keybinding is configurable in `about:addons` on Firefox or `chrome://extensions/shortcuts` on Chrome. To turn Firenvim off in one tab without uninstalling, click the Firenvim button next to the URL bar, or bind a browser shortcut for the same action.

## The permission model is the real adoption decision

Firenvim asks for two permissions, and the README explains why rather than hiding them. Access to your data for all websites is needed to append the Neovim iframe to the DOM. Exchanging messages with programs other than Firefox is needed to start Neovim instances. Neither is optional for the core feature, and neither can be narrowed to a site list without breaking the premise that any textarea works.

So the honest framing is this: the extension has read access to page content across the web by design, and it opens a channel from the browser to a process on your machine. The README's response is a security document and an invitation to email the maintainer if you find a way to compromise it. That is a reasonable posture for a project of this shape, but it does not change what you are agreeing to. If your threat model says no extension gets all-sites access, Firenvim is out, regardless of how good the editing experience is. If you are fine with that class of extension, the remaining question is whether the overlay is better than the editor you are replacing.

## Configuring Firenvim per site with vim.g.firenvim_config

Global tuning happens through a dictionary named `vim.g.firenvim_config` in init.lua, with the keys "globalSettings" and "localSettings". The README explains that `localSettings` maps JavaScript patterns matched against the full URL to settings applied to every URL that pattern matches. When more than one pattern matches, the one with the highest "priority" value wins. The README truncates the worked example and defers the individual settings and their possible values to a later subsection, so the exact set of keys is not something you can learn from the top of the file alone. Plan on reading the full configuration section before writing a config you intend to keep.

The per-buffer naming gives you a second, more surgical lever. Because buffers are named `domainname_page_selector.txt`, an autocmd on `BufEnter` with a pattern like `github.com_*.txt` can set options for one site without touching anything else. This is often the better tool than `localSettings`, because it reuses the same autocmd machinery you already understand and it composes with filetype plugins. The `g:started_by_firenvim` flag and the `UIEnter` client check cover the other common need: turning off UI elements such as the statusline only inside the embedded instance. The README's example sets `laststatus` to 0 when Firenvim started Neovim and 2 otherwise.

One newer option is worth knowing about. With Neovim nightly builds from 2023-02-17 or later, the README says you can use `$NVIM_APPNAME` to give Firenvim a completely separate configuration, provided the variable is set appropriately when you run `firenvim#install()`. That is the cleanest way to keep a minimal, fast config for the browser while your terminal Neovim stays heavy.

## Where Firenvim fails, and what to use instead

The clearest failure mode is the one the README addresses with a single sentence: if you selected an element where you expected the frame and it did not appear, press `<C-e>`. Sites with custom editors, contenteditable regions, or shadow DOM do not always behave like a plain textarea, and the manual trigger is the documented workaround rather than a fix. There is a TROUBLESHOOTING.md at the repository root, which is where you should look when the overlay never appears at all, for example because the native messaging manifest was not registered or the addon cannot reach Neovim.

Safari is a hard no. The README states it does not support WebExtensions, so no amount of configuration will help. Other Chromium-based browsers are in a softer category: expected to work, not specifically tested, which means bugs you hit there may not be bugs the project tracks.

The genuine alternative is a keyboard layer rather than an editor swap. Vimium, which shows up in the searches around this project, leaves the page's own input elements intact and adds Vim-style navigation and hints on top. The difference in approach is total. Firenvim hands your text to a separate process with your real configuration and writes it back on `:w`; Vimium never leaves the page and never gives you ex commands, registers, or your plugins. If what you want is to stop reaching for the mouse, Vimium is the smaller commitment. If what you want is your actual Neovim, including macros and `:normal`, only Firenvim's model delivers that. Neovide and Goneovim, also in the surrounding searches, are standalone GUIs for Neovim and do not touch the browser at all, so they are not substitutes for this problem.

## Licence, upgrade cost, and what the repository tells you about maintenance

Firenvim is GPL-3.0, stated in package.json and shipped as LICENSE.md. That matters most if you plan to redistribute a modified extension or bundle it into something else; the copyleft terms attach to derivative distributions. Using it as an end user does not raise that question. Nothing here is legal advice, and the licence text is the authority.

The release history is uneven in a way worth noting. Version 0.2.17 arrived on 2026-05-08, after 0.2.16 on 2024-04-28 and 0.2.15 on 2023-08-12. The last push to the default branch was on 2026-09-12, so the repository is not dormant, but the tagged releases are not a steady drumbeat either. Practically, that means you should not expect a fix on a schedule; you should expect to pin a version and read the changelog between them. Upgrading is not just a plugin update, because the install step registers native messaging manifests that the browser depends on. Re-run the post-install call after updating, exactly as on first install:

```sh
nvim --headless "+call firenvim#install(0) | q"
```

If you skip that step, the plugin code and the manifests can drift apart, which is the kind of breakage that looks like a browser problem and is not. Building from source is possible and documented in CONTRIBUTING.md; package.json shows the toolchain, including webpack, web-ext and a jest suite with separate firefox and chrome targets. That is a real test setup, not a stub, but it is also a second thing to maintain if you go the source route.

## Conclusion

Adopt Firenvim if you already run Neovim daily and write long text in browser textareas, and you accept an extension that asks for access to your data on all websites plus the ability to exchange messages with other programs. Do not adopt it if you want a Vim keybinding layer that leaves the page's own editor in place, or if you cannot install a Neovim plugin at all; Vimium-style tools and browser-native editors fit those cases better. Before installing, read SECURITY.md as the README instructs, confirm your Neovim version against the $NVIM_APPNAME note, and check TROUBLESHOOTING.md for the case where a click on a textarea produces no overlay.

## FAQ

### Is Neovim really better than Vim?

Firenvim's own documentation does not compare the two editors. What it does say is that Firenvim embeds a Neovim instance in the browser, so the editor you get in a textarea is Neovim, configured by your own init.lua.

### Is Neovim actually worth learning?

The repository does not make that argument. It assumes you already use Neovim: Firenvim installs as a Neovim plugin, runs `firenvim#install(0)`, and loads your existing configuration, including plugins, into the browser overlay.

### Which is better in 2026, Vim or Neovim?

The README does not answer this. It is worth noting that Firenvim's configuration examples target Neovim specifically, using `vim.g.firenvim_config`, `vim.api.nvim_create_autocmd` and `nvim_get_chan_info`, and the README points to an outdated VimScript readme from an older commit.

### Why should you use Neovim?

Firenvim's README does not give general reasons to use Neovim. Its stated purpose is narrower: to turn your browser into a Neovim client, so that clicking a textarea replaces it with a Neovim instance and `:w` writes the buffer back.

## Sources

- [glacambre/firenvim on GitHub](https://github.com/glacambre/firenvim)
- [Issues](https://github.com/glacambre/firenvim/issues)
- [License: GPL-3.0](https://github.com/glacambre/firenvim/blob/master/LICENSE)
- [README](https://github.com/glacambre/firenvim/blob/master/README.md)
- [Releases](https://github.com/glacambre/firenvim/releases)

---

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