ALE (dense-analysis/ale): asynchronous linting in Vim and Neovim
Check syntax in Vim/Neovim asynchronously and fix files, with Language Server Protocol (LSP) support
At a glance
- What is it?
- ALE lints buffers while you type using Vim 8.2 and Neovim 0.7.0 job control, and doubles as a Language Server Protocol client. It is a good fit if you want diagnostics without a Python or Node runtime behind your editor.
- Who is it for?
- Adopt ALE if you want linting in Vim or Neovim without adding a Python or Node dependency to your editor, and you are willing to install the linters themselves yourself. Skip it if you want one language server configuration to drive every editor feature, or if you cannot install command line tools on the machines where you edit.
- Can I use it commercially?
- Yes. BSD-2-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 39 days ago.
- What is it written in?
- Mainly Vim Script, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem ALE solves for Vim and Neovim users
Vim's built-in syntax highlighting tells you a file looks wrong; it does not tell you a name is undefined or an import is unused. ALE (Asynchronous Lint Engine) fills that gap by sending buffer contents to external checkers and returning diagnostics before the file is written to disk. The README states it provides "linting (syntax checking and semantic errors) in Neovim 0.7.0+ and Vim 8.2+ while you edit your text files".
The audience is narrow but real. People who edit over SSH, inside containers, or in a git commit message buffer cannot rely on a GUI editor's language service. ALE is written in Vim script, and its own pitch is that it has "No dependencies for ALE itself" and a "Lightweight plugin architecture (No JavaScript or Python required)". If your editor environment is a terminal with a shell, ALE fits. If you expect an editor to install and manage language servers for you, it does not.
How ALE runs linters without blocking your typing
The mechanism is job control plus timers. The README says ALE "makes use of Neovim and Vim 8 job control functions and timers to run linters on the contents of text buffers and return errors as text is changed in Vim". The buffer text is passed to the checker process, so diagnostics appear before a save.
ALE is also a Language Server Protocol client. The README lists diagnostics, "Go To Definition (:ALEGoToDefinition)", completion, "Finding references (:ALEFindReferences)", "Hover information (:ALEHover)" and "Symbol search (:ALESymbolSearch)". The design goal stated in the README is lazy loading: "If you don't care about Language Server Protocol, ALE won't load any of the code for working with it unless needed."
Two integration details matter for Neovim users. On Neovim 0.8 and later, ALE integrates with the native LSP client by default, so completion plugins built on that client work when ALE starts a language server; the README names nvim-cmp as recommended. On Neovim 0.7 it integrates with the diagnostics API. On Vim there is no native LSP client, so ALE's own client is the whole story.
Fixing is a separate pipeline from linting. ALE runs command line fixers non-blockingly through :ALEFix, and the README names prettier, eslint and autopep8 as examples. Linting and fixing are configured independently, which is worth knowing before you assume one implies the other.
Installing ALE and running a first fix
The README does not give a package manager command. It points to the plugin's own installation path: ALE is a standard Vim plugin, so you install it with whatever plugin manager you already use, then read `:help ale-options` for the option list. The Dockerfile in the repository clones third-party plugins for its test image, which confirms the normal plugin layout rather than any special installer.
Configuration is where ALE actually lives. Fixers are set per buffer or globally, and the README recommends an ftplugin file rather than vimrc for buffer-local settings. This is the example it gives for JavaScript, where prettier runs before ESLint:
" In ~/.vim/ftplugin/javascript.vim, or somewhere similar.
" Fix files with prettier, and then ESLint.
let b:ale_fixers = ['prettier', 'eslint']
" Equivalent to the above.
let b:ale_fixers = {'javascript': ['prettier', 'eslint']}A global dictionary works too, but the README warns that "using a plain List for g:ale_fixers is not supported". The `*` key applies to filetypes that match nothing else:
" In ~/.vim/vimrc, or somewhere similar.
let g:ale_fixers = {
\ '*': ['remove_trailing_lines', 'trim_whitespace'],
\ 'javascript': ['eslint'],
\}To fix on every save, set the switch the README documents:
" Set this variable to 1 to fix files when you save them.
let g:ale_fix_on_save = 1For a first real use, open a file in a supported language, run `:ALEFixSuggest` to see which fixers ALE knows about for that filetype, and add the ones you want to `b:ale_fixers`. Then run `:ALEFix` and watch the buffer change. If nothing happens, the fixer binary is not on your PATH; ALE does not install it for you.
Where ALE stops being the right tool
ALE is a client. Every linter, fixer and language server it drives is a separate program you install and keep current. The README's list of supported tools lives in supported-tools.md, and if your language is not there, ALE has nothing to run. That is the first failure mode: a configured filetype with no installed binary produces silence, not an error you will necessarily notice.
The second is scope. ALE's completion support is explicitly limited. The README says "All of ALE's completion information must come from Language Server Protocol linters, or from tsserver for TypeScript." If you want completion from a non-LSP source, ALE is not that plugin. Its completion works by hijacking omnicompletion as you type, which is a narrower model than a dedicated completion engine.
The third is the LSP division of labour on Neovim. Because ALE hands off to Neovim's native client on 0.8+, features you configure through other plugins that use the same client may overlap with ALE's own LSP features. The README does not describe how to reconcile the two, so on Neovim you are choosing which layer owns which capability. On Vim there is no such ambiguity, and equally no fallback.
ALE compared with vim-lsp, Syntastic and coc.nvim
The honest comparison is about where the work happens. Syntastic is the ancestor ALE replaced in many configurations: it runs checkers synchronously, so the editor waits. ALE's whole reason for existing is the opposite, running checks through Vim 8 job control and timers so typing continues. If you are still on Syntastic and your editor stalls on large files, that is the difference you are feeling.
vim-lsp takes the Language Server Protocol as the primary interface and expects you to configure servers. ALE treats LSP as one supported mode among many linters and fixers, and its README states that LSP code is not loaded unless needed. If your workflow is mostly language servers, vim-lsp is the more direct fit; if it is a mix of standalone linters and occasional servers, ALE's model is broader.
coc.nvim is the opposite architectural bet: it runs a Node process and builds an extension ecosystem on top of it. ALE's README makes the contrast explicit in its own favour, listing "No dependencies for ALE itself" and "No JavaScript or Python required". That claim cuts both ways. coc.nvim gives you a managed environment with extensions; ALE gives you a Vim script plugin that assumes you already have the tools. Neither is wrong, but picking ALE and then expecting coc.nvim's convenience is the mismatch that leads to complaints.
Maintenance, upgrade cost and the BSD-2-Clause licence
ALE is not archived. The last push to master was on 2026-08-21, and the most recent release is v4.0.0 from 2025-03-14. The gap before that was long: v3.3.0 landed on 2022-12-25 and v3.2.0 on 2022-03-05. The pattern is a stable plugin with infrequent tagged releases, and the README supports that reading with the claim that "Breaking changes for the plugin are extremely rare".
Upgrade cost sits mostly outside the plugin. ALE itself is Vim script with no runtime dependency, so updating it is a plugin manager operation. The recurring work is the tools: each linter and language server has its own version and its own output format, and ALE's integrations track those. A language server that changes its diagnostic shape is a real breakage vector, and it arrives through your toolchain, not through ALE.
The repository also carries a Help Wanted note asking for someone to manage issues and pull requests, which is a signal about maintainer bandwidth rather than code quality. Read it as a reason to check whether your specific integration is getting attention before you depend on it.
The licence is BSD-2-Clause. That is a permissive licence, and the practical implication is that you can bundle or modify ALE in a commercial or internal setup with few obligations, typically preserving the copyright notice and licence text. This is not legal advice; read LICENSE in the repository and your organisation's policy before redistributing.
Editorial conclusion
Adopt ALE if you want linting in Vim or Neovim without adding a Python or Node dependency to your editor, and you are willing to install the linters themselves yourself. Skip it if you want one language server configuration to drive every editor feature, or if you cannot install command line tools on the machines where you edit. Before committing, check supported-tools.md for your language, run :ALEFixSuggest in a buffer, and confirm that the linter binary resolves in the same shell that launches Vim.
Frequently asked questions
What is dense-analysis/ale in Neovim?
It is the Asynchronous Lint Engine, a plugin that lints buffers while you edit and also acts as a Language Server Protocol client. On Neovim 0.8 and later it integrates with the native LSP client by default, and on 0.7 it integrates with the diagnostics API.
How do I install ALE with vim-plug?
The README does not document a vim-plug line or any other package manager command. ALE is a standard Vim plugin, so it installs through whatever plugin manager you already use, after which you configure options described in :help ale-options.
Does ALE install the linters and language servers it runs?
No. ALE is a client that sends buffer contents to external programs, so each linter, fixer and language server has to be installed separately and available on your PATH. The list of what it can drive is in supported-tools.md.
How do I fix files automatically when saving in ALE?
Set g:ale_fix_on_save to 1 in your vimrc, and configure the fixers with b:ale_fixers or g:ale_fixers. The README notes that a plain List for g:ale_fixers is not supported, so use a Dictionary keyed by filetype.
Which Vim and Neovim versions does ALE require?
The README states Neovim 0.7.0+ and Vim 8.2+. The job control functions and timers in those versions are what let ALE run checkers without blocking the editor.
Official sources
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.
[](https://hysenlabs.com/projects/dense-analysis-ale)
Community notes