devenv integration
Jotain ships a native integration with devenv, the Nix-based developer environment tool. The library lives inlisp/devenv.el (standalone and reusable — no Jotain dependencies) and
is wired in by init-devenv.el. Everything is driven through the
devenv CLI and degrades to a clean error when the binary is not on
PATH. devenv 2.1+ is recommended; every invocation sets AI_AGENT=1
so devenv’s TUI stays out of the machine-readable output.
Entry point: C-c v
C-c v (or M-x devenv) opens a transient covering the whole surface:
The
-c (--clean) and -r (--refresh-eval-cache) infixes apply to
devenv-test and devenv-build.
Long-running commands (test, build, tasks, update, gc) run in
compilation buffers with Nix trace matching, so M-g M-n jumps to the
file.nix:LINE:COL locations in evaluation errors.
Process dashboard
devenv-processes opens a tabulated view of the devenv process
manager. Keys: s start, k stop, r restart, l/RET logs, u
up, d down, g refresh. Data comes from devenv processes list
(JSON when available, plain table on older devenv), fetched
asynchronously so the UI never blocks.
Environment loading and reload
Environment loading stays with envrc + direnv (seeinit-prog):
.envrc says use devenv, so every project buffer already carries the
devenv shell environment buffer-locally — eglot servers, apheleia
formatters, M-x compile, and the ghostel terminal all see
devenv-provided tools with no extra configuration.
After changing devenv.nix, run devenv-reload (C-c v r). It
invalidates the library’s caches, refreshes the environment through
envrc-reload-all, and — because eglot snapshots the environment when
a server starts — offers to eglot-reconnect every server serving the
project so language servers pick up new PATH entries.
For devenv projects without direnv, devenv-env-global-mode is an
optional native loader: it fetches devenv print-dev-env --json
asynchronously and applies it buffer-locally, envrc-style. Its
predicate skips any project with a .envrc, so it can never
double-manage a buffer envrc owns. While a fetch is in flight,
eglot-ensure is deferred and replayed once the environment lands, so
language servers never start with the wrong PATH.
Auto-activation trust (devenv allow / revoke)
devenv 2.1+ gates shell auto-activation behind a per-project trust
database (~/.local/share/devenv/allowed), managed with devenv allow and devenv revoke. The integration honours the same
contract: the native loader (devenv-env-global-mode) consults the
internal devenv hook-should-activate check and never evaluates an
untrusted devenv.nix automatically — exactly like the zsh/fish/nu
shell hooks. devenv-allow (C-c v a) trusts the project and
immediately activates the loader in its buffers; devenv-revoke
(C-c v x) untrusts it and drops the native environment. On devenv
versions without the trust model (< 2.1) the loader behaves as
before. Note that the direnv/envrc path has its own consent gate
(envrc-allow → direnv allow), independent of devenv’s database.
Mode-line status
devenv-modeline-mode (global, enabled by init-devenv at startup)
adds a status segment to the mode line for buffers inside a devenv
project:
devenv[on]— the buffer’s environment carries the devenv shell (loaded by envrc/direnv or the native loader; detected viaDEVENV_PROFILE).devenv[off]— devenv project, environment not loaded.devenv[!]— auto-activation trust denied; rundevenv-allow.
mouse-1 on the
segment opens the devenv transient. The redisplay path is
subprocess-free: trust is probed once per project in the background
from find-file-hook and cached.
LSP for devenv.nix
devenv 2.0+ shipsdevenv lsp, a bundled nixd preconfigured with the
project’s devenv module options (completion, hover docs for
devenv.nix options). init-devenv routes devenv.nix and
devenv.local.nix buffers to it while nil keeps serving every other
Nix file — the routing entry delegates non-devenv buffers to whatever
contact was registered before it.
MCP server for the AI stack
devenv 2.0+ shipsdevenv mcp, a stdio MCP server exposing nixpkgs
package search, devenv option search, and process control
(list/status/logs/start/stop/restart). devenv-mcp-setup (C-c v M)
registers it with mcp.el
under a per-project name (devenv-<project>); start it from
M-x mcp-hub and run M-x gptel-mcp-connect to hand its tools to
gptel. devenv-mcp-remove unregisters it.
Customization
Thedevenv customization group covers the executable name
(devenv-executable), the quiet-mode environment
(devenv-extra-env), global CLI flags (devenv-global-arguments),
cache TTL and command timeout, detached up
(devenv-up-detached), variables the native loader never applies
(devenv-env-ignored-variables), and the dashboard’s log line count
(devenv-processes-log-lines).