# Hooks
Hooks allow you to run a code snippet at some predefined situations.
They are only available in the interactive mode ([REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)), they do not work if you run Nushell with a script (`nu script.nu`) or command (`nu -c "print foo"`) argument.
Currently, we support these types of hooks:
- `pre_prompt` : Triggered before the prompt is drawn
- `pre_execution` : Triggered before the line input starts executing
- `env_change` : Triggered when an environment variable changes
- `display_output` : A block that the output is passed to
- `command_not_found` : Triggered when a command is not found
To make it clearer, we can break down Nushell's execution cycle.
The steps to evaluate one line in the REPL mode are as follows:
1. Check for `pre_prompt` hooks and run them
1. Check for `env_change` hooks and run them
1. Display prompt and wait for user input
1. After user typed something and pressed "Enter": Check for `pre_execution` hooks and run them
1. Parse and evaluate user input
1. If a command is not found: Run the `command_not_found` hook. If it returns a string, show it.
1. If `display_output` is defined, use it to print command output
1. Return to 1.
## Basic Hooks
To enable hooks, define them in your [config](configuration.md):
```nu
$env.config.hooks = {
pre_prompt: [{ print "pre prompt hook" }]
pre_execution: [{ print "pre exec hook" }]
env_change: {
PWD: [{|before, after| print $"changing directory from ($before) to ($after)" }]
}
}
```
Try putting the above into your config, running Nushell and moving around your filesystem.
When you change a directory, the `PWD` environment variable changes and the change triggers the hook with the previous and the current values stored in `before` and `after` variables, respectively.
Instead of defining just a single hook per trigger, it is possible to define a **list of hooks** which will run in sequence:
```nu
$env.config.hooks = {
pre_prompt: [
{ print "pre prompt hook" }
{ print "pre prompt hook2" }
]
pre_execution: [
{ print "pre exec hook" }
{ print "pre exec hook2" }
]
env_change: {
PWD: [
{|before, after| print $"changing directory from ($before) to ($after)" }
{|before, after| print $"changing directory from ($before) to ($after) 2" }
]
}
}
```
Instead of replacing all hooks, you can append a new hook to existing configuration:
```nu
$env.config.hooks.pre_execution = $env.config.hooks.pre_execution | append { print "pre exec hook3" }
```
## Changing Environment
One feature of the hooks is that they preserve the environment.
Environment variables defined inside the hook **block** will be preserved in a similar way as [`def --env`](environment.md#defining-environment-from-custom-commands).
You can test it with the following example:
```nu
$env.config = ($env.config | upsert hooks {
pre_prompt: { $env.SPAM = "eggs" }
})
$env.SPAM
# => eggs
```
The hook blocks otherwise follow the general scoping rules, i.e., commands, aliases, etc. defined within the block will be thrown away once the block ends.
## `pre_execution` Hooks
`pre_execution` hooks can inspect the to-be-executed command through the [`commandline` command](/commands/docs/commandline.md).
For example, to print the command being executed:
```nu
$env.config = (
$env.config
| upsert hooks.pre_execution [ {||
$env.repl_commandline = (commandline)
print $"Command: ($env.repl_commandline)"
} ]
)
print (1 + 3)
# => Command: print (1 + 3)
# => 4
```
## Conditional Hooks
One thing you might be tempted to do is to activate an environment whenever you enter a directory:
```nu
$env.config = ($env.config | upsert hooks {
env_change: {
PWD: [
{|before, after|
if $after == /some/path/to/directory {
load-env { SPAM: eggs }
}