DEV Community

Cover image for How I use linters to check my writing
Pablo Estrada
Pablo Estrada

Posted on • Originally published at

How I use linters to check my writing

I installed textlint, a pluggable linter for text. This post describes how I configured it, along with initial results and observations.

At work, my team is developing Bento, a free program analysis toolkit for finding bugs that matter in your code. Our program analysis team writes code checks that find problems in projects using specific frameworks such as Flask and Requests. We’ve also added curated checks from some tools such as Flake 8 and ESLint, and characterized the performance of checks that Bento enables or disables.

As we fine-tuned Bento’s configuration, it got less noisy, had a higher signal-to-noise ratio, and became more useful. Since I spend a lot of time writing, I wanted to have similar software analyze and improve my writing, like Bento analyzes and improves source code.


I found helpful articles like Chris Ward’s Customizing Visual Studio Code for Writing. That and others kept pointing to textlint, so I decided to try it.

textlint is described as, “the pluggable natural language linter for text and markdown.” It’s written in JavaScript and inspired by ESLint. Like ESLint, textlint’s pluggable design brings flexibility, extensibility, some initial configuration requirements, and collaboration through contribution.


textlint suggests per-project installation, but I installed it globally since I wasn’t sure how it would perform, and I didn’t want to check in textlint configs or plugin code to any repository while I tinkered with it. I’m using textlint to check my private files more so than files on which I collaborate with others, so global installation has worked well so far. I saved my configuration file to /usr/local/lib/node_modules/textlint/.textlintrc.

I’m using textlint through Visual Studio Code and the vscode-textlint extension, and added this to my settings.json:

"textlint.configPath": "/usr/local/lib/node_modules/textlint/.textlintrc",
"textlint.nodePath": "/usr/local/lib/node_modules/textlint",

Once install, textlint will do nothing straight out of the box since it has no default rules. The user must select and install rules, and this is where the configuration tasks begin. Note that if you install textlint globally then you must also install each reference rule globally.

The textlint project page lists several dozen rules, about half for English and half for Japanese. It’s not too hard to go through each rule and decide if it’s worth trying. Each rule must be installed (in my case globally) and then configured in .textlintrc. Some rules have more options, and hence need more configuration, than others.


I decided to install and configure a bunch of rules, and then observe their behavior. Then I’ll individually turning off rules that don’t seem helpful. I chose these rules:


You can find links to these on the textlint collection of rules page. It took a while to install and configure all the above rules, and I’m not sure I’ve configured them optimally. Here’s a GitHub Gist with my configuration

Consuming output

Results appear inline through squiggly underlines and in Visual Studio Code’s Problems panel, like this:
Problems panel

textlint’s output is also available through the command line and looks like this:
textlint output in command line

Results and observations

With these checks enabled and configured, textlint can product a lot of output. I’m still working through which textlint rules to fine-tune and which to mute. I’ve configured some redundant checks, and occasionally a useful comparison of rules appears:
Check comparison

In other cases the rules are entirely redundant, such as this case in which I’ve enabled Write Good’s “weasel” and Rousseau’s “weasel” rules:
Redundant check output

I also installed Michael Vernier’s SpellChecker extension for Visual Studio Code and configured it in Visual Studio Code’s settings.json:

"spellchecker.ignoreWordsList": [
    "spellchecker.ignoreRegExp": [
        "/\\\\(.*\\\\.(jpg|jpeg|png|md|gif|svg|pdf|PDF|SVG|JPG|JPEG|PNG|MD|GIF)\\\\)/g", //remove links to image and markdown files
        "/((http|https|ftp|git)\\\\S*)/g", //remove hyperlinks
        "/^(\\\\s*)(\\\\w+)?(\\\\s*[\\\\w\\\\W]+?\\\\n*)(\\\\s*)\\\\n*$/gm", //remove code blocks
        "/^>[\\\\s\\\\S]*$/gm", //remove quoted text
    "spellchecker.ignoreFileExtensions": [".textlintrc", ".yml", ".json"],
    "spellchecker.checkInterval": 1500,

and Street Side Software’s Spelling Checker for Visual Studio Code, though I haven’t spent enough time with them to form a solid opinion.

Future wishes

I wish each rule included test files, so I could run each rule and understand its behavior at installation time. This way I could better tune my config from the start. As a workaround I’ve tested rules on the command line using this structure: textlint --rule [RULE NAME] [FILENAME]. It’s rather nice to see textlint’s output in the command line instead of at the bottom of my IDE.

Some of the rules have “auto-fix” functionality, but I haven’t tested this enough yet.

Top comments (2)

lauragift21 profile image
Gift Egwuenu

This is amazing! I can't wait to try it out :)

pabloest profile image
Pablo Estrada

Thank you, @lauragift21 !