nu-shell Nushell treats all data as structured tables — lists of records with rows and columns. Every file and command output becomes a table you can filter, transform, and combine. File I/O & Parsing Files auto-detect from extension. Pipe command output into tables: Core Pipeline Commands Filtering & Selecting - — keep specific columns (keeps table shape) - — drop a column - — extract as a list (not a table) Transforming Data Combining Data String Operations Flow Control & Variables JSON Manipulation (jq equivalents) Nushell replaces entirely. Parse with , transform with pipeline commands, o…

...'` with expressions in parentheses. Double quotes interpret escape sequences; single quotes do not.\n\n```nu\nlet name = \"Nushell\"\n$\"My favorite shell is ($name)\"\n\n# Executing external commands via interpolation (use ^ prefix)\nlet path1 = \"/part1\"\nlet path2 = \"/part2\"\n^$\"($path1)($path2)/file.txt\"\n\n# Recognized escape sequences in double-quoted strings\n\"\\e[31mRed\\e[0m\" # Escape character + ANSI codes\n\"\\n\\t\\r\\b\" # Newline, tab, carriage return, backspace\n```\n\n## Flow Control Statements\n\n### `if` / `else` — Conditional Expression\n\n`if` is an expression (returns a value), not just a statement:\n\n```nu\n# Basic if/else\nif true { print \"yes\" } else { print \"no\" }\n\n# Assignment from conditional\nlet result = if $x > 0 { \"positive\" } else { \"non-positive\" }\n\n# Elif chain (optional else)\nif condition1 { ... } elif condition2 { ... } else { ... }\n\n# The else branch is an expression — allows chained ifs naturally\nif false { 1 } else 100 # => 100\n```\n\n### `for` — Iterate Over a Range or List\n\n```nu\nfor i in 1..5 { print $i } # Iterate range: 1, 2, 3, 4, 5\nfor item in $items { process $item } # Iterate list/table values\n```\n\n### `while` — Conditional Loop\n\n```nu\nmut n = 0\nwhile ($n \u003c 5) {\n print $n\n $n += 1\n}\n```\n\n### `loop` — Infinite Loop with Break/Continue\n\n```nu\nloop {\n let input = (input)\n if $input == \"quit\" { break }\n print $\"You said: ($input)\"\n}\n```\n\n### `match` — Pattern Matching\n\n```nu\nmatch $value {\n \"A\" => { print \"A\" }\n \"B\" | \"C\" => { print \"B or C\" }\n 1..10 => { print \"range 1-10\" }\n _ => { print \"default / other\" }\n}\n\n# Match on record fields\nmatch $record {\n { name: \"admin\", role: \"superuser\" } => { grant_full_access }\n { name: $n, role: \"user\" } => { grant_basic_access $n }\n _ => { deny }\n}\n```\n\n### `try` / `catch` — Error Handling\n\n```nu\n# Try a block; catch errors\ntry { open nonexistent.txt } catch { |err| print $\"Error: ($err.msg)\" }\n\n# Catch specific error types by matching on error record\ntry { int \"not-a-number\" } catch { |e|\n match $e {\n { msg: $msg } => print $\"Type error: ($msg)\"\n _ => print \"Unknown error\"\n }\n}\n\n# Nested try/catch in closures\nopen data.csv | each { |row|\n try { $row.price | into float } catch { 0.0 }\n}\n```\n\n### `break` / `continue` / `return` — Loop Control\n\n```nu\nfor i in 1..10 {\n if $i == 3 { continue } # Skip to next iteration\n if $i == 7 { break } # Exit loop entirely\n print $i # Prints: 1, 2, 4, 5, 6\n}\n\n# return — early exit from custom command\ndef my-cmd [] {\n if ($input | is-empty) { return null }\n $input | where active == true\n}\n```\n\n## Operators\n\n### Arithmetic\n\n`+`, `-`, `*`, `/`, `//` (floor division), `mod`, `**` (power)\n\n### Comparison\n\n`==`, `!=`, `\u003c`, `>`, `\u003c=`, `>=`\n\n### Pattern Matching\n\n| Operator | Description | Example |\n| --------------------------- | -------------------- | ----------------------- |\n| `=~` / `like` | Regex match | `$name =~ \"^A\"` |\n| `!~` / `not-like` | Not regex match | `$name !~ \"pattern\"` |\n| `in` | Member of (no regex) | `\"a\" in [\"a\", \"b\"]` |\n| `not-in` | Not member of | `\"c\" not-in [\"a\", \"b\"]` |\n| `has` | Contains value | `$list has 5` |\n| `starts-with` / `ends-with` | Prefix/suffix check | `$name starts-with \"A\"` |\n| `and` / `or` | Logical operators | `$x > 0 and $y \u003c 10` |\n\n### Bitwise (Nushell-specific names)\n\n`bit-and`, `bit-or`, `bit-xor`, `bit-shl`, `bit-shr`\n\n## Pipes and Redirection\n\nNushell has rich stream handling for external commands:\n\n| Syntax | Description |\n| ----------- | ------------------------------------------ |\n| `\\|` | Standard stdout pipe (internal only) |\n| `e>\\|` | Pipe stderr from external command |\n| `o+e>\\|` | Pipe stdout + stderr from external command |\n| `o> file` | Redirect stdout to file |\n| `e> file` | Redirect stderr to file |\n| `o+e> file` | Redirect both to file |\n\n```nu\n# Capture structured output from external commands\nlet result = do { ^my-command arg1 } | complete\n$result.exit_code # Exit status\n$result.stdout # Parsed nu value\n$result.stderr # Error message\n\n# Pipe specific streams\n^command e>| str upcase # stderr → next command\n^command o+e>| str upcase # stdout + stderr → next command\n```\n\n## Custom Commands (`def`)\n\n```nu\n# Basic definition with positional and named parameters\ndef process-data [\n input: record, # Required positional parameter with type hint\n --verbose # Optional flag (boolean)\n] {\n $input | where status == \"active\"\n}\n\n# Using closure for row processing\nopen data.csv | each { |row|\n if ($row.price > 100) { $row } else { null }\n} | where $it != null\n\n# Exporting from modules (see references/modules.md)\n```\n\n## Special Variables\n\n| Variable | Description | Example |\n| -------- | ------------------------------------------------------------------ | ----------------------------------------------- |\n| `$in` | Current pipeline input | Used implicitly by most commands |\n| `$env` | Environment variables | `$env.PATH`, `$env.HOME` |\n| `$nu` | Nushell metadata (version, config path, env-path) | `$nu.env-path` |\n| `$it` | Iteration variable in closures (legacy: use `$in` or named params) | Deprecated in favor of named closure parameters |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7008,"content_sha256":"6c1a9d36ab06d69fee1a639cae684784be1c8cc4034375726e57e67b7634df20"},{"filename":"references/jq_patterns.md","content":"# jq to Nushell Patterns\n\nNushell replaces `jq` for JSON processing. This reference maps common `jq` patterns to Nushell equivalents.\n\n> **Note**: The [official jq vs Nushell cookbook](https://www.nushell.sh/cookbook/jq_v_nushell.html) is the canonical reference.\n\n## Basic Operations\n\n### Selecting Values\n\n```nu\n# jq: echo '{\"name\":\"Alice\"}' | jq -r '.name'\n'{\"name\": \"Alice\", \"age\": 30}' | from json | get name\n```\n\n### Filtering Arrays\n\n```nu\n# jq: '.[] | select(.age > 28)'\n'[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]'\n| from json\n| where age > 28\n```\n\n### Mapping Arrays\n\n```nu\n# jq: 'map(. * 2)'\n'[1, 2, 3, 4, 5]' | from json | each { $in * 2 }\n\n# Explicit parameter binding\n'[1, 2, 3]' | from json | each { |x| $x * 2 }\n```\n\n### Combining Filters\n\n```nu\n# jq: '.[] | select(.age > 28) | .name'\n'[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]'\n| from json | where age > 28 | get name\n```\n\n### Splitting Strings\n\n```nu\n# jq: '.name | split(\" \") | .[0]'\n'{\"name\": \"Alice Smith\"}' | from json | get name | split words | get 0\n```\n\n### Conditional Logic\n\n```nu\n# jq: 'if .age > 18 then \"Adult\" else \"Child\" end'\n'{\"name\": \"Alice\", \"age\": 30}' | from json\n| if $in.age > 18 { \"Adult\" } else { \"Child\" }\n```\n\n### Handling Null Values\n\n```nu\n# jq: 'map(select(. != null))'\n'[1, null, 3, null, 5]' | from json | where { $in != null }\n```\n\n### Formatting Output\n\n```nu\n# jq: \"Name: \\(.name), Age: \\(.age)\"\n'{\"name\": \"Alice\", \"age\": 30}' | from json\n| format \"Name: {name}, Age: {age}\"\n```\n\n### Building New Objects\n\n```nu\n# jq: '{name: .name, age: (.age + 5)}'\n'{\"name\": \"Alice\", \"age\": 30}' | from json\n| {name: $in.name, age: ($in.age + 5)}\n```\n\n## Nested Items\n\n### Filtering Nested Arrays\n\n```nu\n# jq: '.data[].values[] | select(. > 3)'\n'{\"data\": [{\"values\": [1, 2, 3]}, {\"values\": [4, 5, 6]}]}'\n| from json | get data.values | flatten | where {|x| $x > 3}\n```\n\n### Complex Object Transformation\n\n```nu\n# jq: '.items | map({(.name): (.price * 2)}) | add'\n'{\"items\": [{\"name\":\"Apple\",\"price\":1},{\"name\":\"Banana\",\"price\":0.5}]}'\n| from json | get items | update price {|row| $row.price * 2}\n```\n\n## Statistical Operations\n\n### Sorting\n\n```nu\n# jq: 'sort'\n'[3, 1, 4, 2, 5]' | from json | sort\n```\n\n### Unique Values\n\n```nu\n# jq: 'unique'\n'[1, 2, 2, 3, 4, 4, 5]' | from json | uniq\n```\n\n### Averages\n\n```nu\n# jq: 'map(.score) | add / length'\n'[{\"score\":90},{\"score\":85},{\"score\":95}]' | from json | get score | math avg\n```\n\n### Grouping and Aggregating\n\n```nu\n# jq: 'group_by(.category) | map({category: .[0].category, sum: map(.value) | add})'\n'[{\"category\":\"A\",\"value\":10},{\"category\":\"B\",\"value\":20},{\"category\":\"A\",\"value\":5}]'\n| from json\n| group-by --to-table category\n| update items { |row| $row.items.value | math sum }\n| rename category sum\n```\n\n### Filtering After Aggregation\n\n```nu\n'[{\"category\":\"A\",\"value\":10},{\"category\":\"B\",\"value\":20},{\"category\":\"A\",\"value\":5}]'\n| from json\n| group-by --to-table category\n| update items { |row| $row.items.value | math sum }\n| rename category value\n| where value > 17\n```\n\n### Custom Aggregation with Reduce\n\n```nu\n# jq: 'reduce .[] as $item (0; . + $item.value)'\n'[{\"value\":10},{\"value\":20},{\"value\":30}]'\n| from json | reduce -f 0 { |item, acc| $acc + $item.value }\n```\n\n### Histogram Bins\n\n```nu\n# jq: 'group_by(. / 5 | floor * 5) | map({ bin: .[0], count: length })'\n'[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]'\n| from json\n| group-by --to-table { $in // 5 * 5 }\n| each { |row| {bin: $row.items.0, count: ($row.items | length)} }\n```\n\n## Custom Commands\n\nNushell has no built-in equivalents for `jq`'s recursive descent (`..`), `walk`, or path flattening. These custom commands fill the gap — load via `use toolbox.nu *`.\n\n### cherry-pick — Recursive Key Extraction (jq `.. | .key?`)\n\nRecursively extracts values matching a key from nested records.\n\n```nu\nexport def cherry-pick [\n test # The test function to run over each element\n list: list = [] # Initial list for collecting cherry-picked values\n] {\n let input = $in\n\n if ($input | describe) =~ \"record|table\" {\n $input | values | reduce --fold $list { |value, acc|\n $acc | append [($value | cherry-pick $test)]\n }\n | prepend [(do $test $input)]\n | flatten\n } else {\n $list\n }\n}\n\n# Usage: extract all .value fields recursively\n'{data: {value: 42, nested: {value: 24}}}' | from json\n| cherry-pick {|x| $x.value?}\n# → [null, 42, 24]\n```\n\n### walk — Recursive Transformation (jq `walk(...)`)\n\nTraverses a data structure and applies a transformation function to every leaf value.\n\n```nu\nexport def walk [mapping_fn: closure] {\n let input = $in\n\n match ($input | describe | str replace --regex '\u003c.*' '') {\n \"record\" => {\n $input | items { |key, value|\n {key: $key, value: ($value | walk $mapping_fn)}\n } | transpose -rd\n },\n \"list\" => {\n $input | each { |value| $value | walk $mapping_fn }\n },\n \"table\" | \"block\" | \"closure\" => { error make {msg: \"unimplemented\"} },\n _ => { do $mapping_fn $input },\n }\n}\n\n# Usage: double all integers in a nested structure\n'{data: {values: [1, 2, 3], nested: {values: [4, 5, 6]}}}' | from json\n| walk {|value| if ($value | describe) == \"int\" { $value * 2 } else { $value }}\n```\n\n### flatten record-paths — Flatten to Dot-Paths\n\nFlattens a nested record into a list of `{path, value}` pairs with dot-separated keys.\n\n```nu\nexport def \"flatten record-paths\" [\n --separator (-s): string = \".\" # Separator for chaining paths\n] {\n let input = $in\n if ($input | describe) !~ \"record\" {\n error make {msg: \"The record-paths command expects a record\"}\n }\n $input | flatten-record-paths $separator\n}\n\ndef flatten-record-paths [separator: string, ctx?: string] {\n let input = $in\n let primitive = ($input | describe | str replace --regex '\u003c.*' '')\n\n match $primitive {\n \"record\" => {\n $input | items { |key, value|\n let path = if $ctx == null { $key } else { [$ctx $key] | str join $separator }\n {path: $path, value: $value}\n }\n | reduce -f [] { |row, acc|\n $acc | append ($row.value | flatten-record-paths $separator $row.path) | flatten\n }\n },\n \"list\" => {\n $input | enumerate | each { |e|\n {path: ([$ctx $e.index] | str join $separator), value: $e.item}\n }\n },\n \"table\" | \"block\" | \"closure\" => { error make {msg: \"Unexpected type\"} },\n _ => { {path: $ctx, value: $input} },\n }\n}\n\n# Usage: flatten nested record to dot-paths\n'{person: {name: {first: \"Alice\", last: \"Smith\"}, age: 30}}' | from json\n| flatten record-paths\n# → [{path: \"person.name.first\", value: \"Alice\"}, ...]\n\n# Custom separator\n'{a: {b: {c: null}}}' | from json | flatten record-paths -s \"->\"\n# → [{path: \"a->b->c\", value: null}]\n```\n\n## When to Use DuckDB Instead\n\nFor heavy JSON analytics, DuckDB is more appropriate than Nushell:\n\n- **Schema inference**: `read_json()` auto-detects types and builds columns\n- **SQL queries**: Complex joins, aggregations, window functions\n- **Large datasets**: Streaming processing, Parquet output\n- **Date handling**: Auto-casts date-like columns\n\nSee the `duckdb` skill for JSON processing with DuckDB.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7365,"content_sha256":"d1d622805c0e7f8fc31a08f0177d34b3530a115d3fb947d216fe7c243aed3fbe"},{"filename":"references/modules.md","content":"# Modules and Overlays\n\nModules organize custom commands, aliases, and variables into reusable units. Overlays manage named scopes for commands and environment variables.\n\n## Creating a Module\n\nDefine commands inside a module block:\n\n```nu\n# my-module.nu\nexport def greet [name: string] {\n $\"Hello, ($name)!\"\n}\n\nexport def farewell [name: string] {\n $\"Goodbye, ($name)!\"\n}\n\nexport let version = \"1.0.0\"\n```\n\n## Using a Module\n\n```nu\nuse my-module.nu # Import all exports into current scope\ngreet \"World\" # => Hello, World!\nversion # => 1.0.0\n\n# Import specific items\nuse my-module.nu [ greet ] # Only import greet\nuse my-module.nu --help # Show module help\n\n# Import with alias (namespace)\nuse my-module.nu [ greeting: greet ] # Call as greeting \"World\"\nuse my-module.nu * # Import everything (no prefix)\n\n# Namespace access (no use needed)\nmy-module.nu greet \"World\" # Access via module path\n```\n\n## Creating Modules Inline\n\nDefine a module without a file:\n\n```nu\nmodule my-mod {\n export def hello [] { \"Hello!\" }\n export def goodbye [] { \"Goodbye!\" }\n}\n\nuse my-mod *\nhello # => Hello!\n```\n\n## Exporting Items\n\nWithin a module, use `export` to make items available:\n\n```nu\n# my-module.nu\nexport def process-data [input: record] { ... }\nexport alias ll = ls -la\nexport const MAX_SIZE = 1024\nexport def --env change-dir [path: path] { cd $path }\n```\n\nWithout `export`, items are private to the module:\n\n```nu\n# my-module.nu\ndef private-helper [] { ... } # Not accessible outside\nexport def public-command [] { private-helper } # Accessible\n```\n\n## Modules in config.nu\n\nPersist modules across sessions by adding them to your startup configuration:\n\n```nu\n# In ~/.config/nushell/config.nu\nuse my-scripts/utils.nu *\nuse my-scripts/git-tools.nu [ commit-status, branch-info ]\n```\n\n## Module Path (`$NU_LIB_DIRS`)\n\nNushell searches specific directories when resolving `use` and `source`. Configure via:\n\n1. **Environment variable**: `$env.NU_LIB_DIRS = [...paths...]` in `env.nu`\n2. **Configuration**: Set `$NU_LIB_DIRS` constant in config\n3. **Directory structure**: Nushell auto-loads files from vendor autoload dirs\n\n```nu\n# List current search paths\n$NU_LIB_DIRS\n\n# Add a custom path (in env.nu)\n$env.NU_LIB_DIRS = ($env.NU_LIB_DIRS ++ [$nu.vendor-autoload-dirs, \"~/.nu-modules\"])\n```\n\n## Overlays\n\nOverlays are named sets of commands, environment variables, and aliases that can be activated/deactivated:\n\n### Creating an Overlay\n\n```nu\n# my-overlay.nu\noverlay use my-overlay # Activate the overlay (from a file)\n\n# Or define inline\noverlay new temp-overlay # Create empty overlay\noverlay add temp-overlay { # Add commands to it\n export def tmp-cmd [] { \"temp\" }\n}\n```\n\n### Activating and Deactivating\n\n```nu\nuse my-scripts/git-tools.nu # Commands available in current scope\n\n# Create an overlay to isolate commands\noverlay new git-workspace\nuse my-scripts/git-tools.nu --only [ commit-status branch-info ] | into nuon\n# Commands are now scoped to the git-workspace overlay\n\n# Deactivate when done\noverlay remove git-workspace # Remove overlay, commands disappear\n```\n\n### Viewing Overlays\n\n```nu\noverlays # List all active overlays\noverlay list # Same as above\nscope overlays # Show overlay names\n```\n\n## Modules vs Sourcing\n\n| Aspect | `use module` | `source file.nu` |\n| -------------- | ---------------------------------- | ----------------------------- |\n| Purpose | Organize commands into namespaces | Execute code, set env vars |\n| Reusability | Import specific items with aliases | Everything runs immediately |\n| Scope | Items are isolated until `use` | Runs in current scope |\n| Export control | `export` controls visibility | No concept of exports |\n| Use case | Libraries, reusable command sets | Config loading, one-off setup |\n\n## Module Organization Patterns\n\n### Command Library\n\n```nu\n# utils/csv.nu\nexport def clean-csv [file: path] { ... }\nexport def validate-csv [file: path, cols: list] { ... }\nexport def csv-stats [file: path] { ... }\n\n# usage\nuse utils/csv.nu *\nclean-csv data.csv\n```\n\n### Git Tool Collection\n\n```nu\n# utils/git.nu\nexport def git-status [] { ^git status --short }\nexport def git-branches [] { ^git branch -a | lines }\nexport def git-log [count: int = 10] { ^git log --oneline ...$count }\n\n# usage\nuse utils/git.nu [ git-status git-branches ]\n```\n\n### Subcommand Extension\n\nExtend existing command namespaces with custom subcommands:\n\n```nu\n# Extend the 'str' namespace\ndef \"str my-format\" [input: string] {\n $input | str upcase | str trim\n}\n\n# Now available as: str my-format \"hello\"\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4892,"content_sha256":"2c9bf586f2494db3afa8f37d2d404083b5b82b34f5efbdbf4c5dc7db08878a89"},{"filename":"references/operators.md","content":"# Operators\n\nNushell supports arithmetic, comparison, logical, pattern matching, bitwise, and spread operators.\n\n## Arithmetic Operators\n\n| Operator | Description | Example | Result |\n| -------- | -------------- | ---------- | ----------------- |\n| `+` | Addition | `3 + 5` | `8` |\n| `-` | Subtraction | `10 - 4` | `6` |\n| `*` | Multiplication | `3 * 7` | `21` |\n| `/` | Division | `10 / 3` | `3.33...` (float) |\n| `//` | Floor division | `10 // 3` | `3` (int) |\n| `mod` | Modulo | `10 mod 3` | `1` |\n| `**` | Exponentiation | `2 ** 10` | `1024` |\n\nOperations preserve types where possible: int / int = float, filesize + filesize = filesize, duration + duration = duration.\n\n```nu\n5 + 3 # => 8\n10.5 - 2.3 # => 8.2 (float)\n64mb + 32mb # => 96mb (filesize)\n3day + 12hr # => 3day 12hr (duration)\n10 // 3 # => 3 (floor division)\n10 mod 3 # => 1\n2 ** 8 # => 256\n```\n\n## Comparison Operators\n\n| Operator | Description | Example | Result |\n| -------- | ------------- | -------- | ------ |\n| `==` | Equal | `5 == 5` | `true` |\n| `!=` | Not equal | `5 != 3` | `true` |\n| `\u003c` | Less than | `3 \u003c 5` | `true` |\n| `>` | Greater than | `5 > 3` | `true` |\n| `\u003c=` | Less or equal | `5 \u003c= 5` | `true` |\n| `>=` | Greater or eq | `5 >= 4` | `true` |\n\nComparisons work across compatible types: numbers vs numbers, strings vs strings, datetimes vs datetimes, file sizes vs file sizes, durations vs durations.\n\n```nu\n\"apple\" == \"apple\" # => true\n\"banana\" > \"apple\" # => true (lexicographic)\n2024-01-01 \u003c 2024-06-01 # => true\n64mb >= 32mb # => true\n```\n\n## Pattern Matching Operators\n\n| Operator | Description | Example | Result |\n| ------------- | --------------- | ---------------------------- | ------ |\n| `=~` | Regex match | `\"hello\" =~ \"^h.*o$\"` | `true` |\n| `!~` | Not regex match | `\"world\" !~ \"^h\"` | `true` |\n| `in` | Member of | `\"b\" in [\"a\", \"b\", \"c\"]` | `true` |\n| `not-in` | Not member of | `\"d\" not-in [\"a\", \"b\", \"c\"]` | `true` |\n| `has` | Contains value | `[1 2 3] has 2` | `true` |\n| `starts-with` | Prefix check | `\"hello\" starts-with \"he\"` | `true` |\n| `ends-with` | Suffix check | `\"hello\" ends-with \"lo\"` | `true` |\n\n```nu\n# Regex matching (in where clauses, for example)\nopen data.csv | where name =~ \"^A.*\" # Names starting with A\nopen data.csv | where description !~ \"FPV\" # Exclude FPV entries\n\n# Membership testing\nif \"active\" in $statuses { print \"Found it\" }\n$my_list has 42 # => bool\n\n# Prefix/suffix checks\n$file starts-with \"/etc/\" # => bool\n$name ends-with \".json\" # => bool\n```\n\n## Logical Operators\n\n| Operator | Description | Example | Result |\n| -------- | ----------- | ---------------- | ------- |\n| `and` | Logical AND | `true and false` | `false` |\n| `or` | Logical OR | `true or false` | `true` |\n\n```nu\nopen data.csv | where status == \"active\" and rating > 4.0\nopen data.csv | where category == \"electronics\" or category == \"books\"\n```\n\n## Bitwise Operators\n\nNushell uses explicit function-style names for bitwise operations:\n\n| Operator | Description | Example | Result |\n| --------- | ----------- | ------------- | ------ |\n| `bit-and` | AND | `5 bit-and 3` | `1` |\n| `bit-or` | OR | `5 bit-or 3` | `7` |\n| `bit-xor` | XOR | `5 bit-xor 3` | `6` |\n| `bit-shl` | Shift left | `1 bit-shl 3` | `8` |\n| `bit-shr` | Shift right | `8 bit-shr 2` | `2` |\n\n```nu\n5 bit-and 3 # Binary: 101 & 011 = 001 => 1\n5 bit-or 3 # Binary: 101 | 011 = 111 => 7\n5 bit-xor 3 # Binary: 101 ^ 011 = 110 => 6\n```\n\n## Spread Operator (`...`)\n\nExpand lists, records, or tables inline:\n\n```nu\n# Spread a list into a new list\nlet x = [1 2]\n[ ...$x 3 ] # => [1, 2, 3]\n\n# Spread in record construction\nlet base = { name: \"Sam\", rank: 10 }\n{ ...$base, title: \"Mayor\" } # => {name: Sam, rank: 10, title: Mayor}\n\n# Spread a table into append\n$data | append ...$other_data # Same as $data | append $other_data (flattened)\n\n# Spread arguments to rest parameters in custom commands\nlet guests = [ Dwayne Shanice ]\nvip-greet \"VIP\" ...$guests # Expands list elements as individual args\n```\n\n## String Concatenation (`++`)\n\nThe `++` operator concatenates strings, lists, and tables:\n\n```nu\n\"hello\" ++ \" \" ++ \"world\" # => \"hello world\" (string concat)\n\n[1 2] ++ [3 4] # => [1, 2, 3, 4] (list concat)\n$table | append $other_table # Same as $table ++ $other_table (row stacking)\n```\n\n## Assignment Operators\n\nFor mutable variables only (`mut`):\n\n| Operator | Description | Equivalent to |\n| -------- | ------------------- | ------------------ |\n| `=` | Assign | `$x = 5` |\n| `+=` | Add and assign | `$x = $x + 1` |\n| `-=` | Subtract and assign | `$x = $x - 1` |\n| `*=` | Multiply and assign | `$x = $x * 2` |\n| `/=` | Divide and assign | `$x = $x / 2` |\n| `++=` | Append and assign | `$x = $x ++ [new]` |\n\n```nu\nmut counter = 0\n$counter += 1 # => 1\n$counter -= 5 # => -4\n$counter *= 2 # => -8\nlet items = [1]; mut nums = $items; $nums ++= [2] # => [1, 2]\n```\n\n## Operator Precedence\n\nFrom lowest to highest binding:\n\n1. `or`\n2. `and`\n3. `=~`, `!~`, `starts-with`, `ends-with`, `in`, `not-in`, `has`\n4. `==`, `!=`, `\u003c`, `>`, `\u003c=`, `>=`\n5. `+`, `-`\n6. `*`, `/`, `//`, `mod`\n7. `**`\n\nUse parentheses to override: `(2 + 3) * 4` → `20`.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5987,"content_sha256":"34bcecc73fe55265328a9e0c43c31771dcd0b0135e37fdbd7dddb1dffec6ce28"},{"filename":"references/parsing.md","content":"# Parsing Files and Formats\n\nNushell can read many data formats directly via the `open` command (auto-detected from extension) or explicitly via `from \u003cformat>` commands.\n\n## Supported File Formats for `open`\n\n- **csv, tsv** — CSV/TSV delimited files\n- **json** — JSON objects and arrays\n- **yaml / yml** — YAML documents\n- **xml** — XML documents\n- **toml** — TOML configuration files\n- **ini** — INI configuration files\n- **xlsx / xls** — Excel spreadsheets\n- **ods** — OpenDocument spreadsheet files\n- **ssv** — Space-separated values\n- **eml, ics, vcf** — Email/calendar/contact formats\n- **url** — URL-encoded data\n\n```nu\nopen data.csv # CSV → table\nopen data.json # JSON → record or list\nopen config.yaml # YAML → record\nopen schema.toml # TOML → record\nopen spreadsheet.xlsx # Excel → table(s)\n```\n\n## NUON (Nushell Object Notation)\n\nNUON is a superset of JSON — any valid JSON is valid NUON. It is \"human-friendly\": comments are allowed, commas are not required.\n\n```nu\n# This is valid NUON (from default_config.nu):\n{\n menus: [\n {\n name: completion_menu\n only_buffer_difference: false\n marker: \"| \"\n type: { layout: columnar, columns: 4 }\n style: { text: green, selected_text: green_reverse }\n }\n ]\n}\n```\n\nLimitation: NUON cannot represent blocks (closures).\n\n## Opening in Raw Mode\n\nUse `--raw` to read without parsing:\n\n```nu\nopen README.md --raw # Raw text string instead of parsed table\nopen Cargo.lock # Auto-detected as TOML from extension\nopen raw_data.txt # If extension is unknown, treat as raw string\n```\n\n## Explicit Format Parsing with `from`\n\nWhen a file has no recognized extension, use `from \u003cformat>`:\n\n```nu\n# Parse content as a specific format\nopen Cargo.lock | from toml # File without .toml extension\n\"Some JSON\" | from json # String → parsed value\n\"Some YAML\" | from yaml # String → parsed record\n\n# Convert TO formats\n$table | to json # Table → JSON string\n$data | save output.csv # Write as CSV (auto-detected)\n```\n\n## CSV Parsing Options (`from csv`)\n\n```nu\n# Basic usage\n\"col1,col2\\n1,2\" | from csv\n\n# Custom separator\nopen data.txt | from csv --separator \"\\t\" # Tab-separated\nopen data.txt | from csv --separator \";\" # Semicolon-separated\n\n# Handle variable column counts\nopen data.csv | from csv --flexible # Allow different column counts\n\n# Skip header row (first row is data)\nopen data.csv | from csv --noheaders # Then use `headers` to name columns\n\n# Ignore comment lines\nopen data.csv | from csv --comment \"#\" # Lines starting with # are skipped\n\n# Trim whitespace\nopen data.csv | from csv --trim all # Trim headers and values\nopen data.csv | from csv --trim headers # Trim only headers\nopen data.csv | from csv --trim fields # Trim only values\n\n# Quote/escape handling (defaults handle most cases)\nopen data.csv | from csv --quote '\"' # Handles \"field,with,commas\"\n```\n\n## Space-Separated Values (`from ssv`)\n\nFor parsing command output like `df`, `ls -l`, etc.:\n\n```nu\n# Aligned columns with minimum spacing\ndf -h | str replace \"Mounted on\" Mounted_On | from ssv --aligned-columns --minimum-spaces 1\n\n# Adjust minimum spaces between columns (default is 2)\nps aux | from ssv --minimum-spaces 3\n```\n\n## Auto-Detect Columns (`detect columns`)\n\nMore forgiving than `from ssv`; auto-detects where columns begin and end:\n\n```nu\ndf -h | detect columns\nls -l /usr/bin/ | detect columns\n\n# Combine with str replace for headers with spaces\ndf -h | str replace \"Mounted on\" Mounted_On | detect columns\n```\n\n## Headers Command\n\nConvert a file without headers into a proper table:\n\n```nu\n# From CSV lines (noheader mode)\nopen data.csv | lines | from csv --noheaders | headers\n\n# From split column output\nopen data.txt | lines | split column \":\" | headers\n```\n\n## Parse — Extract Columns from String Patterns\n\n### Brace Pattern Syntax (Most Common)\n\n```nu\n# Simple named fields\n\"red,green,blue\" | split row \",\" | each { |item| $item | parse \"{name}\" }\n\n# Multi-field extraction\n^cargo search shells --limit 10 | lines\n| parse \"{crate_name} = {version} #{description}\"\n| str trim\n```\n\n### Regex Pattern (`--regex` flag)\n\nNamed capture groups use `(?P\u003cname>...)` syntax:\n\n```nu\n# Named captures for flexible extraction\n^cargo search shells --limit 10 | lines\n| each { |line| $line | parse --regex '(?P\u003cname>.+) = \"(?P\u003cversion>.+)\" +# (?P\u003cdesc>.+)' }\n| flatten\n\n# Conditional parsing for different formats\n^command output | lines\n| each { |line|\n if ($line | str contains \"#\") {\n $line | parse --regex '(?P\u003cname>.+) = \"(?P\u003cversion>.+)\" +# (?P\u003cdesc>.+)'\n } else {\n $line | parse --regex '(?P\u003cname>.+) = \"(?P\u003cversion>.+)\"'\n }\n }\n| flatten\n```\n\n## Split Commands\n\n```nu\n# Split a string into a list of values\n\"red,green,blue\" | split row \",\" # → [\"red\", \"green\", \"blue\"]\n\n# Split a column into multiple columns\nopen data.csv | get notes | lines | split column \":\" Name Details\n\n# Split into characters\n'aeiou' | split chars # → [a, e, i, o, u]\n\n# Use with lines to process multi-line text\nrg -c Value | lines | split column \":\" file line_count | into int line_count\n```\n\n## Lines Command\n\nConvert input to individual lines:\n\n```nu\n# Split raw text into lines array\nopen data.csv --raw | lines\nopen data.txt --raw | lines | from csv # Lines → parse as CSV\n\n# Process command output\n^df -h | str replace \"Mounted on\" Mounted_On | detect columns\n```\n\n## SQLite Databases\n\nSQLite databases are auto-detected by `open`, regardless of extension:\n\n```nu\n# Open entire database\nopen foo.db\n\n# Get a specific table\nopen foo.db | get some_table\n\n# Run SQL queries\nopen foo.db | query db \"select * from some_table\"\n```\n\n## Fetching URLs (`http get`)\n\nLoad data from the internet:\n\n```nu\nhttp get https://example.com/data.json # JSON → record/list\nhttp get https://api.example.com/users.csv # CSV → table\nhttp get https://blog.rust-lang.org/feed.xml # XML → structured data\n```\n\n## File Writing (`save` / `to`)\n\n| Output Format | Command | Notes |\n| ------------- | ---------------------------------- | -------------------------------------- |\n| CSV (default) | `save output.csv` | Auto-detected from extension |\n| TSV | `save output.tsv --separator \"\\t\"` | Specify tab separator |\n| JSON | `to json \\| save output.json` | Add `--pretty` for formatted output |\n| YAML | `save output.yaml` | Auto-detected |\n| NUON | `to nuon \\| save output.nu` | Human-friendly format |\n| Append | `save --append data.csv` | Append to existing file |\n| In-place | `collect \\| save --force file.csv` | Required for overwriting the same file |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7043,"content_sha256":"5c00c18eff96af1a0728abf91388feb9c16c8e0b1b39ac84144fcbf7a2b989f1"},{"filename":"references/patterns.md","content":"# Real-World Usage Patterns\n\n## Conditional Updates by Field Value\n\nUpdate specific rows based on a field match. Use `$row.field` inside closures for clarity:\n\n```nu\n# Update specific rows based on title match (one at a time to avoid bash quoting issues)\nopen \"data.csv\"\n| update Description { |row|\n if $row.Title == \"Parc Sant Salvador\" {\n \"New description here\"\n } else {\n $row.Description # Keep original\n }\n}\n| collect | save --force \"data.csv\"\n\n# For multiple entries, run separate update commands:\n# nu -c 'open \"data.csv\" | update col { |row| if $row.Title == \"A\" { \"Desc A\" } else { $row.col } } | collect | save --force \"data.csv\"'\n# nu -c 'open \"data.csv\" | update col { |row| if $row.Title == \"B\" { \"Desc B\" } else { $row.col } } | collect | save --force \"data.csv\"'\n```\n\n## Multi-Condition Updates\n\nHandle duplicate values with additional conditions. Use parentheses for complex `where` clauses:\n\n```nu\nopen \"data.csv\"\n| update Description { |row|\n if ($row.Title == \"El Patio\" and ($row.Address | str contains \"Sevilla\")) {\n \"Specific description for this location\"\n } else {\n $row.Description\n }\n}\n| collect | save --force \"data.csv\"\n```\n\n## Extract Specific Data with Counts\n\n```nu\n# Get all unique categories with counts, sorted by count descending\nopen products.csv | get category | uniq --count | sort-by count --reverse\n\n# Find top 10 by value\nopen sales.csv | sort-by amount --reverse | first 10 | select name amount\n\n# Filter by multiple conditions (chained where)\nopen users.csv | where status == \"active\" | where last_login > \"2024-01-01\"\n```\n\n## Complete ETL Pipeline\n\nA full extract-transform-load pipeline in one chain:\n\n```nu\nopen raw_data.csv\n| from csv --trim all # Load and clean\n| where status != \"deleted\" # Filter out deleted records\n| update created_at { |row| $row.created_at | date to-table } # Parse dates\n| each { |row| { ...$row, total: ($row.price * $row.quantity) } } # Calculate derived field\n| sort-by created_at --reverse # Sort by date, newest first\n| save cleaned_data.csv # Write output\n```\n\n## Numeric Filtering from String Columns\n\nWhen numeric values are stored as strings (e.g., ratings, prices), convert before comparing:\n\n```nu\nopen \"data.csv\"\n| where Rating != \"\" # Filter empty strings first\n| each { |r| { ...$r, Rating_num: ($r.Rating | into float) } }\n| where Rating_num > 4.0\n| select Title Rating_num\n```\n\n## Find and Update Multiple Entries\n\nRun separate update commands for each target entry to avoid bash quoting issues with special characters:\n\n```nu\nnu -c 'open \"data.csv\" | update col { |row| if $row.Title == \"A\" { \"Desc A\" } else { $row.col } } | collect | save --force \"data.csv\"'\n\nnu -c 'open \"data.csv\" | update col { |row| if $row.Title == \"B\" { \"Desc B\" } else { $row.col } } | collect | save --force \"data.csv\"'\n\nnu -c 'open \"data.csv\" | update col { |row| if $row.Title == \"C\" { \"Desc C\" } else { $row.col } } | collect | save --force \"data.csv\"'\n```\n\n## Verify Changes After Update\n\n```nu\n# Check a specific entry after in-place update\nopen \"data.csv\" | where Title == \"EntryName\" | get Description | first\n```\n\n## Filtering by String Length\n\n```nu\n# Find entries with descriptions under 100 chars\nopen \"data.csv\"\n| each { |row| if ($row.Description | str length) \u003c 100 { $row } else { null } }\n| where $it != null\n| select Title Description\n```\n\n## Combining Tables from Different Sources\n\n### Append Rows (Concatenation)\n\n```nu\n# Stack two CSV files with matching column structure\nlet csv1 = (open data1.csv)\nlet csv2 = (open data2.csv)\n$csv1 | append $csv2\n\n# Using the ++ operator (same as append)\n($csv1 ++ $csv2) | save combined.csv\n```\n\n### Merge Columns Side-by-Side\n\n```nu\n# Merge two tables with different columns\nlet orders = (open orders.csv) # columns: order_id, product, amount\nlet products = (open products.csv) # columns: product, category, price\n$orders | merge $products # → order_id, product, amount, category, price\n\n# Merge tables of different sizes — wrap smaller table with chunks + flatten\nlet big = (open large_table.csv)\nlet small = (open lookup_table.csv)\n$big | chunks ($small | length)\n| each { merge $small } | flatten\n```\n\n## Parsing Non-Standard Text Files\n\n### Colon-Separated Data\n\n```nu\n# Parse colon-separated values into a table\nopen data.txt | lines | split column \":\" Name Details\n# Or with parse command:\nopen data.txt | lines | parse \"{Name}:{Details}\"\n```\n\n### Space-Separated Command Output\n\n```nu\n# Parse df output into a queryable table\ndf -h | str replace \"Mounted on\" Mounted_On | detect columns\n| where Use% > \"80%\"\n| select Filesystem Size Used Avail Use% Mounted_On\n```\n\n## Custom Commands for Reusable Workflows\n\n### CSV Cleaning Command\n\n```nu\ndef \"clean-csv\" [file: path] {\n open $file\n | from csv --trim all\n | where ($in | columns | any { |col| $in | get $col != \"\" })\n | update date { |row| $row.date | str trim }\n}\n```\n\n### CSV Validation Command\n\n```nu\ndef \"validate-csv\" [file: path, required_columns: list] {\n let data = (open $file)\n let cols = ($data | columns)\n\n $required_columns | each { |req_col|\n if not ($cols | any { |c| $c == $req_col }) {\n echo $\"ERROR: Missing required column: ($req_col)\"\n }\n }\n\n $data | where ($required_columns | any { |col| $in | get $col == \"\" }) | length\n}\n```\n\n### Quick CSV Stats Command\n\n```nu\ndef \"csv-stats\" [file: path] {\n let data = (open $file)\n {\n rows: ($data | length),\n columns: ($data | columns | length),\n column_names: ($data | columns)\n }\n}\n```\n\n## Saving Options Reference\n\n| Output Format | Command | Notes |\n| ------------- | ---------------------------------- | ------------------------------------------------- |\n| CSV (default) | `save output.csv` | Auto-detected from extension |\n| TSV | `save output.tsv --separator \"\\t\"` | Specify tab separator |\n| JSON | `to json \\| save output.json` | Add `--pretty` for formatted output |\n| YAML | `save output.yaml` | Auto-detected |\n| Append | `save --append data.csv` | Append to existing file |\n| In-place | `collect \\| save --force file.csv` | Required for overwriting the same file being read |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6593,"content_sha256":"214f337b2b42de3800de65ac054eb18bc58d17ad9c0b7263c5f6148eae2cb362"},{"filename":"references/scripts.md","content":"# Writing Nushell Scripts (`.nu` files)\n\nNushell scripts are `.nu` files that can be executed directly from the command line or sourced into the current session.\n\n## Shebang and Execution\n\nStart a script with the shebang to make it executable:\n\n```nu\n#!/usr/bin/env nu\n\n# Script content\nlet dir = ($env.CURRENT_FILE | path dirname)\nprint $\"Script directory: ($dir)\"\n```\n\nMake it executable: `chmod +x script.nu`, then run as `./script.nu`.\n\n## Passing Arguments to Scripts\n\nArguments are available as parameters:\n\n```nu\n#!/usr/bin/env nu\n\ndef my-script [filename: string, --verbose] {\n if $verbose { print $\"Opening ($filename)\" }\n open $filename | length | print\n}\n\nmy-script data.csv --verbose\n```\n\nRun from command line: `nu script.nu data.csv --verbose`\n\nFor the special `$nu.script-arguments` variable (all arguments as a list):\n\n```nu\nlet args = $nu.script-arguments\nfor arg in $args { print $arg }\n```\n\n## `source` vs Executing Scripts\n\n| Aspect | `source script.nu` | `nu script.nu` (execute) |\n| ------------- | ----------------------------- | ------------------------ |\n| Scope | Runs in current scope | New subshell |\n| Env changes | Persist after sourcing | Lost when script ends |\n| Variables set | Available after source | Only inside script |\n| Use case | Load config, define functions | Standalone tool |\n\n```nu\nsource script.nu # Load into current session\nsource-env script.nu # Source and apply environment changes\n```\n\n## `config nu` — Config File Paths\n\nNushell loads configuration from:\n\n- **`config.nu`**: Main config (aliases, custom commands, env config)\n- **`env.nu`**: Environment variables, prompt configuration, hooks\n- **`login.nu`**: Runs for login shells only\n- **`plugin.msgpackz`**: Plugin registry\n\nFind paths programmatically:\n\n```nu\n$nu.config-path # Path to config.nu\n$nu.env-path # Path to env.nu\n$nu.history-path # Command history file\n$nu.default-config-dir # Config directory (~/.config/nushell on Linux)\n```\n\n## Script Structure Best Practices\n\n### 1. Validate Environment Early\n\n```nu\n#!/usr/bin/env nu\n\n# Ensure required tools exist\nif not (^which git | describe) == \"nothing\" {\n print \"git is available\"\n} else {\n error make { msg: \"git is required but not found\" }\n}\n\n# Check for required arguments\nif $nu.script-arguments | length == 0 {\n print \"Usage: script.nu \u003cinput-file>\"\n return 1\n}\n```\n\n### 2. Use `try/catch` for Robustness\n\n```nu\ntry {\n open $input_file | where status == \"active\"\n} catch { |err|\n print $\"Failed to read file: ($err.msg)\"\n exit 1\n}\n```\n\n### 3. Set Exit Codes\n\n```nu\n#!/usr/bin/env nu\n\nlet data = (try { open config.json } catch { null })\nif $data == null {\n print \"Config not found\"\n exit 2 # Non-zero exit signals failure\n}\n\n# Process...\nprint \"Done!\"\nexit 0 # Explicit success (optional)\n```\n\n### 4. Use `path self` for Script-Relative Paths\n\n```nu\nlet script_dir = ($env.CURRENT_FILE | path dirname)\nlet data_file = (path join $script_dir \"data.json\")\nopen $data_file\n```\n\nOr via constant:\n\n```nu\nlet script_dir = (path self | path dirname)\n```\n\n### 5. Handle Missing Files Gracefully\n\n```nu\ndef read-config [file: path] {\n try { open $file } catch {\n print $\"Config file not found: ($file)\"\n null\n }\n}\n```\n\n## Common Script Patterns\n\n### File Processor\n\n```nu\n#!/usr/bin/env nu\n# process.nu — Process all CSV files in a directory\n\ndef process-dir [dir: path] {\n ls $dir | where type == file | where name =~ \"\\.csv$\"\n | each {|file|\n open $file.name\n | where status != \"deleted\"\n | save ($file.name | str replace \".csv\" \"_clean.csv\")\n }\n}\n\nprocess-dir .\n```\n\n### API Consumer\n\n```nu\n#!/usr/bin/env nu\n# fetch.nu — Fetch and parse data from an API\n\ndef fetch-data [url: string] {\n try {\n http get $url | from json\n } catch { |err|\n error make { msg: $\"Failed to fetch ($url): ($err.msg)\" }\n }\n}\n\nlet data = (fetch-data \"https://api.example.com/data.json\")\n$data | where active == true | save active_data.json\n```\n\n### Interactive Prompt Script\n\n```nu\n#!/usr/bin/env nu\n# interactive.nu — Collect user input and process it\n\nlet name = (input \"Enter your name: \")\nlet age = (input \"Enter your age: \" | into int)\n\nif $age >= 18 {\n print $\"Welcome, ($name)! You are of age.\"\n} else {\n print $\"Hi ($name)! Please bring a guardian.\"\n}\n```\n\n## Debugging Scripts\n\n- Use `print` to output debug values at specific points\n- Use `inspect` to see values as they flow through pipelines: `open data.csv | inspect | where ...`\n- Run with `nu -c \"source script.nu; some-command\"` to test interactively\n- Set `$env.NU_LOG_LEVEL = \"debug\"` for std/log debugging\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4853,"content_sha256":"5d5602c5cb3cb2787db9bd5306fe1d325c85fd822fdd930b9d64cb68fce63309"},{"filename":"references/sorting.md","content":"# Sorting Data\n\nNushell supports sorting tables by any column that can be compared (numbers, strings, dates, file sizes).\n\n## Basic Sorting\n\n```nu\nopen data.csv | sort-by price # Ascending\nopen data.csv | sort-by price --reverse # Descending\n```\n\n## Multi-Column Sort\n\nSort by multiple columns. The order of arguments determines priority:\n\n```nu\n# Sort by category first, then by name within each category\nopen data.csv | sort-by category name\n\n# With direction per column (all must use same direction)\nopen data.csv | sort-by category --reverse name # category desc, name asc\n```\n\n## Sorting by Calculated Values\n\nSort using a closure to compute values on the fly:\n\n```nu\n# Sort by computed field\nopen data.csv | sort-by { $in.price * $in.quantity } --reverse\n\n# Sort by string length\nopen data.csv | sort-by { ($in.name | str length) }\n```\n\n## Sorting with Index Preservation\n\nWhen sorting, the internal `#` index changes. To preserve original row positions, convert to a real index column first:\n\n```nu\n# Standard pattern: enumerate → flatten → sort → select\nopen data.csv | enumerate | flatten | sort-by modified | first 5\n```\n\nThe `enumerate | flatten` pattern converts the internal `#` into an `index` column that sorts independently from other columns.\n\n## Sorting by Date\n\n```nu\nopen data.csv | sort-by date # Ascending (oldest first)\nopen data.csv | sort-by date --reverse # Descending (newest first)\n```\n\n## Important Notes\n\n- **Column names with spaces**: quote them — `sort-by \"column name\"`\n- **Numeric columns stored as strings**: convert first with `into float` before sorting\n- **Reverse applies to all sort keys**: `--reverse` affects the entire sort, not individual columns\n- **Null values**: sort to the end of the result\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1769,"content_sha256":"81cac774bdbec1bc174b00bb00da3115c1223f4080245c38022beae3f7d6a951"},{"filename":"references/strings.md","content":"# String Operations\n\nNushell provides a rich set of string manipulation commands under the `str` namespace. These are used extensively for cleaning and transforming text data in tabular pipelines.\n\n## Case Conversion\n\n```nu\n# Convert to uppercase\nopen data.csv | update name { |x| $x | str upcase }\n\n# Convert to lowercase\nopen data.csv | update name { |x| $x | str downcase }\n\n# Capitalize first letter of each word\nopen data.csv | update name { |x| $x | str capitalize }\n\n# Title case (capitalize first letter of each word)\nopen data.csv | update name { |x| $x | str title-case }\n\n# camelCase, PascalCase, kebab-case, snake_case, SCREAMING_SNAKE_CASE\nopen data.csv | update slug { |x| $x | str kebab-case }\nopen data.csv | update name { |x| $x | str snake-case }\nopen data.csv | update name { |x| $x | str camel-case }\n```\n\n## Trimming and Whitespace\n\n```nu\n# Trim leading and trailing whitespace\nopen data.csv | update date { |x| $x | str trim }\n\n# Trim specific characters\nopen data.csv | update field { |x| $x | str trim \" \\t\\r\\n\" }\n```\n\n## Length and Position\n\n```nu\n# String length\n$my_string | str length\n\n# Find substring index (-1 if not found)\n$my_string | str index-of \"pattern\"\n\n# Substring extraction (start_index, length)\n$my_string | str substring 0 5 # First 5 characters\n$my_string | str substring 3 # From position 3 to end\n```\n\n## Search and Match\n\n### `str contains` — Partial Substring Match\n\nRequires `each/where` pattern for filtering rows by partial match:\n\n```nu\n# Filter rows where column contains a substring\nopen \"data.csv\"\n| each { |row| if ($row.Address | str contains \"Barcelona\") { $row } else { null } }\n| where $it != null\n\n# Multiple conditions chain\nopen \"data.csv\"\n| each { |row| if ($row.Address | str contains \"Barcelona\") { $row } else { null } }\n| where $it != null\n| each { |row| if ($row.Description | str contains \"restaurant\") { $row } else { null } }\n| where $it != null\n\n# Filter short descriptions\nopen \"Favorite Places.csv\"\n| each { |row| if ($row.Description | str length) \u003c 100 { $row } else { null } }\n| where $it != null\n| select Title Description\n```\n\n### Regex Pattern Matching in `where`\n\nUse the `=~` (match) and `!~` (exclude) operators directly:\n\n```nu\n# Include rows matching pattern\nopen data.csv | where Title =~ \"FPV\"\n\n# Exclude rows matching pattern\nopen data.csv | where Title !~ \"FPV\"\n\n# Combined with other conditions\nopen data.csv | where status == \"active\" and Title =~ \"FPV\"\n```\n\n### `parse` with Regex Patterns\n\nFor complex extraction, use `parse --regex` with named capture groups:\n\n```nu\n# Named captures: (?P\u003cname>...)\n^cargo search shells --limit 5 | lines\n| each { |line| $line | parse --regex '(?P\u003cname>.+) = \"(?P\u003cversion>.+)\" +# (?P\u003cdesc>.+)' }\n| flatten\n\n# Conditional regex (handle different formats)\n^cargo search shells --limit 5 | lines\n| each { |line|\n if ($line | str contains \"#\") {\n $line | parse --regex '(?P\u003cname>.+) = \"(?P\u003cversion>.+)\" +# (?P\u003cdescription>.+)'\n } else {\n $line | parse --regex '(?P\u003cname>.+) = \"(?P\u003cversion>.+)\"'\n }\n }\n| flatten\n```\n\n## Replace and Transform\n\n### `str replace` — Find and Replace Text\n\n```nu\n# Simple replacement (first occurrence)\n$my_string | str replace \"old\" \"new\"\n\n# Replace in a column\nopen data.csv | update url { |x| $x | str replace \"http://\" \"https://\" }\n```\n\n### `str join` — Concatenate with Separator\n\n```nu\n# Join list of strings\n[\"a\" \"b\" \"c\"] | str join \", \"\n# => a, b, c\n\n# Join from table column values\nopen data.csv | get tags | str join \", \"\n\n# Join with custom separator (useful for building query strings)\nlet labels = [\"feature\" \"bug\" \"docs\"]\n$labels | str join \"+\"\n```\n\n### `str distance` — Edit Distance / Levenshtein\n\n```nu\n# Compare two strings and return the edit distance\n\"hello\" | str distance \"hallo\"\n# => 1 (one character difference)\n```\n\n## String Expansion\n\n```nu\n# Generate all brace expansion combinations\n\"file_{a,b,c}.txt\" | str expand\n# => [file_a.txt, file_b.txt, file_c.txt]\n```\n\n## Special Characters\n\n```nu\n# Output special characters\nchar nl # Newline\nchar tab # Tab\nchar cr # Carriage return\n\n# Escape regex special characters in a string\nmy_pattern | str escape-regex\n```\n\n## String Filtering Patterns for Tabular Data\n\n### Filter by Description Length\n\n```nu\n# Find entries with descriptions under 100 chars\nopen \"data.csv\"\n| each { |row| if ($row.Description | str length) \u003c 100 { $row } else { null } }\n| where $it != null\n| select Title Description\n```\n\n### Filter by Multiple Substring Conditions\n\n```nu\n# Chain multiple str contains filters\nopen \"data.csv\"\n| each { |row| if ($row.Address | str contains \"Barcelona\") { $row } else { null } }\n| where $it != null\n| each { |row| if ($row.Description | str contains \"restaurant\") { $row } else { null } }\n| where $it != null\n```\n\n### Exclude Pattern + Length Filter\n\n```nu\n# Combine regex exclusion with string length filter\nopen \"data.csv\"\n| where Title !~ \"FPV\"\n| each { |row| if ($row.Description | str length) \u003c 150 { $row } else { null } }\n| where $it != null\n```\n\n## Numeric Filtering from String Columns\n\nWhen numeric values are stored as strings (e.g., ratings, prices), convert to float for comparison:\n\n```nu\n# Convert string ratings to floats for comparison\nopen \"data.csv\"\n| where Rating != \"\" # Filter empties first\n| each { |r| { ...$r, Rating_num: ($r.Rating | into float) } }\n| where Rating_num > 4.0\n| select Title Rating_num\n```\n\n## String Formatting in Closures\n\nWhen using string interpolation inside closures (e.g., `each`, `update`):\n\n```nu\n# Use $row.field references for clarity (avoid $in inside each blocks)\nopen data.csv | each { |row| { ...$row, label: $\"($row.name) - ($row.category)\" } }\n\n# Use single-letter aliases for brevity in simple transforms\nopen data.csv | each { |r| { ...$r, total: ($r.price * $r.qty) } }\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5882,"content_sha256":"15eb3ccaa3171ebb0e0860fd6db597c81e70533745e86805987f9521ce3ba468"},{"filename":"references/system.md","content":"# System Interaction and Environment\n\nNushell provides built-in commands for filesystem, process management, system info, and environment variable management.\n\n## Filesystem Commands\n\n### `ls` — List Directory Contents\n\nReturns a table (not text), making it easily filterable and transformable:\n\n```nu\nls # All entries in current directory\nls *.js # Glob pattern filter\nls /var/log/ # Specific directory\n\n# Filter by type (table columns: name, type, size, modified, etc.)\nls | where type == file # Files only\nls | where type == dir # Directories only\n\n# Sort and transform\nls | sort-by size | reverse # Largest first\nls | select name size modified # Pick columns\n```\n\n### `open` — Read a File\n\nAuto-detects format from extension; use `--raw` to read without parsing:\n\n```nu\nopen data.csv # CSV → table\nopen data.json # JSON → record or list\nopen config.yaml # YAML → record\nopen image.jpg | into binary # Binary file\nopen data.txt --raw # Raw text (no format detection)\nopen data.csv --trim # Trim whitespace from headers and values\n```\n\n### `save` — Write a File\n\nFails by default if the target exists; use `-f` (`--force`) to overwrite:\n\n```nu\n$table | save output.csv # Fails if exists\n$data | save -f output.csv # Overwrites\n$record | to json > output.json # Pipe redirect (no overwrite check)\n```\n\n### `mkdir`, `cp`, `mv`, `rm`, `touch` — File Operations\n\n```nu\nmkdir dir1 dir2 subdir/nested # Create directories (including parents)\ncp source.txt dest.txt # Copy file\ncp -r src_dir/ dest_dir/ # Copy directory recursively\nmv old.txt new.txt # Rename/move file\nrm unwanted.txt # Remove file(s)\ntouch empty.file # Create empty file (or update timestamp)\n```\n\n### `du` — Disk Usage\n\nReturns a table of disk usage for files/directories:\n\n```nu\ndu # Current directory\ndu --all # All files, not just directories\ndu | sort-by size | reverse # Largest first\n```\n\n### `glob` — Create List from Glob Pattern\n\nReturns a list of paths matching a glob pattern:\n\n```nu\nglob \"*.js\" # All .js files in current dir\nglob -r \"**/*.rs\" # Recursive glob\n```\n\n### `path` — Path Manipulation\n\n| Command | Description | Example |\n| ------------------ | ------------------------------------ | ---------------------------------------------- |\n| `path basename` | Last component of path | `\"a/b/file.txt\" \\| path basename` → `file.txt` |\n| `path dirname` | Parent directory | `\"a/b/file.txt\" \\| path dirname` → `a/b` |\n| `path exists` | Check if path exists | `$path \\| path exists` → `bool` |\n| `path expand` | Absolute path | `\"~/docs\" \\| path expand` |\n| `path join` | Join path parts | `path join \"a\" \"b\" \"c\"` → `a/b/c` |\n| `path parse` | Structured path data | `\"a/b.txt\" \\| path parse` → {dir, stem, ext} |\n| `path relative-to` | Relative path between two paths | |\n| `path split` | Split into components | `\"a/b/c\" \\| path split` → [a, b, c] |\n| `path type` | Check file type (file, dir, symlink) | |\n\n## Process Management\n\n### `ps` — List Processes\n\nReturns a table with process information:\n\n```nu\nps # All processes\nps | where cpu > 0 | sort-by cpu | reverse # Highest CPU first\nps | where name == \"nu\" | get pid.0 # Get PID of specific process\nps | where name == \"nu\" | get pid.0 | kill $in # Kill by PID\n```\n\n### `kill` — Send Signal to Process\n\nNushell's built-in `kill` works cross-platform:\n\n```nu\nkill \u003cpid> # Send termination signal\n^kill -9 \u003cpid> # External Unix kill with force flag (Unix only)\n```\n\n## System Information\n\n### `sys` — System Overview and Categories\n\nReturns a record with categories as fields. Use subcommands for details:\n\n| Command | Description | Output Columns |\n| ----------- | ---------------------- | --------------------------------------------------- |\n| `sys` | Overall system info | Host, memory, disks, CPUs, users, temps |\n| `sys host` | Host information | os, kernel, hostname, version, arch, etc. |\n| `sys mem` | Memory usage | total, free, used, available, buffers, cached |\n| `sys cpu` | CPU info | per-core utilization and frequency |\n| `sys disks` | Disk devices | name, mount_point, type, removable, size, available |\n| `sys net` | Network interfaces | name, state, receive/transmit bytes |\n| `sys temp` | Component temperatures | component, temperature |\n| `sys users` | Logged-in users | user, terminal, login_time, host |\n\n```nu\nsys mem | json # Memory info as JSON string\nsys | to yaml # All system info as YAML\n```\n\n### `uname`, `whoami` — Basic System Queries\n\n```nu\nuname # OS/kernel information\nwhoami # Current username\npwd # Current working directory (absolute path)\n```\n\n## Environment Variables\n\n### Setting and Modifying `$env`\n\n```nu\n$env.MY_VAR = \"value\" # Set environment variable\n$env.PATH ++= [\"~/.local/bin\"] # Append to PATH list\n$env.PATH = [$env.PATH, \"/custom/path\"] # Alternative append\n```\n\nTo make changes persistent across Nushell sessions, edit `config.nu` and `env.nu`:\n\n```nu\nconfig nu # Open ~/.config/nushell/config.nu in editor\nconfig env # Open ~/.config/nushell/env.nu in editor\nvim $nu.env-path # Directly open config file\n```\n\n### Reading Environment Variables\n\n```nu\n$env.HOME # Home directory\n$env.PATH # Path list\n$env.MY_VAR # Custom variable\n$env # List all environment variables\n```\n\n### `with-env` — Temporarily Set Environment in a Block\n\n```nu\nwith-env { KEY: value } {\n ^my-command # Runs with KEY=value set temporarily\n}\n```\n\n### `load-env` / `export-env` — Apply Environment from Record\n\n```nu\n# Load environment variables from a record\n{ MY_VAR: \"value\", OTHER: \"data\" } | load-env\n\n# Preserve environment changes across subshells (use in env.nu)\nexport-env { $env.MY_VAR = \"persistent value\" }\n```\n\n### `source` / `source-env` — Execute Script Files\n\n```nu\nsource script.nu # Run Nushell script in current scope\nsource-env script.nu # Source and apply environment changes\n```\n\n## Running External Commands\n\nExternal commands (prefixed with `^`) return strings on stdout. Pipe through Nushell's parsing commands to convert to structured data:\n\n```nu\n# Direct external command execution\n^ls -la # List files (returns table via ls nu command instead)\n^df -h # Disk usage (raw text)\n\n# Parse external output into tables\n^df -h | detect columns # Auto-detect column structure\n^ps aux | from ssv --aligned-columns # Space-separated values\n^docker ps --format \"{{.Names}}\" | lines # One name per line → list of strings\n^cargo search shells --limit 5 \\| lines | parse \"{name} = {version} #{desc}\"\n\n# Capture structured output including exit code and stderr\ndo { ^my-command arg1 } | complete # Returns record with: exit_code, stdout, stderr\n```\n\n### `complete` — Command Result Record\n\nThe `complete` command wraps an external command and returns a structured record:\n\n```nu\nlet result = do { ^ls /nonexistent } | complete\n$result.exit_code # Non-zero on failure\n$result.stdout # Parsed nu value (or raw text if not parseable)\n$result.stderr # Error message from stderr\n```\n\n### Running External Commands via Interpolation\n\nBuild command strings dynamically with string interpolation and `^`:\n\n```nu\nlet cmd = \"ls\"\nlet args = [\"-la\", \"/var\"]\n^$\"($cmd)\" ...$args # Executes: ls -la /var\n```\n\n## Directory Stack\n\nNushell maintains a directory stack for quick navigation:\n\n```nu\npushd dir1 # Push directory onto stack and cd there\npopd # Pop and cd to previous directory\ndirs # List directory stack\n```\n\n## Keybindings\n\n```nu\nkeybindings list # Available keybinding options\nkeybindings default # Reset to defaults\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9058,"content_sha256":"7f42e89b4f7430570d171c57719d6b85bee3a7bf690003ff987d069999b70961"},{"filename":"references/tables.md","content":"# Working with Tables\n\nNushell tables are lists of records with consistent keys. All data modifications produce new values (functional, not in-place).\n\n## Sorting\n\n```nu\nls | sort-by size # Ascending by column\nls | sort-by size --reverse # Descending\nls | sort-by category name # Multi-column sort (category first, then name)\n```\n\nSee [sorting.md](sorting.md) for full sorting details.\n\n## Selecting and Filtering Rows\n\n```nu\n# Position-based selection\nopen data.csv | first 10 # Top N rows\nopen data.csv | last 5 # Bottom N rows\nopen data.csv | skip 10 | first 20 # Skip N, take M (rows N+1 to N+M)\n\n# Row index access via select\nls | sort-by name | select 5 # Single row by index (keeps table shape)\n\n# Condition-based filtering (where command)\nopen data.csv | where rating > 4.0\nopen data.csv | where status == \"active\" and category == \"electronics\"\nopen data.csv | where price !~ \"FPV\" # Regex exclude pattern\n```\n\n## Selecting Columns\n\n```nu\n# Keep specific columns (table shape preserved)\nopen data.csv | select name price category\n\n# Drop specific columns (reject is the opposite of select)\nopen data.csv | reject internal_id notes\n\n# Exclude mode (select with --exclude flag)\nopen data.csv | select -exclude internal_id notes\n```\n\n## The `#` Index Column\n\nEvery table displays a `#` index column by default. It has two modes:\n\n### Internal `#` (Default)\n\n- 0-based, consecutive index\n- Always corresponds to the cell-path row-number (`select 0` returns first item)\n- Not accessible by column name — `get index` or `get #` will not work\n- Cannot be sorted independently from other columns\n\n### \"Index\"-Renamed `#`\n\nWhen a column named `index` is created (directly or via `enumerate | flatten`), it takes the place of the internal `#`:\n\n```nu\n# Convert internal # to a real index column that survives sorting\nls | enumerate | flatten | sort-by modified | first 5\n# => The index values are now decoupled from cell-paths and sort with other columns\n\n# Create custom index values\nls | each { insert index { 1000 }} | first 5\n# => # │ name │ type │ size │ modified\n# => 1000│ CNAME │ file │ 15 B │ 9 months ago\n\n# Rows without an index key break table structure → results in list\u003cany>\nls | upsert 3.index { \"--->\" } | describe\n# => list\u003cany> (stream)\n```\n\n## The `table` Command\n\nRenders structured data to a string. Useful for stripping ANSI codes or customizing display:\n\n```nu\n# Strip ANSI colors from table output\nls | table | ansi strip\n\n# Expand collapsed data, hide index, abbreviate rows\nscope modules | table -e # Expand all nested data\nscope modules | table -i false # Hide the # column\nscope modules | table -a 5 # Show first and last 5 entries only\n```\n\n## Concatenating Tables (Append Rows)\n\nUse `append` or the `++` operator to stack tables vertically:\n\n```nu\nlet first = [[a b]; [1 2]]\nlet second = [[a b]; [3 4]]\n$first | append $second\n# => # │ a │ b │\n# => 0 │ 1 │ 2 │\n# => 1 │ 3 │ 4 │\n\n# Same with operator\n$first ++ $second\n\n# Different column sets — columns merge, missing values are empty\nlet third = [[a c]; [3 4]]\n$first | append $second | append $third\n# => # │ a │ b │ c\n# => 0 │ 1 │ 2 │ ❎\n# => 1 │ 3 │ 4 │ ❎\n# => 2 │ 3 │ ❎ │ 4\n```\n\n## Merging Tables (Combine Columns)\n\nUse `merge` to join tables side-by-side by combining their columns:\n\n```nu\n# Basic merge — same row count\nlet t1 = [[a b]; [1 2]]\nlet t2 = [[c d]; [3 4]]\n$t1 | merge $t2\n# => # │ a │ b │ c │ d │\n# => 0 │ 1 │ 2 │ 3 │ 4 │\n\n# Chain merges for more tables\nlet t3 = [[e f]; [5 6]]\n$t1 | merge $t2 | merge $t3\n# => # │ a │ b │ c │ d │ e │ f │\n\n# Dynamic merge of multiple tables using reduce\n[$t1 $t2 $t3] | reduce { |elt, acc| $acc | merge $elt }\n```\n\n## Merging Tables of Different Sizes\n\nWhen the smaller table has fewer rows than the larger one, `merge` leaves empty cells. Use `chunks + each + flatten` to wrap the smaller table:\n\n```nu\nlet big = [[a b]; [1 2] [3 4]] # 2 rows\nlet small = [[c d]; [5 6]] # 1 row\n\n# Without chunks — missing values in extra rows\n$big | merge $small\n# => # │ a │ b │ c │ d │\n# => 0 │ 1 │ 2 │ 5 │ 6 │\n# => 1 │ 3 │ 4 │ ❎ │ ❎ │\n\n# With chunks — wrap smaller table across all rows of larger one\n$big | chunks ($small | length)\n| each { merge $small } | flatten\n# => # │ a │ b │ c │ d │\n# => 0 │ 1 │ 2 │ 5 │ 6 │\n# => 1 │ 3 │ 4 │ 5 │ 6 │\n\n# Three tables: chain the pattern\n$big\n| chunks ($small | length)\n| each { merge $small } | flatten\n| chunks ([$third] | length)\n| each { merge $third } | flatten\n```\n\n## Adding and Modifying Columns\n\n### `insert` — Add a New Column at Beginning\n\n```nu\nopen rustfmt.toml | insert next_edition 2021\n# => edition │ 2018\n# => next_edition │ 2021 ← new column at beginning\n\n# Insert with computed values using closure\nopen data.csv | insert calculated_field { |row| $row.price * $row.quantity }\n```\n\n### `update` — Change Column Values (Column Must Exist)\n\n```nu\n# Per-row transform with closure\nopen data.csv | update price { |row| $row.price * 1.09 }\n\n# Direct value reference (shorter syntax)\nopen data.csv | update price { |x| $x * 1.09 }\n\n# Conditional update using if/else in closure\nopen \"data.csv\"\n| update Description { |row|\n if $row.Title == \"Parc Sant Salvador\" {\n \"New description here\"\n } else {\n $row.Description\n }\n}\n\n# ⚠️ Multi-condition where clauses need parentheses:\nopen \"data.csv\"\n| update Description { |row|\n if ($row.Title == \"El Patio\" and ($row.Address | str contains \"Sevilla\")) {\n \"Specific description\"\n } else {\n $row.Description\n }\n}\n```\n\n### `upsert` — Update or Insert (Column May Not Exist)\n\nCreates the column if it does not exist; updates values if it does.\n\n```nu\nopen data.csv | upsert status \"pending\" # Creates if missing, overwrites if present\n```\n\n### Moving Columns\n\n```nu\nls | move name --after size # Move after a specific column\nls | move name --first # Move to beginning\nls | move name --last # Move to end\n```\n\n### Renaming Columns\n\n```nu\nopen data.csv | rename old_name new_name # One pair\nopen data.csv | rename f1 f2 f3 f4 # Multiple pairs (one-to-one mapping)\nopen data.csv | rename name customer_name # Rename a single column\n```\n\n### Deleting Columns\n\n```nu\nopen data.csv | reject internal_id notes # Drop columns by name\n```\n\n## Column Operations Reference\n\n| Command | Purpose | Example |\n| ----------------------------- | --------------------------- | ----------------------------- | --- | -------------------- |\n| `select cols...` | Keep specified columns | `select name price category` |\n| `reject cols...` | Drop specified columns | `reject id _hidden` |\n| `rename old new...` | Rename columns (pairs) | `rename x lat y lon` |\n| `insert col value` | Add column at beginning | `insert tax 0` |\n| `insert col {closure}` | Add with computed values | `insert total { | r | $r.price \\* $r.qty}` |\n| `update col {closure}` | Transform existing column | `update price { | r | $r.price \\* 1.1}` |\n| `upsert col value` | Insert or update column | `upsert status \"active\"` |\n| `move col --after/first/last` | Reorder columns by position | `move name --after category` |\n| `default val col` | Fill nulls with default | `default 'N/A' missing_field` |\n\n## Aggregation and Statistics\n\n```nu\nopen data.csv | length # Count rows\nopen data.csv | get price | sum # Sum values in column\nopen data.csv | get price | average # Average (mean)\nopen data.csv | get price | min # Minimum value\nopen data.csv | get price | max # Maximum value\nopen data.csv | get category | uniq --count # Unique values with counts → table {value, count}\n\n# Find duplicates\nopen data.csv | get Title | uniq --count | where count > 1\n```\n\n## `enumerate` / `flatten` — Row Indexing Pattern\n\nConvert the internal `#` index into a real `index` column that sorts independently:\n\n```nu\n# Standard pattern: enumerate adds {item, index} pair to each row\n# flatten extracts those into top-level columns\nopen data.csv | enumerate | flatten | sort-by modified | first 5\n```\n\n## `collect` — Buffer a Stream\n\nConverts a streaming table into an in-memory value. Required before `save --force` for in-place updates:\n\n```nu\n# In-place file update (avoid read/write conflict)\nopen \"data.csv\"\n| update column { ... }\n| collect | save --force \"data.csv\"\n```\n\n## Combining Tables from External Sources\n\nParse command output into tables and combine with CSV data:\n\n```nu\n# Merge CSV data with filesystem info\nlet csv_data = (open data.csv)\nlet file_info = (ls | select name size type modified)\n$csv_data | append $file_info # Append rows if columns align\n\n# Parse disk usage table and merge\ndf -h | str replace \"Mounted on\" Mounted_On | detect columns\n| where Use% > \"80%\" # Filter high-usage disks\n```\n\n## `compact` — Remove Rows with All-Empty Fields\n\n```nu\nopen data.csv | compact # Remove rows where every cell is empty/null\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9508,"content_sha256":"5d59230de8dc0bd9eb2f074e0fc56534cc7a6dad94711b3eac3feb0a4ad44ba2"},{"filename":"references/types.md","content":"# Nushell Data Types and Conversions\n\nNushell models data with simple, structured types. Use `describe` to check the type of any value: `42 | describe` → `int`.\n\n## Basic Data Types\n\n### Integers\n\nNumbers without a fractional component (positive, negative, and 0). Annotation: `int`.\n\n**Literal Syntax:** Decimal (`-100`, `0`, `50`), hex (`0xff`), octal (`0o234`), binary (`0b10101`).\n\n```nu\n10 / 2 # => 5\n5 | describe # => int\n```\n\n### Floats/Decimals\n\nNumbers with a fractional component. Annotation: `float`.\n\n**Literal Syntax:** `1.5`, `2.0`, `-15.333`, `Infinity`.\n\n```nu\n2.5 / 5.0 # => 0.5\n# Floats are approximate: 10.2 * 5.1 => 52.01999999999999\n```\n\n### Strings\n\nA series of characters representing text. Annotation: `string`.\n\n**Literal Syntax:** Single-quoted (`'text'`), double-quoted (`\"text\\n\"` with escapes), raw (`r#'text'#`), bare word (no quotes), backtick-quoted (`` `text` ``). String interpolation: `$\"value ($expr)\"` or `

nu-shell Nushell treats all data as structured tables — lists of records with rows and columns. Every file and command output becomes a table you can filter, transform, and combine. File I/O & Parsing Files auto-detect from extension. Pipe command output into tables: Core Pipeline Commands Filtering & Selecting - — keep specific columns (keeps table shape) - — drop a column - — extract as a list (not a table) Transforming Data Combining Data String Operations Flow Control & Variables JSON Manipulation (jq equivalents) Nushell replaces entirely. Parse with , transform with pipeline commands, o…

value ($expr)'`.\n\n```nu\nlet audience: string = \"World\"\n$\"Hello, ($audience)\" # => Hello, World\nr#'Can contain '\\''quotes'\\'''# # Raw strings\n```\n\n### Booleans\n\nTrue or false value. Annotation: `bool`. Literal syntax: `true` or `false`.\n\n```nu\nlet mybool: bool = (2 > 1) # => true\nif $mybool { print \"yes\" }\n```\n\nBooleans are commonly the result of comparisons:\n\n```nu\nlet mybool: bool = ($env.HOME | path exists) # => true\n```\n\n### Dates\n\nRepresents a specific point in time. Annotation: `datetime`.\n\n**Literal Syntax:** ISO format strings, or via commands like `date now`.\n\n```nu\ndate now # => Mon, 12 Aug 2024 13:59:22 -0400\ndate now | format date '%s' # Unix epoch\n\"2024-01-01T12:00:00+05:00\" | into datetime\n```\n\n### Durations\n\nPassage of time, supports fractional values and calculations. Annotation: `duration`.\n\n**Literal Syntax:** `3day`, `2min + 12sec`, `3.14day`.\n\n```nu\n30day / 1sec # => 2592000 (seconds in 30 days)\n3.14day # => 3day 3hr 21min\n```\n\n### File Sizes\n\nSpecialized numeric type for file sizes or number of bytes. Annotation: `filesize`.\n\n**Literal Syntax:** `64mb`, `0.5kB`, `1GiB`.\n\n```nu\n1GiB / 1B # => 1073741824\n(1GiB / 1B) == 2 ** 30 # => true\n0.5kB # => 500 B\n```\n\n### Ranges\n\nDescribes a range of values from start to end, with optional stride. Annotation: `range`.\n\n**Literal Syntax:** `\u003cstart>..\u003cend>` (`1..10`), with stride `\u003cstart>..\u003csecond>..\u003cend>` (`2..4..20`).\n\n```nu\n1..5 # Expands to list [1, 2, 3, 4, 5]\n```\n\n### Binary Data\n\nRaw bytes. Annotation: `binary`.\n\n**Literal Syntax:** `0x[FE FF]` (hex), `0b[10101010101]` (binary), `0o[1234567]` (octal).\n\n```nu\nopen nushell_logo.jpg | into binary | first 2 == 0x[ff d8] # JPEG check\n```\n\n### Cell Paths\n\nExpression to navigate inner values in structured data. Annotation: `cell-path`.\n\n**Literal Syntax:** Dot-separated row/column IDs (`name.4.5`). Use leading `$.` for variable assignment.\n\n```nu\nlet cp = $.2\n[ foo bar goo glue ] | get $cp # => goo\n```\n\n### Closures\n\nAnonymous function (lambda) that accepts parameters and closes over variables from outer scope. Annotation: `closure`.\n\n**Literal Syntax:** `{|args| expressions}`.\n\n```nu\nlet compare_closure = {|a| $a > 5 }\n[ 40 -4 0 8 12 ] | where $compare_closure # => [40, 8, 12]\n{ $in.name.0 | path exists } # Filter closure\n```\n\n## Structured Data Types\n\n### Lists\n\nOrdered sequence of zero or more values of any type. Annotation: `list`.\n\n**Literal Syntax:** `[value1 value2 value3]` (space-separated) or `[value1, value2, value3]` (comma-separated). Similar to JSON arrays.\n\n```nu\n[Sam Fred George] # List of strings\n[ foo bar goo glue ] | get 2 # => goo\n```\n\n### Records\n\nKey-value pairs with string keys. Annotation: `record`.\n\n**Literal Syntax:** `{key1: value1, key2: value2}` or space-separated on multiple lines. Similar to JSON objects.\n\n```nu\nlet my_record = { name: \"Kylian\", rank: 99 }\n$my_record | get name # => Kylian\n```\n\n### Tables\n\nTwo-dimensional container with both columns and rows. Internally, tables are **lists of records**. Annotation: `table`.\n\n```nu\n[{x:12, y:5}, {x:3, y:6}] | get 0 # => {x: 12, y: 5} (record, not list item)\n# Table literal with explicit columns: [[col1, col2]; [val1, val2], ...]\n[[a b]; [1 2]] # Creates a table with columns a, b\n```\n\n## Other Types\n\n| Type | Description | Example |\n| --------- | ------------------------------------------- | ------------------------------------------------- |\n| `any` | Matches any type (superset for annotations) | `let p: any = 5` |\n| `nothing` | Absence of a value | `null`, or result of `$rec.field?` on missing key |\n| `path` | File system path — auto-expands `~`, `.` | Used internally by `path` commands |\n| `glob` | Glob pattern string | `\"*.txt\"` |\n| `block` | Syntactic form for control flow keywords | `{ print \"hello\" }` in `if true { ... }` |\n\n## Type Conversions (`into`)\n\nConvert between types using the `into` command:\n\n```nu\n\"42\" | into int # String → integer\n\"3.14\" | into float # String → float\n42 | into string # Any → string\n\"2024-01-01\" | into datetime # String → datetime\n\"30s\" | into duration # String → duration\n\"64MB\" | into filesize # String → filesize\n\"true\" | into bool # String → boolean\n```\n\n## Useful Type Commands\n\n| Command | Purpose | Example |\n| ------------- | ------------------------------------- | -------- | --------------------- |\n| `describe` | Returns the type of a value | `42 | describe`→`int` |\n| `detect type` | Infers Nushell datatype from a string | `\"hello\" | detect type`→`string` |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6066,"content_sha256":"663e7f2c5947aa088fdf82c8bfaf310ce1330b873aaa2d66e03034968ca6d3e8"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"nu-shell","type":"text"}]},{"type":"paragraph","content":[{"text":"Nushell treats all data as structured tables — lists of records with rows and columns. Every file and command output becomes a table you can filter, transform, and combine.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"File I/O & Parsing","type":"text"}]},{"type":"paragraph","content":[{"text":"Files auto-detect from extension. Pipe command output into tables:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"nu"},"content":[{"text":"open data.csv # CSV → table\ndf -h | detect columns # Command output → table\n$data | save -f output.csv # Write (overwrite with -f)","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Core Pipeline Commands","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Filtering & Selecting","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"nu"},"content":[{"text":"open data.csv | where rating > 4.0 and status == \"active\"\nls | sort-by size | reverse | first 10","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"select col1 col2","type":"text","marks":[{"type":"code_inline"}]},{"text":" — keep specific columns (keeps table shape)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"reject col","type":"text","marks":[{"type":"code_inline"}]},{"text":" — drop a column","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"get col","type":"text","marks":[{"type":"code_inline"}]},{"text":" — extract as a list (not a table)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Transforming Data","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"nu"},"content":[{"text":"# Map rows\n$items | each { |row| { ...$row, tax: ($row.price * 0.1) } }\n\n# Transform a column\n$table | update price { |x| $x * 1.1 }\n\n# Add or update columns\n$table | insert new_col ($in.old_col * 2)\n\n# Rename\n$table | rename old_name new_name","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Combining Data","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"nu"},"content":[{"text":"$first | append $b # Stack rows\n$first | merge $second # Side-by-side columns","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"String Operations","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"nu"},"content":[{"text":"where name =~ \"pattern\" # Regex match\nstr upcase / str downcase # Case conversion\nstr trim / str kebab-case # Formatting\nstr join \",\" $list # Join list with separator\n$\"My value is ($expr)\" # Interpolation","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Flow Control & Variables","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"nu"},"content":[{"text":"let x = (open data.csv); mut count = 0\nif ($x | length) > 0 { print \"has\" } else { print \"empty\" }\nfor row in $items { process $row }\nmatch $value { \"A\" => do_a, \"B\" => do_b, _ => default_action }\ntry { open nonexistent.txt } catch { |err| print $\"Error: ($err.msg)\" }\n\n# Capture external command output\ndo { ^my-command arg1 } | complete # Returns .exit_code, .stdout, .stderr","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"JSON Manipulation (jq equivalents)","type":"text"}]},{"type":"paragraph","content":[{"text":"Nushell replaces ","type":"text"},{"text":"jq","type":"text","marks":[{"type":"code_inline"}]},{"text":" entirely. Parse with ","type":"text"},{"text":"from json","type":"text","marks":[{"type":"code_inline"}]},{"text":", transform with pipeline commands, output with ","type":"text"},{"text":"to json","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"nu"},"content":[{"text":"# Select a field (jq '.name')\n'{\"name\": \"Alice\"}' | from json | get name\n\n# Filter array (jq '.[] | select(.age > 28)')\n'[...]' | from json | where age > 28\n\n# Map values (jq 'map(. * 2)')\n'[1, 2, 3]' | from json | each { $in * 2 }\n\n# Conditional (jq 'if .age > 18 then \"Adult\" else \"Child\" end')\n'{\"age\": 30}' | from json | if $in.age > 18 { \"Adult\" } else { \"Child\" }\n\n# Format string (jq \"Name: \\(.name)\")\n'{\"name\": \"Alice\", \"age\": 30}' | from json | format \"Name: {name}, Age: {age}\"\n\n# Build new record (jq '{name: .name, age: (.age + 5)}')\n'{\"name\": \"Alice\", \"age\": 30}' | from json | {name: $in.name, age: ($in.age + 5)}\n\n# Filter nulls (jq 'map(select(. != null))')\n'[1, null, 3]' | from json | where { $in != null }\n\n# Flatten nested arrays (jq '.data[].values[]')\n'{\"data\": [{\"values\": [1, 2]}]}' | from json | get data.values | flatten\n\n# Sort / unique (jq 'sort' / 'unique')\n'[3, 1, 4]' | from json | sort\n'[1, 2, 2]' | from json | uniq","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Statistical Operations","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"nu"},"content":[{"text":"# Average (jq 'map(.score) | add / length')\n'[...]' | from json | get score | math avg\n\n# Group and aggregate (jq 'group_by(.category)')\n'[...]' | from json | group-by --to-table category\n| update items { |row| $row.items.value | math sum }\n| rename category sum\n\n# Reduce (jq 'reduce .[] as $item (0; . + $item.value)')\n'[...]' | from json | reduce -f 0 { |item, acc| $acc + $item.value }","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Custom Recursive Commands","type":"text"}]},{"type":"paragraph","content":[{"text":"For patterns without built-in equivalents, see ","type":"text"},{"text":"references/jq_patterns.md","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cherry-pick","type":"text","marks":[{"type":"code_inline"}]},{"text":" — recursive key extraction (jq ","type":"text"},{"text":".. | .key?","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"walk","type":"text","marks":[{"type":"code_inline"}]},{"text":" — recursive transformation (jq ","type":"text"},{"text":"walk(...)","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"flatten record-paths","type":"text","marks":[{"type":"code_inline"}]},{"text":" — flatten nested records to dot-paths","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Best Practices","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Prefer internal commands","type":"text","marks":[{"type":"strong"}]},{"text":": Built-ins return structured data. Only use ","type":"text"},{"text":"^","type":"text","marks":[{"type":"code_inline"}]},{"text":" prefix for external binaries when necessary.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Collect before save","type":"text","marks":[{"type":"strong"}]},{"text":": Use ","type":"text"},{"text":"collect | save --force file","type":"text","marks":[{"type":"code_inline"}]},{"text":" to avoid read/write conflicts.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Type safety","type":"text","marks":[{"type":"strong"}]},{"text":": Empty cells parse as empty strings, not null. Filter empties before numeric conversion: ","type":"text"},{"text":"where column != \"\" | into int","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Prefer filters over loops","type":"text","marks":[{"type":"strong"}]},{"text":": Use ","type":"text"},{"text":"where","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"each","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"reduce","type":"text","marks":[{"type":"code_inline"}]},{"text":" instead of ","type":"text"},{"text":"for","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"while","type":"text","marks":[{"type":"code_inline"}]},{"text":" — they stream and parallelize better.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Nushell replaces jq","type":"text","marks":[{"type":"strong"}]},{"text":": For JSON processing, use ","type":"text"},{"text":"from json","type":"text","marks":[{"type":"code_inline"}]},{"text":" + pipeline commands instead of ","type":"text"},{"text":"jq","type":"text","marks":[{"type":"code_inline"}]},{"text":". Nushell works natively with JSON, YAML, CSV, and more.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"For heavy JSON analytics","type":"text","marks":[{"type":"strong"}]},{"text":": Use DuckDB (","type":"text"},{"text":"duckdb","type":"text","marks":[{"type":"code_inline"}]},{"text":" skill) when you need SQL queries, schema inference, or complex joins over JSON data.","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"nu","author":"@skillopedia","source":{"stars":57,"repo_name":"pi","origin_url":"https://github.com/knoopx/pi/blob/HEAD/agent/skills/tools/nu/SKILL.md","repo_owner":"knoopx","body_sha256":"78a42a8bd98ca4e5522eaaca6af36cb4e0e51d57dcc4cb5af11372446146c7ec","cluster_key":"a4cc9a86b1c1ba4b66e34453556c9e76e91fadfa3e1b1a3358e41fa982787570","clean_bundle":{"format":"clean-skill-bundle-v1","source":"knoopx/pi/agent/skills/tools/nu/SKILL.md","attachments":[{"id":"fd50c86e-b1df-58ac-9dfa-a1055c65e7a5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fd50c86e-b1df-58ac-9dfa-a1055c65e7a5/attachment.md","path":"references/cell-paths.md","size":5588,"sha256":"22cb18ac62e0850ddee908d5b74000cab03d08fc8d3957799c326b6d2096f286","contentType":"text/markdown; charset=utf-8"},{"id":"7b3c0631-0cb0-5cc4-9f14-a8b2959399b4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7b3c0631-0cb0-5cc4-9f14-a8b2959399b4/attachment.md","path":"references/custom-commands.md","size":7256,"sha256":"377a6fd209d5f3a47f9d3b9d10fb6abee0eefeaf8a19e6f01c8c2a7dd53ff031","contentType":"text/markdown; charset=utf-8"},{"id":"39d81a1f-a7b3-5327-b26e-298486c77c89","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/39d81a1f-a7b3-5327-b26e-298486c77c89/attachment.md","path":"references/environment.md","size":5446,"sha256":"f2795c1b08af1dbf75fda910437cd025d4802e378583415cdc8c012474c123d6","contentType":"text/markdown; charset=utf-8"},{"id":"bccafc5b-c470-5038-98b2-a5077ef37b90","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bccafc5b-c470-5038-98b2-a5077ef37b90/attachment.md","path":"references/flow-control.md","size":7008,"sha256":"6c1a9d36ab06d69fee1a639cae684784be1c8cc4034375726e57e67b7634df20","contentType":"text/markdown; charset=utf-8"},{"id":"52364ca3-a4c7-5e67-9604-39c722998daf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/52364ca3-a4c7-5e67-9604-39c722998daf/attachment.md","path":"references/jq_patterns.md","size":7365,"sha256":"d1d622805c0e7f8fc31a08f0177d34b3530a115d3fb947d216fe7c243aed3fbe","contentType":"text/markdown; charset=utf-8"},{"id":"4817464b-12cf-5515-8075-faa66f59c3b4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4817464b-12cf-5515-8075-faa66f59c3b4/attachment.md","path":"references/modules.md","size":4892,"sha256":"2c9bf586f2494db3afa8f37d2d404083b5b82b34f5efbdbf4c5dc7db08878a89","contentType":"text/markdown; charset=utf-8"},{"id":"e71f7564-4f86-5d1b-bce2-e7a1c413da75","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e71f7564-4f86-5d1b-bce2-e7a1c413da75/attachment.md","path":"references/operators.md","size":5987,"sha256":"34bcecc73fe55265328a9e0c43c31771dcd0b0135e37fdbd7dddb1dffec6ce28","contentType":"text/markdown; charset=utf-8"},{"id":"bed9e806-c0cd-5720-b60b-a9e318a19b59","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bed9e806-c0cd-5720-b60b-a9e318a19b59/attachment.md","path":"references/parsing.md","size":7043,"sha256":"5c00c18eff96af1a0728abf91388feb9c16c8e0b1b39ac84144fcbf7a2b989f1","contentType":"text/markdown; charset=utf-8"},{"id":"e1586717-d94c-5d5a-b2cd-afc6b4c18c89","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e1586717-d94c-5d5a-b2cd-afc6b4c18c89/attachment.md","path":"references/patterns.md","size":6593,"sha256":"214f337b2b42de3800de65ac054eb18bc58d17ad9c0b7263c5f6148eae2cb362","contentType":"text/markdown; charset=utf-8"},{"id":"122852d1-684e-5945-9fb1-c031832baaaf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/122852d1-684e-5945-9fb1-c031832baaaf/attachment.md","path":"references/scripts.md","size":4853,"sha256":"5d5602c5cb3cb2787db9bd5306fe1d325c85fd822fdd930b9d64cb68fce63309","contentType":"text/markdown; charset=utf-8"},{"id":"f44c3fdb-6bd8-5160-86ff-adc2e7d00ef7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/f44c3fdb-6bd8-5160-86ff-adc2e7d00ef7/attachment.md","path":"references/sorting.md","size":1769,"sha256":"81cac774bdbec1bc174b00bb00da3115c1223f4080245c38022beae3f7d6a951","contentType":"text/markdown; charset=utf-8"},{"id":"8e57fe15-3cd9-5d87-b169-7b2c7143171b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8e57fe15-3cd9-5d87-b169-7b2c7143171b/attachment.md","path":"references/strings.md","size":5882,"sha256":"15eb3ccaa3171ebb0e0860fd6db597c81e70533745e86805987f9521ce3ba468","contentType":"text/markdown; charset=utf-8"},{"id":"c3a267dd-1257-5f91-a7f4-c838e33d02b1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c3a267dd-1257-5f91-a7f4-c838e33d02b1/attachment.md","path":"references/system.md","size":9058,"sha256":"7f42e89b4f7430570d171c57719d6b85bee3a7bf690003ff987d069999b70961","contentType":"text/markdown; charset=utf-8"},{"id":"b559bd3c-091a-5a33-96c6-df04aea6d2d9","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b559bd3c-091a-5a33-96c6-df04aea6d2d9/attachment.md","path":"references/tables.md","size":9508,"sha256":"5d59230de8dc0bd9eb2f074e0fc56534cc7a6dad94711b3eac3feb0a4ad44ba2","contentType":"text/markdown; charset=utf-8"},{"id":"9374a0aa-ec2f-5225-bffe-a31259bc9625","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9374a0aa-ec2f-5225-bffe-a31259bc9625/attachment.md","path":"references/types.md","size":6066,"sha256":"663e7f2c5947aa088fdf82c8bfaf310ce1330b873aaa2d66e03034968ca6d3e8","contentType":"text/markdown; charset=utf-8"}],"bundle_sha256":"2e7e0746f7fa0072786251bca0b444859ba9849f6eb7c820569ac6e218bd9ead","attachment_count":15,"text_attachments":15,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"agent/skills/tools/nu/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"web-development","category_label":"Web"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"web-development","keywords":["nushell","nu","pipeline","csv","tsv","table","filter"],"import_tag":"clean-skills-v1","token_cost":200,"description":"Reads, filters, transforms, and manipulates structured data using Nushell's pipeline commands. Use when working with CSV/TSV files, parsing command output, transforming tabular data, system administration tasks, or building data pipelines."}},"renderedAt":1782986780174}

nu-shell Nushell treats all data as structured tables — lists of records with rows and columns. Every file and command output becomes a table you can filter, transform, and combine. File I/O & Parsing Files auto-detect from extension. Pipe command output into tables: Core Pipeline Commands Filtering & Selecting - — keep specific columns (keeps table shape) - — drop a column - — extract as a list (not a table) Transforming Data Combining Data String Operations Flow Control & Variables JSON Manipulation (jq equivalents) Nushell replaces entirely. Parse with , transform with pipeline commands, o…