Nushell 0.115.0
Today, we're releasing version 0.115.0 of Nu. This release brings a major YAML rework, the new $ans REPL variable for inspecting your last result, Helix-style editing, and a lot of internal cleanup and fixes.
Where to get it
Nu 0.115.0 is available as pre-built binaries or from crates.io. If you have Rust installed you can install it using cargo install nu.
As part of this release, we also publish a set of optional plugins you can install and use with Nushell.
Table of contents
Highlights and themes of this release [toc]
YAML's Always More Labor [toc]
Thanks to @cptpiepmatz, Nushell's YAML support got a proper rebuild. We now use a stable, modern, maintained implementation that no longer tries to make YAML 1.1, the scary one, and YAML 1.2 behave like one big YAML-shaped compromise.
The two specs are now handled separately, from yaml defaults to YAML 1.2, tags work more deliberately, multi-document streams are supported, anchors and merge keys behave properly, and to yaml is clearer about values that cannot round-trip.
Take a look at all the examples here.
Ah, the $ans.last pipeline took so long to run [toc]
Ever had your last pipeline take forever, only to realize you forgot to assign the result to a variable? Worry no longer. Thanks to @fdncred, Nushell now has $ans, a Nushell-specific answer variable heavily inspired by calculators.
$ans keeps track of the last REPL result, including the output, duration, exit code, and the command you typed. Storing the output is opt-in: set $env.config.max_last_result_size to a filesize of your choosing, and $ans.last will keep up to that much of the previous pipeline result.
That means if your pipeline took 15 minutes and you do not want to run it again, you can finally breathe, do a quick let took_too_long = $ans.last, and you're golden. Take a closer look here.
Helix mode! [toc]
Alongside Vim mode, Nushell now has helix edit mode too. Set it with $env.config.edit_mode = helix, and that's it. You get a selection-first, Helix/Kakoune-style editing experience with normal, select, and insert modes.
Thanks to @kronberger-droid for the work here. More details are here.
Lots of internal wrangling [toc]
This release does not have a huge pile of public user-facing additions, but there was a lot of work inside Nushell. Be in awe of the long list of things happening in the ✨ Hall of Fame ✨, and also check out the long list of fixes.
As always, a big shoutout to everyone contributing and making Nushell better. The internals may not always get the flashiest highlight section, but they are doing a lot of heavy lifting this time.
Changes [toc]
Breaking changes [toc]
YAML got a proper rework [toc] PR #18487 by @cptpiepmatz
YAML has been a problem child for quite some time now. This release replaces the old serde_yaml-based implementation with a new one built on serde-saphyr and granit-parser. With that we now get clearer YAML behavior, better round-tripping, proper tag support, multi-document streams, anchors, aliases, merge keys, and a few new options for configuring how the output should look like.
Breaking changes
The big breaking change is that Nu no longer tries to parse YAML as an awkward mix of YAML 1.1 and YAML 1.2. We now default to YAML 1.2, which is usually the the less crazy choice. If your files or scripts relied on old YAML 1.1 scalar magic, pass --spec 1.1.
use std/assert
# Default YAML 1.2 behavior: these stay strings.
assert equal ("yes" | from yaml) "yes"
assert equal ("off" | from yaml --spec 1.2) "off"
# YAML 1.1 keeps the classic YAML oddities.
assert equal ("yes" | from yaml --spec 1.1) true
assert equal ("off" | from yaml --spec 1.1) falseThis specifically breaks octal numbers. In the 1.1 spec, a value is interpreted as an octal number if it starts with the 0 digit. It is then parsed as an octal value. If the value is not valid octal, it is instead returned as a string.
The 1.2 spec made this much more sensible by allowing leading zeros on regular numbers and requiring octal numbers to use the 0o prefix.
use std/assert
# YAML 1.1 uses a leading zero as an octal indicator.
assert equal ("0247" | from yaml --spec 1.1) 0o247
assert equal ("0o247" | from yaml --spec 1.1) "0o247"
# YAML 1.2 replaced that with the `0o` prefix.
assert equal ("0247" | from yaml --spec 1.2) 0247
assert equal ("0o247" | from yaml --spec 1.2) 0o247Did you know that YAML 1.1 supports sexagesimal values like 190:20:30? No, well in the 1.1 spec these as base-60 numbers that can be used to represent time but noone knows that, so 1.2 got rid of them. And as Nushell now defaults to 1.2 we interpret these as strings.
use std/assert
assert equal ("190:20:30" | from yaml) "190:20:30"
assert equal ("190:20:30" | from yaml --spec 1.1) 685230
assert equal ("02472256" | from yaml) 2472256
assert equal ("02472256" | from yaml --spec 1.1) 685230from yaml is stricter about mapping keys now, too. Nushell record keys are strings, so plain YAML keys that resolve to booleans, numbers, or null are rejected by default. If you want the old loose behavior, use --key-resolution verbatim and Nushell will keep the original key text.
'true: enabled' | from yaml
# Error: YAML key resolves to a boolean, but Nushell record keys are strings
'true: enabled' | from yaml --key-resolution verbatim
# => {true: enabled}Tags also mean tags now. Previously, tagged scalars weren't really handled properly, often they were just ignored and handled as plain strings but in YAML they describe the data, usually as some types. Now unknown tags error by default but you can use --ignore-tags to just ignore the tags and deal with them yourself.
'Key: !Sub ${AWS::StackName}' | from yaml
# Error: unknown YAML tag
'Key: !Sub ${AWS::StackName}' | from yaml --ignore-tags
# => {Key: "${AWS::StackName}"}to yaml is also more specific about values that cannot round-trip. By default it errors instead of quietly turning them into something else. If that is unwatned, choose the behavior explicitly with --non-roundtrip null or --non-roundtrip lossy. The --serialize flag is still available but will probably be deprecated in the future.
{|| $in } | to yaml
# Error: closures are not round-trippable through YAML
{|| $in } | to yaml --non-roundtrip null
# => null
{|| $in } | to yaml --serialize
# => !closure "{|| $in }"One more relevant breaking change: generated YAML may not look exactly like it did before. The new serializer quotes strings more carefully, writes tags for Nushell-specific values, and lets you configure indentation. If you depended on a specific YAML output, you might need to check that.
Tags and round-tripping
Nushell now understands standard YAML tags like !!timestamp,!!binary, !!omap, !!pairs, and !!set. It also writes Nushell-specific local tags for values that YAML did not define globally, such as filesizes, durations, ranges, globs, and cell paths.
name: Cargo.toml
size: !filesize 17515
modified: !!timestamp 2026-08-14T23:30:19.144306+02:00
path: !cell-path $.items.0.nameHere, !filesize and !cell-path are Nushell tags, while !!timestamp is a standard YAML tag. When you read this back with from yaml, those fields come back as proper typed values instead of plain strings or integers.
If you want the YAML version and Nushell tag prefix written out explicitly, use to yaml --add-directives or to yaml -d.
ls | where name == Cargo.toml | first | to yaml --add-directives%YAML 1.2
%TAG ! tag:nushell.sh,2026:
---
name: Cargo.toml
type: file
size: !filesize 17515
modified: !!timestamp 2026-08-14T23:30:19.144306+02:00Multiple documents
YAML streams with more than one document work properly now. By default, from yaml returns a single document directly, but returns a list if the stream has multiple documents. If you want to be explicit, use --multiple list to always get a list or --multiple single to reject multi-document input.
name: dev
---
name: prod> $yaml | from yaml
╭───┬──────╮
│ # │ name │
├───┼──────┤
│ 0 │ dev │
│ 1 │ prod │
╰───┴──────╯
> 'name: dev' | from yaml --multiple list
╭───┬──────╮
│ # │ name │
├───┼──────┤
│ 0 │ dev │
╰───┴──────╯
> $yaml | from yaml --multiple single
Error: shell::yaml::parse::too_many_documents
× Too many documents
╭─[repl_entry #8:1:9]
1 │ $yaml | from yaml --multiple single
· ────┬────
· ╰── Found more than one document, but requested only one
╰────
help: Try without `--multiple single`
This also works the other way round. to yaml --multiple writes each item in a list as its own YAML document.
[{name: dev}, {name: prod}] | to yaml --multiplename: dev
---
name: prodAnchors, aliases, and merge keys
Anchors and aliases are handled more completely now, including merge keys. Previously this just did not work at all.
defaults: &defaults
timeout: 30
retries: 3
production:
<<: *defaults
timeout: 60> $yaml | from yaml | get production
╭─────────┬────╮
│ timeout │ 60 │
│ retries │ 3 │
╰─────────┴────╯Useful flags
On the parsing side, the main new flags are from yaml --spec 1.1|1.2, --multiple auto|list|single, --ignore-tags, and --key-resolution strict|verbatim.
On the writing side, the handy flags are --spec, --add-directives/-d, --multiple/-m, --indent/-i, --compact-list-indent, --quote/-q, --non-roundtrip, and --serialize/-s.
For example, --quote and --indent can help when another tool expects a particular style.
{outer: {inner: value}} | to yaml --indent 4 --quote doubleouter:
inner: 'value'Disallowed shadowing parser keywords [toc]
Trying to shadow a keyword will produce an error now.
> def def [] {}
Error: nu::parser::name_is_keyword
× Can't use parser keyword `def` as command name.
╭─[repl_entry #9:1:5]
1 │ def def [] {}
· ─┬─
· ╰── 'def' is a parser keyword
╰────
help: Parser keywords cannot be shadowed (including via module exports and `use *`). Choose a different command name
so language constructs keep working.
The nu binary no longer ships with --testbin [toc] PR #18719 by @cptpiepmatz
The nu binary used to include a handful of test binaries for our integration tests. These were available through nu --testbin. To reduce the size and complexity of the binary, this option is no longer available. Everything the test binaries could do can also be done with Nushell itself.
If your scripts depended on these test binaries, use an equivalent Nushell command or call nu -n -c "some commands" with the same behavior.
Other breaking changes [toc]
- Removed the
idx importandidx exportcommands, which had very little use case, as the search backend (FFF) is not designed for persistent disk caching.idx initis now the one way to build the in-memory index; watching remains enabled by default and can be disabled with--no-watch. (#18679)
Additions [toc]
drop now supports binary inputs, and chunks, first, last, take, skip and drop support filesize arguments [toc]
These commands can work on binary data, it only makes sense for them to work with not just int but filesize arguments as well:
# split compressed file into 10MiB chunks
open --raw file.7z
| chunks 10MiB
| enumerate
| each {|chunk|
let suffix = $chunk.index + 1 | fill -a right -c '0' -w 3
$chunk.item
| save $"file.7z.($suffix)"
}Added constant expressions in match arms [toc]
The match command can now evaluate constants in match arms like this:
> match "test" {
('t' + 'es' + 't') => { print 'OK' }
}
OKor a more real-world case:
> const MY_DIR_CONST = 'D:\Projects\nushell'
> let path = pwd
> $path
D:\Projects\nushell\crates\nu-command
> match $path {
($MY_DIR_CONST + '\sub-dir1') => { print "sub-dir" }
($MY_DIR_CONST + '\crates\nu-command') => { print "nu-command" }
}
nu-commandAdded external_arg annotations for script parameters [toc] PR #18512 by @skyrocket1643
You can now do the following:
def main [
a: external_arg
b: external_arg
-c: external_arg
...rest: external_arg
] {
[
[label value type];
[a $a ($a | describe)]
[b $b ($b | describe)]
[c $c ($c | describe)]
[rest $rest ($rest | describe)]
]
}Then:
> nu ./script.nu 0001 true -c true -- 001 true
╭───┬───────┬──────────────┬────────────╮
│ # │ label │ value │ type │
├───┼───────┼──────────────┼────────────┤
│ 0 │ a │ 0001 │ glob │
│ 1 │ b │ true │ glob │
│ 2 │ c │ true │ glob │
│ 3 │ rest │ ╭───┬──────╮ │ list<glob> │
│ │ │ │ 0 │ 001 │ │ │
│ │ │ │ 1 │ true │ │ │
│ │ │ ╰───┴──────╯ │ │
╰───┴───────┴──────────────┴────────────╯any and all now accept row conditions just like where [toc] PR #18353 by @Mrfiregem
In addition to the current closure syntax, any and all can now be given row conditions to make writing filters more streamlined.
[9 8 7 6] | enumerate | any item == index * 2Just like with where, you can reference column names directly, and use the $it variable to construct predicates given to both commands, or continue to use closures for more extensive constructions.
[1sec 1min 1hr] | all ($it | describe) == 'duration'Added matrix custom value and 21 subcommands [toc]
A new matrix custom value type enables high-performance matrix math in Nushell, backed by the ndarray library for Rust.
Constructors:
matrix zeros <dims>— create a matrix filled with zerosmatrix identity <n>— create an n×n identity matrixinto matrix— convert a table/list-of-lists/list-of-records into a matrix
Access:
matrix get-row <index>— extract a row as a listmatrix get-col <index>— extract a column as a list (2D only)matrix set-row <index> <values>— replace a rowmatrix set-col <index> <values>— replace a column (2D only)
Arithmetic:
matrix add <matrix|scalar>— element-wise addition with optional--broadcastmatrix subtract <matrix|scalar>— element-wise subtraction with optional--broadcastmatrix scale <scalar>— multiply all elements by a scalar- Matrix values also support
<operator>expressions:$m + $n,$m * 2.0,$m == $n
Linear algebra:
matrix multiply <matrix>— dot product (supports 1D×1D, 2D×1D, 1D×2D, 2D×2D)matrix transpose— swap rows and columns (nD reverses all axes)
Transforms:
matrix reshape <dims>— change dimensionsmatrix reshape --flatten— flatten to 1D
Element-wise: (could rename this to matrix each if map is confusing)
matrix map { |e| ... }— apply a closure to each element, returning a new matrix
Reductions:
matrix sum/matrix sum --axis <n>— sum all or along an axismatrix mean— arithmetic mean of all elementsmatrix max/matrix max --axis <n>— maximum all or along an axismatrix reduce --fold <init> { |acc e| ... }— fold all elements to a single value
Output:
matrix into-nu— convert to table (list of lists)matrix into-nu --as-records— convert to table of records with auto-generated column names
Examples
> # Create and manipulate matrices
> [[1 2 3] [4 5 6]] | into matrix | matrix transpose | matrix into-nu | to nuon
[[1.0, 4.0], [2.0, 5.0], [3.0, 6.0]]
> matrix identity 3 | matrix scale 5 | matrix into-nu | to nuon
[[5.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 0.0, 5.0]]
> # Matrix multiplication
> [[1 2] [3 4]] | into matrix | matrix multiply ([[1 0] [0 1]] | into matrix) | matrix into-nu | to nuon
[[1.0, 2.0], [3.0, 4.0]]
> # Element-wise operations
> [[1 2] [3 4]] | into matrix | matrix map { |e| $e * 2 } | matrix sum
20.0
> # Broadcasting
> matrix zeros 2 3 | matrix add --broadcast ([[1.0 2.0 3.0]] | into matrix) | matrix into-nu | to nuon
[[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]]
> # Row/column access
> matrix identity 2 | matrix get-row 1 | to nuon
[0.0, 1.0]
> # Shape metadata via cell path
> matrix identity 2 | $in.shape
╭───┬───╮
│ 0 │ 2 │
│ 1 │ 2 │
╰───┴───╯
> matrix identity 2 | $in.ndim
2
> matrix identity 2 | $in.size
4Standard iterator commands redirect to matrix-specific ones
eachon a matrix → errors: "Usematrix mapfor element-wise operations"par-eachon a matrix → errors: "Usematrix mapfor element-wise operations"reduceon a matrix → errors: "Usematrix reduce --fold <initial> { ... }"
Added std-rfc date floor and date ceil commands [toc]
Added two new std-rfc commands, date floor and date ceil for rounding datetime values down and up, respectively, to specified duration boundaries.
> use std-rfc/date *
> # Round down to the nearest hour
> 2026-07-15T12:11:10-04:00 | date floor 1hr
Wed, 15 Jul 2026 12:00:00 -0400 (a month ago)
> 1969-12-31T23:30:00+00:00 | date floor 1hr
Wed, 31 Dec 1969 23:00:00 +0000 (56 years ago)
> # Round date up to nearest hour
> 2026-07-15T12:11:10-04:00 | date ceil 1hr
Wed, 15 Jul 2026 13:00:00 -0400 (a month ago)
> 1969-12-31T23:30:00+00:00 | date ceil 1hr
Thu, 1 Jan 1970 00:00:00 +0000 (56 years ago)Added idx watch for streaming indexed filesystem changes [toc]
Added idx watch to stream filesystem change events from a live idx index as tabular records (kind, path). Requires idx init with watching enabled. Optional pattern, --ignore, --timeout, and --max-events are supported for filtering and clean stream termination. Events respect gitignore/index ignores and can be piped into normal Nushell pipelines.
Also updated the fff-search dependency to 0.10.0 (enables the watch subscription API).
Examples:
idx init . --wait
idx watch
idx watch "**/*.rs" --ignore [target]
idx watch | where kind == "modified" | each {|e| print $"changed: ($e.path)"}
idx watch --max-events 1 --timeout 5secAdded comparison operators for semver values [toc]
semver values can now be compared with ==, !=, <, <=, >, and >=, using normal semantic version ordering:
> ('2.0.1' | into semver) > ('1.9.9' | into semver)
true
> ('2.0.1' | into semver) < ('1.9.9' | into semver)
false
> ('1.2.3' | into semver) == ('1.2.3' | into semver)
true
> ('1.0.0-alpha' | into semver) < ('1.0.0' | into semver)
trueA version string on the right-hand side is also accepted when it is a valid semver:
> ('2.0.1' | into semver) > '1.9.9'
trueAdded --include to take while and take until [toc]
take until and take while commands get a new --include (-i) flag, which allows you to take extra items after the stream would have otherwise stopped:
> date now
| into record
| transpose key val
| take until { $in.key == day } --include 1
╭───┬───────┬──────╮
│ # │ key │ val │
├───┼───────┼──────┤
│ 0 │ year │ 2026 │
│ 1 │ month │ 8 │
│ 2 │ day │ 15 │
╰───┴───────┴──────╯Improved completion caching, dispatch, and reliability [toc] PR #18761 by @philocalyst
- Added
$env.config.completions.cache_size(default:100) to control that cap. - Completion results now persist across prompts instead of being discarded on every new prompt,.
- Fixed a potential panic when narrowing file/directory completions on a path containing multi-byte (non-ASCII) characters.
commandline complete --typenow validates its--typeargument and no longer panics on an out-of-range cursor.use,overlay use,export use,source-env,hide-env,attr complete, andwhichnow go through the same completion dispatch as other builtins, fixing inconsistent/missing completions in a few of them
Added commandline set-prompt for async prompt updates [toc] PR #18660 by @philocalyst
Added the commandline set-prompt command for ad-hoc updates to a rendered prompt.
Examples:
Stand-in values, with background job spawn:
$env.PROMPT_COMMAND = { $"(ansi green)~(ansi reset)> " }
$env.PROMPT_COMMAND_RIGHT = {
job spawn {
let branch = (git branch --show-current | complete | get stdout | str trim)
commandline set-prompt --right $"(ansi yellow)($branch)(ansi reset)"
}
"" # show nothing on the right until the background job fills it in
}# Replace the left prompt with a freshly rendered string.
job spawn { sleep 1sec; commandline set-prompt $"(ansi green)me> (ansi reset)" }
# Replace the right prompt.
job spawn { sleep 1sec; commandline set-prompt --right $"right (date now | format date '%H:%M:%S')" }
# Replace the default/emacs indicator.
job spawn { sleep 1sec; commandline set-prompt --indicator $" (char prompt)" }
# Replace the vi insert and normal mode indicators independently.
job spawn { sleep 1sec; commandline set-prompt --vi-insert ": " --vi-normal "n " }
# Replace the multiline continuation indicator.
job spawn { sleep 1sec; commandline set-prompt --multiline "... " }
# Replace multiple prompt segments in one call.
job spawn { sleep 1sec; commandline set-prompt --right "67" --indicator "69" }
# Stream a slow prompt segment in from a background job.
job spawn { sleep 1sec; commandline set-prompt $"(git branch --show-current) > " }Added $ans for accessing the last REPL result [toc]
$ans now stores information about the last successful Nushell result as a record, including its output, duration, and exit code. Like $in, $nu, and $env, $ans is now a reserved variable name, so scripts that use let ans = ... will need to be updated.
The amount of memory used to store the last output can be controlled with $env.config.max_last_result_size. It accepts a filesize and defaults to 0b, which disables storing the output in $ans.last and makes that part of the feature opt-in. The rest of the $ans record remains available.
To enable $ans.last, set $env.config.max_last_result_size to a reasonable value such as 1Mb. If the configured limit is reached, the stored output is truncated and a warning is shown when you access it.
> $env.config.max_last_result_size = 10mb
> ls | first 2
╭───┬────────────────┬──────┬───────┬──────────────╮
│ # │ name │ type │ size │ modified │
├───┼────────────────┼──────┼───────┼──────────────┤
│ 0 │ .cargo │ dir │ 0 B │ 2 weeks ago │
│ 1 │ .gitattributes │ file │ 113 B │ 2 months ago │
╰───┴────────────────┴──────┴───────┴──────────────╯
> $ans
╭───────────┬──────────────────────────────────────────────────────╮
│ │ ╭───┬────────────────┬──────┬───────┬──────────────╮ │
│ last │ │ # │ name │ type │ size │ modified │ │
│ │ ├───┼────────────────┼──────┼───────┼──────────────┤ │
│ │ │ 0 │ .cargo │ dir │ 0 B │ 2 weeks ago │ │
│ │ │ 1 │ .gitattributes │ file │ 113 B │ 2 months ago │ │
│ │ ╰───┴────────────────┴──────┴───────┴──────────────╯ │
│ exit_code │ 0 │
│ duration │ 14ms 474µs 800ns │
│ command │ ls | first 2 │
╰───────────┴──────────────────────────────────────────────────────╯$ans.last # previous pipeline value
$ans.exit_code # int (same idea as $env.LAST_EXIT_CODE)
$ans.duration # duration value (from the same timing as $env.CMD_DURATION_MS)
$ans.command # the last input as a raw stringAdded Helix edit mode [toc] PR #18830 by @kronberger-droid
Use $env.config.edit_mode = helix to enable a selection-first, Helix/Kakoune-style edit mode with normal, select, and insert modes. Motions extend or move the selection, while verbs act on it.
Menu keybindings such as Tab, Ctrl-r, and F1 work as they do in the other edit modes. Custom keybindings can target helix_normal, helix_insert, and helix_select, and cursor shapes can be configured with cursor_shape.helix_*.
Helix edit mode is included by default through the helix Cargo feature. To build without it, disable the default features with --no-default-features.
Added configurable visual selection styling [toc] PR #18838 by @kronberger-droid
Added color_config.selection and color_config.selection_cursor to style the line editor's visual selection and the cursor cell inside it:
$env.config.color_config.selection = { attr: r } # default
$env.config.color_config.selection_cursor = { attr: n } # defaultWith the defaults a block cursor looks as before; underscore and line cursor shapes are now visible inside selections.
Added KDL v1/v2 support and JSON-in-KDL output [toc]
from kdl and to kdl now support KDL language versions with --spec 1 or --spec 2 (default 2). Parsing is strict: v1 keyword style (true/false/null) and v2 style (#true/#false/#null) are not mixed unless you convert with an explicit emit spec.
> {a: 1, b: true} | to kdl --spec 1
- a=1 b=true
> {a: 1, b: true} | to kdl --spec 2
- a=1 b=#true
> "item 1 enabled=true" | from kdl --spec 1 | to kdl
item 1 enabled=true
Nu type annotations (YAML-tag analogue)
> # Promote (filesize) on from
> 'node (filesize)1024' | from kdl | get 0.args.0
1,0 kB
> # Emit annotated Nu types
> {size: 1kb} | to kdl
- size=(filesize)1000
Dual data models: nodes and JSON-in-KDL
from kdldefaults to--format nodes: a list of node rows (name,args,props,children) suitable for real config documents.to kdldefaults to--format jik: JSON-in-KDL with a single top-level-node, so records and lists serialize predictably.
> {a: 1, b: true} | to kdl
- a=1 b=#true
> [1 2 3] | to kdl
- 1 2 3
> 'node one; node two' | from kdl | to kdl
node one
node two
This replaces the previous to kdl heuristic that flattened values under synthetic node names such as root.
Added deprecation metadata to scope commands [toc] PR #18815 by @Mrfiregem
You can now programmatically access information about deprecated flags and commands using scope commands.
> scope commands | where name == "str downcase" | first | get deprecation_info.0
╭───────────────────────────┬─────────────────────────────────────────────────────────────────────────────────╮
│ type │ Command │
│ label │ str downcase was deprecated in 0.114.0 and will be removed in a future release. │
│ flag │ │
│ since │ 0.114.0 │
│ expected_removal │ │
│ help │ Use `str lowercase` instead. │
╰───────────────────────────┴─────────────────────────────────────────────────────────────────────────────────╯Added loose semver parsing and semver table coloring [toc]
Semantic version values are now displayed in cyan_bold in tables, making them easier to distinguish from other data types. into semver and into semver-range also now support a --loose option for parsing versions with common v-style prefixes, including v1.2.3, v.1.2.3, v:1.2.3, v-1.2.3, and v_1.2.3.
Other additions [toc]
- Added support for passing lists into
into semver, and for providing cell paths to do things like$nu.os-info | into semver kernel_versionor["1.2.0", "0.3.12"] | into semver. (#18567) polars rollingcan now be used natively with lazy frames and be used in expressions. (#18730)- Add support for additional arguments to
nu -c/nu --commandswith--(#18576) - Added completions to
format duration's andformat filesize's unit argument. (#18783) - In helix edit mode, keybindings with
mode: helix_selectnow target select mode's own keybinding table instead of being shared withhelix_normal. (#18833) - Added
to txtalongsideto text, following the existingto yaml/to ymlpattern. (#18735) into binarynow accepts duration input (e.g.1sec,1hr, …). (#18522)
Performance [toc]
Faster large binary value processing [toc]
Large binary values are now substantially cheaper to clone, stream, slice, and convert.
Commands that repeatedly process large binary values now avoid copying the entire value at each step, with repeated slicing and integer conversion roughly 3.4x faster.
Faster large list and table access [toc]
Large lists and tables are now much faster to read from, load from variables, and capture in closures.
Accessing a small part of a large list, such as $list.0, no longer copies the entire list each time the variable is loaded. In a 100,000-element test, 200 repeated reads improved from roughly 131 ms to 138 µs (~950x faster).
Other performance improvements [toc]
- Improved performance of
str replace --regexandstr replace --multilinewhen working with lists, tables, and records with many string values, roughly a 10x speed boost. (#18508) linescommand with string value (non-stream) input no longer eagerly creates a list. Instead it returns a list stream, producing items lazily just like it does with text/byte stream inputs. (#18753)- Using built-in commands with
--regexparameters should be faster in tight loops now because they are able to use the LRU cache for regex. (#18797)
Other changes [toc]
- It is now not allowed to have
export mainin a module that is named to shadow an keyword. This shows and error now. (#18619) - The default left and right prompts no longer include ansi color escapes if the user has disabled color. (#18506)
- Improved
hash md5andhash sha256help to show that both commands supportlist<string>andlist<binary>inputs. (#18638)
Bug fixes [toc]
Fixed nested try/finally blocks interfering with outer error handling [toc]
When nesting a try/finally block within a try or try/catch block, it no longer prevents the outer block from catching errors.
This is showcased by the following code:
# try-inner.nu
try {
try { print "inner" } finally { print "finally" }
error make { msg: "error" }
}
print "outer"Output before this change:
> run try-inner.nu
inner
finally
Error: nu::shell::error
× error
╭─[D:\Projects\nushell\scratch\try-inner.nu:3:14]
2 │ try { print "inner" } finally { print "finally" }
3 │ error make { msg: "error" }
· ────────────────
4 │ }
╰────
Note that the error was surfaced despite being thrown inside a try block!
Output after this change:
> run scratch/try-inner.nu
inner
finally
outerFixed negative arguments for oneof parameters [toc]
Parameters with int, float and number types can be supplied negative arguments:
> def foo [p: int] { $p }
> foo -2
-2However this didn't work with parameters with types like oneof<int, ...>:
> def foo [p: oneof<int, string>] { $p }
> foo -2
Error: nu::parser::unknown_flag
× The `foo` command doesn't have flag `-2`.
╭─[repl_entry #9:1:6]
1 │ foo -2
· ┬
· ╰── unknown flag
╰────
help: Use `--help` to see available flags
This is now fixed:
> def foo [p: oneof<int, string>] { $p }
> foo -2
-2Fixed ps -l failing when processes exit during collection [toc] PR #18542 by @rabindra789
Fixed a Linux race condition where ps -l could fail if a process exited while process information was being collected.
The exited process is now skipped instead of causing the command to fail.
Example
Before:
Error getting process stat
File not found: /proc/<pid>/statAfter:
ps -l continues running and omits the exited process.
Fix panic and infinite loop in seq on overflow and zero increment [toc] PR #18596 by @santhreal
seq now handles zero increments and integer overflow safely. Using seq <first> 0 <last> returns an increment cannot be 0 error instead of looping indefinitely or producing no output. Sequences that reach the i64 boundary also terminate cleanly rather than panicking or wrapping around.
Fixed recursive glob behavior in the experimental dc-glob backend [toc]
With --experimental-options=[dc-glob] enabled, recursive glob patterns now behave more consistently. A bare ** expands to directories at any depth, including the current directory, while **/* lists files and directories below the starting path without including the starting directory itself. Prefixed patterns such as foo/** similarly include the prefix directory and its nested directories, but not regular files.
Patterns with additional path segments, such as **/*/* and **/*/*/*, now once again enforce their expected minimum depth instead of ignoring the extra /* segments. This behavior differs slightly from the legacy nu-glob backend, but matches the common behavior of the glob crate.
Examples
# enable dc-glob for the session
NU_EXPERIMENTAL_OPTIONS=dc-glob nu
# or: nu --experimental-options=[dc-glob]
mkdir 0/1/2/3
touch 0/1/2/3/file.txt
cd 0
glob '**'
# start dir + nested directories only (no file.txt)
glob '**/*'
# everything under start ÔÇö not the start dir itself
glob '**/*/*'
# paths at least 2 components deep
glob '**/*/*/*'
# paths at least 3 components deep (e.g. 1/2/3 and 1/2/3/file.txt)
mkdir foo/bar
touch foo/sibling.txt
glob 'foo/**'
# foo and foo/bar only (not sibling.txt)Matcher-level checks (debug flags require dc-glob):
glob --dbg-matches '**/*/*' '1' # false
glob --dbg-matches '**/*/*' '1/2' # true
glob --dbg-matches '**/*/*/*' '1/2' # false
glob --dbg-matches '**/*/*/*' '1/2/3' # true
glob --dbg-matches '**/foo' 'foo' # true
glob --dbg-matches 'foo/**' 'foo' # true
glob --dbg-matches 'foo/**' 'foo/bar' # true
glob --dbg-matches 'foo/**' 'foobar' # false
glob --dbg-matches '*/*' '1' # falseFixed inconsistent group-by handling of null keys [toc]
group-by no longer maps null to the empty string, and treats null the same for list values, cell paths, and closures.
> # list: null became "" → 2 groups
> [ a null ] | group-by | values | length
2
> # cell path: null dropped → 1 group
> [ { x: a } { x: null } ] | group-by x | values | length
1
> # closure: null became "" → 2 groups
> [ { x: a } { x: null } ] | group-by { get x } | values | length
2
> # null and "" collapsed into one group
> [ a "" null ] | group-by | to nuon --raw
{a:[a],"":["",null]}> # All three return 1 (null omitted from record output)
> [ a null ] | group-by | values | length
1
> [ { x: a } { x: null } ] | group-by x | values | length
1
> [ { x: a } { x: null } ] | group-by { get x } | values | length
1
> # Use --to-table to keep null groups
> [ a null ] | group-by --to-table
╭───┬───────┬───────────╮
│ # │ group │ items │
├───┼───────┼───────────┤
│ 0 │ a │ ╭───┬───╮ │
│ │ │ │ 0 │ a │ │
│ │ │ ╰───┴───╯ │
│ 1 │ │ ╭───┬──╮ │
│ │ │ │ 0 │ │ │
│ │ │ ╰───┴──╯ │
╰───┴───────┴───────────╯
> [ { x: a } { x: null } ] | group-by x --to-table
╭───┬───┬───────────╮
│ # │ x │ items │
├───┼───┼───────────┤
│ 0 │ a │ ╭───┬───╮ │
│ │ │ │ # │ x │ │
│ │ │ ├───┼───┤ │
│ │ │ │ 0 │ a │ │
│ │ │ ╰───┴───╯ │
│ 1 │ │ ╭───┬───╮ │
│ │ │ │ # │ x │ │
│ │ │ ├───┼───┤ │
│ │ │ │ 0 │ │ │
│ │ │ ╰───┴───╯ │
╰───┴───┴───────────╯
> # null and empty string stay separate
> [ "" null ] | group-by --to-table | to nuon --raw
[[group,items];["",[""]],[null,[null]]]
> # record output: only "" remains; null is omitted
> [ a "" null ] | group-by | to nuon --raw
{a:[a],"":[""]}> # Missing optional column still skipped
> [{foo: 123}, {foo: 234}, {bar: 345}] | group-by foo?
╭─────┬─────────────╮
│ │ ╭───┬─────╮ │
│ 123 │ │ # │ foo │ │
│ │ ├───┼─────┤ │
│ │ │ 0 │ 123 │ │
│ │ ╰───┴─────╯ │
│ │ ╭───┬─────╮ │
│ 234 │ │ # │ foo │ │
│ │ ├───┼─────┤ │
│ │ │ 0 │ 234 │ │
│ │ ╰───┴─────╯ │
╰─────┴─────────────╯
> # only groups "123" and "234"
> # Optional path with explicit null is also skipped
> [{x: a}, {x: null}] | group-by x?
╭───┬───────────╮
│ │ ╭───┬───╮ │
│ a │ │ # │ x │ │
│ │ ├───┼───┤ │
│ │ │ 0 │ a │ │
│ │ ╰───┴───╯ │
╰───┴───────────╯
> # only group "a"Fixed scope commands to include local scopes [toc]
Fixed scope variables, scope commands, scope aliases, scope modules, and scope externs so they report both the current local scope and the global/permanent scope. Nested definitions inside do, if/for bodies, and custom commands now appear while that scope is active (and disappear afterward). Outer variables remain visible inside closures (for example let a = 1; do { let b = 2; scope variables } lists both $a and $b).
After this change
Outer + local variables
let a = 1
do {
let b = 2
scope variables | where name in ["$a", "$b"] | sort-by name | select name value
}
# name value
# $a 1
# $b 2Local commands / aliases / modules
do {
def local-cmd [] { "hi" }
alias la = ls
use spam.nu # module file in the cwd
scope commands | where name == "local-cmd" | length # 1
scope aliases | where name == "la" | length # 1
scope modules | where name == "spam" | length # 1
}
# after the block ends, those local names are gone againKeyword blocks (IR-inlined)
if true {
def local-cmd [] { "hi" }
scope commands | where name == "local-cmd" | length # 1
}
# after if:
scope commands | where name == "local-cmd" | length # 0for loop variable + locals
for i in 1..1 {
let d = 4
# scope variables includes $i and $d (and outer globals)
}Shadowed let
let x = "first"
# scope variables shows $x with value "first" after the first let
let x = "second"
# then shows the live second bindingFixed source losing visibility of outer variables [toc]
Fixes the bugs found when a script or REPL input used source to run a .nu file, variables defined before the source call could become invisible inside the sourced file, producing a "variable not found" error.
Example reproducing the bug
let xxx = 'let in script'
source sss.nuWhere sss.nu contains:
print $xxxRunning nu lll.nu would fail with:
Error: nu::shell::variable_not_found
× Variable not found
╭─[sss.nu:1:7]
1 │ print $xxx
· ──┬─
· ╰── variable not found
╰────The same error could also appear in the REPL after re-declaring a variable:
❯ let xxx = 'value 1'
❯ source sss.nu # OK: prints "value 1"
❯ let xxx = 'value 2'
❯ source sss.nu # Error: variable not foundAfter this change the last statement above would print value 2. See the tests and the issue to see more variations.
Errors for... error make? [toc]
Not specifying the span for error labels (or not doing so correctly) confusingly fell back to using the record's own span instead:
> open first.nu | nu-highlight
let var = 2
let span = (metadata $var).span
error make {
msg: "my error"
label: { text: "two" }
}
> run first.nu
Error: nu::shell::error
× my error
╭─[D:\Projects\nushell\scratch\first.nu:6:9]
5 │ msg: "my error"
6 │ label: { text: "two" }
· ───────┬───────
· ╰── two
7 │ }
╰────
> open second.nu | nu-highlight
let var = 2
let span = (metadata $var).span
error make {
msg: "my error"
label: { text: "two", start: $span.start, end: $span.end }
}
> run second.nu
Error: nu::shell::error
× my error
╭─[D:\Projects\nushell\scratch\second.nu:6:9]
5 │ msg: "my error"
6 │ label: { text: "two", start: $span.start, end: $span.end }
· ─────────────────────────┬─────────────────────────
· ╰── two
7 │ }
╰────
So error make succeeded instead of throwing an error. Well, it did throw an error, the one user was trying to, not the one it should due to error make receiving an invalid argument.
From now on error make will raise an error of its own when receiving an invalid argument.
> open first.nu | nu-highlight
let var = 2
let span = (metadata $var).span
error make {
msg: "my error"
label: { text: "two" }
}
> run first.nu
Error: nu::shell::missing_required_columns
× Value is missing required columns.
╭─[D:\Projects\nushell\scratch\first.nu:6:9]
5 │ msg: "my error"
6 │ label: { text: "two" }
· ───────┬───────
· ╰── missing `span: record<start: int, end: int>` column
7 │ }
╰────
> open second.nu | nu-highlight
let var = 2
let span = (metadata $var).span
error make {
msg: "my error"
label: { text: "two", start: $span.start, end: $span.end }
}
> run second.nu
Error: nu::shell::missing_required_columns
× Value is missing required columns.
╭─[D:\Projects\nushell\scratch\second.nu:6:9]
5 │ msg: "my error"
6 │ label: { text: "two", start: $span.start, end: $span.end }
· ─────────────────────────┬─────────────────────────
· ╰── missing `span: record<start: int, end: int>` column
7 │ }
╰────
Math commands: records with list columns and optional cell paths [toc]
Fixed reducing math commands on records whose columns are lists (including uneven lengths). For example:
> { alice: [0.1 0.6 0.2], bob: [0.8 0.3 0.2 0.9] } | math avg
╭───────┬──────╮
│ alice │ 0.30 │
│ bob │ 0.55 │
╰───────┴──────╯All of the following math commands now accept optional cell paths / columns to operate on only those fields:
Reducing (list cells become a scalar):math avg, math sum, math product, math max, math min, math median, math mode, math stddev, math variance
Element-wise (list cells stay lists):math abs, math cbrt, math ceil, math floor, math sqrt, math round, math log
> # Reduce only one column
> { alice: [1 2 3], bob: [4 5 6] } | math avg alice
╭───────┬───────────╮
│ alice │ 2.00 │
│ │ ╭───┬───╮ │
│ bob │ │ 0 │ 4 │ │
│ │ │ 1 │ 5 │ │
│ │ │ 2 │ 6 │ │
│ │ ╰───┴───╯ │
╰───────┴───────────╯
> # Element-wise on one column
> { alice: [-1 -2 -3], bob: [-4 -5] } | math abs alice
╭───────┬────────────╮
│ │ ╭───┬───╮ │
│ alice │ │ 0 │ 1 │ │
│ │ │ 1 │ 2 │ │
│ │ │ 2 │ 3 │ │
│ │ ╰───┴───╯ │
│ │ ╭───┬────╮ │
│ bob │ │ 0 │ -4 │ │
│ │ │ 1 │ -5 │ │
│ │ ╰───┴────╯ │
╰───────┴────────────╯
> # Works in const context too
> const data = {alice: [1 2 3], bob: [4 5 6]}
> $data | math sum alice
╭───────┬───────────╮
│ alice │ 6 │
│ │ ╭───┬───╮ │
│ bob │ │ 0 │ 4 │ │
│ │ │ 1 │ 5 │ │
│ │ │ 2 │ 6 │ │
│ │ ╰───┴───╯ │
╰───────┴───────────╯Examples for each command:
let rec = { alice: [1 2 3], bob: [4 5 6] }
$rec | math avg alice # alice: 2
$rec | math sum alice # alice: 6
$rec | math product alice # alice: 24
$rec | math max bob # bob: 6
$rec | math min bob # bob: 4
$rec | math median alice # alice: 2
$rec | math mode alice # alice: [1, 2, 3] modes as list
$rec | math stddev alice # alice: ~0.82
$rec | math variance alice # alice: ~0.67
{ alice: [-1 -2], bob: [-3 -4] } | math abs alice | to nuon
# {alice: [1, 2], bob: [-3, -4]}
{ alice: [8 27], bob: [64] } | math cbrt alice | to nuon
# {alice: [2.0, 3.0], bob: [64]}
{ alice: [1.2 2.3], bob: [3.4] } | math ceil alice | to nuon
# {alice: [2, 3], bob: [3.4]}
{ alice: [1.2 2.3], bob: [3.4] } | math floor alice | to nuon
# {alice: [1, 2], bob: [3.4]}
{ alice: [4 9], bob: [16] } | math sqrt alice | to nuon
# {alice: [2.0, 3.0], bob: [16]}
{ alice: [1.2 2.7], bob: [3.1] } | math round alice | to nuon
# {alice: [1, 3], bob: [3.1]}
{ alice: [1 10 100], bob: [1000] } | math log 10 alice | to nuon
# {alice: [0.0, 1.0, 2.0], bob: [1000]}Existing list, table, number, duration, and range inputs keep their previous behavior when no cell paths are given.
Made error messages more consistent. On the commands that make sense, I added int, float, duration, filesize. On others, product, sqrt, cbrt, and log, only work with ints and floats.
Fixed math max on empty streams [toc]
Previously the empty list (top) would display and error but the empty stream (bottom) would not. This should now be fixed.
[] | math max
['x'] | each { try { into int } } | math maxClearer delimiter errors [toc]
Nushell now reports unclosed and unbalanced delimiters with:
- The kind of delimiter involved (
{,},[,],(,),",',>,|, …) - Where it opened and where the closer was expected (when known)
- Help text that suggests a fix, sometimes with a structure hint (e.g. which
defor record field is open)
Common mistakes such as forgetting [ before list elements, forgetting ( before a grouped expression, forgetting { after if/while/for/try/match, or writing bare record fields without { point near the mistake instead of only at a distant } or EOF.
Fixed path type treating empty strings as directories [toc]
"" | path type now returns null instead of "dir"
Fixed passing quoted # strings as script parameters [toc]
Quotes strings with "#" in them like "#00abcd" are now allowed to be passed as parameters.
Example
def main [color: string] {
$"Your color is ($color)"
}Pass a hex color as a parameter.
> let myColor = "#000000"
> run test.nu $myColor
Your color is #000000
> run test.nu "#abcdef"
Your color is #abcdefFixed config reloads duplicating unnamed keybindings [toc] PR #18828 by @kronberger-droid
Assigning $env.config.keybindings or $env.config.menus now merges into the defaults rather than replacing them, so $env.config.keybindings = [] and $env.config.menus = [] no longer clear anything. Set event: null on a matching binding to unbind a key.
Other fixes [toc]
lswithdc-globenabled no longer fails when encountering files named literally with glob syntax like*. (#18632)- Fixed
idxso deleted files and directories no longer appear as live index entries. (#18673) - Fixed watched
idx importruntimes so filesystem changes appear consistently in listings, find results, status, content search, and watch events. (#18674) - Nushell now reports incompatible right-hand-side uses of
$inin typed math expressions during parsing, matching the existing behavior for the left-hand side. (#18723) - With the
dc-globexperimental option enabledls **now works again. (#18724) - If you have a broken symlink for startup files in nushell, that should not prevent nushell from starting up with defaults. (#18726)
- Now it's easier to see what the default settings are when you don't have them configured. Show (nearly) all settings in
$env.config. If you haven't set any, or launched withnu -n, it will show defaults. (#18747) - Fixed
generaterejectingnullvalue pipeline input despite working with "empty" pipeline input. (#18751) - If you set part of the color config, the defaults for the other parts will still be applied. (#18770)
- Fixed an issue where saving structured data (like a record or table) to a file with no known serializer (no extension, or an unknown one such as
.foo) failed with a crypticCan't convert to string. Nushell now explains that no serializer matches the file's extension and suggests... | to json | save <file>or... | table | ansi strip | save <file>. (#18773) - Fixed an issue where
stor import --file-namewith a path that does not exist created an empty file and discarded the contents of the in-memory database without reporting an error. It now fails with a file not found error and leaves the in-memory database untouched. (#18809) - Quotes inside
(...)subexpressions of interpolated strings now work:$"('" "')"prints" "instead of becoming an unclosable string. (#18812) - Fixed an issue where the icon for a folder with a dot was treated as a file. (#18817)
$answorks with TUIs better (#18820)- Fixed module item completion for
usecommands to work without a string for possible items to match against. (#18826) - Single semver values do not output as a table anymore (#18834)
Hall of fame [toc]
Thanks to all the contributors below for helping us solve issues, improve documentation, refactor code, and more! 🙏
| author | change | link |
|---|---|---|
| @cptpiepmatz | Remove all tests that use nu_with_plugins! | #18585 |
| @Bahex | Add test_value! macro | #18582 |
| @m-novotny | Fix default configuration links (#18598) | #18599 |
| @drbrain | Allow PluginCommand::get_dynamic_completion() to use EngineInterface::get_plugin_config() | #18587 |
| @sid-6581 | Fix submodule import in test_docker.nu | #18606 |
| @Bahex | CompleteResult type for working with complete in tests | #18604 |
| @Alb-O | Fuse uniq-by validation and extraction | #18507 |
| @Bahex | Update some tests to use the new test infra | #18651 |
| @cptpiepmatz | Update terminal tests | #18663 |
| @philocalyst | Updates to use CompletionResult | #18671 |
| @pyz4 | Date floor/ceil rounding for durations >= 1day | #18696 |
| @rvhelden | Pass Stack to the IR debugger instruction callbacks | #18708 |
| @cptpiepmatz | Do not run CI on lower layers of stacked PRs | #18720 |
| @ZayanKhan-12 | Fix devdocs links in AGENTS.md | #18721 |
| @cptpiepmatz | Add test binaries as a separate crate | #18644 |
| @cptpiepmatz | Add test_*! macro and more assertions to the testing prelude | #18647 |
| @cptpiepmatz | Remove use_nu_with_plugins from Test | #18645 |
| @cptpiepmatz | Add run_multiple to NuTester and update ShellErrorExt | #18664 |
| @cptpiepmatz | Update the table tests | #18648 |
| @cptpiepmatz | Update overlay tests | #18658 |
| @cptpiepmatz | Update modules/mod.rs tests | #18652 |
| @cptpiepmatz | Update parser tests | #18668 |
| @cptpiepmatz | Update hooks tests | #18669 |
| @cptpiepmatz | Refactor some tests | #18712 |
| @cptpiepmatz | Update some more tests that used nu_repl_code | #18649 |
| @cptpiepmatz | Refactor most test files that used nu --testbin | #18713 |
| @cptpiepmatz | Update redirection tests | #18714 |
| @cptpiepmatz | Update eval tests | #18716 |
| @cptpiepmatz | Update run external tests | #18715 |
| @cptpiepmatz | Update external commands tests | #18717 |
| @cptpiepmatz | Update internal commands tests | #18718 |
| @cptpiepmatz | Update the help text of test binaries | #18739 |
| @cptpiepmatz | Refactor open tests | #18740 |
| @cptpiepmatz | Refactor a handful of tests to use test() | #18748 |
| @fdncred | Update doc_config.nu / tweak explore section | #18750 |
| @Bahex | Job spawn closure should be ran with empty pipeline, not null | #18752 |
| @cptpiepmatz | Stabilize unreliable tests in CI | #18756 |
| @cptpiepmatz | More updated tests | #18768 |
| @cptpiepmatz | Remove nu! and update tests | #18776 |
| @fdncred | Reduce ast footprint, increase ir footprint - phase 0 | #18808 |
| @brandondong | Fix configuration book link in README | #18831 |
| @kronberger-droid | Stop stat-ing all of PATH once the external cap is hit | #18835 |
Full changelog [toc]
| author | title | link |
|---|---|---|
| @Alb-O | perf(filters): fuse uniq-by validation and extraction | #18507 |
| @Alb-O | perf(str): prepare replace matcher once | #18508 |
| @Alb-O | perf: avoid cloning binary values | #18572 |
| @Alb-O | perf: avoid cloning list values | #18636 |
| @Alb-O | fix(idx): exclude tombstoned entries | #18673 |
| @Alb-O | fix(idx): keep watched imports live | #18674 |
| @Alb-O | refactor(idx): remove import/export, keep single live index | #18679 |
| @Bahex | Add test_value! macro | #18582 |
| @Bahex | CompleteResult type for working with complete in tests | #18604 |
| @Bahex | take while/until commands can include items after the match | #18623 |
| @Bahex | Replace built-in date floor/ceil commands with nu rewrites | #18640 |
| @Bahex | Update some tests to use the new test infra | #18651 |
| @Bahex | fix(generate): handle null input the same as empty pipeline | #18751 |
| @Bahex | job spawn closure should be ran with empty pipeline, not null | #18752 |
| @Bahex | lines: do not prematurely collect output for string value input | #18753 |
| @Bahex | feat(error make)!: raise errors for invalid labels | #18755 |
| @Bahex | feat(format duration/filesize): add completions for units | #18783 |
| @Bahex | Fix module item completion | #18826 |
| @Mrfiregem | feat(any/all): Allow using row conditions alongside closures | #18353 |
| @Mrfiregem | fix: default left and right prompts respect user color settings | #18506 |
| @Mrfiregem | feat(into semver): add cell-path support | #18567 |
| @Mrfiregem | Show deprecation entries in scope commands output | #18815 |
| @Totara-thib | Pin CI actions to commit SHAs and declare workflow permissions | #18787 |
| @Tyarel8 | feat(chunks, first, last, take, drop and skip): arg can now also be a filesize for binary | #18511 |
| @Tyarel8 | fix parse_calls negative number detection | #18514 |
| @ZayanKhan-12 | docs: fix devdocs links in AGENTS.md | #18721 |
| @aionescu | fix(try): only pop error handler if it was pushed by current try block | #18519 |
| @alerque | Bump pin of transient dependency causing unsound transmute | #18581 |
| @app/dependabot | build(deps): bump crate-ci/typos from 1.47.2 to 1.48.0 | #18502 |
| @app/dependabot | build(deps): bump plist from 1.8.0 to 1.10.0 | #18544 |
| @app/dependabot | build(deps): bump calamine from 0.35.0 to 0.36.0 | #18547 |
| @app/dependabot | build(deps): bump humantime from 2.3.0 to 2.4.0 | #18548 |
| @app/dependabot | build(deps): bump bstr from 1.12.1 to 1.13.0 | #18608 |
| @app/dependabot | build(deps): bump regex from 1.12.3 to 1.13.0 | #18609 |
| @app/dependabot | build(deps): bump open from 5.3.4 to 5.4.0 | #18610 |
| @app/dependabot | build(deps): bump aws-credential-types from 1.2.14 to 1.3.0 | #18612 |
| @app/dependabot | build(deps): bump actions/labeler from 6 to 7 | #18687 |
| @app/dependabot | build(deps): bump actions/setup-python from 6 to 7 | #18688 |
| @app/dependabot | build(deps): bump aws-config from 1.8.15 to 1.10.0 | #18689 |
| @app/dependabot | build(deps): bump http from 1.4.0 to 1.5.0 | #18784 |
| @app/dependabot | build(deps): bump Swatinem/rust-cache from 2.9.1 to 2.9.2 | #18822 |
| @app/dependabot | build(deps): bump actions-rust-lang/setup-rust-toolchain from 1.12.0 to 1.17.0 | #18823 |
| @app/dependabot | build(deps): bump taiki-e/install-action from 2.85.8 to 2.85.11 | #18824 |
| @app/dependabot | build(deps): bump bytesize from 2.4.0 to 2.7.0 | #18825 |
| @ayax79 | Lazy and expression support for polars rolling | #18730 |
| @brandondong | Fix configuration book link in README | #18831 |
| @cacdu | fix(save): give actionable error when structured data has no serializer | #18773 |
| @cpea2506 | Bump devicons to 0.6.13 | #18817 |
| @cptpiepmatz | Rework our YAML implementation using serde-saphyr | #18487 |
| @cptpiepmatz | Do not run CI for draft PRs | #18584 |
| @cptpiepmatz | Remove all tests that use nu_with_plugins! | #18585 |
| @cptpiepmatz | Also trigger CI on ready_for_review | #18586 |
| @cptpiepmatz | Add test binaries as a separate crate | #18644 |
| @cptpiepmatz | Remove use_nu_with_plugins from Test | #18645 |
| @cptpiepmatz | Add test_*! macro and more assertions to the testing prelude | #18647 |
| @cptpiepmatz | Update the table tests | #18648 |
| @cptpiepmatz | Update some more tests that used nu_repl_code | #18649 |
| @cptpiepmatz | Update modules/mod.rs tests | #18652 |
| @cptpiepmatz | Update overlay tests | #18658 |
| @cptpiepmatz | Update terminal tests | #18663 |
| @cptpiepmatz | Add run_multiple to NuTester and update ShellErrorExt | #18664 |
| @cptpiepmatz | Update parser tests | #18668 |
| @cptpiepmatz | Update hooks tests | #18669 |
| @cptpiepmatz | Refactor some tests | #18712 |
| @cptpiepmatz | Refactor most test files that used nu --testbin | #18713 |
| @cptpiepmatz | Update redirection tests | #18714 |
| @cptpiepmatz | Update run external tests | #18715 |
| @cptpiepmatz | Update eval tests | #18716 |
| @cptpiepmatz | Update external commands tests | #18717 |
| @cptpiepmatz | Update internal commands tests | #18718 |
| @cptpiepmatz | Remove --testbin from nu | #18719 |
| @cptpiepmatz | Do not run CI on lower layers of stacked PRs | #18720 |
| @cptpiepmatz | Update kitest | #18727 |
| @cptpiepmatz | Update the help text of test binaries | #18739 |
| @cptpiepmatz | Refactor open tests | #18740 |
| @cptpiepmatz | Refactor a handful of tests to use test() | #18748 |
| @cptpiepmatz | Stabilize unreliable tests in CI | #18756 |
| @cptpiepmatz | More updated tests | #18768 |
| @cptpiepmatz | Remove nu! and update tests | #18776 |
| @danielcadev | Fix RHS pipeline input type checking (issue #18682) | #18723 |
| @danielcadev | fix(save): serialize structured data to text files | #18735 |
| @dmatos2012 | Add uutils ln command | #18571 |
| @drbrain | Allow PluginCommand::get_dynamic_completion() to use EngineInterface::get_plugin_config() | #18587 |
| @fdncred | reorganize nushell configuration | #18510 |
| @fdncred | The source command no longer breaks variable visibility | #18538 |
| @fdncred | Add matrix commands | #18553 |
| @fdncred | add const eval in match arms | #18559 |
| @fdncred | Revert "Add uutils ln command" | #18605 |
| @fdncred | disallow export main from modules with keyword names | #18619 |
| @fdncred | fix bug where ls with dc-glob would fail with literal * name files | #18632 |
| @fdncred | add idx watch command | #18639 |
| @fdncred | update nushell to latest reedline commit | #18655 |
| @fdncred | disallow keywords from being shadowed | #18662 |
| @fdncred | update some dependencies | #18678 |
| @fdncred | bump nushell to latest reedline commit a2c6e124 | #18681 |
| @fdncred | agent.md updates | #18683 |
| @fdncred | Make scope subcommands report local and global scope | #18684 |
| @fdncred | update fff-search to 0.10.1 and tokio to 1.53.1 | #18693 |
| @fdncred | bump reedline dep to latest commit 7eb9bf2 | #18695 |
| @fdncred | add splashboard to .gitignore | #18701 |
| @fdncred | better lex/parse errors | #18702 |
| @fdncred | fix dc-glob ls ** and ls **/*/*/* among other things | #18704 |
| @fdncred | add comparison operators to semver like > <, == | #18706 |
| @fdncred | add more consistency with null types | #18709 |
| @fdncred | fix ls ** when using dc-glob experimental option | #18724 |
| @fdncred | fix startup with dangling symlinks | #18726 |
| @fdncred | add $ans record for storing the last result from the repl | #18729 |
| @fdncred | make $env.config show default configuration when not set even with nu -n | #18747 |
| @fdncred | Update doc_config.nu / tweak explore section | #18750 |
| @fdncred | update math commands to handle records and support cell path rest params | #18754 |
| @fdncred | fix color config fallbacks | #18770 |
| @fdncred | fix math max empty list vs empty string | #18772 |
| @fdncred | update nushell to latest reedline commit 60d99674 | #18775 |
| @fdncred | upgrade kdl to support --spec 1 or --spec 2 | #18779 |
| @fdncred | bump deps | #18780 |
| @fdncred | allow parameters with # to be passed | #18782 |
| @fdncred | update uu-utils crates to v0.10.0 | #18795 |
| @fdncred | Allow all built-in commands with --regex to use LRU | #18797 |
| @fdncred | update deps | #18802 |
| @fdncred | reduce ast footprint, increase ir footprint - phase 0 | #18808 |
| @fdncred | fix: allow semver to have coloring, add --loose flag | #18819 |
| @fdncred | bug: make $ans work better with TUIs | #18820 |
| @fdncred | add cli key to $ans record, rename last_result_size to max_last_result_size | #18827 |
| @fdncred | fix: single semver output as table instead of value | #18834 |
| @fdncred | rename $ans.cli to $ans.command | #18836 |
| @hexbinoct | Lex quotes inside interpolated string subexpressions | #18812 |
| @ian-h-chamberlain | Support CLI args for commandline (nu -c) scripts | #18576 |
| @jakobwsmnn | fix: into binary not accepting Duration type as input | #18522 |
| @kobihikri | ci: pin milestone-action to a full commit SHA | #18601 |
| @kronberger-droid | chore(reedline): bump reedline to latest commit | #18685 |
| @kronberger-droid | chore(reedline): bump reedline to latest commit 83c17a2 | #18694 |
| @kronberger-droid | Bump reedline to e4fe8ed | #18798 |
| @kronberger-droid | fix(completion): stop the cache reordering the answer it stands in for | #18806 |
| @kronberger-droid | fix(config): match unnamed keybindings by the key they bind | #18828 |
| @kronberger-droid | chore(reedline): bump to latest reedline commit 6b9115d | #18829 |
| @kronberger-droid | chore(reedline): bump reedline to 61715da including helix-mode | #18830 |
| @kronberger-droid | feat(config): give helix_select keybindings their own table | #18833 |
| @kronberger-droid | fix(completion): stop stat-ing all of PATH once the external cap is hit | #18835 |
| @kronberger-droid | feat(config): make the visual selection style configurable | #18838 |
| @latent-9 | fix(stor): reject a missing file in stor import instead of discarding the in-memory database | #18809 |
| @m-novotny | Fix default configuration links (#18598) | #18599 |
| @oh-summy | fix(help): document list input support for hash md5/sha256 | #18638 |
| @pheenty | add lacy tool into the list of projects that support nushell | #18618 |
| @pheenty | treat empty string as an invalid path in path type | #18785 |
| @philocalyst | non-blocking completions | #18334 |
| @philocalyst | async prompt updating | #18660 |
| @philocalyst | Updates to use CompletionResult | #18671 |
| @philocalyst | Rework how completer works | #18761 |
| @pyz4 | feat(date): add new commands date floor and date ceil | #18620 |
| @pyz4 | fix: date floor/ceil rounding for durations >= 1day | #18696 |
| @rabindra789 | fix(ps): skip exited processes instead of erroring in ps -l | #18542 |
| @rvhelden | Pass Stack to the IR debugger instruction callbacks | #18708 |
| @santhreal | Fix panic and infinite loop in seq on overflow and zero increment | #18596 |
| @sid-6581 | fix: fix submodule import in test_docker.nu | #18606 |
| @skyrocket1643 | parser: add external shape annotation | #18512 |
| @sylvestre | docs: credit uutils/coreutils for built-in commands in dev FAQ | #18529 |
| @xtqqczze | build(deps): bump num-bigint from 0.4.6 to 0.4.8 | #18746 |