Crust logoCrust

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, deploy

Configuration

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, deploy

Help 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 number

How Suggestions Work

The plugin uses Levenshtein distance to find similar commands:

  1. Prefix matches — If the input is a prefix of a command (or vice versa), it's considered a match with distance 0
  2. Fuzzy matches — Commands within a Levenshtein distance of 3 are included
  3. Alias-aware — Aliases declared via meta.aliases are matched as candidates, but every match is mapped back to its canonical name before being reported. So a typo of an alias (issuess for issues) suggests the canonical (issue), and a candidate that matches both an alias and its canonical is deduplicated.
  4. 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;

On this page