What problem are you trying to solve?
I'm trying to wrap every Devbox-executed command with a command wrapper (specifically rtk exec --) for instrumentation, tracing, and policy enforcement without breaking reproducibility.
The core issue is that Devbox currently has no mechanism to intercept or wrap commands executed via devbox run. This makes it impossible to:
- Instrument commands: Add tracing/telemetry to every command execution
- Enforce policies: Validate or block commands before execution
- Sandbox commands: Wrap execution with security/policy tools
- Transform commands: Modify arguments, environment, or I/O dynamically
Devbox's execution model is:
devbox run <script> → spawn non-interactive shell → run command
Non-interactive shells always source $BASH_ENV or .zshenv, but this is a fragile workaround, not a proper solution.
What solution would you like?
I propose adding a comprehensive hook system under the existing shell configuration in devbox.json:
{
"shell": {
"init_hook": [...],
"scripts": { ... },
// NEW: Run hooks for devbox run
"run_hooks": {
"pre_run": [{
"command": "policy-checker --cmd {cmd} --args {args}",
"can_block": true,
"can_modify_args": false,
"can_modify_env": false,
"can_modify_stdin": false
}],
"command_wrapper": ["rtk exec --"],
"post_run": [{
"command": "telemetry-collector --exit {exit} --stdout {stdout}",
"can_modify_exit": true,
"can_modify_stdout": false,
"can_modify_stderr": false
}]
}
}
}
Three hook types:
-
pre_run: Runs before command execution
can_block: Hook can refuse execution (return non-zero)
can_modify_args: Hook can change command arguments
can_modify_env: Hook can change environment variables
can_modify_stdin: Hook can change stdin input
-
command_wrapper: Simple string wrapper for the entire command
- Executes:
rtk exec -- <original command>
- Use case: Simple instrumentation wrappers
-
post_run: Runs after command execution
can_modify_exit: Hook can change the exit code
can_modify_stdout: Hook can change stdout
can_modify_stderr: Hook can change stderr
- Receives: exit code, stdout, stderr as context
Key design principles:
- Explicit capability gates: Each hook declares what it can do (security, clarity, validation)
- Symmetric design: Both pre and post hooks have consistent gating
- Default-deny: Dangerous capabilities are opt-in
- Follows Devbox conventions: Uses existing
shell namespace
- Backward compatible: All hooks are optional
Additional context:
This feature would enable:
- Security tools: Policy enforcement, sandboxing, secret scanning
- Observability: Telemetry, tracing, execution logging
- Development workflow: Input validation, output formatting, conditional execution
- Tool integration: OpenTelemetry, Hermes, policy agents, sandbox wrappers
The implementation would be straightforward (wrap the exec call in the devbox run codepath) and high-value for the ecosystem without breaking reproducibility when properly configured.
Alternatives you've considered
- Devbox shell hooks → Only run for
devbox shell, not devbox run
- Devbox scripts → Requires wrapping each script manually (tedious, error-prone)
- PATH shims → Devbox resolves commands inside the environment, bypassing wrappers
- Aliasing → Aliases don't apply in non-interactive shells
- $BASH_ENV/.zshenv workaround → Fragile, doesn't provide proper control flow or access to execution context
- post_run hooks only → Can't prevent execution or modify inputs
This design matches patterns from other tools:
- Nix flakes:
apps.<name>.program wrapping
- direnv: Hook mechanisms for environment setup
- Bazel: Toolchain wrapping and hooks
- Git: pre-commit/post-commit hooks
- CI/CD systems: before_script/after_script stages
What problem are you trying to solve?
I'm trying to wrap every Devbox-executed command with a command wrapper (specifically
rtk exec --) for instrumentation, tracing, and policy enforcement without breaking reproducibility.The core issue is that Devbox currently has no mechanism to intercept or wrap commands executed via
devbox run. This makes it impossible to:Devbox's execution model is:
Non-interactive shells always source
$BASH_ENVor.zshenv, but this is a fragile workaround, not a proper solution.What solution would you like?
I propose adding a comprehensive hook system under the existing
shellconfiguration indevbox.json:{ "shell": { "init_hook": [...], "scripts": { ... }, // NEW: Run hooks for devbox run "run_hooks": { "pre_run": [{ "command": "policy-checker --cmd {cmd} --args {args}", "can_block": true, "can_modify_args": false, "can_modify_env": false, "can_modify_stdin": false }], "command_wrapper": ["rtk exec --"], "post_run": [{ "command": "telemetry-collector --exit {exit} --stdout {stdout}", "can_modify_exit": true, "can_modify_stdout": false, "can_modify_stderr": false }] } } }Three hook types:
pre_run: Runs before command executioncan_block: Hook can refuse execution (return non-zero)can_modify_args: Hook can change command argumentscan_modify_env: Hook can change environment variablescan_modify_stdin: Hook can change stdin inputcommand_wrapper: Simple string wrapper for the entire commandrtk exec -- <original command>post_run: Runs after command executioncan_modify_exit: Hook can change the exit codecan_modify_stdout: Hook can change stdoutcan_modify_stderr: Hook can change stderrKey design principles:
shellnamespaceAdditional context:
This feature would enable:
The implementation would be straightforward (wrap the exec call in the
devbox runcodepath) and high-value for the ecosystem without breaking reproducibility when properly configured.Alternatives you've considered
devbox shell, notdevbox runThis design matches patterns from other tools:
apps.<name>.programwrapping