Repository navigation
devbox run hooks for pre, post, and command wrapping #2862
Description
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 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 input
-
command_wrapper: Simple string wrapper for the entire command- Executes:
rtk exec -- <original command> - Use case: Simple instrumentation wrappers
- Executes:
-
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 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
shellnamespace - 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, notdevbox 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>.programwrapping - 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
Activity
mikeland73 commentedon Sep 28, 2026
Triage: looks hard, p4
devbox runhas no pre, post or wrapper hook. Scripts and commands go throughDevbox.RunScript(internal/devbox/devbox.go:273), and nothing there intercepts them.command_wrapper, a prefix argv applied inRunScript, which is easy to implement. The rest of the pre/post capability model is the part that looks hard to maintain. Workarounds for now are a wrapper script defined as a devbox script, orBASH_ENV, as you noted.Generated by Claude Code
levonk commentedon Sep 30, 2026
@mikeland73 Would you like me to submit a issue and PR just for command wrapper?
mikeland73 commentedon Sep 30, 2026
@levonk hold off for now. I'm mostly going through bugs but don't have bandwidth to address new features.
This feature is one that we've always wanted so really appreciate the contribution. I want to spend some time making sure the schema makes sense and is extensible (e.g. what if we want to add more hooks in the future, not just run hooks).
Also, orthogonally, I want to get rid of "shell" field in devbox.json and just flatten it. There's a PR for that, but I haven't had the time to test and merge it.
levonk commentedon Oct 1, 2026
We really appreciate all the work. Thank you!