Skip to content

Add direnv support - #5660

Merged
stefanhaller merged 5 commits into
masterfrom
direnv-support
Jun 4, 2026
Merged

Add direnv support#5660
stefanhaller merged 5 commits into
masterfrom
direnv-support

Conversation

@stefanhaller

@stefanhaller stefanhaller commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Supports loading direnv's environment files (.envrc) when switching repos or worktrees, or when entering or exiting submodules.

There's no configuration for this; the functionality is automatically enabled when direnv is installed.

Closes #3653.

stefanhaller and others added 5 commits June 4, 2026 09:05
If we return the error here, we don't switch repos, but the chdir
happened already, so this would be an inconsistent state (a lot of
lazygit's code assumes that the current directory is always the worktree
root). Only log the error; failing to record the current directory is
not the end of the world.

Also, it is very unlikely to happen; RecordCurrentDirectory only writes
to a small file, and if this fails, then either there is filesystem
corruption of the disk is full, and in both cases the user likely has
much bigger problems.
The for-loop here was a verbatim copy of openRecentRepo, so call that instead.
When a user opens a repo from the recent-repos menu or jumps between
worktrees inside lazygit, only the env vars present at process startup
reach subprocesses. That breaks pre-commit hooks and other tools whose
dependencies are pulled in by a per-repo .envrc — users were left with
read-only operations because the env their shell would normally load via
direnv never made it into lazygit's git invocations.

Shell out to `direnv export json` after each chdir and apply the JSON
delta via os.Setenv/Unsetenv. direnv tracks the previous load in its own
DIRENV_DIFF env var, so the delta also unloads vars from the old repo
when entering one without a matching .envrc. If direnv isn't on PATH the
call is a no-op, so users who don't use direnv pay nothing and users who
do need no config to opt in. Any stderr direnv emits (loading messages,
"blocked .envrc" errors, etc.) goes to the command log.

The integration test puts a fake direnv on PATH and asserts that a value
it exports reaches a custom command after switching repos. Wiring this
up needed runner.go to support `{{actualPath}}` placeholders in
ExtraEnvVars, mirroring the existing support for ExtraCmdArgs, so the
test can prepend a fixture-relative directory to PATH.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a user switches into a repo whose .envrc hasn't been approved with
`direnv allow`, the previous behavior was to drop a "blocked" error
popup and leave the user to fix it externally. That meant opening a
terminal, running `direnv allow`, and then either restarting lazygit or
switching repos and back to refresh the env — easy to get wrong, easy
to forget.

When `direnv export json` exits non-zero, follow up with `direnv status
--json` to ask direnv whether the current directory has a not-yet-
allowed .envrc, and if so, get its path. Then show a confirmation popup
with the .envrc contents inline so the user can read what they're
approving. Confirming runs `direnv allow <path>` and re-runs the load
so the new env reaches subprocesses immediately; cancelling leaves the
env unloaded (the same state as before this commit when direnv refused
to load the .envrc).

Using `direnv status --json` instead of parsing the "is blocked"
stderr line means we rely on direnv's structured output rather than
its human-readable error format, which is more stable across versions
and avoids assumptions about output formatting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@stefanhaller
stefanhaller enabled auto-merge June 4, 2026 07:05
@stefanhaller
stefanhaller merged commit 38526c9 into master Jun 4, 2026
23 of 24 checks passed
@stefanhaller
stefanhaller deleted the direnv-support branch June 4, 2026 07:10
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jul 9, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [jesseduffield/lazygit](https://github.com/jesseduffield/lazygit) | minor | `v0.62.2` → `v0.63.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jesseduffield/lazygit (jesseduffield/lazygit)</summary>

### [`v0.63.0`](https://github.com/jesseduffield/lazygit/releases/tag/v0.63.0)

[Compare Source](jesseduffield/lazygit@v0.62.2...v0.63.0)

<!-- Release notes generated using configuration in .github/release.yml at v0.63.0 -->

#### What's Changed

##### Enhancements 🔥

- Add direnv support by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5660](jesseduffield/lazygit#5660)
- Improve cycling through multiple pagers by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5678](jesseduffield/lazygit#5678)
- Detect external repo changes via background polling by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5662](jesseduffield/lazygit#5662)
- Make the side panels configurable by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5702](jesseduffield/lazygit#5702)
- Add a global keybinding for editing the config file by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5728](jesseduffield/lazygit#5728)
- Improve resolving non-textual and submodule merge conflicts by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5735](jesseduffield/lazygit#5735)
- Auto-dismiss the continue-rebase prompt when it becomes stale by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5758](jesseduffield/lazygit#5758)
- Support custom pagers and passphrase prompts on Windows by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5740](jesseduffield/lazygit#5740)
- Make creating worktrees simpler and less error-prone by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5741](jesseduffield/lazygit#5741)
- Improve deleting worktrees and their branches by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5748](jesseduffield/lazygit#5748)
- Allow overriding the platform used for default keybindings by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5671](jesseduffield/lazygit#5671)
- Add `gui.shrinkSidePanelsToContent` option by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5754](jesseduffield/lazygit#5754)
- Show renamed files in the custom patch builder by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5759](jesseduffield/lazygit#5759)

##### Fixes 🔧

- Fix unstaging a submodule with dirty content by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5666](jesseduffield/lazygit#5666)
- Fix coloring of wrapped delta lines by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5711](jesseduffield/lazygit#5711)
- Fix Files Panel artefacts during rebase commands by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5661](jesseduffield/lazygit#5661)
- Keep selected commits stable across refreshes by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5717](jesseduffield/lazygit#5717)
- Fix quoting of shell commands on Windows by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5704](jesseduffield/lazygit#5704)
- Silently consume unrecognized or malformed escape sequences by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5738](jesseduffield/lazygit#5738)
- Don't include common ancestor when picking "both" for a conflict in diff3 style by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5747](jesseduffield/lazygit#5747)

##### Maintenance ⚙️

- Some fixes to our infrastructure by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5705](jesseduffield/lazygit#5705)
- Restructure the `just` recipes for running integration tests by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5720](jesseduffield/lazygit#5720)
- Fix flaky TestNewCmdTaskInstantStop test by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5743](jesseduffield/lazygit#5743)
- Bump golang.org/x/sync from 0.20.0 to 0.21.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5684](jesseduffield/lazygit#5684)
- Bump golang.org/x/sys from 0.45.0 to 0.46.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5685](jesseduffield/lazygit#5685)
- Bump github.com/sahilm/fuzzy from 0.1.2 to 0.1.3 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5706](jesseduffield/lazygit#5706)
- Bump actions/cache from 5 to 6 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5722](jesseduffield/lazygit#5722)
- Bump actions/checkout from 6 to 7 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5723](jesseduffield/lazygit#5723)
- Bump goreleaser/goreleaser-action from 7.2.2 to 7.2.3 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5745](jesseduffield/lazygit#5745)
- Bump golangci/golangci-lint-action from 9.2.0 to 9.3.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5746](jesseduffield/lazygit#5746)
- Bump golang.org/x/net from 0.47.0 to 0.55.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;5752](jesseduffield/lazygit#5752)
- Pin gofumpt version to 0.9.2 by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5753](jesseduffield/lazygit#5753)
- Fix a few flaky tests by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5756](jesseduffield/lazygit#5756)

##### I18n 🌎

- Update translations from Crowdin by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5760](jesseduffield/lazygit#5760)

##### Performance Improvements 📊

- Prevent staging from becoming slower over time by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5712](jesseduffield/lazygit#5712)

**Full Changelog**: <jesseduffield/lazygit@v0.62.2...v0.63.0>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTYuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI1Ni4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWlub3IiXX0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Direnv support in lazygit

1 participant