Humanize OpenRouter Output in Java: A Zero-Dependency Linter for Bold-Label Bullets, Emoji and Title Case + 5 Free Tools (2026) A developer built a zero-dependency Java linter that flags template-style Markdown in LLM-generated status updates fetched through OpenRouter, catching bold-label bullets, emoji, and Title Case headings before a scheduled job posts them to an internal wiki. The single-file tool runs on Java 17+ with no build step, uses exit codes 0/1/2 for pass, rewrite, and API failure, and supports a --json report plus OPENROUTER_MODEL and OPENROUTER_BASE_URL overrides for model switching and mock testing. Last verified November 2026. Disclosure: my team makes UnAIMyText, which is third in the tool list below. The Java is free to copy. I look after a small Java service at work that writes the weekly status update for each engineering team. A scheduled job sends merged pull requests and closed tickets to an LLM through OpenRouter and posts the result to our internal wiki. The updates were accurate, and they all looked like the same slide deck: bold-label bullets, Title Case headings, a rocket in front of half of them. Our wiki's style guide says sentence case and no emoji, and people had stopped reading. So I wrote a linter. One Java file, nothing but the JDK, and it fails an update before the job posts it. My earlier checkers in this series looked at wording and punctuation. This one looks at Markdown structure: - Faster Builds: CI now caches... once is fine. When more than half of the bullets in a list of three or more open with a bold label, it reads like a template. The exit code is 0 for a pass, 1 for a rewrite and 2 when the API call fails. --json prints a machine-readable report. OpenRouter's API reference https://openrouter.ai/docs/api reference/overview describes POST /api/v1/chat/completions with an OpenAI-style body and a bearer token. A few details from it shaped the code: HTTP-Referer and X-OpenRouter-Title are optional headers that identify your app X-Title is also accepted . The linter only sends them if you set OPENROUTER APP URL . finish reason is normalized to tool calls , stop , length , content filter or error . Anything other than message.content can be null. Both count as a failed request. The default model is openai/gpt-oss-20b , which is a reasoning model. OpenRouter's reasoning tokens guide https://openrouter.ai/docs/guides/best-practices/reasoning-tokens says that on Chat Completions, reasoning appears in a reasoning field on each message, and that reasoning.exclude omits it from the response the tokens are still billed . The request sets "reasoning": {"exclude": true} , and the linter reads only message.content either way, because that's what gets posted. OPENROUTER MODEL switches models and OPENROUTER BASE URL points the linter at a mock. Java 17 or newer. Run it straight from source with java StatusLint.java ; there's no build step. python import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; / Flags bold-label bullets, emoji and Title Case headings in generated Markdown. / public class StatusLint { // House style knobs. static final int MIN BULLETS = 3; static final double MAX BOLD SHARE = 0.5; static final int MAX EMOJI = 1; static final int MAX TITLE CASE HEADINGS = 1; static final Pattern FENCE = Pattern.compile " ?ms ^ . ?^ \\t $" ; static final Pattern HEADING = Pattern.compile "^\\s{0,3} {1,6}\\s+ .+? \\s \\s $" ; static final Pattern BULLET = Pattern.compile "^\\s ?: - + |\\d+ . \\s+ . $" ; static final Pattern BOLD LABEL = Pattern.compile "^ ?:\\ \\ | ^ {1,40} ?:: ?:\\ \\ | | ?:\\ \\ | : " ; static final Pattern SMALL WORDS = Pattern.compile "a|an|and|as|at|but|by|for|in|nor|of|on|or|the|to|vs|via|with" ; record Result int bullets, int boldBullets, int emoji, int headings, List