Did You Mean
Suggest corrections when users mistype subcommand names.
The didYouMeanPlugin catches COMMAND_NOT_FOUND errors and provides "Did you mean?" suggestions based on Levenshtein distance. It does not provide shell tab-completion.
Usage
import { Crust } from "@crustjs/core";
import { didYouMeanPlugin } from "@crustjs/plugins";
const main = new Crust("my-cli")
.use(didYouMeanPlugin())
.run(() => { /* ... */ });
await main.execute();$ my-cli buld
Unknown command "buld". Did you mean "build"?
Available commands: build, dev, deployConfiguration
Error Mode (Default)
Prints the error to stderr and sets exit code to 1:
didYouMeanPlugin()
// or
didYouMeanPlugin({ mode: "error" })Output (to stderr):
Unknown command "buld". Did you mean "build"?
Available commands: build, dev, deployHelp Mode
Prints the suggestion and the parent command's help text to stdout:
didYouMeanPlugin({ mode: "help" })Output (to stdout):
Unknown command "buld". Did you mean "build"?
my-cli - My CLI tool
USAGE:
my-cli <command> [options]
COMMANDS:
build Build the project
dev Start dev server
deploy Deploy to production
OPTIONS:
-h, --help, --no-help Show help
-v, --version, --no-version Show version numberHow Suggestions Work
The plugin uses Levenshtein distance to find similar commands:
- Prefix matches — If the input is a prefix of a command (or vice versa), it's considered a match with distance 0
- Fuzzy matches — Commands within a Levenshtein distance of 3 are included
- Alias-aware — Aliases declared via
meta.aliasesare matched as candidates, but every match is mapped back to its canonical name before being reported. So a typo of an alias (issuessforissues) suggests the canonical (issue), and a candidate that matches both an alias and its canonical is deduplicated. - Sorting — Results are sorted by distance (closest first), then alphabetically
Only the top suggestion appears in the "Did you mean?" message. All available commands are listed separately (in error mode).
Plugin Order
The didYouMeanPlugin wraps the middleware chain in a try/catch. Place it before the help plugin so it can catch routing errors:
new Crust("my-cli")
.use(versionPlugin("1.0.0"))
.use(didYouMeanPlugin({ mode: "help" }))
.use(helpPlugin())Non-Matching Errors
The plugin only handles COMMAND_NOT_FOUND errors. All other errors are re-thrown and handled normally by the middleware chain or .execute().
Type
interface DidYouMeanPluginOptions {
mode?: "error" | "help"; // Default: "error"
}
function didYouMeanPlugin(options?: DidYouMeanPluginOptions): CrustPlugin;