Repository navigation
Conversation
Projects that provide their toolchain through direnv (Nix dev shells, devenv, mise) only worked in integrated terminals: agents never go through a shell, so they ran without the project's tools. Provider sessions now load the `.envrc` governing their workspace, as a shell with the direnv hook would, for every provider. Trust stays with direnv: only `.envrc` files approved with `direnv allow` are loaded, and a blocked or failing one surfaces as a thread warning while the agent starts without it. Before each message on a reused session, the server runs direnv's own staleness check against the environment the session started with. It is cheap when nothing changed, and when the user allowed or edited the `.envrc` or a watched file such as `flake.lock` changed, the session resumes with the new environment instead of requiring a new thread. Concurrent loads of one checkout share a single evaluation, since a first `nix develop` can take minutes. A blocked `.envrc` warning offers "Allow .envrc" on web and mobile, backed by a `projectEnvironment.allowDirenv` RPC that resolves the path from the thread. The behavior is on by default and can be turned off per environment or project with "Load direnv environment".
Testing the draft in a real client showed two problems. The timeline folded a lone warning into a collapsed work group on web and mobile, which hid its "Allow .envrc" button behind a click; warnings that offer an action now stay on their own row, like errors and answered questions do. Sessions also restart for reasons unrelated to the environment (an interrupted turn, a Claude model selection), and each restart re-published the same blocked-.envrc warning. Session start now skips a failure identical to the one the thread already shows, as the per-message check did.
…emounts In a real client the button read "Allowed" directly above the agent's earlier "NOT SET", which looked like a failure, and it reverted to "Allow .envrc" whenever the virtualized timeline remounted the row. The label now says the environment applies to the next message, and the outcome is kept per warning so it survives remounts on web and mobile.
otavio
force-pushed
the
t3code/support-direnv-agent-environment
branch
from
September 26, 2026 04:07
060891d to
1c37efe
Compare
1 of 4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What Changed
Provider sessions now load the direnv environment (
.envrc) of their workspace, the way a shell with the direnv hook does. This applies to every provider: Codex, Claude, Cursor, Grok, OpenCode and Antigravity..envrcfiles approved withdirenv alloware loaded. A blocked, failing or timed-out one shows as a thread warning, and the agent starts without it..envrc, or a watched file such asflake.lockchanged, the session restarts from its saved state and picks up the new environment, so no new thread is needed.nix developcan take minutes..envrcwarning has this button on web and mobile. It calls a newprojectEnvironment.allowDirenvRPC with theorchestration:operatescope. The server resolves the.envrcfrom the thread, so a client cannot allow an arbitrary path.CODEX_HOMEorCLAUDE_CONFIG_DIR, win over the.envrc.docs/user/project-settings.md.Why
Projects that provide their toolchain through direnv (Nix dev shells, devenv, mise) only worked in integrated terminals. Agents never run through a shell, so they started without the project's tools, compilers and pinned runtimes.
UI Changes
A blocked
.envrcwarning in the thread timeline gets an Allow .envrc button. After you click it, the button reads "Allowed · applies to your next message". Dev-server run against a demo project:What the screenshot shows:
NOT SET: the.envrcwas explicitly denied, which the server honours silently..envrcwas edited, so direnv no longer trusts it. The per-message check picked this up and posted the blocked warning with the button.loaded from .envrc.Warnings with an action stay on their own row instead of folding into a collapsed work group (web and mobile), and the button keeps its state when the timeline remounts the row.
This PR also adds a "Load direnv environment" toggle in Settings → General (web) and Agent behavior (mobile). Screenshots of the toggle and of mobile are still to come.
Checklist
Verification
server.test.tsWebSocket suite).direnvbinary: blocked, then allow, then load, then an unchanged check. Editing the.envrcblocks it again, and after a new allow the check detects the change and loads the new values.Not included
There is no "Loading project environment…" status while a slow evaluation runs; the thread shows the generic working timer. Adding that needs a progress field or activity that nothing carries today, so it is left for a separate PR.
Done with Claude Opus 5.5 in Claude Code (via T3 Code).