[FEATURE] GPU device passthrough in sandbox mode
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Sandbox mode blocks GPU access because /dev/dri and /dev/kfd (etc) aren't passed through. This breaks Vulkan, ROCm/HIP, and CUDA workflows when the sandbox is enabled.
Step 1: Configure sandbox for filesystem protection
{
"sandbox": { "enabled": true, "autoAllowBashIfSandboxed": true },
"permissions": { "allow": ["Bash"] }
}
Step 2: Ask Claude to verify GPU access
Check if the GPU is available and run a simple PyTorch test
Step 3: Claude runs diagnostics:
# AMD GPU
rocm-smi --showid
hipconfig --version
# NVIDIA GPU
nvidia-smi
# Vulkan (any GPU)
vulkaninfo --summary
Step 4: Today, all fail - devices don't exist in sandbox:
$ rocm-smi --showid
No AMD GPUs found
$ vulkaninfo --summary
GPU0: llvmpipe (LLVM 20.1.8, 256 bits) # CPU fallback only
deviceType = PHYSICAL_DEVICE_TYPE_CPU
$ ls /dev/dri /dev/kfd
ls: cannot access '/dev/dri': No such file or directory
ls: cannot access '/dev/kfd': No such file or directory
Expected: GPU device nodes passed through, hardware detected.
Proposed Solution
Add sandbox.devices setting, e.g. for AMD:
{
"sandbox": {
"enabled": true,
"devices": ["/dev/dri", "/dev/kfd"]
}
}
Or for NVIDIA:
{
"sandbox": {
"enabled": true,
"devices": ["/dev/dri", "/dev/nvidia0", "/dev/nvidiactl", "/dev/nvidia-uvm"]
}
}
Claude Code's sandbox already uses https://github.com/containers/bubblewrap on Linux. Bwrap natively supports device passthrough via https://www.mankier.com/1/bwrap:
--dev-bind-try SRC DEST Bind mount host path SRC on DEST, allowing device access.
Ignores non-existent SRC (graceful on systems without GPUs).
So the setting above would add to the bwrap invocation:
--dev-bind-try /dev/dri /dev/dri \
--dev-bind-try /dev/kfd /dev/kfd
or
--dev-bind-try /dev/nvidia0 /dev/nvidia0 \
--dev-bind-try /dev/nvidiactl /dev/nvidiactl \
--dev-bind-try /dev/nvidia-uvm /dev/nvidia-uvm
Alternative Solutions
The only way around this I've found is to disable sandboxing, which is unfortunate. I'd love to use sandboxing instead of needing to run things through docker (where I can then do GPU passthrough but with much more pain).
Priority
Critical - Blocking my work
Feature Category
Configuration and settings
Use Case Example
My primary use is developing GPU-accelerated code with Claude Code in sandbox mode. I want to automate kernel authoring, fine-tuning/optimization, and correctness testing as well as run my existing test suites (pytorch CUDA/ROCM, ONNX, vLLM, etc).
There's a few other things we use as well (namely ffmpeg as part of image pipelines), but there's quite a bit of popular GPU-accelerated tools that cannot run properly in sandbox mode which would be generally useful:
| Software | Use Case | Blocked By |
|-----------------------|------------------------------|------------------------|
| PyTorch | ML training/inference | /dev/kfd, /dev/nvidia* |
| TensorFlow | ML training/inference | /dev/kfd, /dev/nvidia* |
| JAX | ML research | /dev/kfd, /dev/nvidia* |
| IREE | ML compiler runtime | /dev/kfd, /dev/dri |
| Blender | 3D rendering (Cycles) | /dev/dri, /dev/nvidia* |
| FFmpeg | Video encoding (VAAPI/NVENC) | /dev/dri, /dev/nvidia* |
| darktable/RawTherapee | Photo processing (OpenCL) | /dev/dri |
Concretely, I want to enable the sandbox and then have Claude be able to run directly or indirectly via scripts/tools commands like:
python3 -c "import torch; print(torch.cuda.is_available())" # NVIDIA
python3 -c "import torch; print(torch.hip.is_available())" # AMD
Additional Context
Prior Art
Flatpak uses identical bwrap flags for GPU-accelerated sandboxed apps:
- https://docs.flatpak.org/en/latest/sandbox-permissions.html grants access to /dev/dri for OpenGL/Vulkan
- Flatpak https://github.com/flatpak/flatpak/issues/3330 including /dev/dri, /dev/nvidia*, /dev/mali when DRI access is requested
- This is standard practice for thousands of sandboxed Linux desktop apps
Common GPU device nodes:
| Device | Purpose |
|-------------------|-------------------------------------|
| /dev/dri/card* | DRM display devices |
| /dev/dri/renderD* | GPU compute/render (Vulkan, OpenGL) |
| /dev/kfd | AMD ROCm/HIP kernel driver |
| /dev/nvidia* | NVIDIA CUDA/driver |
Technical Considerations
- Security: Device access is read/write to GPU hardware only - no filesystem escape. Flatpak considers --device=dri a https://docs.flatpak.org/en/latest/sandbox-permissions.html safe for general use.
- Ordering: bwrap processes args in order. Device binds should come before --dev /dev to avoid shadowing (https://github.com/containers/bubblewrap/issues/248).
- PCI sysfs: Some GPU tools also need read-only access to /sys/bus/pci and /sys/devices/pci* for device enumeration (https://wiki.alpinelinux.org/wiki/Bubblewrap/Examples).
- Graceful degradation: --dev-bind-try (not --dev-bind) ensures systems without GPUs don't error.
References
- https://www.mankier.com/1/bwrap - --dev-bind, --dev-bind-try documentation
- https://docs.flatpak.org/en/latest/sandbox-permissions.html - --device=dri for GPU access
- https://wiki.archlinux.org/title/Bubblewrap/Examples - GPU passthrough patterns
- https://wiki.alpinelinux.org/wiki/Bubblewrap/Examples - mpv GPU example with renderD128
- https://developer.nvidia.com/blog/improving-cuda-initialization-times-using-cgroups-in-certain-scenarios/ - bwrap with NVIDIA devices
Test Cases
These commands should work in sandbox mode with GPU passthrough:
# AMD ROCm/HIP
rocm-smi --showid # List AMD GPUs
rocminfo # ROCm device info
hipconfig --version # HIP configuration
clinfo # OpenCL devices
# NVIDIA CUDA
nvidia-smi # List NVIDIA GPUs
nvcc --version # CUDA compiler
# Vulkan (vendor-agnostic)
vulkaninfo --summary # Should show real GPU, not llvmpipe
vkcube # Vulkan test cube
# OpenGL
glxinfo | grep "OpenGL renderer" # Should show GPU, not llvmpipe
# Simple compute test
python3 -c "import torch; print(torch.cuda.is_available())" # NVIDIA
python3 -c "import torch; print(torch.hip.is_available())" # AMD
7 Comments
I did end up with a workaround, but this would be a really good feature to support natively so trickery is not required.
Hope that helps someone trying to teach claude to do GPU stuff :)
small comment but i also had to
chmod +x ~/.local/bin/bwrap, otherwise the script worked well!This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
still happening
Thanks @benvanik, the script works!
In my case, if there are multiple GPUs, we also need to add them (e.g.,
/dev/nvidia1) to theGPU_DEVICESotherwise pytorch will complain.thanks @benvanik -
For those working on Apple Metal MPS GPUs , I've also been able to find a workaround (Tested with M4 and PyTorch). I've created a skill (and prerequisite shell script ) to make sure that things stay in sandboxed commands while invoking the Metal arguments - hope it helps!
https://github.com/casualic/mac-sandbox-gpu
Confirming this on NVIDIA L40S (8× GPUs, driver 580.126.09, Claude Code 2.1.89).
We wrote a diagnostic script that tests bwrap directly, independent of Claude Code:
bwrap --dev /dev → CUDA unavailable, no /dev/nvidia* visible
bwrap --dev /dev --dev-bind /dev/nvidia0 /dev/nvidia0 --dev-bind /dev/nvidiactl /dev/nvidiactl --dev-bind /dev/nvidia-uvm /dev/nvidia-uvm → CUDA available, full 8-GPU access, tensor allocation works
No cgroup device controller restrictions (cgroup v2)
This confirms the fix is purely adding --dev-bind-try entries. The sandbox.devices config proposed here would unblock GPU-accelerated ML workflows (PyTorch/gReLU training loops) that currently require sandbox.enabled: false.
+1 for --dev-bind-try over --dev-bind for graceful degradation on non-GPU nodes.