Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions internal/devbox/devbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,18 @@ func (d *Devbox) EnvExports(ctx context.Context, opts devopt.EnvExportsOpts) (st
return "", err
}

// When we also run the init hooks we are fully entering the Devbox
// environment (this is what the direnv integration does via
// `devbox shellenv --init-hook`), so mark the shell as Devbox-enabled.
// This mirrors Shell() and RunScript(), and matches the documented
// behavior that DEVBOX_SHELL_ENABLED is set whenever the environment is
// loaded. We intentionally gate this on RunHooks so that the global
// integration (`devbox global shellenv`, which does not run init hooks)
// does not set it in every shell and break shell-inception detection.
if opts.RunHooks {
envs[envir.DevboxShellEnabled] = "1"
}

// Use the appropriate export format based on shell type
var envStr string
if opts.ShellFormat == devopt.ShellFormatNushell {
Expand Down
13 changes: 13 additions & 0 deletions testscripts/shell/shellenv_init_hook.test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
exec devbox init

# When run with --init-hook (as the direnv integration does via
# `devbox shellenv --init-hook`), we are fully entering the Devbox
# environment, so DEVBOX_SHELL_ENABLED must be exported. See issue #2746.
exec devbox shellenv --init-hook
stdout 'export DEVBOX_SHELL_ENABLED="1";'

# Plain shellenv (used by the global integration `devbox global shellenv`,
# which runs in every shell) must NOT set DEVBOX_SHELL_ENABLED, otherwise
# shell-inception detection would break in every shell.
exec devbox shellenv
! stdout 'DEVBOX_SHELL_ENABLED'
Loading