Open-source project
flycheck/flycheck avatar
flycheck/flycheck

Flycheck: on-the-fly syntax checking for GNU Emacs

On the fly syntax checking for GNU Emacs

2,534 stars455 forksEmacs LispGPL-3.0

At a glance

What is it?
Flycheck runs external linters and compilers against the buffer you are editing and reports what they find. It is for Emacs users who want diagnostics without leaving the editor, and it is a different bet from language-server tooling.
Who is it for?
Adopt Flycheck if you already live in Emacs and want a single diagnostics surface that can mix external linters with Eglot's LSP output, and if you are willing to install and configure the underlying tools yourself. Skip it if you expect a checker to work out of the box on a fresh machine: Flycheck orchestrates programs, it does not ship them, and a missing executable shows up as a checker error rather than as silence.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 31 days ago.
What is it written in?
Mainly Emacs Lisp, according to GitHub's language statistics.

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

Editorial analysis

What Flycheck does that a language server does not

Flycheck is a dispatcher. It watches the buffer you are editing, decides which checker applies to that buffer, runs that program, parses its output, and puts the results in the buffer as diagnostics. The programs it runs are ordinary command line tools: compilers, linters, type checkers. Flycheck does not implement any of those analyses itself, and the README describes it as an extension for on-the-fly syntax checking rather than a static analysis engine.

The audience is Emacs users who already have a linter installed and want its output surfaced while typing, without a separate terminal pane or a save-and-run loop. The project ships bundled checkers and the documentation points to a languages page that lists them, so the practical question for a new user is not whether Flycheck supports a language but whether a checker exists and whether the underlying binary is present.

The newer part of the design is that Flycheck is no longer only a wrapper around external binaries. The README shows a setup where Eglot's LSP diagnostics are reported through Flycheck, and a separate mode for reading diagnostics straight from a linter's own LSP server, naming RuboCop, Ruff, Biome and Harper as examples. That matters because it turns Flycheck into one place to look for problems, regardless of whether the problem came from a subprocess or from a language server.

How the checker pipeline is wired

The repository is a single large Emacs Lisp file, flycheck.el, alongside a test directory, a doc directory, a Makefile and an Eask file. There is no separate runtime, no daemon and no network service. Everything executes inside the Emacs process, and the checkers it invokes are child processes.

From the README's description, the flow is: a global minor mode enables checking, a checker is selected for the current buffer, the checker's command runs, and its output is turned into diagnostics displayed in the buffer. The annotation mode is what puts diagnostics inline next to the code, described in the README as Error Lens style. Without it, diagnostics still exist but are surfaced through the usual Emacs interfaces rather than as inline text.

The Eglot integration reverses the usual direction. Instead of Flycheck shelling out to a binary, global-flycheck-eglot-mode takes the diagnostics Eglot already received from the language server and routes them into Flycheck. The README presents this as the modern setup: on-the-fly checking everywhere, inline diagnostics, and LSP diagnostics flowing through Flycheck. The alternative, global-flycheck-lsp-mode, is for people who want diagnostics from a linter's own LSP server without running Eglot at all.

This is a deliberate architectural choice with a cost. Flycheck stays small and language-agnostic, but it inherits every problem of the tools it calls: version drift in the linter, different output formats between linter releases, and startup latency for slow binaries. A language server that owns both the analysis and the reporting does not have that seam.

Installing Flycheck and getting a first diagnostic

The README states that Flycheck is available with package.el on NonGNU ELPA, MELPA Stable and MELPA. The install command given in the README is a single package-install call from inside Emacs:

code
M-x package-install RET flycheck RET

After installation, the README says to enable the global mode in your Emacs config:

elisp
(global-flycheck-mode +1)

For people who use use-package, the README gives this equivalent, which defers the mode until after init:

emacs-lisp
(use-package flycheck
  :ensure t
  :config
  (add-hook 'after-init-hook #'global-flycheck-mode))

The README's modern setup adds inline diagnostics and routes Eglot's LSP diagnostics through Flycheck. It uses the hook form of use-package and enables two additional modes:

emacs-lisp
(use-package flycheck
  :ensure t
  :hook ((after-init . global-flycheck-mode)
         ;; Show diagnostics inline, next to the code (Error Lens style)
         (after-init . global-flycheck-annotate-mode))
  :config
  ;; Report Eglot's LSP diagnostics through Flycheck
  (global-flycheck-eglot-mode 1))

If you would rather read diagnostics from a linter's own LSP server, the README says to use global-flycheck-lsp-mode instead, and names RuboCop, Ruff, Biome and Harper as servers that fit that path. The README also points to the bundled checkers page and to an Installation page and Quickstart guide for a gentler introduction. What you should see after enabling the mode is diagnostics appearing in a buffer whose language has a checker and whose checker binary is installed; if the binary is missing, the checker cannot run, and the README does not describe a fallback that substitutes for it.

The checker is only as present as the binary behind it

The most common failure mode is not a Flycheck bug. It is a checker whose executable is not installed, or is installed under a name or path Emacs does not see. Flycheck's job is to run a program and parse its output; if the program is absent, there is nothing to parse. The README does not document a mechanism that installs linters for you, and the bundled checkers page is a list of what Flycheck knows how to drive, not a list of what is on your machine.

This is the case where Flycheck is the wrong tool. If you want a single install that brings both the analysis and the reporting, a language server that ships its own diagnostics is a better fit, and the README itself acknowledges that path by offering global-flycheck-lsp-mode for reading diagnostics directly from a linter's LSP server. Choosing Flycheck means accepting responsibility for the toolchain underneath it.

The second limitation is latency. Every checker is a subprocess, and any subprocess has startup cost. The README does not publish timing numbers, and it would be wrong to guess at them, but the design means the editor waits on external programs rather than on in-process analysis. For a fast linter this is imperceptible; for a slow one it is the difference between checking as you type and checking when you stop.

The third is output parsing. A checker command produces text, and Flycheck has to understand that text. When a linter changes its output format between releases, the parsing is what breaks, and the fix lives in Flycheck rather than in your config. The repository's CHANGELOG.md and its release history are where that kind of maintenance shows up.

Flycheck versus Flymake, and versus Eglot alone

Flymake is the alternative that ships with Emacs itself. The comparison is not about capability so much as about where the integration lives: Flymake is part of Emacs and needs no package installation, while Flycheck is a package you install from NonGNU ELPA, MELPA Stable or MELPA. Flycheck's README describes a broader modern setup, including inline annotations and two distinct ways to pull LSP diagnostics into the same reporting layer, and that is the practical difference a reader is choosing between. If you want zero additional packages and are satisfied with Emacs' built-in checking, Flymake is the smaller commitment. If you want Flycheck's annotation mode and its Eglot and LSP routing modes, you are opting into a package with its own release cadence.

The second alternative is Eglot on its own. Eglot is a language server client, and a language server reports diagnostics as part of its normal operation. The difference in approach is that Eglot owns the analysis through the server, while Flycheck owns the reporting and delegates analysis to whatever it runs. The README's global-flycheck-eglot-mode exists precisely because these are not mutually exclusive: it takes Eglot's diagnostics and reports them through Flycheck. So the real question is not Flycheck or Eglot but whether you want one diagnostics surface. If you enable that mode, you do; if you do not, you have two places to look.

A third option, global-flycheck-lsp-mode, sits between them: it reads diagnostics from a linter's own LSP server without Eglot. The README names RuboCop, Ruff, Biome and Harper as servers in that category. That path is for people who want LSP-style diagnostics from a specific linter but do not want a general language server client in the loop.

Maintenance, licensing and what upgrading costs

The repository is not archived, and the last push was on 2026-09-02. Recent releases are v39.0 on 2026-08-10, v38.3 on 2026-07-29 and v38.2 on 2026-07-29. That is a project with a live release trail rather than a frozen one.

Upgrade cost is mostly borne by the checkers, not by Flycheck itself. A Flycheck release can change how a checker's output is parsed, and that is the change most likely to affect you, because it can turn working diagnostics into wrong ones or into none. The CHANGELOG.md at the repository root is the file to read before upgrading, and it is the only place that would record that kind of change.

The licence is GPL-3.0, stated in the README badge and in the COPYING file. The Makefile carries the standard GPL notice as well. For most Emacs users this is a non-issue: you are installing and using the package, not redistributing it. It becomes a consideration if you embed Flycheck in something you ship, because GPL-3.0 carries obligations that permissive licences do not. That is a question for your own legal review, not something this article can settle.

There is also a funding dimension. The README lists Open Collective, GitHub Sponsors, Patreon and PayPal as ways to support development. That is worth knowing when you are judging how much maintenance capacity sits behind a package you are about to make part of your daily editing loop.

Editorial conclusion

Adopt Flycheck if you already live in Emacs and want a single diagnostics surface that can mix external linters with Eglot's LSP output, and if you are willing to install and configure the underlying tools yourself. Skip it if you expect a checker to work out of the box on a fresh machine: Flycheck orchestrates programs, it does not ship them, and a missing executable shows up as a checker error rather than as silence. Before committing, verify three things on your own setup: that your Emacs package archive is NonGNU ELPA, MELPA Stable or MELPA; that the specific checker for your language is listed in the bundled checker documentation; and that the linter binary it names is on the PATH Emacs actually sees.

Frequently asked questions

How does Flycheck compare with Flymake in Emacs?

Flymake ships with Emacs, while Flycheck is installed as a package from NonGNU ELPA, MELPA Stable or MELPA. Flycheck's README describes a setup with inline annotations and modes that route Eglot or linter LSP diagnostics through it, which is the practical difference to weigh.

How does Flycheck compare with LSP tooling?

Flycheck runs external checker programs and parses their output, while an LSP server performs the analysis and reports diagnostics itself. The README bridges the two: global-flycheck-eglot-mode reports Eglot's LSP diagnostics through Flycheck, and global-flycheck-lsp-mode reads diagnostics from a linter's own LSP server.

How does Flycheck compare with Eglot?

Eglot is a language server client that obtains diagnostics from a server, and Flycheck is the reporting layer. They are not exclusive: the README's modern setup enables global-flycheck-eglot-mode so that Eglot's diagnostics are reported through Flycheck.

Official sources

  1. flycheck/flycheck on GitHub
  2. License: GPL-3.0
  3. Project website
  4. README
  5. 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/flycheck-flycheck.svg)](https://hysenlabs.com/projects/flycheck-flycheck)