SKILL.md
Grammar Checker Guide
A skill for using grammar and style checking tools to polish academic manuscripts. Covers tool comparison, configuration for scholarly writing, common academic English pitfalls, and workflows for integrating automated checking into the writing process.
Tool Comparison
Overview
| Tool | Best For | Academic Mode? | Privacy | Cost |
|---|---|---|---|---|
| Grammarly | General grammar, clarity | Yes (tone settings) | Cloud-based | Free / Premium |
| LanguageTool | Open-source, privacy | Yes (formal style) | Self-hostable | Free / Premium |
| ProWritingAid | Style depth, reports | Yes (academic style) | Cloud-based | Subscription |
| Writefull | Academic-specific | Designed for academic | Cloud-based | Free / Premium |
| Vale | CLI/CI linting for docs | Configurable rules | Local only | Free (open-source) |
Privacy Considerations
For unpublished research:
- Check the tool's data retention policy before pasting manuscript text
- LanguageTool can be self-hosted (no data leaves your machine)
- Vale runs entirely locally
- Grammarly Enterprise offers data processing agreements
For sensitive or embargoed work:
- Use local-only tools (Vale, local LanguageTool server)
- Avoid pasting full manuscripts into cloud-based free tiers
- Review the tool's terms regarding data use for model training
Configuring Tools for Academic Writing
LanguageTool Setup
import os
import json
import urllib.request
def check_text_with_languagetool(text: str, language: str = "en-US") -> list:
"""
Check text using the LanguageTool API.
Args:
text: The text to check
language: Language code (en-US, en-GB, de-DE, etc.)
"""
api_url = os.environ.get(
"LANGUAGETOOL_URL",
"https://api.languagetool.org/v2/check"
)
data = urllib.parse.urlencode({
"text": text,
"language": language,
"enabledCategories": "GRAMMAR,TYPOS,PUNCTUATION,STYLE",
"level": "picky"
}).encode("utf-8")
req = urllib.request.Request(api_url, data=data)
response = urllib.request.urlopen(req)
result = json.loads(response.read())
issues = []
for match in result.get("matches", []):
issues.append({
"message": match["message"],
"context": match["context"]["text"],
"offset": match["offset"],
"length": match["length"],
"suggestions": [r["value"] for r in match.get("replacements", [])[:3]],
"rule_id": match["rule"]["id"]
})
return issues
