diff --git a/cookbook/direnv.md b/cookbook/direnv.md index 4375f4dfdf..9f8c44e1ca 100644 --- a/cookbook/direnv.md +++ b/cookbook/direnv.md @@ -4,35 +4,46 @@ title: Direnv # Direnv -Many people use [direnv](https://direnv.net) to load an environment upon entering a directory as well as unloading it when exiting the directory. -Configuring direnv to work with nushell requires nushell version 0.66 or later. +Many people use [direnv](https://direnv.net) to load an environment when entering a directory and unload it when exiting the directory. ---- +## How direnv works + +From [direnv.net](https://direnv.net): + +> Before each prompt, direnv checks for the existence of a `.envrc` file (and optionally a `.env` file) in the current and parent directories. If the file exists (and is authorized), it is loaded into a bash sub-shell and all exported variables are then captured by direnv and then made available to the current shell. + +## Configuring direnv in Nushell + +In Nushell, it's possible to run direnv each time the prompt displays (using a [`pre_prompt` hook](/book/hooks.html)). However, it's more efficient to update only when the directory is changed using an `env_change` hook along with: + +- [`from json`](/commands/docs/from_json.md) to convert the direnv output to structured data +- [`load-env`](/commands/docs/load-env.md) +- An `env-conversion` helper for the `PATH` from the [Standard Library](/book/standard_library.md) -### Configuring direnv +::: note -To make direnv work with nushell the way it does with other shells, we can use the "hooks" functionality: +The direnv configuration below requires Nushell 0.104 or later. + +::: ```nu -$env.config = { - hooks: { - pre_prompt: [{ || - if (which direnv | is-empty) { - return - } - - direnv export json | from json | default {} | load-env - if 'ENV_CONVERSIONS' in $env and 'PATH' in $env.ENV_CONVERSIONS { - $env.PATH = do $env.ENV_CONVERSIONS.PATH.from_string $env.PATH - } - }] +use std/config * + +# Initialize the PWD hook as an empty list if it doesn't exist +$env.config.hooks.env_change.PWD = $env.config.hooks.env_change.PWD? | default [] + +$env.config.hooks.env_change.PWD ++= [{|| + if (which direnv | is-empty) { + # If direnv isn't installed, do nothing + return } -} + + direnv export json | from json | default {} | load-env + # If direnv changes the PATH, it will become a string and we need to re-convert it to a list + $env.PATH = do (env-conversions).path.from_string $env.PATH +}] ``` -::: tip Note -you can follow the [`nu_scripts` of Nushell](https://github.com/nushell/nu_scripts/blob/main/nu-hooks/nu-hooks/direnv/config.nu) -for the always up-to-date version of the hook above -::: +As with other configuration changes, this can be made permanent by adding it to your startup [configuration](/book/configuration.md). -With that configuration in place, direnv should now work with nushell. +With this in place, direnv will now add/remove environment variables when entering/leaving a directory with an `.envrc` or `.env` file.