Technology Tales

Notes drawn from experiences in consumer and enterprise technology

Running LanguageTool locally for privacy and unlimited checking

Published on 28th February 2026 Estimated Reading Time: 13 minutes

The search for a Grammarly replacement that offered more flexibility led here: LanguageTool, a capable grammar, spelling and style checker that works across a wide range of platforms. After some research, it emerged as the right fit, and it has been working well in daily use since, covering both browser extensions for general writing and a local instance for editing in VS Code. It supports more than 30 languages and integrates with browsers including Chrome, Chromium, Ungoogled-Chromium, Edge, Firefox and Opera, with mail clients such as Gmail and Thunderbird, and with office suites including LibreOffice, Apache OpenOffice, Microsoft Word and Google Docs. Whilst the service can be used via cloud APIs, there are many reasons to run it locally, among them the removal of text length limits that apply to cloud requests and the benefit of keeping content on the machine in question rather than sending it to remote servers.

The LibreOffice 7.4 Change and Why Local Matters

A change in LibreOffice from version 7.4 highlights why a local server is attractive. LanguageTool stopped being an add-on and became part of LibreOffice's code, but that shift brought constraints. Where the old add-on imposed no text size cap, the integrated checker limits free requests to 10,000 characters and Premium to 100,000 characters, and it sends content to LanguageTool's servers in Germany for processing, which many will consider a privacy concern. Similar cloud-based behaviour is the default for browser and mail client extensions, and running a small HTTP server locally avoids these issues entirely, restoring unlimited text size and keeping all checking on the machine.

Setting Up the Java Server

The simplest way to install LanguageTool on both Linux and macOS is via Homebrew. The formula handles Java automatically, removing the need to install or manage a runtime separately. Two commands are all that is required:

brew install languagetool
brew services start languagetool

The second command registers LanguageTool as a managed service so that it starts automatically at login, with no need for a separate startup script. The server listens on port 8081 by default. Updates are then handled in the same way as any other Homebrew package:

brew update && brew upgrade languagetool

Manual Installation via ZIP

For those who prefer not to use Homebrew, the manual route remains available. The Linux Mint forum tutorial linked above covers each step in full. Java 8 or later is required, and the openjdk-11-jre package in Linux Mint's repositories suffices for this purpose. The LanguageTool desktop bundle can be downloaded as LanguageTool-stable.zip, and the archive extracts to a versioned directory such as LanguageTool-5.9. Moving that directory to /home/username/opt and renaming it to LanguageTool simplifies paths considerably.

A file named LTserver.sh in /home/username/opt can then launch the server:

nohup java -cp ~/opt/LanguageTool/languagetool-server.jar org.languagetool.server.HTTPServer --port 8081 --allow-origin > /dev/null 2>&1 &

The nohup command at the start and the & at the end keep the service alive after its terminal closes and start it in the background, whilst > /dev/null 2>&1 silences output. Making the script executable and adding it to Startup Applications in a desktop environment such as MATE (with a brief delay after login) produces an automatic launch on sign-in. Those who prefer a manual approach can omit nohup … & and simply close the terminal to stop the server.

Confirming the Server Is Working

A simple request confirms that everything is working. Visiting the test URL in a browser returns JSON output showing the software version and a sample match, explaining that the sentence should begin with an uppercase letter. If the server is not running, the browser will show a connection refused message instead. On one user's hardware, the idle server consumed roughly 816 MB of RAM, which rose slightly during active checking.

With the process confirmed, browser and mail extensions can be directed away from the cloud to the local endpoint by opening their advanced options and selecting the local server at localhost. LibreOffice 7.4 users can also connect the integrated checker to the local service by setting the base URL to http://localhost:8081/v2 under Tools > Options > Languages and Locales > LanguageTool Server.

A Note on Startup Reliability (Manual Installation)

For those using the manual ZIP installation, there is a small operational note worth knowing from community experience. One user reported that the server did not start automatically at login despite the startup entry being present, and adding a short diagnostic to the beginning of the script caused it to start reliably. The following lines served only to write a timestamp to a log file, yet after inserting them the server came up as expected:

dt=$(date '+%d/%m/%Y %H:%M:%S')
echo "LanguageTool started successfully at" "$dt" >> /home/username/bin/LTserver.log

The underlying cause was not identified and could have been a subtle formatting or timing quirk, but the observation may help others encountering the same behaviour. It is worth trying this addition if automatic startup proves unreliable.

Network Security and Keeping the Server Updated

LanguageTool's HTTP server offers further configuration that affects accessibility. A single-user setup should keep the machine's firewall blocking incoming connections so that only localhost can reach the service. If the machine is to host LanguageTool for an internal network, adding --public to the server command line allows access from other devices, making the full command:

nohup java -cp ~/opt/LanguageTool/languagetool-server.jar org.languagetool.server.HTTPServer --port 8081 --allow-origin --public > /dev/null 2>&1 &

In that case, the firewall should allow incoming connections to port 8081 from local addresses, whilst denying others. Any instance reachable from the wider internet is best placed behind an Apache or nginx reverse proxy with TLS. Updates are handled by checking the download page periodically, extracting the latest LanguageTool-stable.zip and copying its contents into ~/opt/LanguageTool.

Running LanguageTool via Docker

Those who prefer containerised services can run LanguageTool under Docker and still keep traffic within a home or office network. A widely used image is erikvl87/languagetool, which exposes the HTTP server on port 8010 and accepts optional configuration via environment variables. A concise docker-compose.yml maps the port, binds a volume for optional n-gram data and tunes the Java heap, as shown below:

version: "3"
services:
  languagetool:
    image: erikvl87/languagetool
    ports:
      - 8010:8010
    environment:
      - langtool_languageModel=/ngrams
      - Java_Xms=512m
      - Java_Xmx=1g
    volumes:
      - ./ngrams:/ngrams

The langtool_languageModel=/ngrams environment variable enables the large n-gram data sets for German, English, Spanish, French and Dutch, which help with commonly confused words such as "their" and "there". The image defaults to a 256 MB minimum heap and a 512 MB maximum, and the settings above increase those values. To bind only to the local machine, changing the published port to localhost:8010:8010 prevents remote access. With the compose file in place, sudo docker-compose up -d starts the service in the background.

Integrating with Visual Studio Code

The VS Code integration is the centrepiece of this setup for local editing. A practical walkthrough on GNU/Linux.ch covers exactly this configuration, using the same Docker image described above. In Visual Studio Code, the LanguageTool Linter extension by David L. Day integrates checking into the editor. Installation can be done through the Extensions view or by running ext install davidlday.languagetool-linter from VS Code's command palette (Ctrl+P).

The extension's settings then need the LanguageTool server address, which should be set to http://127.0.0.1:8010 when the container runs on the same machine, or to the server's IP and port (for example http://192.168.0.2:8010) when it runs elsewhere on the local network. For a quick trial without running a server, the public API can be selected, though that brings the same limitations and privacy considerations as any cloud use. With the local endpoint configured, open Markdown files are checked continually, and possible issues are flagged with quick fixes available from within the editor.

Managing Rules and Disabling Checks

LanguageTool allows fine-grained control over which checks are active, and the official guide to enabling and disabling rules sets out five important points before getting into the steps. Rules cover grammar, spelling, punctuation and style, and they are all enabled by default. Some are available only to Premium users. Turning off "Picky Mode" automatically disables certain classes such as style suggestions, so behaviour may change noticeably after doing so. Rules can be disabled in add-ons and extensions, and once turned off there, they can only be re-enabled via those same add-ons.

In LanguageTool's online editor, clicking "Ignore" in the dialogue box that appears will disable a rule only for the current text, and the same applies if "Ignore in this text" is chosen from the list of issues on the right-hand panel. When a permanent toggle is wanted during browser-based use, selecting "Turn off rule everywhere" in the add-on disables it across documents until it is switched back on.

Re-enabling Disabled Rules

Re-enabling rules in an add-on follows a consistent pattern. In the Chrome extension on a Google Doc, clicking the LanguageTool icon or the error indicator opens the panel, and the settings cog at the bottom right leads to configuration. Scrolling down reveals the "Disabled rules" section, and hovering over an entry shows "Click to enable rule", which restores the individual check immediately. If a broad reset is needed, choosing "Enable all" turns everything back on at once, and the same approach applies across the other add-ons even if the precise placement varies slightly.

Command-Line Use for Bulk Text and Automation

For those who want to use LanguageTool on the command line, the Tips and Tricks page documents several switches and workflows that help with bulk text and automation. The tagger can be run without rule checking by adding --taggeronly or -t, which is useful when tagging large corpora. Input can also come from standard input by using - as the filename, so LanguageTool can sit in a pipeline. The following command processes substantial input and has been used with multi-gigabyte text:

java -jar languagetool-commandline.jar -l <language> -c <encoding> -t <corpus_file> > <tagged_corpus_file>

Automatic application of suggestions is enabled with --apply or -a, in which case only the first suggestion per rule is used, and the output is the corrected text. Because only a basic check ensures that the original error is still present before a suggestion is applied, it is wise to enable only reliable rules with -e or disable known problematic ones with -d. If a round of changes would introduce issues that other rules would catch, running LanguageTool again on the output resolves them in a second pass.

Collecting matches and tags for separate analysis is equally simple with the following command:

java -jar languagetool-commandline.jar -l <language> -c <encoding> <file> > results.txt 2> tags.txt

This writes rule matches to results.txt and part-of-speech tags to tags.txt. Developers working on rules will find that verbose mode (invoked with -v) prints helpful metadata including the XML line number for a rule or subrule inside a <rulegroup>, which pinpoints the exact location when debugging.

Adding Custom Rules Without Modifying Core Files

Adding or packaging rules for long-term reuse is supported without modifying core files, as the Tips and Tricks page explains in detail. From version 6.0, LanguageTool loads an optional grammar_custom.xml placed alongside a language's grammar.xml, and the custom file can define rules that survive upgrades provided their IDs do not collide with existing ones. Alternatively, an external file can be referenced by declaring an entity near the top of grammar.xml:

<!ENTITY UserRules SYSTEM "file:///path/to/user-rules.xml">

Inserting &UserRules; inside an appropriate <category> then pulls in those rules. For external rules, setting external="yes" on each category suppresses the link to community rule details, which would otherwise be shown in the stand-alone GUI.

Writing and Testing Rules

Writing robust rules involves understanding negation and structural nuances. Negation can apply to tokens, to parts of speech, or via exceptions, though care is needed because negating a token with a SENT_END tag will match any end-of-sentence token rather than excluding it. Tokens can be constrained by whether whitespace precedes them using the spacebefore attribute, which helps when matching punctuation or quotation marks. Suggestions can adjust case with case_conversion, and more involved changes can rely on regular expressions inside a <match> element to alter parts of a word whilst preserving intended capitalisation.

Testing rules pays dividends during development. The bundled testrules.sh (or its Windows counterpart) runs unit-style checks and validates XML, and passing a two-letter language code limits the run to a single language. Maven can also be used with mvn clean test. When a suggestion is generated programmatically rather than as a fixed string, adding a correction attribute to an incorrect example asserts what the final suggestion should be and causes a test failure if it diverges. Context-sensitive rules for commonly confused words can avoid false positives by including exceptions for words that indicate the correct usage, as in a Dutch example distinguishing "aanvaart" and "aanvaardt" where the presence of "boot" or "haven" suppresses the warning.

Finding Good Rule Examples with Corpus Tools

Finding good examples for rule development benefits from corpus tools, and the Tips and Tricks page covers this and much more besides. For English, the Google Web 1T 5-Gram Database can be queried by searching for `xyz *` to see common following words or `* xyz` to see common preceding words, which grounds a rule in real usage rather than conjecture. The Corpus of Contemporary American English offers KWIC display to view neighbour words around a query and may request registration after several searches.

Both the 1T data and COCA skew towards American English, however, so those working on British English rules will find the British National Corpus more appropriate, being 100 million words of British English searchable through the same interface. For a broader view across multiple varieties of English, including British, Australian, Irish and South African, the Corpus of Global Web-Based English covers 20 national varieties and is freely available on the same platform. For other languages that LanguageTool supports, corpus availability varies considerably, and the LanguageTool developer documentation is the best starting point for finding suitable resources for a given language.

A Private, Flexible and Useful Toolkit

What began as a search for a more flexible Grammarly alternative has settled into a setup that covers two distinct use cases: browser extensions for everyday writing in web applications, and a local server feeding the VS Code extension for longer-form editing. A local LanguageTool server removes size limits and keeps content on the machine, fitting neatly behind LibreOffice's integrated checker, within browser and mail extensions and inside editors such as VS Code. The sources gathered during those early days of getting this running are what inform this account, and the configuration has been working well enough for the purpose since. Rules can be tuned or switched off where they hinder rather than help, then restored easily when needed. Keeping the server updated and placed behind sensible network boundaries rounds out a setup that serves everyday writing as well as more specialised tasks.

Add a Comment

Your email address will not be published. Required fields are marked *

Please be aware that comment moderation is enabled and may delay the appearance of your contribution.

  • The content, images, and materials on this website are protected by copyright law and may not be reproduced, distributed, transmitted, displayed, or published in any form without the prior written permission of the copyright holder. All trademarks, logos, and brand names mentioned on this website are the property of their respective owners. Unauthorised use or duplication of these materials may violate copyright, trademark and other applicable laws, and could result in criminal or civil penalties.

  • All comments on this website are moderated and should contribute meaningfully to the discussion. We welcome diverse viewpoints expressed respectfully, but reserve the right to remove any comments containing hate speech, profanity, personal attacks, spam, promotional content or other inappropriate material without notice. Please note that comment moderation may take up to 24 hours, and that repeatedly violating these guidelines may result in being banned from future participation.

  • By submitting a comment, you grant us the right to publish and edit it as needed, whilst retaining your ownership of the content. Your email address will never be published or shared, though it is required for moderation purposes.