From 92ab5ab9e4015eb13473a285771982204173d3bf Mon Sep 17 00:00:00 2001 From: Tim 'Piepmatz' Hesse Date: Sat, 26 Sep 2026 17:28:56 +0200 Subject: [PATCH 1/8] Release notes for `v0.116.0` Please add your new features and breaking changes to the release notes by opening PRs against the `release-notes-v0.116.0` branch. ## TODO - [ ] PRs that need to land before the release, e.g. [deprecations] or [removals] - [ ] add the full changelog - [ ] categorize each PR - [ ] write all the sections and complete all the `TODO`s [deprecations]: https://github.com/nushell/nushell/labels/deprecation [removals]: https://github.com/nushell/nushell/pulls?q=is%3Apr+is%3Aopen+label%3Aremoval-after-deprecation --- blog/2026-10-23-nushell_v0_116_0.md | 713 ++++++++++++++++++++++++++++ 1 file changed, 713 insertions(+) create mode 100644 blog/2026-10-23-nushell_v0_116_0.md diff --git a/blog/2026-10-23-nushell_v0_116_0.md b/blog/2026-10-23-nushell_v0_116_0.md new file mode 100644 index 00000000000..257e1dee046 --- /dev/null +++ b/blog/2026-10-23-nushell_v0_116_0.md @@ -0,0 +1,713 @@ +--- +title: Nushell 0.116.0 +author: The Nu Authors +author_site: https://www.nushell.sh/blog +author_image: https://www.nushell.sh/blog/images/nu_logo.png +excerpt: Today, we're releasing version 0.116.0 of Nu. This release adds... +--- + + + + + +# Nushell 0.116.0 + + + +Today, we're releasing version 0.116.0 of Nu. This release adds... + +# Where to get it + +Nu 0.116.0 is available as [pre-built binaries](https://github.com/nushell/nushell/releases/tag/0.116.0) or from [crates.io](https://crates.io/crates/nu). 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](https://www.nushell.sh/book/plugins.html) you can install and use with Nushell. + +# Table of contents + + + +# Highlights and themes of this release + + + + +# Changes + +## Breaking changes + +* Replaced `to yaml`/`to yml`'s `--compact-list-indent` flag with `--list-indent` flag which takes either `compact` or `indented`. ([#19005](https://github.com/nushell/nushell/pull/19005)) + +## Additions + +### Named flags: null can omit or pass through based on type + +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`), so defaults and “flag not passed” behavior work—especially useful when shadowing builtins with `%cp` / `%ls` and writing `--flag=$maybe_null` +- **Passes `null` through** if the type accepts `nothing` (e.g. `--x: any`, `--x: oneof`), so callers can still express an explicit null when they opt into that in the signature + +```nushell +def f [--x: oneof = 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 + +Internal and custom commands accept spreading a record as named flags: + +```nushell +def wrap [--preserve: list, --recursive, ...rest] { + %cp ...{ preserve: $preserve, recursive: $recursive } ...$rest +} + +let flags = {preserve: [mode], recursive: true} +wrap ...$flags src dest +``` + +- Null fields follow the same type rule as named flags above +- Switch fields: `true` sets the flag; `false` / `null` omit +- Field values are type-checked against the flag signature +- Unknown flag names in the record error at runtime +- Spreading a **list** into a command with no `...rest` errors clearly (it is not treated as named flags) + +### New Polars commands can create date and datetime ranges +Implemented commands for creating date and datetime ranges: + +- `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 + +Added a `tutor` shortcuts tutorial covering command history shortcuts. + +image + +The variable tutorial now also documents the $env built-in variable. + +image + +### The interactive tutor now covers custom commands and pipeline input + +Added new `tutor` tutorials for defining custom commands and working with pipeline input. + +image + +image + +### `$env.config.completions.persistent_menus` keeps completion and history menus open while editing + +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. + +```nushell +$env.config.completions.persistent_menus = true +``` + +### `view source --dependencies` can now include custom command dependencies + +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: + +```nushell +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` + +Added a new `tutor conditionals` tutorial for learning conditional logic, pattern matching, and conditional filtering. + +image +image + +### `std/log` commands can now attach structured context fields + +Added a `--context` flag to all std/log emitters + +Examples: +``` +> log info 'hello' --context {user: Ana} +2026-09-05T15:39:01.826|INF|hello user="Ana" +``` + +### Summary + +This PR 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`). + +Also in this PR: `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 button`s 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: + +```nushell +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 run +``` + +Chrome, 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: + +1. its own `--data`, or the value piped into it inside a child list (`[(ls | tui table)]`); +2. what its `--from` source produced (§4); +3. the nearest ancestor container's data; +4. the outer pipeline's data. + +So one pipeline can feed every list, or each pane can have its own rows: + +```nushell +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 out +``` + +A 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 `action`s, `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. + +```nushell +ls +| tui table +| tui bind ctrl+r {|| ls } # reload +| tui bind s {|state| {action: submit, selected: $state.selected.name} } # submit the name +| tui run +``` + +### `nu --dap` starts a Debug Adapter Protocol server for Nushell scripts + +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. + +### Bump to db34d84 + +- Added the `SwitchMode` keybinding event, `{ send: SwitchMode, mode: vi_normal }`, taking the same mode names `mode` takes on a keybinding. A switch into the mode already active reports itself inapplicable, so an `until` list falls through to its next event where it used to stop; `ViChangeMode` and `HelixChangeMode` share that. +- Added `vi_visual` as a keybinding mode and `$env.config.cursor_shape.vi_visual`, which follows `vi_normal` while left on `inherit`. Bindings for `vi_normal` no longer apply in visual mode. + +### Completion input now exposes the command being completed + +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 + +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 + +* Floating point number strings may now be parsed via `into float` if they use a comma as decimal separator. ([#18882](https://github.com/nushell/nushell/pull/18882)) +* `to yaml --non-roundtrip` now also accepts a raw `null` instead of only `"null"` for the null configuration. ([#18851](https://github.com/nushell/nushell/pull/18851)) +* Allow `take until`, `take while`, `skip until`, `skip while`, and `chunk-by` to use row condition syntax alongside closures. ([#18844](https://github.com/nushell/nushell/pull/18844)) +* Include UTC offset in `date list-timezone` output. ([#18922](https://github.com/nushell/nushell/pull/18922)) +* You can now hash a value using the sha512 algorithm using the `hash sha512` built-in. ([#19027](https://github.com/nushell/nushell/pull/19027)) +* Added `mkdir --fail-if-exists `, which errors if the directory already exists instead of silently succeeding. Default `mkdir` behavior is unchanged. ([#19021](https://github.com/nushell/nushell/pull/19021)) +* `save --force` now creates missing parent directories before writing the destination file. ([#19039](https://github.com/nushell/nushell/pull/19039)) +* `update cells` has 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](https://github.com/nushell/nushell/pull/19060)) +* Added forward slash and backslash to `char`, independent of the underlying operating system. ([#19082](https://github.com/nushell/nushell/pull/19082)) + +## Performance + +### Faster typing of `use` in the REPL + +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. + +```nushell +# 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 + +- `$nu.startup-time` now measures from process creation (on macOS and Windows; from `main` on other platforms) to the moment the first prompt is ready, so it includes config files, plugins, `env_change` and `pre_prompt` hooks, and prompt evaluation. Hooks that run before the first prompt see a provisional value; the final value is available from the first command on. +- The banner's "Startup Time" line is now printed right before the first prompt, after the startup hooks, so it shows the final value. The welcome message still appears first; output from `env_change`/`pre_prompt` hooks now lands between the welcome message and the startup time line. `banner` gained a `--no-startup-time` flag. +- `$nu.startup-time` is now set when running a script (it was `-1ns`). +- Improved performance of parsing config files and modules: command lookups no longer rebuild overlay visibility maps, which roughly halves config load time for configs that `use` many modules. +- Improved performance of loading the plugin registry file (about 5x on a 20-plugin registry). +- `gstat` computes the nearest tag much faster on large repositories (about 4x on the nushell repo); output is unchanged. +- `table` and `term size` no longer spawn `tput` when no terminal is attached; they use `COLUMNS`/`LINES`, or 80x24, instead. +- `--log-level perf` now reports the time spent before `main`, engine setup, standard library loading, and a final "startup (process start to first prompt)" line. + +### Other performance improvements + +* Optimize style_computer.rs#style_primitive to use shallow_get_type() instead of get_type() ([#18975](https://github.com/nushell/nushell/pull/18975)) +* Improved parsing performance: scripts, modules and `source`d 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](https://github.com/nushell/nushell/pull/19055)) + +## Other changes + +### Propagate `local-socket` feature into `nu-plugin-test-support` + +todo(plugins): + +Fixed compiling `nu-plugin-test-support` by default together with `nu-plugin`. + +### The MCP HTTP server now listens only on `127.0.0.1` by default + +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 + +* - The `each` command's documentation now includes more information on supported input types. ([#18893](https://github.com/nushell/nushell/pull/18893)) +* Refreshing `$env.ENV_CONVERSIONS` now also normalizes `PATH` into its usual list form. The `load-env` help documents how to refresh environment conversions after importing string values. ([#18832](https://github.com/nushell/nushell/pull/18832)) + +## Bug fixes + +### `lines --skip-empty` now works consistently across input types + +`lines --skip-empty` now skips empty lines for string and byte stream input, not only list streams. + +```nushell +"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 + +`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. + +```nushell +{} | format pattern '{' +# Error: nu::shell::delimiter_error (there are unmatched curly braces) + +"hello " | parse "hello {" +# Error: nu::shell::delimiter_error (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 + +```nushell +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.0 +``` + +### `format date` no longer errors under Thai, Lao and similar locales + +`format date` with `%x`, `%X` or `%c` failed with `nu::shell::type_mismatch, invalid format` under locales such as `th_TH` and `lo_LA`, which write the year with a modifier the date library does not implement. The default config runs `date now | format date '%x %X'`, so affected users saw it at every startup. These now render in the locale's own field order, without the era: + +```nushell +# with LC_TIME=th_TH.UTF-8 +date now | format date '%c' +# before: Error: nu::shell::type_mismatch, invalid format +# after: ศ. 22 ต.ค. 21, 20:00:12 +``` + +A modifier you type yourself no longer errors either: `%Ey` and `%Od` now render as `%y` and `%d` would. + +### `format date %r` now works under the last two locales that still failed + +#18918 fixed `format date` under locales whose formats use `%E`/`%O`, but `az_IR` and `fa_IR` still failed on `%r`, because they define no am/pm format and their plain time format carries the modifier again: + +```nushell +# with LC_TIME=fa_IR.UTF-8 +date now | format date %r +# before: Error: nu::shell::type_mismatch, invalid format +# after: 20:00:12 +``` + +Every other locale, including `de_DE`, `fr_FR` and `nl_NL`, renders exactly as before. + +### Faster repeated `source` of the same file + +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. + +After this PR `source` / `source-env` go through `parse()` again. A cached block is reused only when it is safe. Stale captures fall through and parse fresh. That is the #18515 path. Empty-capture libraries hit the cache. That is the 0.114 path. + +### Redirected `nu --help` output no longer contains ANSI color escapes + +`nu --help` no longer writes ANSI escape sequences when its stdout is redirected to a pipe or file. + +For example: + +```sh +nu --help > help.txt +``` + +now produces plain text instead of ANSI-colored text. + +### Fix improper cant convert error in path-relative-to + +Fixed `path relative-to` providing improper error messages when its argument was not a parent of the input. + + - - - # Nushell 0.116.0 - - -Today, we're releasing version 0.116.0 of Nu. This release adds... +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 @@ -51,6 +45,40 @@ As part of this release, we also publish a set of optional [plugins](https://www # Highlights and themes of this release +## I'm too lazy to type, lemme press tab + +Pressing Tab is easy. Making everything behind it agree on how completions work took a bit more effort. Thanks to [@philocalyst](https://github.com/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. + +::: warning Breaking change +Existing custom completers and menu sources may need updating. See the examples and migration table in [unified custom completions](#unified-custom-completions). +::: + +There are plenty of smaller improvements around that big rework, too. Completers can now [see which command you are completing](#completion-input-now-exposes-the-command-being-completed), and external completers [receive expanded aliases](#external-completers-now-receive-expanded-alias-commands-and-show-warnings-after-menus-close). Sourced menus [refresh properly after partial completion](#sourced-menus-now-refresh-correctly-after-partial-completion), warnings wait until the menu closes, and you can opt into [keeping completion and history menus open while editing](#env-config-completions-persistent-menus-keeps-completion-and-history-menus-open-while-editing). Less fighting the menu, more pressing Tab. + +## Teach me things + +Nushell's interactive `tutor` has more lessons for you. Thanks to [@nos1dot618](https://github.com/nos1dot618), you can now learn about [command-history shortcuts and `$env`](#the-interactive-tutor-now-teaches-command-history-shortcuts-and-the-env-variable), write your own [custom commands and work with pipeline input](#the-interactive-tutor-now-covers-custom-commands-and-pipeline-input), and get to grips with [`if`, `match`, and `where`](#the-interactive-tutor-now-teaches-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 + +Ever wanted your script to have a little interface? Thanks to [@fdncred](https://github.com/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](#build-interactive-terminal-interfaces-with-tui), then head over to the [original PR](https://github.com/nushell/nushell/pull/19025) for more. Even this changelog cannot easily cover everything these commands can do. + +## Interactive debugging! + +That script is doing something strange again. Time to set a breakpoint. Thanks to [@rvhelden](https://github.com/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](#nu-dap-starts-a-debug-adapter-protocol-server-for-nushell-scripts). + +## Make Nushell faster + +There is less waiting around this release, too. [Typing and completing `use` in the REPL](#faster-typing-of-use-in-the-repl) does less work, and [large configs load faster](#nu-startup-time-is-now-accurate-and-nushell-starts-faster-with-large-configs), 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](#other-performance-improvements), and the [repeated `source` slowdown introduced in 0.115](#faster-repeated-source-of-the-same-file) is fixed. Thanks to everyone making the shell a little quicker, one less bit of unnecessary work at a time. +