The Complete Computing Environment



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.

It supports hooks for all the common shells like bash, zsh, tcsh and fish. This allows project-specific environment variables without cluttering the ~/.profile file.

Because direnv is compiled into a single static executable, it is fast enough to be unnoticeable on each prompt. It is also language-agnostic and can be used to build solutions similar to rbenv, pyenv and phpenv.

It also supports Nix-shell, though looking at the wiki page makes me want to consider using a different tool like nix-direnv:

Those who have installed and are using the Nix package manager often use its command-line tool nix-shell to enter into a Nix shell, which is just a Bash session with environment variables set up for a project. We can configure Direnv to load environment variables from the Nix shell for a project. Nix has support for lots of different programming languages, so once we get Direnv integrated with Nix, we can do all of our language-specific configuration with Nix. Our .envrc can be short and simple.

Anyways it has an Emacs package which works really well and refreshes the process environment when swapping buffers.

(use-package direnv
(provide 'cce/direnv)
{pkgs, ...}:
  programs.direnv.enable = true;
  programs.direnv.nix-direnv.enable = true;
{ ... }: {
  nix.extraOptions = ''
    keep-outputs = true
    keep-derivations = true

With direnv activated, any directory with a shell.nix in it and an .envrc file that says use nix in it can be allowed to spawn development environments:

cat ~/org/arcology-fastapi/.envrc

Direnv arroyo-db integration

One of the issues of doing Literate Programming with Org Babel is that if I work inside of my org-roam directory the direnv stuff won't map to the tangled directory. If I add a ARROYO_DIRENV_DIR file property to a document it will use the directory environment from that directory instead of the org-roam directory:

(with-eval-after-load "arroyo-db"
  (add-to-list 'arroyo-db-keywords "ARROYO_DIRENV_DIR")
  (defun direnv--directory ()
    "Return the relevant directory for the current buffer, or nil."
    (let* ((buffer (or (buffer-base-buffer) (current-buffer)))
           (mode (buffer-local-value 'major-mode buffer))
           (file-name (buffer-file-name buffer))
           (arroyo-maybe (when (and file-name
                                    (equal (file-name-extension file-name) "org"))
                            (arroyo-db-get "ARROYO_DIRENV_DIR" (expand-file-name file-name)))))
            (cond (arroyo-maybe
                   (file-name-directory file-name))
                  ((apply #'direnv--provided-mode-derived-p mode direnv-non-file-modes)