Skip to content

Repository files navigation

direnv Everywhere

direnv for JetBrains IDEs.

Your .envrc environment, everywhere the IDE runs something. Run configurations, the build process, Gradle, Maven, External Tools and the terminal — scoped to the project, reloaded automatically, and never leaking your secrets.

Implements IJPL-11588, open since 2023 with 83 votes. direnv-vscode served as the reference for direnv's behaviour.


The problem

You use direnv. Your JDK comes from Nix, your toolchain from Devbox, your credentials from a .env file the shell loads for you. In the terminal, everything works.

Then you open the IDE, and none of it exists. So you either copy variables into every run configuration by hand and keep them in sync forever, or you launch the IDE from a shell where direnv has already run — and then you can only ever have one project open, because that environment is global to the process.

Both workarounds appear, almost word for word, in the comments on IJPL-11588.

What this plugin does

Where Works
Run/Debug configurations — every language yes
Build process (compilation) yes
Gradle sync, Gradle tasks, Maven yes
Terminal yes
External Tools, File Watchers yes
Git hooks — pre-commit and the rest, when you commit from the IDE yes
Processes started by other plugins yes
Indexing and static analysis partly — via SDK suggestion, see Limitations

The environment is resolved per project and working directory, then injected as each process starts. Two projects open side by side keep separate environments. A nested .envrc in a subdirectory gets its own. The IDE's own process environment is never modified — that is what makes the isolation real rather than approximate.

It keeps itself up to date

Change flake.lock, and the environment reloads. Not because the plugin knows anything about Nix, but because direnv reports every file the environment depends on and the plugin watches all of them — .envrc, flake.nix, .env, devbox.json, whatever your setup uses.

Run direnv allow in an ordinary terminal, and the IDE notices within seconds and loads the environment. No button, no restart.

Detection combines file system events with a two-second poll of the watched files. The poll is not redundant: the IDE delivers no events at all for direnv's allow stamps under ~/.local/share/direnv, so approval granted in a terminal would otherwise go unnoticed. direnv itself detects changes the same way, by comparing modification times.

Security is the default, not a setting

An .envrc is arbitrary shell code, so:

  • direnv allow is never invoked automatically — under any setting, ever. Approval is always an explicit action, and the UI offers Open .envrc before Allow, so reading comes first.
  • Untrusted projects never run direnv at all. Opening a repository does not execute its code.
  • Variable values never leave memory. Not into logs, not into run configurations, not into any file under .idea/. The types that carry environment data refuse to render their own values, and a test asserts it with a canary string.

Want to see what was applied? The environment viewer lists variable names and whether each was added, changed or removed. Knowing that PGPASSWORD was set is the useful part; its value is not, and materialising it into a run configuration would put it straight into git.

How it compares

Four other direnv plugins are published on the JetBrains Marketplace. The table is built from their own Marketplace descriptions and, where the source is public, from their code — checked in August 2026 against the versions current then. A dash means the plugin does not offer or document the capability, not that it was tested and failed. Corrections are welcome as issues.

direnv Everywhere better_direnv DirEnv Pro Direnv Direnv Loader
Where the environment lands
Run/Debug configurations every type six languages ¹ every type every type
Terminal
Build process (compilation)
Gradle sync, Maven import run configs only Gradle tasks
External Tools, other plugins' processes
A toolchain from direnv offered as project SDK Java
Scope
Projects side by side keep separate environments
An .envrc below the project root root only by hand ²
Staying current
Reloads on flake.lock, .env, … (DIRENV_WATCHES) discarded ³ .envrc on save
Notices direnv allow run in a terminal
Applies the variables direnv unsets
Security
direnv allow is never run for you guaranteed opt-in auto-allow opt-in auto-allow
Nothing executes in an untrusted project
Values stay out of run configs and .idea/ written in ⁴
Day to day
Nothing to switch on per run configuration a checkbox each ⁵ load by hand a checkbox each ⁵
Current state visible at a glance status bar, banner notifications notifications notifications
Applied variables listed by name with values ⁴
Executable, timeout and extra env configurable hardcoded ⁶ executable only

¹ Java, Go, Node.js, Python, PHP and Ruby. Its description notes that "each run configuration type needs to be added manually", and the source carries one extension class per product — that is the cost this plugin avoids by hooking the platform below the run configuration instead of above it. ² The root .envrc is loaded automatically; any other one is imported through a context-menu action. ³ It deletes DIRENV_WATCHES from the exported environment, so nothing outside .envrc — a flake.lock, a .env, an allow stamp — can trigger a reload. ⁴ By design: values are merged into the Environment Variables field of every run configuration, where they are visible and editable — and saved with the configuration. ⁵ Per run configuration, so a newly created one starts without the environment until you remember. ⁶ It invokes direnv by name, with no setting to point at another binary; its per-configuration settings are the two checkboxes above.

What they do that this plugin does not. better_direnv registers .envrc as a shell file type, so the file itself gets syntax highlighting; here that is left to the Shell Script plugin. It has also been maintained far longer than this one.

Requirements

  • A JetBrains IDE, build 261 (2026.1) or newer — IDEA, PyCharm, GoLand, WebStorm, CLion, RubyMine, PhpStorm, RustRover. Verified against IDEA Community and PyCharm Community.
  • direnv installed and available on PATH.

The 2026.1 floor is a hard requirement rather than a preference: it is the first release whose terminal extension point works correctly across EEL boundaries, and without it the terminal cannot be supported properly.

Limitations

Stated plainly, because a plugin that hides these costs you an afternoon:

  • The environment has to be loaded already. Injection reads what is cached and never starts direnv itself, so a process launched before the first load finishes — or in a project you have not trusted, or whose .envrc is still blocked — starts without it, silently. Opening the project triggers the load, so in practice the cache is warm long before you run anything.
  • Git hooks run only if the IDE is told to run them. The commit options carry a Run Git hooks checkbox; with it off no hook runs at all, and no environment can reach one. That is the IDE's setting rather than this plugin's, but it is the first thing to check when a hook does not see what you expect.
  • Indexing and static analysis do not follow PATH. The IDE resolves toolchains through project SDKs, so a JDK provided by direnv is offered as an SDK rather than adopted silently. That is deliberate: a Nix store path can vanish after garbage collection, and rewriting your project SDK at that moment would break the project with no explanation.
  • Non-local run targets (Docker, SSH, remote interpreters) bypass the mechanism the plugin hooks into.
  • A running Gradle daemon may reuse the previous environment. The plugin deliberately does not stop daemons: the only API is internal, it kills every daemon on the machine including other projects', and the problem is unconfirmed. If you hit it, stop the daemon manually and please open an issue.
  • WSL is implemented against the documented EEL API but has not been verified on real hardware. Reports and fixes are welcome.
  • SDK suggestions currently cover Java. Go, Python and Node.js reuse the same tested resolver and need only their product module.

Building

./gradlew buildPlugin   # plugin ZIP in build/distributions/
./gradlew test          # direnv is NOT required to run the tests
./gradlew runIde        # sandbox IDE with the plugin installed

The build provisions its own JDK 21, so a clean checkout builds without installing anything first.

Contributing

See CONTRIBUTING.md for the module layout, how to add support for another IDE, and the rules a change must not break. Release notes are in CHANGELOG.md.

License

Apache-2.0.

About

direnv support for JetBrains IDEs. Loads your .envrc into run configurations, the build process, Gradle, Maven and the terminal, scoped per project and working directory.

Resources

Contributing

Stars

4 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages