vterm exposes a vterm-environment custom variable — a list of "VAR=VALUE" strings prepended to process-environment when spawning the shell process. It also honours dir-locals.el, so per-project overrides just work:
;; globally
(setq vterm-environment '("CC=clang" "CXX=clang++"))
;; or in a project's .dir-locals.el
((nil . ((vterm-environment . ("CC=clang" "CXX=clang++")))))
Ghostel has no equivalent. The extra-env argument to ghostel--spawn-pty is assembled entirely internally and is not exposed to users.
Motivating case
Emacs built with native compilation (libgccjit) sets CC=/path/to/gcc-NN and LIBRARY_PATH=... via LSEnvironment in Info.plist so that libgccjit can find a compatible compiler at runtime. These entries are injected by macOS into the Emacs process environment at launch, before any shell runs, and are then inherited by every subprocess — including shells spawned by Ghostel.
This causes CMake to pick up GCC as the C compiler while falling back to the system c++ (Clang) for C++, producing a mismatched toolchain. The fix is straightforward — prepend CC=clang CXX=clang++ (or unset both) for the shell process — but there is currently no way to do this without patching Ghostel or advising its internals.
Proposed implementation
Add a ghostel-environment defcustom (list of strings, same type as vterm-environment) and splice it into ghostel--spawn-pty alongside the existing extra-env:
(defcustom ghostel-environment nil
"List of extra environment variables for ghostel shell processes.
Each element should be a string of the form \"VAR=VALUE\". To unset
a variable inherited from Emacs, include just \"VAR\" with no value.
This variable is consulted after `hack-dir-local-variables', so it
can be set per-project via `.dir-locals.el'."
:type '(repeat string)
:group 'ghostel)
In ghostel-mode (where hack-dir-local-variables is already called), pick up the local binding:
(let ((ghostel-env (assq 'ghostel-environment dir-local-variables-alist)))
(when ghostel-env
(make-local-variable 'ghostel-environment)
(setq ghostel-environment (cdr ghostel-env))))
And in ghostel--spawn-pty, prepend it:
(process-environment
(append
ghostel-environment
(cons "INSIDE_EMACS=ghostel" (ghostel--terminal-env))
extra-env
process-environment))
The ordering (user vars first) mirrors vterm and ensures user entries take precedence over anything Ghostel injects.
vterm exposes a
vterm-environmentcustom variable — a list of"VAR=VALUE"strings prepended toprocess-environmentwhen spawning the shell process. It also honoursdir-locals.el, so per-project overrides just work:Ghostel has no equivalent. The
extra-envargument toghostel--spawn-ptyis assembled entirely internally and is not exposed to users.Motivating case
Emacs built with native compilation (
libgccjit) setsCC=/path/to/gcc-NNandLIBRARY_PATH=...viaLSEnvironmentinInfo.plistso thatlibgccjitcan find a compatible compiler at runtime. These entries are injected by macOS into the Emacs process environment at launch, before any shell runs, and are then inherited by every subprocess — including shells spawned by Ghostel.This causes CMake to pick up GCC as the C compiler while falling back to the system
c++(Clang) for C++, producing a mismatched toolchain. The fix is straightforward — prependCC=clang CXX=clang++(or unset both) for the shell process — but there is currently no way to do this without patching Ghostel or advising its internals.Proposed implementation
Add a
ghostel-environmentdefcustom (list of strings, same type asvterm-environment) and splice it intoghostel--spawn-ptyalongside the existingextra-env:In
ghostel-mode(wherehack-dir-local-variablesis already called), pick up the local binding:And in
ghostel--spawn-pty, prepend it:The ordering (user vars first) mirrors vterm and ensures user entries take precedence over anything Ghostel injects.