CLI tool
purcell/exec-path-from-shell avatar
purcell/exec-path-from-shell

exec-path-from-shell: syncing Emacs with your login shell

Make Emacs use the $PATH set up by the user's shell

1,575 stars84 forksEmacs LispNOASSERTION

At a glance

What is it?
exec-path-from-shell is an Emacs Lisp library that copies PATH, MANPATH and selected environment variables from a user's shell into Emacs. It is useful for GUI and daemon sessions whose inherited environment differs from the shell, but startup configuration and repeated shell launches affect its cost.
Who is it for?
Adopt exec-path-from-shell if Emacs is launched with an incomplete environment and you can configure a supported shell to produce the required values efficiently. Do not adopt it if every non-exported shell variable must be visible or if starting a shell during Emacs initialization is unacceptable.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 126 days ago.
What is it written in?
Mainly Emacs Lisp, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why Emacs loses PATH in GUI and daemon sessions

exec-path-from-shell addresses a specific mismatch between terminal commands and commands launched by Emacs. A terminal typically inherits or constructs an environment through the user's shell startup files, while a GUI Emacs process on OS X or Linux may begin with a minimal set of variables. An Emacs daemon started by `systemd` or `launchd` can have the same problem. The result is familiar: an executable is available in the shell but Emacs cannot find it.

The library is aimed at Emacs users who depend on environment-defined command locations, especially executables under version managers, language toolchains, local software trees and platform-specific directories. Its initial environment synchronization sets `$MANPATH`, `$PATH` and Emacs's `exec-path`. Other variables can be requested through `exec-path-from-shell-variables` or copied individually with `exec-path-from-shell-copy-env`.

This is not a general shell evaluator. The README warns that variables which were never exported may not be visible. A shell-local variable such as a path held only in a non-exported variable therefore does not automatically qualify. The integration boundary is the exported shell environment.

The shell-to-Emacs environment data flow

The documented mechanism has two stages. First, `exec-path-from-shell` asks the user's shell to print selected environment variables. Second, it copies the returned values into the environment held by Emacs. In its standard initialization path, it derives `$MANPATH`, `$PATH` and `exec-path` from that shell environment.

The supported shells are `zsh`, `bash`, `tcsh`, `fish` and `nu`. This is meaningful for users whose shell startup behavior differs substantially from Bash. For PowerShell or `pwsh`, the README points to the separate `exec-path-from-powershell` package, which can help share an Emacs configuration with those shells.

The shell run by this package inherits Emacs's existing environment. That detail controls whether shell configuration behaves predictably. Startup files that append to an inherited value, such as adding a directory to `$PATH`, can retain a default path that Emacs was supposed to replace. Exact assignments reduce that dependency. The library therefore relies on the shell producing its intended exported environment, not merely on replacing paths inside Emacs afterward.

Installing exec-path-from-shell through MELPA

The documented package installation path uses Emacs's package interface after package support has been initialized. Run the following interactive command and accept the package name when prompted:

elisp
M-x package-install RET exec-path-from-shell RET

The README also lists MELPA, stable MELPA and NonGNU ELPA badges, so packaged distribution is the main documented route. Developers who already work from a checkout may instead clone the repository, then install `exec-path-from-shell.el` through `M-x package-install-file`. The repository does not provide GitHub releases, so the README's `[download]` link points to its tags page rather than to a documented release artifact.

Add the library to `init.el` after calling `package-initialize`. The README calls this placement out because package loading must occur first. If MELPA is not already configured in the Emacs installation, the README does not include a complete archive configuration tutorial, although the repository `Makefile` identifies `https://melpa.org/packages/` as an archive URL.

Initializing a GUI Emacs session from zsh or bash

The standard GUI configuration limits initialization to the window systems associated with OS X and Linux in the README. Add this after package initialization:

elisp
(when (memq window-system '(mac ns x pgtk))
  (exec-path-from-shell-initialize))

When the condition matches, Emacs should obtain `$MANPATH`, `$PATH` and `exec-path` from the configured shell. Outside those GUI window systems, the snippet does not invoke initialization automatically.

A daemon needs a separate trigger because its launch path differs from the GUI example. The README gives this configuration for a daemon session:

elisp
(when (daemonp)
  (exec-path-from-shell-initialize))

If both cases need support in one configuration, the two snippets can coexist, although the README presents them as alternative situations rather than documenting a combined recipe. The first thing to check after installation is whether subprocesses started by Emacs can locate the same tools that work in the terminal.

Copying SSH, locale and other selected variables

The default synchronization does not automatically cover every variable an Emacs setup may need. Add variables to `exec-path-from-shell-variables` before initialization so that one shell invocation can collect them. The README's example adds SSH agent, locale and Nix-related values:

elisp
(require 'exec-path-from-shell)
(dolist (var '("SSH_AUTH_SOCK" "SSH_AGENT_PID" "GPG_AGENT_INFO" "LANG" "LC_CTYPE" "NIX_SSL_CERT_FILE" "NIX_PATH"))
  (add-to-list 'exec-path-from-shell-variables var))

After adding them, call `exec-path-from-shell-initialize`. A single variable can also be requested directly:

elisp
(exec-path-from-shell-copy-env "PYTHONPATH")

The README says that `exec-path-from-shell-copy-env` can also be called interactively. Direct calls are convenient for occasional imports, but each invocation starts a shell. For routine startup, collecting a complete variable list in one initialization call is the documented approach. This distinction matters when shell startup is slow or when Emacs creates several frames through different launch paths.

Shell startup time and the 750ms warning

Startup cost is the main operational constraint described by the README. By default, `exec-path-from-shell` starts an interactive, login shell so that startup files are more likely to load. Interactive shells can enable output, prompts and features intended for direct human use. The README warns that this frequently pushes startup beyond 750ms.

Environment definitions should live where non-interactive shells will load them. The documented examples are `~/.profile` or `~/.bash_profile` for Bash, and `~/.zshenv` for zsh, rather than `~/.bashrc` or `~/.zshrc`. Once those files provide the required exported values, `exec-path-from-shell-arguments` can often be changed to `nil`. The README does not print a complete shell-startup benchmark, so exact latency depends on the user's files and shell.

Emacs prints a warning when evaluation exceeds `exec-path-from-shell-warn-duration-millis`, which is 500ms by default. For diagnostics, set `exec-path-from-shell-debug` before running package functions. According to the README, detailed logging then appears in `*Messages*`, including the shell command line and its output. This gives a concrete first troubleshooting step without changing the selected environment variables.

Limits, licensing and the maintenance record

Several boundaries are explicit. Non-exported shell variables may remain invisible. Each call to `exec-path-from-shell-copy-env` starts a shell, so repeated imports are inefficient. The supported-shell list excludes PowerShell, and the package relies on startup files producing the values that Emacs needs. If those files alter an inherited `$PATH`, Emacs may pass an unwanted base path into the shell.

The repository is not archived, and its last push was on 2026-06-19. That date supports describing recent repository activity, but the project has no GitHub releases. The available documentation therefore gives users no release-based upgrade schedule through that channel.

The repository identifies its license as a custom license that GitHub cannot classify. `LICENSE.md` is the authoritative project file for its exact terms. Because this review does not interpret that text as legal advice, users should check the file for obligations relevant to modification, redistribution or organizational use before adoption. The single-file implementation and package-based installation keep the visible component small, while shell configuration remains the main upgrade-sensitive part of an installation.

Editorial conclusion

Adopt exec-path-from-shell if Emacs is launched with an incomplete environment and you can configure a supported shell to produce the required values efficiently. Do not adopt it if every non-exported shell variable must be visible or if starting a shell during Emacs initialization is unacceptable. Verify shell startup files, `exec-path-from-shell-arguments`, the selected variables and timing before changing a working Emacs setup.

Frequently asked questions

How do I install exec-path-from-shell in Emacs?

Use `M-x package-install`, enter `exec-path-from-shell`, and initialize it from `init.el` after calling `package-initialize`. The README also permits installing `exec-path-from-shell.el` through `M-x package-install-file` after downloading or cloning the source.

Which shells does exec-path-from-shell support?

The documented shells are `zsh`, `bash`, `tcsh`, `fish` and `nu`. PowerShell and `pwsh` are not in that list; the README directs users to the separate `exec-path-from-powershell` package.

Why does exec-path-from-shell warn about startup time?

It warns when evaluation exceeds `exec-path-from-shell-warn-duration-millis`, set to 500ms by default. The README explains that interactive login-shell startup can be slow and recommends placing environment variables in startup files loaded by non-interactive shells, then adjusting `exec-path-from-shell-arguments`, often to `nil`.

Official sources

  1. Issues
  2. purcell/exec-path-from-shell on GitHub
  3. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/purcell-exec-path-from-shell.svg)](https://hysenlabs.com/projects/purcell-exec-path-from-shell)

Was this useful?