Nushell 0.86

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.86 of Nu. This release adds fish-like directory completions, type system improvements, our first officially supported uutils command, and much more.

Where to get it

Nu 0.86 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
The optional dataframe functionality is available by cargo install nu --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>.

Table of content

Themes of this release / New features [toc]

Hall of fame [toc]

Bug fixes [toc]

Thanks to all the contributors below for helping us solve issues and bugs 🙏. This effort is a major part of what is moving Nushell closer to 1.0 with each release.

authortitlepr
@anka-213open in new windowFix exponential parser time on sequence of [[[[#10439open in new window
@anka-213open in new windowFix tilde-expansion for multi-byte unicode chars#10434open in new window
@sholderbachopen in new windowImprove select row perf for large N#10355open in new window
@anka-213open in new windowPrevent cubic time on nested parentheses#10467open in new window
@amtoineopen in new windowfix public boolean switches in the standard library#10477open in new window
@bobhyopen in new windowstd dt datetime-diff: fix uninitialized field ref when borrowing#10466open in new window
@NotLebedevopen in new windowFix default argument value type checking#10460open in new window
@fdncredopen in new windowfix magenta_reverse and friends#10491open in new window
@zhiburtopen in new windownu-table: Fix failing test (relied on termwidth assumptions)#10492open in new window
@sholderbachopen in new windowFix editor config for reedline and config nu/env#10535open in new window
@fennewaldopen in new windowFix Default Prompt Tilde Insertion Logic#10539open in new window
@jntrnropen in new windowfix windows default prompt slash direction#10555open in new window
@lavafrothopen in new windowfix: complete paths surrounded by quotes or backticks#10600open in new window
@dmatos2012open in new windowucp: Change error when directory is specified but not recursive#10609open in new window
@zhiburtopen in new windownu-explore: Try to fix a truncation issue in expand view#10580open in new window
@kubouchopen in new windowFix wrong parsing of signatures in predecl scan#10637open in new window
@kubouchopen in new windowFix parsing of signature inp/out types in predecls#10642open in new window
@gaetschwartzopen in new windowfix labelled error from shell error#10639open in new window
@CAD97open in new windowFix registry query flag validation#10648open in new window
@CAD97open in new windowFix clippy in registry_query.rs#10652open in new window
@WindSoilderopen in new windowfix clippy#10659open in new window
@sholderbachopen in new windowFix output types of math commands to be narrower#9740open in new window
@zhiburtopen in new windownu-table: Use config color scheme in kv tables and table -e#10720open in new window
@lavafrothopen in new windowfix: only escape path containing numbers if they can be valid floating points#10719open in new window
@fdncredopen in new windowevaluate $nu during --ide-check#10470open in new window
@WindSoilderopen in new windowallow early return outside of main#10514open in new window
@lavafrothopen in new windowPreserve relative paths for local files#10658open in new window
@bobhyopen in new windowglob with ../ prefix now works;#10504open in new window
@fnuttensopen in new windowAdd support for HTTP proxy in network commands#10401open in new window

Enhancing the documentation [toc]

Thanks to all the contributors below for helping us making the documentation of Nushell commands better 🙏

authortitlepr
@sholderbachopen in new windowDocstring some intricacies around SyntaxShape#10544open in new window
@Hofer-Julianopen in new windowAdd long options for bits and bytes#10601open in new window
@Hofer-Julianopen in new windowAdd long options for conversions#10602open in new window
@Hofer-Julianopen in new windowUse long options for debug#10621open in new window
@Hofer-Julianopen in new windowAdd long options for core and dataframes#10619open in new window
@Hofer-Julianopen in new windowAdd long options for filters#10641open in new window
@Hofer-Julianopen in new windowAdd long options for formats#10645open in new window
@amtoineopen in new windowadd examples with .. and / to path join#10620open in new window
@DanyPDevopen in new windowAdd themes to help command when available #10318#10623open in new window

Internal changes [toc]

Thanks to all the contributors below for working on the internals of Nushell, doing refactoring and bookkeeping, ... 🙏

authortitlepr
@fdncredopen in new windowallow values command to support LazyRecords#10418open in new window
@sholderbachopen in new windowRemove dead BSON related tests#10458open in new window
@sholderbachopen in new windowSimplify nu! test macros.#10403open in new window
@sholderbachopen in new windowImprove assertions in src/tests.rs#10449open in new window
@sholderbachopen in new windowSplit up nu-protocol/src/engine/engine_state.rs#10368open in new window
@sholderbachopen in new windowRemove unused SyntaxShape::Variable#10511open in new window
@sholderbachopen in new windowRemove parsing literals of unrepresentable SyntaxShapes#10512open in new window
@amtoineopen in new windowbreak the definition of LS_COLORS onto multiple lines#10538open in new window
@sholderbachopen in new windowRename SyntaxShape::Custom to CompleterWrapper#10548open in new window
@bobhyopen in new windowtoolkit check pr does same clippy checks as github CI#10528open in new window
@Hofer-Julianopen in new windowchore: Small refactor of eval.rs#10554open in new window
@stormasmopen in new windowengine eval.rs remove pub from fn eval_element_with_input#10587open in new window
@sholderbachopen in new windowParse custom completer annotation only in args#10581open in new window
@sholderbachopen in new windowMove SyntaxShape specifier parsing into own file#10448open in new window
@Hofer-Julianopen in new windowLet run_in_login_mode succeed even with broken local config#10622open in new window
@fdncredopen in new windowchange canonicalize test use a more deeply rooted folder#10685open in new window
@quat1024open in new windowUse heck for string casing (again)#10680open in new window
@lavafrothopen in new windowrefactor: move the partial_from function to the single place it is invoked#10705open in new window

Platform support [toc]

Thanks to all the contributors below for helping Nushell be used on more platforms easily 🙏

authortitlepr
@fdncredopen in new windowoptimize aarch64 when able#10433open in new window
@hustceropen in new windowAdd full releases of Nu binaries along with the standard releases#10457open in new window
@hustceropen in new windowfeat: Update nightly build workflow add full release support#10485open in new window
@hustceropen in new windowUpdate winget submission workflow include only default msi files#10487open in new window
@hustceropen in new windowImprove release script for github release workflow#10502open in new window
@hustceropen in new windowUpdate build flags for riscv64gc and armv7 targets#10564open in new window

Making errors better [toc]

Thanks to all the contributors below for making errors better and less confusing for users 🙏

authortitlepr
@amtoineopen in new windowshow the whole path in "missing mod.nu" errors#10416open in new window
@amtoineopen in new windowshow the full directory / file path in "directory not found" error#10430open in new window
@WindSoilderopen in new windowmake better error message for not operator#10507open in new window
@amtoineopen in new windowimprove assertion error messages in std assert#10551open in new window
@GPadleyopen in new windowMap DirectoryNotFound to FileNotFound for open command (issue #10085)#10089open in new window
@brunerm99open in new windowAdd warning to url join when input key is not supported (#10506)#10565open in new window
@amtoineopen in new windowmake "can't follow stream paths" error a bit better#10569open in new window
@brunerm99open in new windowgive better error if required field of url join is invalid#10589open in new window

Improving the completions in the REPLopen in new window [toc]

With Nushell 0.86.0 come a few improvements to the completions!

@ZerdoX-xopen in new window did add built-in support for the doas command in addition to sudo in #10256open in new window.

In #10543open in new window, @lavafrothopen in new window have implement Fish-like completions for nested directories. This means that now typing tar/de/inc in the REPLopen in new window of Nushell and hitting TAB will autocomplete to ./target/debug/incremental if you are in a Rust directory with compiled artifact.

Animation showing shorthand directory expansion

Breaking change

See a full overview of the breaking changes

As a consequence to #10543open in new window, @jntrnropen in new window helped remove the cd with abbreviation feature from Nushell. This feature will be taken care of by the Fish-like completions described above and the removal mainly means that $env.config.cd.abbreviations is not longer a valid config field: do not forget to update your configs 😉

The type system [toc]

With this new release, we are still working on the type system of Nushell.

@WindSoilderopen in new window has been working on the arguments and options of custom commands. With #10424open in new window, default values won't overwrite type annotations anymore, i.e. the following is now possible:

def foo [x: any = null] { print $"$x" }

foo "string"  # will show `x: string`
foo null      # will show `x: `

Breaking change

See a full overview of the breaking changes

Continuing with the options on custom commands, let's talk about an important change introduced by #10456open in new window about boolean switches:

  • annotating a boolean option will create an option and will require to pass a boolean value
def foo [--option: bool] { if $option { print "yeah" } }

foo --option        # will give an error
foo --option false  # won't print anything
foo --option true   # will print "yeah"
  • to create a boolean switch, you need to omit the type annotation
def bar [--switch] { if $switch { print "yeah" } }

bar           # won't print anything
bar --switch  # will print "yeah"

💡 Note Boolean options are one step towards addressing a major pain point of Nushell: Passing flags around to other commands. Calling a command with a flag, such as def inner [--foo] { ... }, from another command used to require if-else to pass the flag:

def outer [--foo] {
   if $foo {
       inner --foo
   } else {
       inner
   }
}

With boolean options, it is now possible to define def inner [--foo: bool] { ... } and then call simply as

def outer [--foo] {
   inner --foo $foo
}

Once again, @NotLebedevopen in new window has been pushing forward type annotations to their limits, this time by allowing complex types in input/output signaturate for custom commands and in let assignments. This means that #10405open in new window allows one to write things like:

let my_r: record<a :int> = { a: 123 }

or

def my_complex_command []: nothing -> record<a: int> { { a: 123 } }

💡 Note
other contributions worth mentionning about the type system:

authortitlepr
@sholderbachopen in new windowUse int type name consistently#10579open in new window
@sholderbachopen in new windowRelax type-check of key-less table/record#10629open in new window
@fdncredopen in new windowchange Type::Float => SyntaxShape::Number to SyntaxShape::Float#10689open in new window

Unified command definitions

Nushell currently has three ways to define a command:

  • def to define a regular command
  • def-env to define a command that preserves the environment
  • extern-wrapped to define a command with a signature where unknown flags and parameters are collected into strings without throwing an error
  • (extern defines an external signature, not a real command)

In this release, @kubouchopen in new window unified the syntax in #10566open in new window such that the def-env and extern-wrapped are now defined with the --env and --wrapped options to the def keyword. We made this change to go in line with the let-env removal and simplifying the language in general. Also, confusingly, extern-wrapped has nothing to do with extern apart from the permissive signature. We hope the new notation makes it clearer. A bonus feature of this change is that now you can define def --env --wrapped!

💡 Note In the next release, def-env and extern-wrapped will get deprecated. If you have any of those definitions in your scripts, simply replace them with def --env or def --wrapped. In the following releases, they will be removed completely.

Some news with the standard library [toc]

Thanks to @Yethalopen in new window and their work in #10545open in new window, the use of the test runner and the std testing run-tests command should be faster!

Work has been done to improve the std log module:

Finally, a bug with std dirs goto, a shell command in the prelude of the library, has been fixed by @bobhyopen in new window in #10706open in new window.

Miscellaneous [toc]

Nushell now supports the keyboard enhancement protocol from Kittyopen in new window with the work of @Abdillahopen in new window in #10540open in new window. This feature is off by default but can be turned on in config.nu with the $env.use_kitty_protocol config option.

Nushell and Direnv are now integrated with each other thanks to @amtoineopen in new window in direnv/direnv#1175open in new window and #10675open in new window.

With the changes from #10593open in new window written by @gaetschwartzopen in new window, open can now read tar.gz file because from can handle multiple extensions. To be more precise, if from tar.gz and from gz are defined at the same time, open foo.tar.gz will try to call from tar.gz first and then fall back to from gz.

Let's finish with some delight to make the Nushell experience a bit nicer:

Our set of commands is evolving [toc]

As usual, new release rhyms with changes to commands!

It's official! 🥳 With the landing of PR 10678open in new window the uutils/coreutils version of cp is now the default copy command in nushell. We're so happy to have this command landed and we're working on several other commands. If you'd like to help out please visit our Discordopen in new window and ask about helping. The coreutilsopen in new window team would also appreciate your help since changes need to be made there before integrating into nushell.

New commands [toc]

  • when parsing raw data streams from external commands, a common task in Nushell is to give explicit types to all fields and columns of the parsed data structure. Until now, this had to be done manually but, thanks to @fdncredopen in new window and #10427open in new window, the new into value command should help make that task easier by trying to infer the types for you:
# should help you catch integer user and group IDs in the `/etc/passwd` file on *nix systems
open /etc/passwd | lines | split column ":" user . uid gid desc home shell | into value
unfold [0, 1] {|fib| {out: $fib.0, next: [$fib.1, ($fib.0 + $fib.1)]} } | first 10

To crawl multi-page API responses, e.g. when listing issues of a GitHub repository, the unfold is very handy and allows to transform

mut pages = []
for page in 1.. {
  let resp = http get (
    {
      scheme: https,
      host: "api.github.com",
      path: "/repos/nushell/nushell/issues",
      params: { page: $page, per_page: $PAGE_SIZE }
    } | url join)

  $pages = ($pages | append $resp)

  if ($resp | length) < $PAGE_SIZE {
    break
  }
}
$pages

into

unfold 1 {|page|
  let resp = http get (
    {
      scheme: https,
      host: "api.github.com",
      path: "/repos/nushell/nushell/issues",
      params: { page: $page, per_page: $PAGE_SIZE }
    } | url join)

  if ($resp | length) < $PAGE_SIZE {
    {out: $resp}
  } else {
    {out: $resp, next: ($page + 1)}
  }
}

Changes to existing commands [toc]

The open command is now case-insensitive when it comes to file extensiens thanks to @poketchopen in new window in #10451open in new window.

A bug inside from ics and from vcf has been fixed thanks to @joergschopen in new window in #10577open in new window.

Breaking change

See a full overview of the breaking changes

With #10526open in new window from @WindSoilderopen in new window, the --column option of the rename command now takes a record instead of a list:

> ls | where type == file | rename --column {name: filename, size: nb_bytes}
#┬filename─┬type┬nb_bytes┬─────modified──────
0│LICENSE  │file│ 35.1 KB│2022-12-23 11:34:42
1│README.md│file│  9.3 KB│2023-10-04 18:41:25
─┴─────────┴────┴────────┴───────────────────

The do command can now mutate its outside environment with a new --env option added by @ClipplerBloodopen in new window in #10572open in new window. This means that the following will now be possible:

do --env { cd some/where }

A few updates on the explore command [toc]

Once again, @rgwoodopen in new window has done work to simplify the explore command

Deprecated commands [toc]

The following commands and options are being deprecated and will be removed soon:

Removed commands [toc]

The following commands are being removed from Nushell:

Breaking changes [toc]

In 0.86, we now differentiate between a switch --x and a flag with a boolean argument --x: bool. If you declare a flag as a parameter and give it the : bool type annotation, we now require that the flag is followed by a boolean value. Previously, we took the boolean type to mean that the flag was actually a switch.

Before

> [UserID ABCdefGHI foo123bar] | str camel-case
╭───┬───────────╮
 0  userID    
 1  abcdefGHI 
 2  foo123Bar 
╰───┴───────────╯
> [UserID ABCdefGHI foo123bar] | str snake-case
╭───┬─────────────╮
 0  user_id     
 1  ab_cdef_ghi 
 2  foo_12_3bar 
╰───┴─────────────╯

After

> [UserID ABCdefGHI foo123bar] | str camel-case
╭───┬───────────╮
 0  userId    
 1  abCdefGhi 
 2  foo123bar 
╰───┴───────────╯
> [UserID ABCdefGHI foo123bar] | str snake-case
╭───┬─────────────╮
 0  user_id     
 1  ab_cdef_ghi 
 2  foo123bar   
╰───┴─────────────╯

cd with abbreviations was a feature you could enable to expand an abbreviated path for you automatically. It would do so after you hit return. In comparing the experience between this and the fish-like path abbreviation completions added in 0.86, we decided the new style of completions satisfied this in a much more visual way.

After this change, we need to use -c flag like this:

> [[a, b, c]; [1, 2, 3]] | rename -c { a: ham }
But we can rename many columns easily, here is another example:
> [[a, b, c]; [1, 2, 3]] | rename -c { a: ham, b: ham2 }

Full changelog [toc]

Nushell

Extension

Documentation

Nu_Scripts

Reedline