Nushell 0.116.0
Today, we're releasing version 0.116.0 of Nu. This release brings a major custom completion rework, new tui commands for building terminal interfaces, interactive debugging, more tutor lessons, and a faster shell.
In memory of Yash
"It is with profound grief and deep love that the family of Yash Thakur announces his passing on April 2, 2026."
The Nushell team is deeply saddened by Yash's passing.
We found out about his passing recently and wanted to acknowledge his dedication and contributions to our project, as well as the friendship he shared with the Nushell community. Our condolences go out to his friends and family.
Yash started working on Nushell at the young age of 19 in September 2023.
He quickly learned the project and, in a short time, became a valuable contributor to the inner workings of Reedline, the parser, completions, and other components. At the time of his passing, he was also helping develop a new parser for Nushell.
Please consider reading the beautiful obituary written for Yash to learn more about his life, passions, interests, and amazing spirit.
Where to get it
Nu 0.116.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]
I'm too lazy to type, lemme press tab [toc]
Pressing Tab is easy. Making everything behind it agree on how completions work took a bit more effort. Thanks to @philocalyst, custom completions now share one input and output model across parameter completers, command-wide completers, external completers, and menu sources. Completers can ask for the token, the completion location, or the whole buffer, and combine their suggestions with other completion sources.
Breaking change
Existing custom completers and menu sources may need updating. See the examples and migration table in unified custom completions.
There are plenty of smaller improvements around that big rework, too. Completers can now see which command you are completing, and external completers receive expanded aliases. Sourced menus refresh properly after partial completion, warnings wait until the menu closes, and you can opt into keeping completion and history menus open while editing. Less fighting the menu, more pressing Tab.
Teach me things [toc]
Nushell's interactive tutor has more lessons for you. Thanks to @nos1dot618, you can now learn about command-history shortcuts and $env, write your own custom commands and work with pipeline input, and get to grips with if, match, and where.
If you have been meaning to move beyond the commands you already know, this is a good excuse. Run tutor and try a lesson right there in your shell.
Build your TUI straight in Nushell [toc]
Ever wanted your script to have a little interface? Thanks to @fdncred, the new tui commands let you build interactive terminal interfaces straight from Nushell. Put together tables, textboxes, menus, and more, then get the user's selections and entered values back as a record.
You probably won't replace your entire Ratatui application this afternoon, but a picker or a small form no longer needs a separate Rust project. You can even open it as a floating dialog, and your shell comes back intact when you quit. Take a look at the commands and examples here, then head over to the original PR for more. Even this changelog cannot easily cover everything these commands can do.
Interactive debugging! [toc]
That script is doing something strange again. Time to set a breakpoint. Thanks to @rvhelden, Nushell now has a Debug Adapter Protocol server, started with nu --dap, so you can debug your scripts from an editor that supports DAP.
Set breakpoints, step through pipelines, inspect variables, and evaluate watch expressions. You can even step backward through a recorded timeline when you realize you just stepped past the interesting bit. A lot of work behind a small flag. More details are here.
Make Nushell faster [toc]
There is less waiting around this release, too. Typing and completing use in the REPL does less work, and large configs load faster, along with the plugin registry. gstat also finds the nearest tag faster in large repositories.
$nu.startup-time now measures all the way to the first prompt being ready, so you get a more honest account of where that time went. There is also faster parsing and less work when styling values, and the repeated source slowdown introduced in 0.115 is fixed. Thanks to everyone making the shell a little quicker, one less bit of unnecessary work at a time.
Changes [toc]
Breaking changes [toc]
Unified custom completions [toc] PR #18791 by @philocalyst
Custom completions now use one shared input and output model across parameter completers, command-wide completers, external completers, and menu sources. This makes completion behavior more consistent, but it means existing custom completers and menu sources may need to be updated.
Previously, different completion entry points received different arguments. Parameter completers received something like [context, offset], command-wide completers received [spans], external completers commonly received {|spans| ...}, and menu sources received {|buffer, position| ...}.
Completers now declare which completion inputs they want by naming their positional parameters. The recognized names are token, place, and buffer, and they can be declared in any order.
def complete-branch [token: record] {
git branch --format '%(refname:short)' | lines | where $it =~ $token.text
}
def complete-from-place [place: record] {
if $place.kind == "flag-value" and $place.flag == "profile" {
[debug release]
}
}
def complete-from-buffer [buffer: string] {
$buffer | split row " "
}token describes the token at the cursor, with fields like text, kind, and span. place describes the resolved completion site and replacement range, including fields like cursor, target, kind, flag, index, and shape when applicable. buffer is the exact command line from the beginning of the line through the cursor, including text before pipes, inside closures, and after separators.
Use buffer instead of calling commandline from inside a completer. buffer is always the line currently being completed; commandline can be empty in some editor states, such as after ;.
Menu sources use this same input model now. A source that used to look like this:
source: {|buffer, position|
$buffer | str substring ..<$position | split row " " | last
}should usually become either:
source: {|token| $token.text }or, if it really needs the whole line:
source: {|buffer| $buffer }External completers also need to migrate from the old spans-style input to the new named inputs. For example, a whole-line external completer should declare buffer:
$env.config.completions.external.completer = {|buffer|
let words = $buffer | split row " "
carapace ($words | first) nushell ...$words | from json
}If a completer declares an unrecognized positional name, Nushell passes nothing for that parameter and writes a diagnostic to the completion log.
Custom completer output is also handled more consistently. A completer can now return null to decline and let another completion source answer, a string or list of strings, suggestion records, or an envelope record with completions, options, and fallback.
def complete-preset [token: record] {
{
completions: [
{value: main, description: "default branch"}
{value: release, description: "release branch"}
]
options: {
filter: true
completion_algorithm: "substring"
match_description: true
}
fallback: true
}
}fallback: true keeps the custom results and continues to the next completion source, so custom completions can appear beside built-in file completion or command-wide completions. Parameter completers are filtered by default; command-wide and external completers are not, because they usually do their own filtering. Set options.filter explicitly if you need the other behavior.
The old global background-completions option has been removed. Completers normally run on a background worker. If a completer needs to own the terminal, such as one that launches fzf or input list, mark the completer command with @interactive:
@interactive
def pick-file [token: record] {
ls | get name | to text | ^fzf --query $token.text | lines
}
def open-file [path: string@pick-file] {
open $path
}When completing open-file <Tab>, pick-file runs inline on the line-editor thread with stdin and the terminal available. This blocks the editor while the picker is open, then returns the selected values as completion suggestions. Calling an @interactive completer directly is not the intended test path, because the completion engine supplies its inputs.
External completers are closures and cannot carry @interactive themselves. To make an external completer interactive, have the closure call an @interactive command:
@interactive
def carapace-fzf [buffer: string] {
let words = $buffer | split row " "
carapace ($words | first) nushell ...$words | from json | ^fzf | lines
}
$env.config.completions.external.completer = {|buffer|
carapace-fzf $buffer
}commandline complete gained tools for developing completers. commandline complete --input returns the {token, place, buffer} record a completer would receive without running the completer. commandline complete --detailed returns suggestions in the custom-completer output format. commandline complete --type directory|path|glob|command|variable|env-var runs one built-in completion source, which is useful when composing Nushell's built-in completions with custom ones. --input cannot be combined with --detailed or --type.
Some completion behavior changed as part of this unification:
- Parameter completers that fail now return no suggestions instead of unexpectedly falling back to the working directory.
- Command-wide and external completers can return
nullto decline, allowing file completion or another source to answer. - Completion state is resolved at the cursor more accurately, including nested closures, aliases, multi-word command heads, flag values, cell paths, and empty argument slots.
- Aliases resolve through to their completion command, including whether that command is interactive.
- Malformed suggestions, styles, spans, or options are reported in the completion log without discarding unrelated valid suggestions.
Common migrations:
| Previous form | New form |
|---|---|
def comp [input pos] { ... } | def comp [token: record] { $token.text | ... } |
def comp [spans] { ... } | def comp [buffer: string] { $buffer | split row " " | ... } when whole-line input is needed |
{ |spans| ... } external completer | { |buffer: string| ... } |
{ |buffer position| ... } menu source | { |token: record| ... }, { |place: record| ... }, or { |buffer: string| ... } |
| Global background-completion opt-out | @interactive on the terminal-owning completion command |
Other breaking changes
- Replaced
to yaml/to yml's--compact-list-indentflag with--list-indentflag which takes eithercompactorindented. (#19005)
Additions [toc]
Named flags: null can omit or pass through based on type [toc]
When a named flag is given null, Nushell now:
- Omits the flag if its type does not accept
nothing(e.g.--x: int,--preserve: list<string>), so defaults and “flag not passed” behavior work—especially useful when shadowing builtins with%cp/%lsand writing--flag=$maybe_null - Passes
nullthrough if the type acceptsnothing(e.g.--x: any,--x: oneof<int, nothing>), so callers can still express an explicit null when they opt into that in the signature
def f [--x: oneof<int, nothing> = 5] { $x }
f # 5
f --x=null # null
def g [--x: int = 5] { $x }
g --x=(null) # 5 (omitted → default) note: in this example null is wrapped in parens because this syntax would fail with `g --x=null` as you're typing due to parse checking.Record spread into named flags [toc]
Internal and custom commands accept spreading a record as named flags:
def wrap [--preserve: list<string>, --recursive, ...rest] {
%cp ...{ preserve: $preserve, recursive: $recursive } ...$rest
}
let flags = {preserve: [mode], recursive: true}
wrap ...$flags src destNull fields follow the same type rule as named flags above. For switch fields, true sets the flag, while false or null omits it. Field values are type-checked against the flag signature, and unknown flag names in the record cause a runtime error. Spreading a list into a command with no ...rest produces a clear error, since lists are not treated as named flags.
New Polars commands can create date and datetime ranges [toc]
Implemented commands for creating date and datetime ranges:
| Command | Description |
|---|---|
polars date-range | Create a date range expression. |
polars date-ranges | Create a column of date ranges. |
polars datetime-range | Create a datetime range expression. |
polars datetime-ranges | Create a column of datetime ranges. |
The interactive tutor now teaches command-history shortcuts and the $env variable [toc] PR #18903 by @nos1dot618
Added a tutor shortcuts tutorial covering command history shortcuts.
> tutor shortcut
You can use shortcuts to quickly insert text from command history into the
input buffer.
You can use !! to insert the last command you entered into the input buffer.
!!
After pressing Enter, !! is expanded into the previous command in the input
buffer. The expanded command is not executed until you press Enter again.
You can also use !! as part of a larger command.
tutor shortcut
!! | find "shortcut"
The above expands !! into the previous command while keeping the rest of the
text in the input buffer.
You can use !$ to insert the last spatially delimited argument from the
previous command into the input buffer.
echo hello world
echo !$
After pressing Enter, !$ is expanded to world in the input buffer. The
resulting command is not executed until you press Enter again.
You can use !<idx> to insert a command from the command history into the input
buffer. The index corresponds to the command's index in the history.
history
!5
After pressing Enter, !5 is expanded to the command with history index 5 in
the input buffer.
You can use !-<number> to insert a command from a number of entries back in
the history into the input buffer.
!-5
After pressing Enter, !-5 is expanded to the command from five entries back in
the history.
The variable tutorial now also documents the $env built-in variable.
> tutor variable
Variables are an important way to store values to be used later. To create a
variable, you can use the let keyword. The let command will create a
variable and then assign it a value in one step.
let x = 3
Once created, we can refer to this variable by name.
$x
Nushell also comes with built-in variables. The $nu variable is a reserved
variable that contains a lot of information about the currently running
instance of Nushell. The $env variable contains the environment variables
available to the current Nushell process. The $it variable is the name given
to row-condition closure parameters if you don't specify one. And $in is the
variable that allows you to work with all of the data coming in from the
pipeline in one place.
The interactive tutor now covers custom commands and pipeline input [toc] PR #18927 by @nos1dot618
Added new tutor tutorials for defining custom commands and working with pipeline input.
> tutor custom-command
Custom commands allow you to create your own commands in Nushell. You can
define a custom command using the def keyword.
For example, this defines a command called greet:
def greet [] {
print "Hello!"
}
You can then run it just like any other command:
greet
Custom commands can also accept arguments. You define the arguments between
the square brackets:
def greet [name] {
print $"Hello, ($name)!"
}
Now you can pass a name to the command:
greet "Nushell"
You can give arguments a type to make the expected input clearer:
def add [a: int, b: int] {
$a + $b
}
You can also provide default values for arguments:
def greet [name = "world"] {
print $"Hello, ($name)!"
}
You can learn more about using pipeline input with custom commands by running:
tutor pipeline-input
You can learn more about custom commands and see additional examples by
running:
help def
> tutor pipeline-input
Custom commands can receive values from the pipeline. This allows you to
create commands that work naturally with other Nushell commands.
For example, this custom command takes pipeline input and doubles each value:
def double [] {
each { |x| $x * 2 }
}
You can use it as part of a pipeline:
[1 2 3] | double
Custom commands can also access all of their pipeline input through $in:
def total [] {
$in | math sum
}
This allows the custom command to work with the entire value coming through
the pipeline:
[1 2 3 4] | total
You can learn more about closures, which are commonly used when processing
pipeline data, by running:
tutor closures
$env.config.completions.persistent_menus keeps completion and history menus open while editing [toc] PR #18573 by @maxim-uvarov
Added $env.config.completions.persistent_menus. When set to true, an active completion or history menu stays open while you edit: erasing characters (or emptying the commandline) refilters the menu instead of closing it. Default false keeps the old behavior.
$env.config.completions.persistent_menus = trueview source --dependencies can now include custom command dependencies [toc] PR #18801 by @maxim-uvarov
Added --dependencies (-d) to view source. It appends the source of every custom command the target calls, transitively — including commands private to a module, which cannot be viewed any other way — and prepends every constant those bodies read, with the value the engine holds:
> module m {
const LIMIT = 42
def helper [] { $LIMIT }
export def bar [] { helper }
}
> use m
> view source "m bar" --dependencies
const LIMIT = 42
def "m bar" [] { helper }
def helper [] { $LIMIT }The interactive tutor now teaches if, match, and where [toc] PR #18972 by @nos1dot618
Added a new tutor conditional tutorial for learning conditional logic, pattern matching, and conditional filtering.
> tutor conditional
Conditional commands allow you to choose which code to run based on a value or
condition.
The if command runs a block when its condition is true:
if 5 > 3 {
print "5 is greater than 3"
}
You can use else to run a different block when the condition is false:
let age = 20
if $age >= 18 {
"adult"
} else {
"minor"
}
You can also chain multiple conditions with else if:
let score = 75
if $score >= 90 {
"A"
} else if $score >= 80 {
"B"
} else if $score >= 70 {
"C"
} else {
"F"
}
The if command returns a nushell value, so it can be store in a variable or
use in a pipeline:
let result = if 10 > 5 { "yes" } else { "no" }
$result
When you have several possible values to match, the match command can be more
convenient. It checks a value against several patterns:
let number = 2
match $number {
1 => "one",
2 => "two",
3 => "three",
_ => "something else"
}
The _ pattern acts as a catch-all for anything that did not match an earlier
branch.
The match command can also be used to unpack structured values:
let user = { name: "Alice", admin: true }
match $user {
{ admin: true } => "administrator",
{ admin: false } => "regular user",
_ => "unknown"
}
Conditions can also be used to filter values in a pipeline with the where
command:
[1 2 3 4 5] | where $it > 2
This keeps only the values for which the condition is true:
╭───┬───╮
│ 0 │ 3 │
│ 1 │ 4 │
│ 2 │ 5 │
╰───┴───╯
For tables, the where command is particularly useful for selecting rows:
ls | where size > 1kb
You can learn more about filtering pipelines with:
help where
You can learn more about blocks, which are used by the if command and other
control flow commands, by running:
tutor blocks
You can also see more details about the if and match commands with:
help if
help match
std/log commands can now attach structured context fields [toc] PR #18971 by @neveroNiwe
Added a --context flag to all std/log emitters
Example:
> use std/log
> log info 'hello' --context {user: Ana}
2026-09-26T18:56:49,484|INF|hello user="Ana"Build interactive terminal interfaces with tui [toc]
Summary
This release adds a tui command family so a Nushell user can build an interactive TUI or popup from a pipeline, without writing Rust. The commands live in a new nu-tui crate; the ratatui style conversions are shared with explore.
Interactive tui run always uses the alternate screen, so the shell comes back intact when you quit. --dialog is the same session in a smaller floating window. tui debug paints the same UI to a string and reports how it was laid out, for scripts and tests.
tui run returns one record, {action, focused, selected, page, values, rows, live}, where values holds every widget's state by id. Colors come from a new $env.config.tui section (documented in config nu --doc).
This release also fixes a related memory leak: nu-utils now reads the OS locale once per process. sys_locale goes through CoreFoundation on macOS and its autoreleased objects were never collected on a plain Rust thread, so any loop that formats filesizes (the TUI redraws per frame) grew memory without bound.
Command reference
Every builder takes --id and --focus (start with that widget focused). Data widgets (table, tree, log, select, progress, label) also take --data and --from; list widgets (table, tree, select) also take --on-select and --multi. The remaining flags are listed.
| Command | Positional | Flags | Role |
|---|---|---|---|
tui | Help listing subcommands | ||
tui label | text or closure | --title, --status | Static text: inline, on the title bar, or on the status bar. A closure follows a row |
tui menu | [items] | Menu bar with mnemonics, dropdowns, and hook actions | |
tui textbox | --placeholder, --value | Editable field | |
tui table | source closure | --columns, --capture-keys, --index | Navigable rows. Scalars show as one item column |
tui select | [items] | --display, --index | Radio list, or checkbox list with --multi |
tui button | label, hook | Runs a hook, or submits its label. Adjacent buttons share a row | |
tui progress | source closure | --value, --total, --label | Gauge fed by a value, the data, or a source row |
tui log | source closure | --max-lines | Append-only log. Follows the tail of a stream |
tui tree | source closure | --walk, --column | Nested records, or a directory walk |
tui search | --placeholder, --bind, --fuzzy, --case-sensitive, --columns | Search box. Filters the lists in its scope | |
tui preview | closure | --from, --max-bytes | Text for the selected row: a file, or whatever the closure returns |
tui split | [children] | --vertical, --sizes, --ratio | Side-by-side or stacked panes with draggable dividers |
tui box | title, [children] | A titled, bordered group | |
tui tab | title, [children] | A page in the tab bar | |
tui bind | key, hook | Run a hook when a key is pressed anywhere | |
tui run | hook | --dialog, --size, --refresh, --no-mouse | Event loop |
tui debug | hook | --keys, --until, --size, --dialog | Headless render, key replay, and layout/focus introspection |
Layout model
Widgets in the outer pipeline stack top to bottom, one row each. The exception is buttons: adjacent tui buttons pack onto one row, left to right (§12). tui split, tui box, and tui tab take a list of child widgets and arrange them. Children are built inside parentheses:
ls
| tui label --title "files"
| tui split --sizes [60% 1fr] [
(tui box "list" [ (tui search --bind /) (tui table --columns [name type size]) ])
(tui preview { nu-highlight })
]
| tui label --status "enter: pick /: filter q: quit"
| tui runChrome, that is tui label --title, tui label --status, and tui menu, goes in the outer pipeline only and stays visible on every page. tui tab is also outer-pipeline only. tui search can go in either place; its position decides what it filters (§3).
Auto ids are table-0, search-0, …, numbering widgets of each kind in tree order. When two children both contain a table-0, the second becomes table-1 and a --from table-0 inside that child follows it. An explicit --id is never renumbered; two of the same explicit id is an error. Pass --id when another widget needs a stable name; tui debug shows the resolved ids.
Data flow
Each widget shows the first of these that exists:
- its own
--data, or the value piped into it inside a child list ([(ls | tui table)]); - what its
--fromsource produced (§4); - the nearest ancestor container's data;
- the outer pipeline's data.
So one pipeline can feed every list, or each pane can have its own rows:
ls | tui split [ (tui table) (tui tree) ] | tui run # both read ls
tui split [ (ps | tui table) (ls | tui table) ] | tui run # each has its own
tui split [ (tui table --data (ps)) (tui table --data (ls)) ] # the same, spelled outA builder reads a stream for a quarter of a second. A producer that finishes in that time (ls, ps, open) is collected into the widget's data; one that keeps going (1.., tail -f) stays live and flows on to tui run (§9). A child list can only hold collected values, so keep unbounded producers in the outer pipeline.
Hook contract
One contract covers every closure that reacts to the user: tui bind, menu actions, tui button, --on-select, and the tui run closure. The hook receives the state record (the same record tui run returns, §Result record) as $in, and as its first parameter when it declares one. Its output decides what happens:
| Returns | Effect |
|---|---|
| nothing | nothing changes |
{action: submit, selected: ...} | the TUI closes with that selection |
{action: quit} | the TUI closes without a selection |
| anything else | it replaces the shared data list; every widget reading it redraws |
An error goes to the status bar as error:… and the TUI stays open.
ls
| tui table
| tui bind ctrl+r {|| ls } # reload
| tui bind s {|state| {action: submit, selected: $state.selected.name} } # submit the name
| tui runnu --dap starts a Debug Adapter Protocol server for Nushell scripts [toc]
Added a Debug Adapter Protocol server to Nushell. Running nu --dap starts a DAP server over stdio, so any DAP-capable editor (VS Code, Zed, Neovim, …) can debug .nu scripts — set breakpoints (including conditional breakpoints and logpoints), step through code and pipelines, inspect variables and $env, evaluate watch expressions, and even step backward through a recorded timeline.
Completion input now exposes the command being completed [toc] PR #19054 by @philocalyst
Added place.command to completion input records. Custom completers that declare place can now read the command being completed as a list of shell words, so external completers can reliably use $place.command.0 and ...$place.command even after pipes, semicolons, inside closures, or inside subexpressions.
Sourced menus now refresh correctly after partial completion [toc] PR #19054 by @philocalyst
Fixed sourced menus with partial completion enabled so Tab completion refreshes against the updated line after inserting a common prefix. This avoids corrupting the command line or replacing the wrong span, such as bits r becoming bits ror o instead of bits ror.
Other additions [toc]
- Floating point number strings may now be parsed via
into floatif they use a comma as decimal separator. (#18882) to yaml --non-roundtripnow also accepts a rawnullinstead of only"null"for the null configuration. (#18851)- Allow
take until,take while,skip until,skip while, andchunk-byto use row condition syntax alongside closures. (#18844) - Include UTC offset in
date list-timezoneoutput. (#18922) - You can now hash a value using the sha512 algorithm using the
hash sha512built-in. (#19027) - Added
mkdir --fail-if-exists <dir>, which errors if the directory already exists instead of silently succeeding. Defaultmkdirbehavior is unchanged. (#19021) save --forcenow creates missing parent directories before writing the destination file. (#19039)update cellshas a new--recursive(-r) flag. With it, the closure runs on every leaf value inside nested records and lists instead of on the containing cell as a whole. The default behavior is unchanged. (#19060)- Added forward slash and backslash to
char, independent of the underlying operating system. (#19082) - Added the
SwitchModekeybinding event,{ send: SwitchMode, mode: vi_normal }, taking the same mode namesmodetakes on a keybinding. A switch into the mode already active reports itself inapplicable, so anuntillist falls through to its next event where it used to stop;ViChangeModeandHelixChangeModeshare that. (#19077) - Added
vi_visualas a keybinding mode and$env.config.cursor_shape.vi_visual, which followsvi_normalwhile left oninherit. Bindings forvi_normalno longer apply in visual mode. (#19077)
Performance [toc]
Faster typing of use in the REPL [toc]
The REPL no longer parse-time-loads a module just to syntax-highlight it. Typing use std or use std/iter no longer stalls on the first exact match of std (most noticeable in debug builds). Execution is unchanged: the module still loads when you run the line.
Completing use std/ (and export use / overlay use) lists virtual standard-library children without walking the current directory. $NU_LIB_DIRS is still searched. Completing a real path such as use ./foo/ is unchanged.
Syntax highlighting also does less work per keystroke: it reuses the last parse of the same line (for example when only the cursor moves) and copies less text while painting.
# These should feel instant to type in the REPL, including debug `cargo run`
use std
use std/iter
use std/assert$nu.startup-time is now accurate and Nushell starts faster with large configs [toc]
More accurate startup reporting
$nu.startup-time now measures the time until the first prompt is ready, starting at process creation on macOS and Windows, or at main on other platforms. This includes config files, plugins, env_change and pre_prompt hooks, and prompt evaluation. Startup hooks see a provisional value; the final value is available from the first command onward. Scripts also get a startup time instead of -1ns.
The banner's "Startup Time" line now appears after the startup hooks, just before the first prompt, so it shows the final value. The welcome message still appears first, with hook output between it and the timing line. Use banner --no-startup-time to hide the timing line.
For a closer look, --log-level perf reports time spent before main, in engine setup, and loading the standard library, followed by a final "startup (process start to first prompt)" line.
Faster loading and commands
Command lookups no longer rebuild overlay visibility maps, roughly halving config load time for configs that use many modules. Loading the plugin registry is also faster: about 5× for a registry with 20 plugins.
gstat finds the nearest tag faster in large repositories—about 4× in the Nushell repo—with unchanged output. When no terminal is attached, table and term size avoid spawning tput and use COLUMNS/LINES, falling back to 80×24.
Other performance improvements [toc]
- Optimize
style_computer.rs#style_primitiveto useshallow_get_type()instead ofget_type()(#18975) - Improved parsing performance: scripts, modules and
sourced files parse about 1.4-1.5x faster, and the REPL's per-keystroke parse benefits accordingly. No change to what is accepted, rejected, or reported. (#19055)
Other changes
The MCP HTTP server now listens only on 127.0.0.1 by default [toc]
The MCP HTTP server now binds to 127.0.0.1 by default instead of 0.0.0.0, so it is no longer exposed to other hosts on the network unless explicitly configured.
Added --mcp-host for choosing the MCP HTTP bind address. Use --mcp-host 0.0.0.0 with --mcp-transport http if you intentionally want the MCP server to listen on all interfaces.
Additional changes [toc]
- The
eachcommand's documentation now includes more information on supported input types. (#18893) - Refreshing
$env.ENV_CONVERSIONSnow also normalizesPATHinto its usual list form. Theload-envhelp documents how to refresh environment conversions after importing string values. (#18832)
Bug fixes [toc]
lines --skip-empty now works consistently across input types [toc]
lines --skip-empty now skips empty lines for string and byte stream input, not only list streams.
> "foo\n\nbar" | lines --skip-empty
╭───┬─────╮
│ 0 │ foo │
│ 1 │ bar │
╰───┴─────╯Whitespace-only lines are treated as empty, same as they already were for list streams.
format pattern and parse now reject unclosed { patterns [toc]
format pattern already reported a delimiter error for a lone }. A pattern that ended with { succeeded and dropped the brace. parse simple patterns did the same.
Both commands now treat an unescaped { without a matching } as a delimiter error.
> {} | format pattern '{'
Error: nu::shell::delimiter_error
× Delimiter error
╭─[repl_entry #20:1:6]
1 │ {} | format pattern '{'
· ───────┬──────
· ╰── there are unmatched curly braces
╰────
> "hello " | parse "hello {"
Error: nu::shell::delimiter_error
× Delimiter error
╭─[repl_entry #21:1:18]
1 │ "hello " | parse "hello {"
· ────┬────
· ╰── Found opening `{` without an associated closing `}`
╰────
Escaped braces ({{ and }}) still insert a literal brace. A lone } in parse is still a literal character to match, not an error. parse --regex is unchanged.
into string now preserves string typing for semver values [toc]
> let s = "1.0.0" | into semver | into string
> $s | describe
string
> "/tmp" | path join ("1.115.0" | into semver | into string)
/tmp/1.115.0format date handles locale-specific formats correctly [toc] PR #18918 by @aron-intframe
PR #18924 by @aron-intframe
format date now handles %E and %O modifiers in locale-specific formats. Under locales such as Thai (th_TH) and Lao (lo_LA), %x, %X and %c render in the locale's own field order, without the era. This also fixes startup errors from the default config's date now | format date '%x %X'.
> $env.LC_TIME = "th_TH.UTF-8"
> date now | format date '%c'
ส. 26 ก.ย. 26, 20:30:58Explicit modifiers work too: %Ey and %Od render as %y and %d would. For locales without an AM/PM format, including az_IR and fa_IR, %r falls back to the locale's plain time format and handles its modifiers:
> $env.LC_TIME = "fa_IR.UTF-8"
> date now | format date %r
20:34:19Other locales, including de_DE, fr_FR and nl_NL, continue to render as before.
Faster repeated source of the same file [toc]
0.115 started re-parsing every source / source-env of a file that had already been parsed, so configs and libraries that source the same helpers many times got slower as more files were loaded. A 63-file case that stayed around 50ms in 0.114 grew to hundreds of milliseconds.
This release restores safe reuse of cached blocks for source and source-env. Libraries without captured values can use the cache, as in 0.114, while blocks with stale captures are parsed again to keep their values up to date.
Redirected nu --help output no longer contains ANSI color escapes [toc] PR #18899 by @catlover-bot
nu --help no longer writes ANSI escape sequences when its stdout is redirected to a pipe or file.
For example:
nu --help > help.txtNow produces plain text instead of ANSI-colored text.
Table display now respects $env.config.table.trim wrapping and truncating more consistently [toc]
Fixed $env.config.table.trim so wrapping and truncating actually differ on default table display (table -e on terminals 100 columns or wider), including with header_on_separator.
| Mode | Behavior |
|---|---|
| Wrapping | Shows more columns, wrapping long cells onto extra lines. |
| Truncating | Keeps one line per row, drops extra columns with a trailing ..., and marks cut cells with truncating_suffix. |
In both modes, columns are no longer squeezed to a single character, avoiding the vertical s/i/z/e layout for size. The trailing ... column indicates omitted columns; truncating_suffix only marks a visible cell whose content was cut.
Examples:
> $env.config.table.trim = { methodology: wrapping, truncating_suffix: "..." }
> ls -al | first 5
╭───┬─────────────────────────────────────────┬──────┬────────┬──────────┬────────┬────────┬─────╮
│ # │ name │ type │ target │ readonly │ size │ create │ ... │
│ │ │ │ │ │ │ d │ │
├───┼─────────────────────────────────────────┼──────┼────────┼──────────┼────────┼────────┼─────┤
│ 0 │ .abc___________________________________ │ file │ │ false │ 0 B │ a minu │ ... │
│ │ │ │ │ │ │ te ago │ │
│ 1 │ .cargo │ dir │ │ false │ 0 B │ a year │ ... │
│ │ │ │ │ │ │ ago │ │
│ 2 │ .git │ dir │ │ false │ 4,0 kB │ 2 year │ ... │
│ │ │ │ │ │ │ s ago │ │
│ 3 │ .gitattributes │ file │ │ false │ 113 B │ 3 mont │ ... │
│ │ │ │ │ │ │ hs ago │ │
│ 4 │ .githooks │ dir │ │ false │ 0 B │ 3 mont │ ... │
│ │ │ │ │ │ │ hs ago │ │
╰───┴─────────────────────────────────────────┴──────┴────────┴──────────┴────────┴────────┴─────╯> $env.config.table.trim = { methodology: truncating, truncating_suffix: "..." }
> ls -al | first 5
╭───┬─────────────────────────────────────────┬──────┬────────┬──────────┬────────┬────────┬─────╮
│ # │ name │ type │ target │ readonly │ size │ cre... │ ... │
├───┼─────────────────────────────────────────┼──────┼────────┼──────────┼────────┼────────┼─────┤
│ 0 │ .abc___________________________________ │ file │ │ false │ 0 B │ 2 m... │ ... │
│ 1 │ .cargo │ dir │ │ false │ 0 B │ a y... │ ... │
│ 2 │ .git │ dir │ │ false │ 4,0 kB │ 2 y... │ ... │
│ 3 │ .gitattributes │ file │ │ false │ 113 B │ 3 m... │ ... │
│ 4 │ .githooks │ dir │ │ false │ 0 B │ 3 m... │ ... │
╰───┴─────────────────────────────────────────┴──────┴────────┴──────────┴────────┴────────┴─────╯length, columns, and is-empty now surface errors from streamed input [toc]
Fixed an issue where length, columns, and is-empty / is-not-empty could silently ignore errors in streamed input and return incorrect results instead of surfacing the original error.
For example, [[name size]; [a 100b] [b 200b]] | where size <= 150 | length now errors with nu::shell::operator_incompatible_types instead of returning 2, and likewise for columns / is-empty.
> [[name size]; [a 100b] [b 200b]] | where size <= 150 | length
Error: nu::shell::operator_incompatible_types
× Types 'filesize' and 'int' are not compatible for the '<=' operator.
╭─[repl_entry #52:1:18]
1 │ [[name size]; [a 100b] [b 200b]] | where size <= 150 | length
· ──┬─ ─┬ ─┬─
· │ │ ╰── int
· │ ╰── does not operate between 'filesize' and 'int'
· ╰── filesize
╰────
Chained par-each pipelines no longer deadlock on same-size thread pools [toc]
Chaining par-each commands with the same thread count could cause a pipeline to hang. The commands could share a thread pool while both were still running: the earlier stage would wait for the next stage to consume its output, while the next stage waited for a free worker.
This release reuses cached thread pools only when they are idle. Stages running at the same time use separate pools, allowing pipelines like this to finish:
> 0..99
| par-each --threads 1 {|it| $it }
| par-each --threads 1 {|it| $it }
| length
100Expanded nested tables now keep their table borders when cells wrap [toc]
table --expand now preserves the borders of nested tables, including those in plugin list output. Previously, wrapping a nested table as plain text could break its layout.
Long cells wrap or truncate within the nested table according to $env.config.table.trim, keeping its structure intact. Scalar values in the outer table continue to follow the same wrapping or truncation setting.
mkdir --verbose no longer reports existing directories as newly created [toc] PR #19017 by @Developer1010x
Fixed mkdir --verbose reporting created: true for directories that already existed. Such rows now report created: false. Directories that are actually created are unaffected.
finally now always runs, in the right order, however a try block is left [toc]
Cleanup runs in the right order
When an outer catch handles an error, every finally block between the error and that handler now runs, innermost first. This also applies to errors raised inside a catch or another finally block. An error raised in finally still replaces the original error.
An error or return inside try now runs finally and takes effect without executing the statements after the try expression. Likewise, break and continue run finally before control returns to the loop. They also leave error handlers intact, fixing cases where a later, unrelated error triggered a leftover handler.
Consistent input to finally
$in is now always defined inside finally and matches the block's optional parameter (finally {|x| ... }):
How try/catch completes | Value passed to finally |
|---|---|
| Success | The value produced by try/catch |
| Error | The error record |
return, exit, break or continue | nothing |
Changes to view ir
view ir now shows begin-finally, end-finally and unwind-jump in place of pop-finally. The register-less finally instruction has also been removed.
List literals and match patterns now reject semicolon separators [toc] PR #19063 by @windlandneko
List literals and match list patterns now reject unexpected semicolon separators instead of silently accepting malformed input or discarding subsequent content.
Header-only table syntax such as [[a b];] now also produces a parse error.
> [[a b];]
Error: nu::parser::parse_mismatch
× Parse mismatch: expected table row.
╭─[repl_entry #60:1:8]
1 │ [[a b];]
· ▲
· ╰── expected table row
╰────
help: Check the syntax around this position — a typo, missing delimiter, or wrong separator is common.
LSP hover tooltips now render Markdown without accidental bold text [toc]
LSP hover descriptions now render as normal text. A missing blank line before the Markdown separator made the description look like a heading instead.
Renders some greeting message
Usage
hello {flags}Renders some greeting message
Usage
hello {flags}* These previews are approximations for illustration, not actual LSP output. The exact appearance depends on your editor.
External completers now receive expanded alias commands and show warnings after menus close [toc] PR #19085 by @kronberger-droid
External completers receive the command name and its arguments in $place.command, with one list item per shell word. This list describes the command at the cursor, including when it appears after a pipe or ;, or inside a closure.
For example, this completer passes the command name and argument list to Carapace:
$env.config.completions.external.completer = {|place|
carapace $place.command.0 nushell ...$place.command | from json
}Aliases are expanded before the list reaches the completer. If gco is an alias for git checkout, typing gco ma gives the completer [git, checkout, ma].
The legacy spans input receives the same list. Incomplete arguments stay together: typing foo [a b produces [foo, "[a b"], keeping the unfinished list as one argument instead of splitting it into brackets, words and spaces.
Deprecation warnings for menu source configurations now appear after the command line is handed back, once the completion menu has closed. This keeps warnings from appearing over the menu.
Other fixes [toc]
- 2 issues were identified which may result in invalid suggestions when an unresolved command is entered. (#18728)
- Fixed an issue where YAML values containing
.infor.nanas embedded text could be incorrectly converted to floating-point values. Values such asa.infraanda.nanotubenow remain strings when decoded withfrom yaml. (#18897) - Invalidate the config any time anything changes under $env.config (#18950)
- Nushell now supports color coded
lsoutput for a broader range of files by default (e.g..avif,.odin, etc.), with the exception of.kexwhich has been removed..csvhas a new default color value. (#18937) - Fixed an issue in
keybindings listenwhereEscwouldn't quit if a state (e.g.NumLockorCapsLock) was reported. (#18867) trywith acatchorfinallyblock no longer prints a stray blank line after an external command's output. (#18811)- Fixed an issue where each while silently stopped when the closure or input ByteStream produced an error. These errors are now preserved and reported. (#18958)
- External command arguments beginning with { are now parsed as closures or records; literal curly-braced arguments must be quoted. (#18837)
- Fixed an issue where
--ide-checksilently succeeded when the target file could not be read. Nushell now reports the file read error and exits with a non-zero status. (#18961) - Fixed an issue in workspace compilation where using the "plugin" feature flag that would result in a compilation error. (#18988)
- Fixed an issue where
commandline completeignored an external completer assigned to$env.config.completions.external.completerearlier in the same script. (#19012) - Adds a default value to
error make's labelstext(#19037) - Fixed
query web -t []failing withplugin_failed_to_decodeon HTML tables that have no<th>headers and more than one row. Such tables now produce one record per row with generatedcolumn0,column1, ... column names. (#19041) - Fixed a panic when printing empty lists/records or narrow-fitting tables on a zero-column pty (e.g. some CI environments). Nushell now falls back to plain text output or a warning instead of crashing. (#19045)
- mktemp --directory is now relative to the working directory if a template is passed (#18996)
defaultnow accepts cell paths for its column arguments, sodefault 5 a.bfills the nested fieldbinsidea(creatingaif needed) instead of adding a literal"a.b"key. Quote the argument, as indefault 5 "a.b", to target a key that actually contains a dot. (#19058)- Fixed an issue where
flattensilently dropped a nested record field when a top-level column of the same name came later in the record. The nested field is now renamed to<parent>_<field>, as it already was for the opposite field order. Theflattenhelp text now describes how record input is handled. (#19059) - Fixed an issue where
std dt datetime-diffreported an incorrect day count when the difference crossed a month boundary — for example, the difference between2021-01-15and2021-03-01was1month 17daysinstead of the correct1month 14days. This also corrects the standard-library startup banner, which formats its uptime withdatetime-diffviapretty-print-duration. (#19064) - Fixed
rmwith leading-dot globs such asrm -r dir/.*on Windows deletingdirand its parent directory. The.and..entries are now skipped on all platforms. (#19065) table --theme markdownandtable --theme restructured(and the matching$env.config.table.modevalues) now always produce valid Markdown / reStructuredText, even when$env.config.table.header_on_separatoris enabled. (#19066)- Fixed
rm --interactiveon Windows answering two prompts with a single key press. (#19067) - Fixed
idx searchreturning at most 200 matches per file and ignoring the exact--limitvalue. (#19078) - Fixed an issue where Nushell ignored
XDG_CONFIG_HOMEfor users without a home directory. Config loads fromXDG_CONFIG_HOMEagain, and$nu.home-dirreports an error when there is no home directory. (#19083) - Fixed
path relative-toproviding improper error messages when its argument was not a parent of the input. (#18792) view sourcenow renders a rest parameter as...rest: stringrather than...rest:string, matching how it already renders every other parameter. (#19024)
Notes for plugin developers [toc]
- Fixed compiling
nu-plugin-test-supportby default together withnu-plugin. (#18947)
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 most fs helpers from nu-test-support | #18910 |
| @fdncred | Fix completion tests by resolving ".." in WORKSPACE_ROOT path | #18941 |
| @fdncred | IR-shaped const evaluation for run_const (AST migration phase 2) | #18967 |
| @hustcer | Fix nushell command docs build error | #19084 |
Full changelog [toc]
| author | title | link |
|---|---|---|
| @Developer1010x | fix(mkdir): don't report an existing directory as created in --verbose | #19017 |
| @Developer1010x | docs(mkdir): the --verbose example showed output that never occurs | #19023 |
| @Developer1010x | fix(view source): put a space after the colon on a rest parameter | #19024 |
| @Dheebz | fix(env): normalize PATH when refreshing ENV_CONVERSIONS | #18832 |
| @Dheebz | fix(parser): parse brace expressions in external calls | #18837 |
| @Dheebz | fix: use stack config for commandline completions | #19012 |
| @Dorumin | Don't go to tmp if --directory | #18996 |
| @Jorge-Polanco-Roque | feat(mkdir): add --fail-if-exists flag to error on existing directory | #19021 |
| @KaiSforza | error make: Allow no text value | #19037 |
| @KaiSforza | scripts/nix: Update the flake lock | #19038 |
| @LouisDeconinck | fix(query web): parse headerless tables row by row | #19041 |
| @LouisDeconinck | fix(table): don't panic when the terminal is too narrow to draw | #19045 |
| @Mrfiregem | let more commands use row conditions | #18844 |
| @Mrfiregem | Include UTC offset in date list-timezone output | #18922 |
| @app/dependabot | build(deps): bump taiki-e/install-action from 2.85.11 to 2.86.6 | #18904 |
| @app/dependabot | build(deps): bump uuid from 1.24.0 to 1.25.0 | #18906 |
| @app/dependabot | build(deps): bump tango-bench from 0.7.2 to 0.8.0 | #18907 |
| @app/dependabot | build(deps): bump crate-ci/typos from 1.48.0 to 1.50.0 | #18954 |
| @app/dependabot | build(deps): bump hustcer/milestone-action from 3.1 to 3.2 | #18955 |
| @app/dependabot | build(deps): bump ureq from 3.3.0 to 3.4.0 | #18957 |
| @app/dependabot | build(deps): bump taiki-e/install-action from 2.86.6 to 2.87.7 | #18990 |
| @app/dependabot | build(deps): bump crate-ci/typos from 1.50.0 to 1.50.1 | #18991 |
| @app/dependabot | build(deps): bump the uutils group with 8 updates | #18992 |
| @app/dependabot | build(deps): bump aws-config from 1.10.0 to 1.12.0 | #18994 |
| @app/dependabot | build(deps): bump taiki-e/install-action from 2.87.7 to 2.87.12 | #19028 |
| @app/dependabot | build(deps): bump actions-rust-lang/setup-rust-toolchain from 1.17.0 to 2.0.0 | #19029 |
| @app/dependabot | build(deps): bump dirs from 6.0.0 to 7.0.0 | #19030 |
| @app/dependabot | build(deps): bump tabled from 0.21.0 to 0.22.0 | #19031 |
| @app/dependabot | build(deps): bump taiki-e/install-action from 2.87.12 to 2.87.17 | #19068 |
| @app/dependabot | build(deps): bump crate-ci/typos from 1.50.1 to 1.50.2 | #19069 |
| @app/dependabot | build(deps): bump rstest from 0.26.1 to 0.27.0 | #19070 |
| @app/dependabot | build(deps): bump serde-saphyr from 1.2.0 to 1.3.0 | #19071 |
| @aron-intframe | fix(format date): render locales whose format carries %E or %O | #18918 |
| @aron-intframe | fix(format date): resolve %r when the locale's am/pm fallback also carries %O | #18924 |
| @ayax79 | Polars date range | #18887 |
| @ayax79 | MCP: set default bind host to 127.0.0.1 | #18952 |
| @bobisageek | fix keybindings listen - ignore KeyEventState when checking for Esc | #18867 |
| @catlover-bot | fix: strip ANSI from redirected CLI help | #18899 |
| @costajohnt | fix(config): keep XDG config when there is no home directory | #19083 |
| @cptpiepmatz | Allow raw null as a value for to yaml --non-roundtrip | #18851 |
| @cptpiepmatz | Allow float value strings with commas in into float | #18882 |
| @cptpiepmatz | Prepare patch release | #18884 |
| @cptpiepmatz | Bump patch version after release | #18885 |
| @cptpiepmatz | Remove most fs helpers from nu-test-support | #18910 |
| @cptpiepmatz | Propagate local-socket feature into nu-plugin-test-support | #18947 |
| @cptpiepmatz | Replace to yaml --compact-list-indent with --list-indent | #19005 |
| @cuishuang | ide: report file read failures from --ide-check | #18961 |
| @dilr | Document behavior of each for more types of inputs. | #18893 |
| @fdncred | named parameters can pass null or omit parameter entirely for easier shadowing | #18796 |
| @fdncred | reduce ast dependency for ir calls - phase 1 | #18813 |
| @fdncred | perf - stop parse-time-loading modules and extra cwd walks while typing use std/ | #18841 |
| @fdncred | fix unmatched { at end of format pattern and parse patterns | #18871 |
| @fdncred | fix lines --skip-empty for string and byte stream input | #18872 |
| @fdncred | fix: infer string from semver | into string. | #18901 |
| @fdncred | fix(tests): fix completion tests by resolving ".." in WORKSPACE_ROOT path | #18941 |
| @fdncred | update proc_macro_error to 3 and other dependencies | #18945 |
| @fdncred | update fff-search to 0.10.6 | #18946 |
| @fdncred | fix parsing performance regression | #18948 |
| @fdncred | when config changes invalidate cache | #18950 |
| @fdncred | bump reedline to a8e9364 | #18959 |
| @fdncred | engine: IR-shaped const evaluation for run_const (AST migration phase 2) | #18967 |
| @fdncred | bump rust toolchain to 1.96.1 | #18968 |
| @fdncred | fix table truncating vs wrapping | #18979 |
| @fdncred | fix nested table after wrapping/truncating changes | #19007 |
| @fdncred | Revert "mkdir errors on already-created dir" | #19008 |
| @fdncred | the tui family of commands | #19025 |
| @fdncred | update rustls & friends | #19026 |
| @fdncred | update some deps | #19034 |
| @fdncred | bump uu_* crates to 0.12.0 | #19040 |
| @fdncred | perf(startup): make $nu.startup-time accurate and speed up config loading, plugin registry, and gstat | #19049 |
| @fdncred | fix(engine): run every finally on the way out of nested try blocks, and unwind break/continue through them | #19052 |
| @fdncred | perf(parser): reduce parse time by 30% - 50% | #19055 |
| @fdncred | bump fff-search to 0.11.0 | #19057 |
| @fdncred | fix(default): accept cell paths for column arguments | #19058 |
| @fdncred | fix(flatten): keep nested fields that collide with top-level columns | #19059 |
| @fdncred | feat(update cells): add --recursive flag to visit nested leaf values | #19060 |
| @fdncred | fix lsp hover tooltip markdown | #19080 |
| @fly1d | fix(yaml): do not parse embedded float tokens | #18897 |
| @hexbinoct | Don't print a stray blank line when try with catch or finally collects an external | #18811 |
| @hustcer | Fix nushell command docs build error | #19084 |
| @i-api | docs(nuon): add a specification of the NUON format | #18925 |
| @kronberger-droid | chore(reedline): bump reedline to 73b928a | #18890 |
| @kronberger-droid | chore(reedline): bump reedline fc19b91 | #18892 |
| @kronberger-droid | fix(nix): bump rust-overlay so the 1.96.1 toolchain resolves | #18985 |
| @kronberger-droid | chore: bump reedline 06bf606 | #18986 |
| @kronberger-droid | chore: bump reedline to 436f17b | #19013 |
| @kronberger-droid | chore(reedline): bump reedline to e0f1c0b | #19042 |
| @kronberger-droid | fix(reedline): forward Menu::settings through SourcedMenu | #19043 |
| @kronberger-droid | fix(ci): run ready_for_review CI on the PR head, not on main | #19047 |
| @kronberger-droid | feat(reedline): bump to db34d84 | #19077 |
| @kronberger-droid | fix(completions): expand alias heads in place.command, keep completer warnings off the menu | #19085 |
| @luangucun | each while: preserve errors instead of silently stopping | #18958 |
| @magnify035 | chore(ls): update default color mappings | #18937 |
| @maxim-uvarov | Add completions.persistent_menus config option | #18573 |
| @maxim-uvarov | View source dependencies | #18801 |
| @mikehasa | fix(std/dt): correct datetime-diff day count when borrowing a month | #19064 |
| @mkatychev | fix(nu-plugin): add socket feature flag to handle --no-default-features correctly | #18988 |
| @mrhard9090 | fix(rm): skip . and .. glob matches on Windows | #19065 |
| @mrhard9090 | fix(table): keep markdown and restructured headers off the separator | #19066 |
| @mrhard9090 | fix(rm): answer one --interactive prompt per key press on Windows | #19067 |
| @mrhard9090 | fix(idx search): don't cap matches at 200 per file | #19078 |
| @neveroNiwe | Add structured context support to std/log | #18971 |
| @nos1dot618 | docs(tutor): add reedline shortcuts tutorial and document $env | #18903 |
| @nos1dot618 | docs(tutor): add custom commands and pipeline input tutorials | #18927 |
| @nos1dot618 | docs(tutor): add conditional(if, match, where) tutorials | #18972 |
| @pheenty | fix improper cant convert error in path-relative-to | #18792 |
| @philocalyst | Unified Completions | #18791 |
| @philocalyst | fixes for unified/completions in general | #19054 |
| @pickx | roundup of 2 fixes for "did you mean?" | #18728 |
| @pickx | mkdir errors on already-created dir | #19006 |
| @pickx | char: add forward slash/backslash. | #19082 |
| @rvhelden | Add a nu-dap crate and nu --dap: a Debug Adapter Protocol server for Nushell | #18738 |
| @sebaschi | feat(hash): add sha512 subcommand | #19027 |
| @sidsri14 | fix: propagate error stream values in length, columns, and is-empty | #18976 |
| @surma | feat(save): create parent directories with --force | #19039 |
| @user93390 | update(style_computer.rs): fixed unessesary string allocations | #18975 |
| @windlandneko | fix(parser): reject unexpected semicolons in list literals and patterns | #19063 |
| @zozo123 | Test Incredibuild self-hosted runner in CI | #18810 |
| @zozo123 | Fix par-each deadlock when chaining same-size thread pools | #18999 |