Skip to content

Load and unload custom variables, functions, and aliases as you cd through directories in your terminal.

License

Notifications You must be signed in to change notification settings

tothpeter/local_sherpa

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Local Sherpa - Folder based development environment in your terminal

Logo

Sherpa is a shell extension that allows you to define new or override existing variables, aliases and functions on a per-folder basis, with support for nesting.

It only supports Zsh and Bash but functional wise it is similar to Direnv with added support for aliases and functions.

Video Demo

ASCII Demo

$ cd ~/projects

$ echo "$VAR_1"
GLOBAL VAR
$ alias_1
GLOBAL ALIAS
$ function_1
GLOBAL FUNCTION

$ cd project_awesome

$ echo "$VAR_1"
LOCAL VAR PROJECT AWESOME
$ alias_1
LOCAL ALIAS PROJECT AWESOME
$ function_1
LOCAL FUNCTION PROJECT AWESOME

$ cd ..

$ echo "$VAR_1"
GLOBAL VAR
$ alias_1
GLOBAL ALIAS
$ function_1
GLOBAL FUNCTION

The above is accomplished with the help of Sherpa and the files below.

# ~/.bashrc or ~/.zshrc etc...
export VAR_1="GLOBAL VAR"

alias alias_1='echo "GLOBAL ALIAS"'

function_1() {
  echo "GLOBAL FUNCTION"
}
# ~/projects/project_awesome/.envrc
export VAR_1="LOCAL VAR PROJECT AWESOME"

alias alias_1='echo "LOCAL ALIAS PROJECT AWESOME"'

function_1() {
  echo "LOCAL FUNCTION PROJECT AWESOME"
}

Status

Version: beta 1.

example workflow

Basic usage

  1. $ cd ~/projects/project_awesome
  2. $ sherpa edit
    1. Sherpa opens the env file in your editor
    2. You update, save then close it
    3. Sherpa unloads the previous version, trusts and loads the current one automatically
  3. You can nest envs by repeating this in subdirectories
  4. Disco

For more details see the Features section.

Supported shells

  • Zsh
  • Bash

Tested on

  • macOS 12 - Monterey
  • macOS 13 - Ventura
  • macOS 14 - Sonoma
  • Ubuntu 20.04
  • Ubuntu 22.04

Supported Shell entities for unloading

  • Exported variables
  • Aliases
  • Functions

Experimental feature: Non-exported variables and dynamically created entities are supported by setting the SHERPA_ENABLE_DYNAMIC_ENV_FILE_PARSING environment variable to true. This executes the env file in a subshell three times when cd'ing into a directory.

Good to know

When sherpa loads the env, it sources the env file meaning its whole content is executed in the current shell.

Installation

# Clone the repo
$ git clone git@github.com:tothpeter/local_sherpa.git ~/.dotfiles/lib/local_sherpa

# Hook it into your shell
## Zsh
$ echo "source ~/.dotfiles/lib/local_sherpa/init.sh" >> ~/.zshrc
## Bash
$ echo "source ~/.dotfiles/lib/local_sherpa/init.sh" >> ~/.bashrc

# Exclude the env files (.envrc) globally in Git
$ echo ".envrc" >> $(git config --global core.excludesfile)

# Reload or restart your shell

# Optional but recommended
alias se='sherpa edit'
alias st='sherpa trust'
alias upgrade_sherpa='git -C ~/.dotfiles/lib/local_sherpa pull'

Features

See the full list of commands by running $ sherpa in your shell.

Security

Sherpa won't load any env file unless you trust them first.
This is to prevent running malicious code when you cd into a directory.

$ echo "alias rs=rspec" > ~/projects/project_awesome/.envrc
$ cd ~/projects/project_awesome
Sherpa: The env file is not trusted. Run `sherpa trust` to mark it as trusted.
$ rs
command not found: rs
$ sherpa trust
Sherpa: Trusted!
$ rs
# rspec starts

When an env file changes you have to trust the directory again.

Use sherpa edit. It opens the env file in your default editor then trusts it automatically when you close it.

You can untrust a directory with sherpa untrust.

Loading envs from parent directories automatically

It is not supported currently. Feel free to open a feature request.

Env loading and unloading

  • Sherpa supports nested envs
    • It unloads the envs in the correct order when leaving a directory to restore the overridden items.
    • Subfolders can override the items defined in the parent folders.
  • Sherpa does not unload the loaded envs when you cd into a subdirectory.
  • Experimental feature: Non exported variables and dynamically created entities are unloaded only if the SHERPA_ENABLE_DYNAMIC_ENV_FILE_PARSING environment variable is set to true.

Demo

# Given the following directory structure with the corresponding env files
# ~/projects/.envrc
# ~/projects/project_awesome/.envrc
# ~/projects/project_awesome/subdir

$ cd ~/projects/
# Sherpa loads the env for projects
# Items defined in this folder override the items defined in the global env
$ cd project_awesome
# Sherpa does not unload the previous env
# Sherpa loads the env for project_awesome
# Items defined in this folder override the items defined in previous envs
$ cd subdir
# Sherpa does not unload the previous envs
$ cd ..
# Sherpa does not reload the env for project_awesome
$ cd ..
# Sherpa unloads the env for project_awesome and restores the env for projects
# This rolls back the overrides made by the env of project_awesome
$ cd ..
# Sherpa unloads the env for projects and restores the global env
# This rolls back the overrides made by the env of projects

Aliases and functions in the env file taking precedence

Declaring a function in the env file with the same name as an existing alias will override the alias automatically. No need to call unalias.
The same applies to declaring aliases in the env file with the same name as existing functions.

Running a script when leaving a directory

It is not supported currently. Feel free to open a feature request.
Alternatively, you can use: https://github.com/hyperupcall/autoenv

Configuration

Set the following environment variable anywhere to instruct Sherpa on how to operate.

export SHERPA_ENV_FILENAME='.env' # Default: .envrc
# To support unloading non-exported variables and dynamically created Shell entities
export SHERPA_ENABLE_DYNAMIC_ENV_FILE_PARSING=true

Settings

Log level

It affects only the current and new terminal sessions.

$ sherpa talk more   # - Decrease the log level | Alias: -
$ sherpa talk less   # - Increase the log level | Alias: +
$ sherpa debug       # - Debug level            | Alias: dd
$ sherpa shh         # - Silence
$ sherpa log         # - Open the log options menu | Alias: talk
$ sherpa log [LEVEL] # - Set a specific log level  | Levels: debug, info, warn, error, silent | Alias: talk

Disable/enable Sherpa

It affects only the current and new terminal sessions.

$ sherpa off # aliases: sleep, disable
Sherpa: All envs are unloaded. Sherpa goes to sleep.
$ sherpa on # aliases: work, enable
Sherpa: Env is loaded. Sherpa is ready for action.

Cookbook

Run RSpec in a container or else

# Run RSpec in the `project-awesome-api` Docker container

# ~/projects/project_awesome_api/.envrc
alias de='docker exec -it project-awesome-api'
alias rs='de rspec'
# Run RSpec on the host machine

# ~/projects/project_for_mortals/.envrc
alias rs='bin/rspec'

With this config RSpec will run depending on in which directory you cd into.

Run the tests the same way in different projects

# ~/projects/project_ruby_with_docker/.envrc
alias t='docker exec -it project-awesome-api rspec'

# ~/projects/project_elixir/.envrc
alias t='mix test'

# ~/projects/project_js_with_jest/.envrc
alias t='yarn test'

Rails console in production 🤫

# ~/projects/project_with_heroku/.envrc
alias rc_prod='heroku run rails c -a APP_NAME'

# ~/projects/project_with_aws/.envrc
alias rc_prod='ssh -i /path/key-pair-name.pem user@hostname "/var/app/current/bin/rails console"'

Start your dev environment

# ~/projects/project_with_docker/.envrc
alias up='docker-compose up -d'
alias upb='docker-compose up --build -d'
alias down='docker-compose down'

# ~/projects/project_basic/.envrc
alias up='bin/rails s'

Troubleshooting

$ sherpa diagnose
$ sherpa status

Local development

Testing

All *_test.sh files are run recursively from the tests directory.

# Run all the tests for all the supported shells
$ make test

# Run a single test for all the supported shells
$ make test tests/features/edit_test.sh

# Run all the tests from a folder for all the supported shells
$ make test tests/features

# Run all the tests for Zsh
$ make test_zs

# Run a single test for Zsh
$ make test_zs tests/features/edit_test.sh

# Run all the tests from a folder for Zsh
$ make test_zs tests/features

# Run all the tests for Bash
$ make test_bash

# Run a single test for Bash
$ make test_bash tests/features/edit_test.sh

# Run all the tests from a folder for Bash
$ make test_bash tests/features

# Run all the tests for all the supported shells in Ubuntu
$ make test_all_in_ubuntu

# Run a single test for all the supported shells in Ubuntu
$ make test_all_in_ubuntu tests/features/edit_test.sh

# Test the performance for all the supported shells
# It is not a real test, it is more like a benchmark
$ make test_performance

Linting

$ make lint

Credits

The core functionality (var, func and alias stashing) of this project was inspired by Varstash.

Special thanks to its author:

About

Load and unload custom variables, functions, and aliases as you cd through directories in your terminal.

Topics

Resources

License

Stars

Watchers

Forks

Languages