Skip to content

About

Local-first AI grammar checker and writing assistant for Neovim. Private, offline grammar and fluency suggestions from an on-device LLM, powered by Refine for macOS.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Repository files navigation

Refine icon

Refine.nvim

A local-first AI grammar checker and writing assistant for Neovim, powered by Refine.

macOS 14 or newer Neovim 0.11 or newer MIT license

Refine is an AI grammar checker powered by a local language model, so it can run entirely offline. This plugin brings its contextual grammar and fluency suggestions to Neovim, helping you improve your writing without leaving your editor.

Features:

  • Private, offline checks powered by a local LLM on your device
  • Native highlights and floating cards for reviewing changes in context
  • Clear explanations of why each change is suggested

Requirements

  • macOS 14+
  • Neovim 0.11+
  • Refine 1.35+

Refine is free to use for grammar and fluency checks, with no account or credit card required.

Quick Start

1. Install and set up Refine

Install Refine with Homebrew:

brew install --cask refine

You can also download Refine for Mac directly.

2. Install refine.nvim

Choose one of the following installation methods. No setup() call is required.

Option 1: With lazy.nvim

Add refine.nvim to your lazy.nvim plugin spec:

{
  "refine-sh/refine.nvim",
}

Option 2: Without a plugin manager

Alternatively, clone the plugin into Neovim's native package directory:

mkdir -p ~/.local/share/nvim/site/pack/refine/start
git clone --filter=blob:none https://github.com/refine-sh/refine.nvim \
  ~/.local/share/nvim/site/pack/refine/start/refine.nvim

3. Start writing

Restart Neovim if it was already open, then open a supported prose buffer while Refine is running. Automatic Checks are enabled by default, so suggestions appear after you pause while editing.

Use :RefineCheck whenever you want an immediate manual check. An explicit check can launch Refine in the background without stealing focus. Passive buffer activity never launches the app.

Recommended mappings

The plugin installs no permanent key mappings. These mappings cover the common review workflow:

vim.keymap.set({ "n", "x" }, "<leader>rc", "<Plug>(RefineCheck)")
vim.keymap.set("n", "<leader>rs", "<Plug>(RefineShow)")
vim.keymap.set("n", "]r", "<Plug>(RefineNext)")
vim.keymap.set("n", "[r", "<Plug>(RefinePrevious)")
vim.keymap.set("n", "<leader>ra", "<Plug>(RefineApply)")

Record custom Apply and Dismiss combinations in Refine's Shortcuts settings, such as Option+Right Arrow or Control+Option+K. Combinations are synchronized when both Refine and this plugin support them; older versions keep the previous single-key bindings shown in Refine. Command combinations require Neovide; terminal frontends and ambiguous control-key aliases may be unavailable.

Refine also records held modifier combinations and modifier double-taps. These gestures cannot be observed through Neovim's input path, so the plugin displays an unavailable message and installs no fallback mapping. Use the existing Refine commands or explicit action mappings instead.

When the configured Apply key cannot be intercepted by Neovim, the activation tip says Apply shortcut unavailable. The card explains how to configure another Apply key in Refine or add the Neovim mapping above. Refine does not remap the key automatically.

The Check mapping supports Normal and Visual mode. Characterwise and linewise Visual selections preserve their exact endpoints. Blockwise selections are not supported.

See Advanced configuration for every available <Plug> target and card mapping.

Commands

Command Action
:[range]RefineCheck Check the buffer or the complete sentences touched by a line range.
:RefineShow Open and focus the suggestion under the cursor, or focus its open preview.
:RefineNext / :RefinePrevious Move through suggestions, opening and focusing each card. Navigation wraps.
:RefineApply Apply the open suggestion, or the suggestion under the cursor.
:RefineDismiss Dismiss the open suggestion, or the suggestion under the cursor.
:RefineExplain Request an explanation for the current suggestion.
:RefineReport Send feedback about the current suggestion when available.
:RefineClose Close the card without applying or dismissing the suggestion.
:RefineStatus Show the current integration state.

A plain click on an underlined suggestion also opens and focuses its card. Every card opens focused, so a, d, e, r, and q act immediately; the cursor stays on the suggestion and closing the card returns focus to it.

Checking status in your statusline

Refine can show check progress in your statusline. It never rewrites 'statusline' for you, so add its component to your own.

1. Add the component to your config

Put this in your Neovim config, usually ~/.config/nvim/init.lua:

vim.o.statusline = "%f %m%r%=%{v:lua.require'refine'.statusline()} %l:%c"

That is a complete statusline showing the file name, the Refine component, and the cursor position. If you already have a statusline you like, copy just the %{v:lua.require'refine'.statusline()} part into it.

Using lualine? Add it as a component instead:

require("lualine").setup({
  sections = {
    lualine_x = {
      { function() return require("refine").statusline() end },
      "encoding", "fileformat", "filetype",
    },
  },
})

2. Restart Neovim and write

Open a Markdown or text file and type a sentence. As Refine checks it, the component moves through these states:

Text Meaning
Refine … Connecting to Refine.
Refine 3/7 Checking, showing progress reported by Refine.
Refine 5 Check complete, with the number of suggestions.
Refine ! Refine is unavailable.
Refine · Waiting for the next check.

The component is intentionally empty in any buffer Refine is not checking, so an unsupported filetype shows nothing at all. If it stays empty, or you want custom wording and icons instead of this text, see Advanced configuration.

Supported writing formats

Markdown, plain text, Git commit messages, email, TeX, and LaTeX are enabled by default. You can add another Neovim filetype or disable a default through advanced configuration.

Only ordinary, editable, valid UTF-8 buffers within the configured size limit are eligible. Refine never changes file format or end-of-line settings.

Local AI and privacy

The plugin sends a complete canonical snapshot of each eligible buffer to the local Refine app. When Refine uses a downloaded local model, that source and the model response stay on your Mac. Once downloaded, the model continues working offline.

Refine can also use a provider you connect. Those requests go directly from your Mac to that provider and may include the source, so that provider's terms and privacy practices apply. Downloads, updates, optional license services, and hosted providers still require an internet connection.

The Neovim plugin connects only to the local Refine app through a same-UID Unix-domain socket using Refine's current per-launch token. This boundary excludes network clients and other OS users, but it does not identify a specific plugin or protect against another process already running as you. The plugin makes no direct network, telemetry, analytics, or update-check requests. Persistent diagnostics are off by default; when enabled for troubleshooting, they retain only bounded, redacted metadata and never source, diffs, explanations, launch tokens, or provider credentials.

:RefineReport is a separate, explicit feedback action. Only when you invoke it, the Refine app may send original and revised excerpts plus suggestion, model, language, custom-instruction, Refine-version, and macOS-version context to Refine's feedback service.

Read How Refine works, the offline grammar checker guide, and the privacy policy for full details.

Protocol compatibility and support

Integration Protocol 1.0 is a supported public API that third-party writing-host clients may implement. Refine for Neovim requires the exact 1.0 wire contract. Refine maintains exact Protocol 1.0 compatibility throughout the Refine 1.x release line.

The supported production profile connects a conforming writing-host client to the shipping Refine server on the same Mac and as the same OS user, with Refine already running. Network transports, cross-user access, and third-party production servers are outside that profile. Technical conformance is self-assessed and does not imply certification or endorsement.

A protocol mismatch stops before source is sent and reports the exact local and remote versions. Because version ordering does not identify which component should change, the diagnostic asks for a compatible app-and-plugin pair without inferring an update direction.

Troubleshooting

Run the built-in health check:

:checkhealth refine

It checks the Neovim version and macOS platform, plugin configuration, local endpoint permissions, protocol compatibility, frontend detection, action-key support, integration state, and the optional debug-log path.

:RefineStatus provides a shorter view of the current buffer state. If no suggestions appear, first confirm that Refine is running, Automatic Checks are enabled, and the current filetype is supported.

Documentation

  • Advanced configuration covers filetypes, buffer overrides, mappings, statusline integration, frontend detection, and diagnostics.
  • :help refine is the complete public interface reference.
  • Contributing covers development setup, tests, module boundaries, and documentation synchronization.
  • Changelog records user-visible changes.

License

MIT

About

Local-first AI grammar checker and writing assistant for Neovim. Private, offline grammar and fluency suggestions from an on-device LLM, powered by Refine for macOS.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages