 ##  [A small contribution to Nushell: when completion should also look at the description](/index.php/node/229) 

    *Submitted by Lennart on Tue, 26 May 2026 - 12:17*  

 I recently made a small contribution to [Nushell](https://www.nushell.sh/) — the open source shell I use daily. It's a tiny improvement in how custom completers work, but it solves a specific friction I encountered every single time I had to use my own terminal tool. Here's what it's about.

## The Problem

In Nushell, you can write your own "completers" — small functions that suggest values when you press tab. A completion has two fields: a `value` (what gets inserted) and a `description` (what is displayed next to it). For example, a list of airports:

```
def "nu-complete airports" [] {
    [
        { value: "LAX", description: "Los Angeles" }
        { value: "JFK", description: "New York — John F. Kennedy" }
        { value: "CPH", description: "Copenhagen" }
        { value: "LHR", description: "London Heathrow" }
        { value: "NRT", description: "Tokyo Narita" }
    ]
}

```

Until now, Nushell only matched against the `value`. If you typed `LAX<tab>`, you would get `LAX — Los Angeles`. Fine. But if you couldn't remember the IATA code and just typed `Los<tab>`, you got nothing. The description was decoration, not something that could be searched.

It's annoying when it's your own brain that can't remember that Narita is `NRT` but can easily remember it's Tokyo.

## The Contribution

Custom completers can now choose to match the user's prefix against *both* value and description, by setting `match_description: true` in options:

```
def "nu-complete airports" [] {
    {
        options: {
            case_sensitive: false,
            completion_algorithm: "substring",
            match_description: true,
        },
        completions: [
            { value: "LAX", description: "Los Angeles" }
            { value: "JFK", description: "New York — John F. Kennedy" }
            { value: "CPH", description: "Copenhagen" }
            { value: "LHR", description: "London Heathrow" }
            { value: "NRT", description: "Tokyo Narita" }
        ]
    }
}

```

With `match_description: true` enabled, you can now type `Tokyo<tab>` and get `NRT` inserted. Or `Copenhagen<tab>` and get `CPH`. What's inserted is still always the `value` — the description is only for finding the right suggestion, not for ending up on the command line.

## Why it's a Small Thing with a Big Impact

I came up with it myself because I have a `send.nu` command that sends emails to contacts from my address book. Previously, I had to remember the email addresses. Now, I can type the recipient's name, press tab, and get the address inserted:

```
def "nu-complete recipients" [] {
    {
        options: {
            case_sensitive: false,
            completion_algorithm: fuzzy,
            match_description: true,
        },
        completions: (contacts | each {|c| { value: $c.EMAIL, description: $c.FN }})
    }
}

```

The brain remembers people by name, not by email string. The shell should meet the brain where it is.

## What I'm Taking Away

Two things.

First: open source is still the easiest way to get rid of a specific annoyance. The total time from "this should work" to "this works in everyone's installation in a few weeks" is manageable if the project is well-organized — and Nushell is.

Second: good tools meet you where you are. It's the same mindset I use when advising companies about AI. A system that requires the user to translate their own knowledge into the system's language (IATA codes, customer numbers, internal IDs) before it will help, is a system with a design flaw. Let the machine do the translation — it's better at it than we are.