Environment

A common task in a shell is to control the environment that external applications will use. This is often done automatically, as the environment is packaged up and given to the external application as it launches. Sometimes, though, we want to have more precise control over what environment variables an application sees.

You can see the current environment variables in the $env variable:

~> $env | table -e
╭──────────────────────────────────┬───────────────────────────────────────────╮
                                   ╭──────┬────────────────────────────────╮ 
 ENV_CONVERSIONS                          ╭─────────────┬──────────────╮  
                                    PATH   from_string  <Closure 32>   
                                           to_string    <Closure 34>   
                                          ╰─────────────┴──────────────╯  
                                          ╭─────────────┬──────────────╮  
                                    Path   from_string  <Closure 36>   
                                           to_string    <Closure 38>   
                                          ╰─────────────┴──────────────╯  
                                   ╰──────┴────────────────────────────────╯ 
 HOME                              /Users/jelle                              
 LSCOLORS                          GxFxCxDxBxegedabagaced                    
| ...                              | ...                                       |
╰──────────────────────────────────┴───────────────────────────────────────────╯

In Nushell, environment variables can be any value and have any type. You can see the type of an env variable with the describe command, for example: $env.PROMPT_COMMAND | describe.

To send environment variables to external applications, the values will need to be converted to strings. See Environment variable conversions on how this works.

The environment is initially created from the Nu configuration files and from the environment that Nu is run inside of.

Setting environment variables

There are several ways to set an environment variable:

$env.VAR assignment

Using the $env.VAR = "val" is the most straightforward method

> $env.FOO = 'BAR'

So, if you want to extend the Windows Path variable, for example, you could do that as follows.

$env.Path = ($env.Path | prepend 'C:\path\you\want\to\add')

Here we've prepended our folder to the existing folders in the Path, so it will have the highest priority. If you want to give it the lowest priority instead, you can use the append command.

load-env

If you have more than one environment variable you'd like to set, you can use load-env to create a table of name/value pairs and load multiple variables at the same time:

> load-env { "BOB": "FOO", "JAY": "BAR" }

One-shot environment variables

These are defined to be active only temporarily for a duration of executing a code block. See Single-use environment variables for details.

Calling a command defined with def --env

See Defining environment from custom commands for details.

Using module's exports

See Modules for details.

Reading environment variables

Individual environment variables are fields of a record that is stored in the $env variable and can be read with $env.VARIABLE:

> $env.FOO
BAR

Sometimes, you may want to access an environmental variable which might be unset. Consider using the question mark operator to avoid an error:

> $env.FOO | describe
Error: nu::shell::column_not_found

  × Cannot find column
   ╭─[entry #1:1:1]
 1  $env.FOO
   · ──┬─ ─┬─
   ·      ╰── cannot find column 'FOO'
   ·   ╰── value originates here
   ╰────

> $env.FOO? | describe
nothing

> $env.FOO? | default "BAR"
BAR

Alternatively, you can check for the presence of an environmental variable with in:

> $env.FOO
BAR

> if "FOO" in $env {
>     echo $env.FOO
> }
BAR

Scoping

When you set an environment variable, it will be available only in the current scope (the block you're in and any block inside of it).

Here is a small example to demonstrate the environment scoping:

> $env.FOO = "BAR"
> do {
    $env.FOO = "BAZ"
    $env.FOO == "BAZ"
}
true
> $env.FOO == "BAR"
true

Changing directory

Common task in a shell is to change directory with the cd command. In Nushell, calling cd is equivalent to setting the PWD environment variable. Therefore, it follows the same rules as other environment variables (for example, scoping).

Single-use environment variables

A common shorthand to set an environment variable once is available, inspired by Bash and others:

> FOO=BAR $env.FOO
BAR

You can also use with-env to do the same thing more explicitly:

> with-env { FOO: BAR } { $env.FOO }
BAR

The with-env command will temporarily set the environment variable to the value given (here: the variable "FOO" is given the value "BAR"). Once this is done, the block will run with this new environment variable set.

Permanent environment variables

You can also set environment variables at startup so they are available for the duration of Nushell running. To do this, set an environment variable inside the Nu configuration file. For example:

# In config.nu
$env.FOO = 'BAR'

Defining environment from custom commands

Due to the scoping rules, any environment variables defined inside a custom command will only exist inside the command's scope. However, a command defined as def --env instead of def (it applies also to export def, see Modules) will preserve the environment on the caller's side:

> def --env foo [] {
    $env.FOO = 'BAR'
}

> foo

> $env.FOO
BAR

Environment variable conversions

You can set the ENV_CONVERSIONS environment variable to convert other environment variables between a string and a value. For example, the default environment configopen in new window includes conversion of PATH (and Path used on Windows) environment variables from a string to a list. After both env.nu and config.nu are loaded, any existing environment variable specified inside ENV_CONVERSIONS will be translated according to its from_string field into a value of any type. External tools require environment variables to be strings, therefore, any non-string environment variable needs to be converted first. The conversion of value -> string is set by the to_string field of ENV_CONVERSIONS and is done every time an external command is run.

Let's illustrate the conversions with an example. Put the following in your config.nu:

$env.ENV_CONVERSIONS = {
    # ... you might have Path and PATH already there, add:
    FOO : {
        from_string: { |s| $s | split row '-' }
        to_string: { |v| $v | str join '-' }
    }
}

Now, within a Nushell instance:

> with-env { FOO : 'a-b-c' } { nu }  # runs Nushell with FOO env. var. set to 'a-b-c'

> $env.FOO
  0   a
  1   b
  2   c

You can see the $env.FOO is now a list in a new Nushell instance with the updated config. You can also test the conversion manually by

> do $env.ENV_CONVERSIONS.FOO.from_string 'a-b-c'

Now, to test the conversion list -> string, run:

> nu -c '$env.FOO'
a-b-c

Because nu is an external program, Nushell translated the [ a b c ] list according to ENV_CONVERSIONS.FOO.to_string and passed it to the nu process. Running commands with nu -c does not load the config file, therefore the env conversion for FOO is missing and it is displayed as a plain string -- this way we can verify the translation was successful. You can also run this step manually by do $env.ENV_CONVERSIONS.FOO.to_string [a b c]

(Important! The environment conversion string -> value happens after the env.nu and config.nu are evaluated. All environment variables in env.nu and config.nu are still strings unless you set them manually to some other values.)

Removing environment variables

You can remove an environment variable only if it was set in the current scope via hide-env:

> $env.FOO = 'BAR'
...
> hide-env FOO

The hiding is also scoped which both allows you to remove an environment variable temporarily and prevents you from modifying a parent environment from within a child scope:

> $env.FOO = 'BAR'
> do {
    hide-env FOO
    # $env.FOO does not exist
  }
> $env.FOO
BAR
Contributors: Jakub Žádník, Justin Ma, Antoine Stevan, JT, Jelle Besseling, Leon, Michael Angerman, Reilly Wood, 132ikl, Arnau Siches, Dan Davison, Darren Schroeder, Hofer-Julian, Hristo Filaretov, Ibraheem Ahmed, Jonas Gollenz, Jonathan Turner, Michael Angerman, Máté FARKAS, WindSoilder, Zhora Trush, chtenb, petrisch, prrao87