# direnv a workspace's `.envrc` reaches the model's `run()` jobs the way direnv loads it into the person's shell, and direnv's own allow list decides: a file they allowed loads, a blocked or denied one does not. albedo keeps no state of its own about it. ## in the kernel `priv/python/albedo_direnv.py` runs before each `run()` (`run.py`) and brings `os.environ` up to date with `direnv export json`, as direnv's shell hook does before each prompt. the kernel is the shell: its folder is `os.getcwd()`, so `os.chdir` into another project loads that one's `.envrc`, and leaving it unloads it. jobs inherit `os.environ`, so everything the kernel starts afterwards (pipes, `files` searches) sees the same environment. it runs wherever the kernel does, remote hosts included. - direnv is looked up once per kernel on its PATH; without it nothing runs. - with no `.envrc` in the folder or above it, and nothing this kernel loaded to take back, it costs a few `stat`s. an environment the daemon inherited from the shell that started it is left alone. - an unchanged file answers nothing in a few milliseconds; an edited one (or a file it watches) reloads by itself. a first evaluation (`use flake` building a dev shell) may take up to 600 s and holds that `run()`. - what direnv says (`direnv: loading …`, `direnv: export +FOO ~PATH`, `direnv: unloading`) prints into the cell, so the model sees why its environment changed. direnv's blocked message is reworded so it does not tell the model to run `direnv allow`: allowing is the person's call. If a previously loaded file changes and is blocked, the kernel unloads the old environment before starting the job without it; a blocked reload never keeps stale values from the old file. direnv watches file mtimes at one-second resolution, so an `.envrc` rewritten within the same second as its last load is not noticed until it changes again. - it never raises: a failure starts the job without the environment. ## in the tui when a chat opens, and after `/cd`, the tui runs `direnv status --json` in the workspace (`chat_direnv.go`), only when the daemon and the workspace are both on this machine: `direnv allow` is the person's own act there. for a file direnv blocks (new, or changed since it was allowed) it shows a question above the composer. while the composer is empty the question owns the letter keys: `y` runs `direnv allow ` and the next `run()` loads it, `n` (or `esc`) puts it away until the chat opens again, as direnv repeats its blocked message at the next `cd`. every other letter is held back, so the first letter of a prompt typed without reading never answers it; a draft already in the composer keeps typing normally. denied files never ask.