clemens-e316k downloadsAdvanced grammar and spell checking, powered by LanguageTool.
Check grammar and spelling with LanguageTool without leaving Obsidian. Run a check on the whole document or just the selected text, or let the plugin check automatically as you type. Mistakes are underlined in the editor; click one to review suggestions, apply a correction, or add the word to your personal dictionary.
The plugin works with the free public LanguageTool API, with LanguageTool Premium, and with self-hosted servers, so your notes never have to leave your own infrastructure.

A note on AI usage: I use Claude during development. It lets me build features and fixes faster than my free time would otherwise allow. Every change is still reviewed by me before it is released. If you are not comfortable with AI-assisted code, that's a fair position, and you should simply not use this plugin.
Copy main.js, styles.css, and manifest.json from the latest release into VaultFolder/.obsidian/plugins/obsidian-languagetool-plugin/. Release assets are signed with GitHub artifact attestations; you can verify them with gh attestation verify main.js -R Clemens-E/obsidian-languagetool-plugin.
Run Check Text from the command palette, bind it to a hotkey under Settings, Hotkeys (filter for "LanguageTool" to find all of the plugin's commands), or use the optional ribbon icon. With no selection, the whole document is checked; with a selection, only the selected text is checked.
Potential issues are underlined. Click an underline to open a popover with the message, up to three suggested replacements, and an ignore button. For spelling errors the ignore button is Add to personal dictionary, which stores the word in Obsidian's own spellcheck dictionary, so both the plugin and Obsidian's built-in spellcheck accept it from then on.
Press Escape to close the popover without changing anything; the underline stays, so you can come back to it by clicking the word again.
Underlines disappear on their own when you edit the text they cover. Text inside code blocks, math, frontmatter, and similar regions is never underlined. In aliased links ([[note|alias]]) only the alias is checked, since that is the text you see; the link target is treated as markup. Embeds (![[...]]) are skipped entirely.
Enable Autocheck Text in the settings (or run Toggle Automatic Checking) to check as you type. The plugin waits until you stop typing for the configured AutoCheck Delay and then checks only the lines you changed.
Single notes can deviate from that global setting with the lt-autocheck frontmatter key, which works in both directions and is remembered every time the note is opened, because it lives in the note itself:
---
lt-autocheck: false
---
false keeps a note off automatic checking even when the setting is on, true checks a note automatically even when the setting is off. Manual checks are unaffected in both cases. Run Toggle automatic checking for current document (or use the status bar menu) to set the key without editing the frontmatter by hand; toggling back to the global behavior removes the key again.
Turn on Ribbon Icon in the settings to get a spell-check icon in the ribbon (the left sidebar on desktop, the drawer on mobile) that checks the current note. It is off by default. On mobile it is the only tap target for a manual check besides the command palette, since the status bar does not exist there.
The Aa button in the status bar shows a sync icon while a check is running. Clicking it opens a small menu: check the current document, enable or disable automatic checking globally or for the current document only, or clear all suggestions.
| Command | What it does |
|---|---|
| Check Text | Checks the document, or only the selection if there is one |
| Clear Suggestions | Removes all underlines without changing the text |
| Toggle Automatic Checking | Turns autocheck on or off |
| Toggle automatic checking for current document | Pins autocheck on or off for the current note through its lt-autocheck frontmatter key |
| Jump to next Suggestion | Selects the next underline after the cursor and scrolls to it |
| Jump to previous Suggestion | Selects the previous underline before the cursor |
| Accept suggestion #1 / #2 / #3 | With the cursor inside an underline, applies the first, second, or third suggested replacement directly, without opening the popover |
| Ignore suggestion at cursor | With the cursor inside an underline, ignores that match for the rest of the session, like the popover's ignore button |
| Add word at cursor to personal dictionary | With the cursor inside a spelling underline, adds the word to your personal dictionary (the same one Obsidian's own spellchecker uses). A notice offers an undo |
LanguageTool detects the language of the whole text, so a note that mixes languages (say, an English template filled with German prose) can end up checked in the wrong one. Pin the language for a single note with the lt-language frontmatter key, using a LanguageTool code such as de-DE, en-US, or just de:
---
lt-language: de-DE
---
The keys language and lang are accepted as well, so notes that already carry them for other plugins (for example obsidian-dictionary) need no extra key. A pinned language wins over the Static Language setting; lt-language: auto re-enables detection for one note while a static language is set globally. Language varieties from the settings only apply to notes that are auto-detected, because LanguageTool does not combine them with a fixed language.
Add the tag lt-ignore to a file's frontmatter to exclude it from all checks, including manual ones:
---
tags:
- lt-ignore
---
http://localhost:8010); the plugin adds the API path itself.When auto-detect recognizes a language that has regional variants, it cannot know which one you write. These dropdowns pin the variant used for English, German, Portuguese, and Catalan (for example "English (US)" vs "English (British)", which differ in spelling rules). Picking a variety switches Static Language back to Auto Detect, since the two settings would otherwise conflict.
PUNCTUATION,CASING.Checking text means sending it to the configured LanguageTool server. With the standard or premium endpoint, that is LanguageTool's cloud; their privacy policy applies. The plugin only ever sends the text being checked (the whole document, the selection, or the changed lines during autocheck), never your whole vault.
If you do not want your notes to leave your machine, run your own LanguageTool server and point the plugin at it with the Custom URL endpoint. The easiest way is the Docker image:
docker run -d --name languagetool -p 8010:8010 erikvl87/languagetool
Then set the endpoint to Custom URL and enter http://localhost:8010.
The plugin supports LanguageTool Premium:
⚠️ Please report bugs and issues with this plugin to this GitHub repository, and not to the LanguageTool support: this is an unofficial community plugin.
On Obsidian 1.11.4 and newer, the plugin can keep your API key in Obsidian's encrypted SecretStorage instead of in plaintext in the plugin's data.json. Fresh installs use SecretStorage automatically when available; existing setups keep their plaintext key until you enable "Store API key securely (this device only)" in the plugin settings, which moves the key into a secret and removes it from data.json. Your username/email is not a secret and always stays in the synced settings.
Upsides of secure storage
.obsidian/plugins/obsidian-languagetool-plugin/data.json, so vault backups, Git-synced vaults, and sync services never see it.Downsides / trade-offs
data.json (plaintext, synced). This is only possible on a device where the secret is actually set. On other devices the plugin refuses the switch, so the key reference is not lost for the device that holds it.