Nushell 0.72

Nushell, or Nu for short, is a new shell that takes a modern, structured approach to your command line. It works seamlessly with the data from your filesystem, operating system, and a growing number of file formats to make it easy to build powerful command line pipelines.

Today, we're releasing version 0.72 of Nu. This release includes many new features: mutability, looping, early returns, changes to the core commands, and much more.

Where to get it

Nu 0.72 is available as pre-built binariesopen in new window or from crates.ioopen in new window. If you have Rust installed you can install it using cargo install nu.

NOTE: as part of this release, we are no longer including additional features in --features=extra. With 0.72, SQLite features have moved into the main Nushell installation and dataframe functionality is now part of --features=dataframe.

As part of this release, we also publish a set of optional plugins you can install and use with Nu. To install, use cargo install nu_plugin_<plugin name>.

Themes of this release / New features


Starting with 0.72, it's now much easier to run a command that might fail and then handle the failure if it happens.

try {
    1 / 0
} catch {
    print "look, no crash"

The catch part of the try/catch is optional. Without it, the try block will run, and any error that occurs will be ignored.

You can also access the error, if one happens, using a closure syntax:

try {
    1 / 0
} catch {|e|
    print "look, no crash."
    print $e

Auto-expanding data views

Expanded data view

With the new default config, we now also detect the terminal width and will automatically expand the data view to include more information if it's available.

This uses an improved expanding data view capability from 0.70.


This release also includes a new way of redirecting the stdout and/or stderr of external commands. This gives easier access to the output streams than was previously possible.

> cat foo.txt out> bar.txt
> cat missingfilename.txt err> my_error.txt

You can also create a stream built from the above, allowing one stream to empty and then be followed by the other stream:

> git status out+err> git_status.txt


We have now split closures and blocks into two separate value types. A closure can have parameters, can close over variables outside of its scope, and can be passed as a value.

An example closure:

ls | each {|it| print $ }

You can also think of creating a custom command like def foo [] { ... } as creating a closure.

A block is much simpler and is used as the bottom of commands like if and loops.

An example block:

if true {
    print "hello!"

Blocks don't close over (or capture) variables, don't have parameters, and can't be passed as a value. Blocks, however, do have one special trick...


Starting in this release, you can create local mutable variables. You can create mutable variables using the mut keyword:

mut x = 1
$x = $x + 100
print $x

A mutable variable can only live and change in the closure in which it's created. Blocks, however, have access to the mutable variables in the parent closure. For example, mutating a variable inside of the block used in an if call is valid:

mut x = 1
if true {
    $x += 1000
print $x


The 0.72 release also includes a few new looping commands: loop and while.

The loop command runs a block forever:

loop {
    print "hit ctrl-c to break out of this example"

The while command will run its block as long as a condition is met:

mut x = 0
while $x < 10 {
    print $x
    $x += 1


Loops can now also use the break and continue feature common in many programming languages. break will break out of the current loop. And continue will continue the loop at the next iteration.


The 0.72 release also includes the ability to return early from a closure or command.

def foo [x] {
    if $x > 10 {
        return 1000

Command refinement, simplification, and elimination

This release contains many breaking changes to Nu's built-in commands (sorry!). As we move toward version 1.0 we want to ensure that Nu ships with a small curated set of consistent, well-designed "standard library" commands. This requires taking a hard look at existing commands, and in some cases breaking changes are unavoidable. We expect that this effort will span a few release cycles.

Dataframes no longer included by default - smaller binaries

Nu's dataframe support is extensive, impressive, and very useful to users who rely on it. However, it comes at a high cost in terms of compile time, binary size, and complexity. Starting with version 0.72, dataframe commands are no longer included in the release binaries published on GitHub or the default binaries published via package managers (like Homebrew, winget, Scoop). As a result of this change, the main Nu executable is now about 50% smaller.

To continue using dataframe commands, you can build Nu from source using the dataframe Cargo featureopen in new window. For example, to install using Cargo: cargo install nu --features=dataframe

Allow reloading overlay definitions (kubouchopen in new window)

A common pattern in using overlays is shadowing an existing environment variable, such as PROMPT_COMMAND. However, overlay use would keep loading the value from the first activation. It is best explained with an example. Assume the following module:

module prompt {
    export-env {
        let-env PROMPT_COMMAND = (date now | into string)

Calling overlay use prompt for the first time changes the prompt to the current time, however, subsequent calls to overlay use won't change the time. That's because overlays, once activated, store their state so they can be hidden and restored at later time. To force-reload the environment, we added a new --reload flag: Calling overlay use --reload prompt repeatedly now updates the prompt with the current time each time.

virtualenv activation changes (kubouchopen in new window)

Since the version 20.17.0 of virtualenvopen in new window, the new way to activate an environment is to call overlay use instead of the source This change is in line with gradual deprecation of source and moving us towards using modules as overlays in more cases. Please, check the activation script itselfopen in new window for more details.

Breaking changes

New boolean operator xor - Planned operator simplification

To complement our logical boolean operators and/&& and or/|| we added boolean xoropen in new window. This is consistent with bit-and, bit-xor, and bit-or.

We are currently considering to deprecate the C-style symbols &&/|| in favor of the spelled out and/or to increase consistency and provide more actionable error messages when trying to use &&/|| in a similar fashion to bash.

Config options have been grouped together

The structure of $env.config (and thus the record used with let-env config = statements in and other places) has been reorganised. Various options are now grouped into subrecords (similar to table_trim) and had their names shortened. This allows files to be better structured, and thus easier to edit and read, while also allowing future options to be added without making the


Your existing options WILL still work in this version!! However, you will get a warning message if you use the old versions of the options (as you might already be aware). Support for these old options will be dropped in a future Nushell update, so take care to convert your files when you can.

The changes are:

  • use_ls_colors and clickable_links have been moved to into an ls subrecord.
  • rm_always_trash has been moved into the rm record. Further rm config options to accompany it may appear in the future.
  • cd_with_abbreviations has been moved into a cd record. Further cd config options to accompany it may appear in the future.
  • history_file_format, sync_history_on_enter and max_history_size have been moved to a history subrecord.
  • filesize_metric and filesize_format have been moved to a filesize subrecord.
  • case_sensitive_completions, quick_completions, partial_completions and completion_algorithm have been moved into a completions subrecord.
  • The completions subrecord also contains an external subrecord.
    • enable_external_completion, max_external_completion_results, and external_completer have been moved into the aforementioned subrecord.
  • table_mode, table_index_mode and the table_trim subrecord have been moved into a table subrecord.

The new grouped options look like this:

  ls: {
    use_ls_colors: true # use the LS_COLORS environment variable to colorize output
    clickable_links: true # enable or disable clickable links. Your terminal has to support links.
  rm: {
    always_trash: true # always act as if -t was given. Can be overridden with -p
  cd: {
    abbreviations: true # allows `cd s/o/f` to expand to `cd some/other/folder`
  table: {
    mode: rounded # basic, compact, compact_double, light, thin, with_love, rounded, reinforced, heavy, none, other
    index_mode: always # "always" show indexes, "never" show indexes, "auto" = show indexes when a table has "index" column
    trim: {
      methodology: wrapping # wrapping or truncating
      wrapping_try_keep_words: true # A strategy used by the 'wrapping' methodology
      truncating_suffix: "..." # A suffix used by the 'truncating' methodology
  history: {
    max_size: 10000 # Session has to be reloaded for this to take effect
    sync_on_enter: true # Enable to share history between multiple sessions, else you have to close the session to write history to file
    file_format: "plaintext" # "sqlite" or "plaintext"
  completions: {
    case_sensitive: false # set to true to enable case-sensitive completions
    quick: true  # set this to false to prevent auto-selecting completions when only one remains
    partial: true  # set this to false to prevent partial filling of the prompt
    algorithm: "prefix"  # prefix or fuzzy
    external: {
      enable: true # set to false to prevent nushell looking into $env.PATH to find more suggestions, `false` recommended for WSL users as this look up my be very slow
      max_results: 100 # setting it lower can improve completion performance at the cost of omitting some options
      completer: null # check 'carapace_completer' above as an example
  filesize: {
    metric: true # true => KB, MB, GB (ISO standard), false => KiB, MiB, GiB (Windows standard)
    format: "auto" # b, kb, kib, mb, mib, gb, gib, tb, tib, pb, pib, eb, eib, zb, zib, auto

To output your existing options in the above format (that could be pasted into your file before you delete the old options), run this code in your copy of Nushell:

$env.config | do { { ls: { use_ls_colors: $in.use_ls_colors clickable_links: $in.show_clickable_links_in_ls } rm: { always_trash: $in.rm_always_trash } cd: { abbreviations: $in.cd_with_abbreviations } table: { mode: $in.table_mode index_mode: $in.table_index_mode trim: $in.table_trim } history: { max_size: $in.max_history_size sync_on_enter: $in.sync_history_on_enter file_format: $in.history_file_format } completions: { case_sensitive: $in.case_sensitive_completions quick: $in.quick_completions partial: $in.partial_completions algorithm:$in.completion_algorithm external: { enable: $in.enable_external_completion max_results: $in.max_external_completion_results completer:$in.external_completer } } } } | to nuon | str substring 1..-1

Minimum Rust version has bumped to 1.65

Due to some breakage in dependencies, we've gone ahead and bumped the required version of Rust to 1.65, which addresses the issue. Apologies to anyone who is inconvenienced by the bump. We anticipate returning to the Rust-1 versions in the future.

Full changelog