Skip to content

Update Cookbook direnv instructions for new std helper #1878

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 34 additions & 23 deletions cookbook/direnv.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.