Charlie KrugThe Build Log

← All posts

Your code has a linter. The --help it prints does not.

Flagcraft grades any CLI's --help output against the Command Line Interface Guidelines, in your browser, citing the exact rule each finding breaks. Paste docker and watch -v mean two different things.

Paste docker --help into a box and the first thing you learn is that -v is a liar. At the top level, docker -v prints the version. Inside docker run, -v mounts a volume. Same letter, two meanings, one command tree, and it has shipped that way to a very large number of installs because there is no test anywhere that would fail on it.

That gap is what Flagcraft pokes at. The Command Line Interface Guidelines are a careful, opinionated spec for how a good CLI should behave: provide both -h and --help, keep a flag's meaning consistent across subcommands, use exit code 1 for a general failure and 2 for misuse, name long flags in lowercase with hyphens. It is well-regarded, and almost nobody follows it to the letter, because it is prose. Your code style gets enforced by eslint or gofmt on every commit. The surface your users actually read, the --help screen, has no linter at all. Flagcraft is that linter.

Text in, not source in

The decision that makes it useful is that it reads text, not source. It never asks for your repo and never runs your program. You paste the same --help output any user would see, and that is the entire input. argparse, clap, cobra, commander, and a parser you hand-rolled at 2am all print roughly the same shape: column-aligned rows where a short flag, a long flag, and a description sit in loose columns. A single parser normalizes those layouts into one model, a list of flags each with its short form, long form, and description, plus the original line for context. Then a rule engine walks that model.

The hard part is not the rules, it is the parsing. Integrating with a dozen argument-parser libraries would be tedious but bounded. Robustly reading free-form, human-aligned text that was never meant to be machine-read is the actual generality problem, and it is why the library logic sits at 100% line and branch coverage, with property-based fuzzing and deliberately nasty inputs (unicode, CRLF, pathological line lengths). The grader re-runs on every keystroke, so it cannot be allowed to throw.

Cite the rule, don't just scold

Each check is self-contained: an id, a plain-language message, and a citation to the guideline section it encodes. That last part is the point. A finding does not say "this looks wrong." It says -f means --file in one place and --force in another, and here is the Consistency section that tells you not to do that. The tool teaches the spec instead of hitting you with it. New coverage is pure addition, one more independent check, never a rewrite of the ones already there.

The current rule set is small and honest about it: a missing -h/--help, a long flag that isn't lowercase and hyphen-separated, one short flag bound to two different long flags, a missing --version, and exit codes that fail to tell a general failure apart from a usage error where the text mentions them at all. Five checks. The fun is how many famous tools trip them. git, docker, and kubectl are one-click presets precisely because they are mature, beloved, and still carrying the small drift the guidelines warn about, drift nobody caught because nobody was checking the surface.

And nothing leaves your machine. It is a static bundle with no backend, so "your help text is not uploaded anywhere" is true because there is nowhere to upload it, not because a policy page promises it.

Try it

Open Flagcraft, click the git preset, and read the report it produces on a tool you have used a thousand times. Then run your own: paste your CLI's --help, watch the findings update as you type, and follow one citation back to the guideline it names. The source is on GitHub.

Flagcraft is live. Free, in your browser, no signup.

This post is part of the build log: every app my automated factory ships gets written up here, honestly. Browse everything at apps.charliekrug.com. Comments are open below.

Comments

Loading comments…