fix(integrate): run init_hook when reopening an editor in the Devbox environment#2874
fix(integrate): run init_hook when reopening an editor in the Devbox environment#2874mikeland73 wants to merge 3 commits into
Conversation
`devbox integrate vscode` (the VSCode/Cursor "Reopen in Devbox" action) launched the editor with the computed Devbox environment but never ran the project's init hook. It used Devbox.EnvVars, which deliberately excludes hooks. As a result, environment variables exported by init_hook (and any other side effects) were missing from the reopened environment, even though they are present in a normal `devbox shell`. Add Devbox.EnvVarsWithInitHook, which sources the init hook in a subshell and captures the resulting environment (NUL-separated so multiline values survive, with the hook's stdout redirected to stderr so it can't corrupt the dump). If the hook errors, it falls back to the hook-less environment so the integration keeps working. The integrate command now uses this method. Fixes #2703.
- Use fileutil.Exists instead of os.Stat to detect a missing hooks file, avoiding the nilerr lint error from returning nil after a non-nil error. - Use t.Context() instead of context.Background() in tests (usetesting).
There was a problem hiding this comment.
Pull request overview
This PR fixes devbox integrate vscode so the VSCode/Cursor “Reopen in Devbox” flow captures environment variables and side effects from a project’s init_hook, matching what users get in a normal devbox shell.
Changes:
- Added
Devbox.EnvVarsWithInitHookto compute env vars by sourcing the generated hooks file in a subshell and capturing the resulting environment. - Added unit tests covering NUL-separated env parsing and init hook capture behavior (including preventing hook stdout from corrupting the captured env).
- Updated
integrate vscodeto useEnvVarsWithInitHookinstead ofEnvVars.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| internal/devbox/inithookenv.go | Implements env capture that includes init hook effects by sourcing hooks in a subshell and parsing captured env output. |
| internal/devbox/inithookenv_test.go | Adds unit tests for NUL-env parsing and init-hook-based env capture behavior. |
| internal/boxcli/integrate.go | Switches VSCode integration to use the new env computation that includes init hook effects. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address review feedback on captureEnvWithInitHook: - Pass the hooks path as a positional parameter ($1) to `sh -c` instead of interpolating it into the script, so paths containing spaces, quotes, $() or backticks can't alter shell parsing. - Dump the environment with awk's POSIX ENVIRON instead of `env -0`. macOS' default /usr/bin/env does not support `-0`, which would have made the hook capture silently fall back to the hook-less env on macOS. awk is portable across Linux and macOS.
|
Heads up on CI: the one red check — Evidence it's a flake, not a regression:
I don't have permission to re-run failed jobs (API returns 403). Could a maintainer re-run that job? It should go green on retry. Happy to push a no-op commit to re-trigger CI instead if you'd prefer. Generated by Claude Code |
Summary
Fixes #2703.
devbox integrate vscodepowers the VSCode/Cursor "Reopen in Devbox" action. It computes the Devbox environment and relaunches the editor with it — but it usedDevbox.EnvVars, which deliberately excludes the init hook:So any environment variables exported by a project's
init_hook(and any other init-hook side effects) were missing from the reopened editor, even though they are present in a normaldevbox shell. Editors like Cursor that open their own terminals — and don't get thedevbox shellinjection — were left without those variables.Fix
Add
Devbox.EnvVarsWithInitHook, which sources the init hook in a subshell and captures the resulting environment, then havedevbox integrate vscodeuse it instead ofEnvVars.Implementation details:
. "<hooks>" 1>&2) so the hook's own output can never corrupt the captured environment (the integrate command speaks an IPC protocol to the editor over a separate fd, so this is important).env -0) so values containing newlines survive intact.shellgen.WriteScriptsToFiles, and sourced the same wayEnvExports/direnv already source it — so this matches existing behavior of running hooks outside an interactive shell.How was it tested?
go build ./internal/...andgo vet ./internal/devbox/ ./internal/boxcli/pass.internal/devbox/inithookenv_test.go:TestParseNulEnv— parsing ofenv -0output, including a value with an embedded newline and an empty value.TestCaptureEnvWithInitHook— a hook that sets a new var, overrides an existing one, and prints to stdout; asserts the new/overridden vars are captured and the hook's stdout does not leak into the env.TestCaptureEnvWithInitHook_NoHooksFile— returns the base env unchanged when there is no hooks file.cc @tm-michael (issue reporter) — thanks for the clear repro.
🤖 Generated with Claude Code
https://claude.ai/code/session_01DYWzKQqM51H27NT2ARCrYy
Generated by Claude Code