Nushell Command Completion Guide

Configure Nushell command completion with Carapace and Fish for tools like Git and Docker, and choose a completer per command to speed up terminal work.
Back

📢 Update

Nushell 0.116 reworked the Completion API. In the latest version, external completers now natively support alias resolution, so you no longer need to write your own logic to expand or complete aliases.

This post has been updated accordingly:

  • Updated the Completion API configuration syntax;
  • Removed the now-redundant section on alias handling.

Nushell is a modern shell built with Rust. Unlike Fish, which only supports UNIX platforms, Nushell runs across platforms, so you can use the same shell on different systems. It also has an active community.

Fish has a more mature completion ecosystem, though. For example, it natively supports completion for Claude Code, while Nushell community support for it arrived a little later.

The good news is that Nushell offers two approaches to completion, and they work well together:

  1. Custom Completions: hand-written completion scripts. See the Nushell community script repository.
  2. External Completers: bridges to external completion tools such as Fish, Carapace, and Zoxide.

This post focuses on the second approach: reusing Fish’s completion capabilities in Nushell.

Overall Architecture

In completions.nu, we split the completion system into two core modules:

  1. Bridge: connects to external completion systems (Fish / Carapace).
  2. Dispatcher: selects the most suitable completer for each command.
内置 / 原生补全器外部桥接 Bridge原生/特定命令其他命令行工具用户输入分发调度 Dispatcher根据命令类型匹配最佳补全器Nu Native Completer自定义逻辑 / 复杂规则Fish Shell CompleterCarapace Completer返回补全候选词列表

Step 1. Bridge Fish and Carapace

Fish is a mature shell with an extensive completion ecosystem. It also provides a complete --do-complete interface that lets us call its completion logic directly from the command line:

# Call Fish's completion logic to get candidates for `git switch or`$ fish --command "complete --do-complete 'git switch or'"origin/HEAD    Remote Branchorigin/dev     Remote Branchorigin/main    Remote Branch

Carapace is another general-purpose, cross-platform completion engine that provides a common interface for multiple shells. Call it with carapace <command> <shell> <args...> to get completion data directly in JSON format:

# Call Carapace to get JSON completion output for `git switch or` in Nushell# Carapace outputs JSON on a single line by default; jq formats it here for readability$ carapace git nushell git switch or | jq[  {    "value": "origin/head ",    "display": "origin/head",    "description": "remote branch"  },  {    "value": "origin/dev ",    "display": "origin/dev",    "description": "remote branch"  },  {    "value": "origin/main ",    "display": "origin/main",    "description": "remote branch"  }]

With Nushell’s External Completer API, we can integrate these capabilities into Nushell:

let fish_completer = {|place|    fish --command $"complete '--do-complete=($place.command | str replace --all "'" "\\'" | str join ' ')'"    | from tsv --flexible --noheaders --no-infer    | rename value description    | update value {|row|      let value = $row.value      let need_quote = ['\' ',' '[' ']' '(' ')' ' ' '\t' "'" '"' "`"] | any {$in in $value}      if ($need_quote and ($value | path exists)) {        let expanded_path = if ($value starts-with '~') {$value | path expand --no-symlink} else {$value}        $'"($expanded_path | str replace --all "\"" "\\\"")"'      } else {$value}    }}let carapace_completer = {|place|    CARAPACE_LENIENT=1 carapace $place.command.0 nushell ...$place.command | from json}

Step 2. Dispatch to a Completer

Completion quality varies by tool and completer:

  • Some tools have the most complete support in Fish, such as git and bun.
  • Others are better served by Carapace.

So we use a dispatch strategy: send selected commands to Fish and everything else to Carapace.

With Nushell 0.116, the dispatcher can work directly with the command spans it receives, without any code to look up or expand aliases:

let external_completer = {|place|    match $place.command.0 {        nu | tv | bun | git | rclone => $fish_completer        _ => $carapace_completer    } | do $in $place}

Step 3. Enable the External Completer

Finally, enable external completion in the Nushell configuration:

$env.config.completions = {  case_sensitive: false  quick: true  partial: true  algorithm: "prefix"  external: {    enable: true    completer: $external_completer  }  use_ls_colors: true}

You can also configure menu and keybindings for a smoother experience. See my configuration repository, Efterklang/dotfiles.

Demo

Once configured, type ssh and press Tab to automatically list remote hosts from ~/.ssh/config. Completion for git is fully available too:

nu_completion
nu_completion