Tools¶
How development tools are made available inside the sandbox.
devsandbox makes development tools available inside the sandbox while maintaining security boundaries.
Inspecting Tools¶
Use the tools command to see which tools are available and how they're configured.
List Available Tools¶
# List tools detected on your system
devsandbox tools list
# Include unavailable tools
devsandbox tools list --all
# JSON output for scripting
devsandbox tools list --json
Example output:
┌───────────────┬───────────┬───────────────────────────────────────────────┐
│ NAME │ STATUS │ DESCRIPTION │
├───────────────┼───────────┼───────────────────────────────────────────────┤
│ claude │ available │ Claude Code AI assistant │
│ copilot │ available │ GitHub Copilot integration │
│ git │ available │ Git configuration (safe mode, no credentials) │
│ go │ available │ Go language environment isolation │
│ mise │ available │ Tool version manager (node, python, go, etc.) │
│ nvim │ available │ Neovim editor configuration │
│ oh-my-posh │ missing │ Oh My Posh prompt with sandbox indicator │
│ oh-my-zsh │ missing │ Oh My Zsh framework with sandbox indicator │
│ opencode │ available │ OpenCode AI assistant │
│ pi │ available │ Pi coding agent AI assistant │
│ portal │ available │ XDG Desktop Portal (notifications) │
│ powerlevel10k │ missing │ Powerlevel10k zsh theme │
│ starship │ available │ Starship prompt with sandbox indicator │
│ tmux │ missing │ Tmux terminal multiplexer with sandbox indicator │
└───────────────┴───────────┴───────────────────────────────────────────────┘
Note: Tools show as "available" if their binary is found or config exists, "missing" otherwise.
Tool Details¶
View bindings, environment variables, and shell init for a specific tool:
# Show details for a tool
devsandbox tools info mise
# Show details for all tools
devsandbox tools info --all
# JSON output
devsandbox tools info mise --json
Example output:
Tool: mise
Status: available
Description: Tool version manager (node, python, go, etc.)
Binary: /home/user/.local/bin/mise
Bindings:
~/.local/bin (read-only, optional)
~/.config/mise (read-only, optional)
~/.local/share/mise (read-only, optional)
Environment Variables: (none)
Shell Init:
if command -v mise &>/dev/null; then eval "$(mise activate bash)"; fi
Verify Tool Setup¶
Check tool availability and verify binding paths exist:
# Check all tools
devsandbox tools check
# Check specific tools
devsandbox tools check mise git claude
# JSON output
devsandbox tools check --json
Example output:
Checking tools...
✓ mise (/home/user/.local/bin/mise)
✓ ~/.local/bin
✓ ~/.config/mise
✓ ~/.local/share/mise
✓ git (/usr/bin/git)
○ ~/.local/share/devsandbox/<project>/home/.gitconfig.safe (optional, missing)
✓ claude (/home/user/.local/bin/claude)
✓ ~/.claude
✓ ~/.claude.json
✗ starship (not available)
! starship binary not found in PATH
Summary: 3/4 tools available
Tool Management with mise¶
mise is the recommended (but optional) tool manager. If installed, all mise-managed tools are automatically available inside the sandbox.
How It Works¶
By default, mise directories are bind-mounted read-only:
~/.config/mise → Sandbox (read-only)
~/.local/share/mise → Sandbox (read-only)
~/.local/state/mise → Sandbox (read-only)
This means:
- All installed tool versions are available
- Tool configurations (
.mise.toml) are respected - New tools cannot be installed from inside the sandbox (by default)
Writable Mise (Overlay Mode)¶
Configure the overlay mount mode for mise to allow installing tools inside the sandbox. In ~/.config/devsandbox/config.toml:
[tools.mise]
mount_mode = "overlay" # Persist tool installations across sessions
# mount_mode = "tmpoverlay" # Discard on exit (safer)
With overlay enabled:
- Sandbox can install new tool versions
- Host mise directories remain unchanged
- Changes are isolated to the sandbox
The global [overlay] default setting controls all tools. Per-tool mount_mode overrides the global default. See Sandboxing: Overlay Filesystem for details on overlay modes and how layering works.
Supported Tools¶
Any tool installable via mise works inside the sandbox:
| Category | Examples |
|---|---|
| Languages | Node.js, Python, Go, Rust, Ruby, Java |
| Package Managers | npm, pnpm, yarn, pip, cargo, uv, poetry |
| Build Tools | make, cmake, ninja |
| Utilities | jq, yq, gh, aws-cli |
Installing Tools¶
Install tools on your host system (outside the sandbox):
# Install Node.js
mise install node@20
# Install Python
mise install python@3.12
# Install multiple tools
mise install node@20 python@3.12 go@1.22
Tools are then automatically available in all sandboxes.
Shell Configuration¶
devsandbox detects your shell from $SHELL and loads appropriate configurations:
Bash¶
~/.bashrc → Sandbox (read-only)
~/.bash_profile → Sandbox (read-only)
~/.profile → Sandbox (read-only)
Zsh¶
Fish¶
Note: Shell configurations are read-only. Changes made inside the sandbox won't persist.
Prompt Tools¶
devsandbox can display a sandbox indicator in your shell prompt. Several popular prompt tools are supported.
Environment Variables¶
Inside the sandbox, these variables are always set:
DEVSANDBOX=1- Indicates running inside a sandboxDEVSANDBOX_PROJECT=<name>- The project name
You can use these in custom prompt configurations.
Starship¶
Starship is automatically configured with a [sandbox] indicator:
Powerlevel10k¶
Powerlevel10k is configured with a custom devsandbox segment that shows
when $DEVSANDBOX is set.
Oh My Zsh¶
Oh My Zsh gets a sandbox indicator prepended to the PROMPT.
Oh My Posh¶
Oh My Posh configurations are mounted. You can add a custom segment using the $DEVSANDBOX
environment variable.
tmux¶
tmux is configured to show [SANDBOX] in the status bar with a red background when
running inside the sandbox.
Editor Support¶
Neovim¶
Neovim configuration is available inside the sandbox:
~/.config/nvim → Sandbox (read-only)
~/.local/share/nvim → Sandbox (read-only)
~/.local/state/nvim → Sandbox (read-only)
This includes:
- Your init.lua/init.vim
- Installed plugins
- LSP configurations
- Color schemes
Other Editors¶
For other editors, mount their config directories manually or use the sandbox home.
AI Coding Assistants¶
AI coding assistants execute arbitrary code - installing packages, running builds, making network requests. Running them inside devsandbox ensures they can do their job without accessing your credentials, keys, or secrets.
Claude Code¶
Claude Code is fully supported:
# Run Claude Code in sandbox
devsandbox claude
# With permissions disabled (recommended in sandbox)
devsandbox claude --dangerously-skip-permissions
Everything after devsandbox is passed to the sandboxed command. --dangerously-skip-permissions is a Claude Code flag that skips permission prompts - safe inside the sandbox because devsandbox provides the security boundary.
Configuration directories are mounted read-write to allow Claude to save settings:
~/.claude → Sandbox (read-write)
~/.config/Claude → Sandbox (read-write)
~/.claude.json → Sandbox (read-write)
These directories are isolated to the sandbox home - not your real host directories. Claude's conversation state and settings persist across sandbox sessions for the same project but are not shared with your host.
aider¶
aider works out of the box:
OpenCode¶
OpenCode is detected and supported:
Pi Coding Agent¶
Pi is fully supported:
Install via mise:
Configuration directories are mounted with credential protection:
~/.pi/agent → Sandbox (protected: settings + auth credentials)
~/.pi/agent/sessions → Sandbox (persistent: session history preserved)
The ~/.pi/agent directory (containing settings.json and auth.json) is
mounted with tmpoverlay so API keys and settings are shielded from sandbox
code. Session history in ~/.pi/agent/sessions uses a persistent overlay so
conversations survive across sandbox sessions for the same project.
GitHub Copilot¶
Works inside editors (Neovim, VS Code) running in the sandbox.
Other AI Tools¶
Any CLI-based AI tool works in the sandbox. This includes Continue, Cline, and similar tools. If the tool runs as a CLI process, wrap it with devsandbox.
Git¶
Git access is configurable via [tools.git] in ~/.config/devsandbox/config.toml:
Modes¶
readonly (default)¶
Maximum isolation - .git directory is mounted read-only:
- View history, diff, log, status
- Branch operations (local only)
- No commits (
.gitis read-only) - No SSH access
- No GPG signing
- No credential helpers
This is the safest mode for running untrusted code that needs to read repository data.
readwrite¶
Full git access for trusted projects:
- All git operations including commits
- SSH keys (read-only access to
~/.ssh) - GPG signing (read-only access to
~/.gnupg) - Git credentials (read-only access to
~/.git-credentials) - SSH agent forwarding (
SSH_AUTH_SOCK)
Security note: SSH and GPG directories are mounted read-only to protect private keys.
disabled¶
No git configuration, but .git remains writable:
Git commands work but without user.name/email (commits require --author). Use this if you want to allow commits without exposing any credentials.
Go¶
Go is fully supported with isolated caches:
GOPATH → ~/.local/share/devsandbox/<project>/home/go
GOCACHE → ~/.local/share/devsandbox/<project>/home/.cache/go-build
GOMODCACHE → ~/.local/share/devsandbox/<project>/home/.cache/go-mod
GOTOOLCHAIN → local (prevents auto-downloads)
Module Cache¶
Each project has its own module cache. To share modules across projects, you can symlink the cache directories (outside the sandbox).
Node.js / npm¶
Works normally with mise-installed Node.js:
Global Packages¶
Global npm packages are installed to the sandbox home:
Python¶
Works normally with mise-installed Python:
Virtual Environments¶
Create venvs inside your project directory:
Docker¶
Docker is supported via a socket proxy that provides read-only access to the host Docker daemon.
Configuration¶
Enable Docker in your project's .devsandbox.toml:
Or in the global config ~/.config/devsandbox/config.toml:
Allowed Operations¶
The Docker proxy allows:
| Operation Type | Allowed | Examples |
|---|---|---|
| Read operations | ✓ | docker ps, docker images, docker inspect |
| Container logs | ✓ | docker logs <container> |
| Container exec | ✓ | docker exec -it <container> bash |
| Container attach | ✓ | docker attach <container> |
| Create containers | ✗ | docker run, docker create |
| Delete containers | ✗ | docker rm, docker kill |
| Modify containers | ✗ | docker stop, docker restart |
| Build images | ✗ | docker build |
| Push images | ✗ | docker push |
This allows debugging and inspecting running containers without the ability to modify the Docker environment.
Socket Auto-Detection¶
On Linux, the Docker socket defaults to /run/docker.sock.
On macOS, the socket location varies by Docker runtime. devsandbox probes these paths in order and uses the first one found:
| Priority | Path | Runtime |
|---|---|---|
| 1 | ~/.docker/run/docker.sock |
Docker Desktop |
| 2 | /var/run/docker.sock |
OrbStack (symlink) |
| 3 | ~/.colima/default/docker.sock |
Colima |
To override auto-detection, set the socket path explicitly:
How It Works¶
- A Unix socket proxy is created at
$HOME/docker.sockinside the sandbox - The
DOCKER_HOSTenvironment variable is set to point to this socket - All requests are filtered before being forwarded to the host Docker socket
- Write operations are blocked with an HTTP 403 error
Limitations¶
- Only Unix socket access is supported - TCP connections to Docker daemons are not proxied
- Exec/attach sessions allow interactive terminal access to existing containers
Error Logging¶
Proxy errors are logged to ~/.local/share/devsandbox/<project>/logs/internal/tools-errors.log
Checking Docker Status¶
Example output:
Kitty Terminal¶
When running inside kitty with remote control enabled, devsandbox runs a filtering proxy for the kitty remote-control socket. The host kitty socket is not bind-mounted into the sandbox; only the proxy socket is. Sandboxed code can perform only the kitty operations declared by enabled tools, scoped to windows the sandbox itself opened (ownership tracking).
Prerequisites¶
Add to your ~/.config/kitty/kitty.conf:
Restart kitty after changing the config.
Activation¶
The proxy starts when all of the following hold:
KITTY_LISTEN_ONis set on the host.- The
kittybinary is on PATH. - At least one enabled tool declares a kitty capability (or
mode = "enforce"is set).
If no tool declares a capability and mode = "auto" (the default), the proxy stays inactive - zero attack surface when nothing needs it. revdiff is the built-in consumer: if the revdiff binary is on PATH, the proxy activates automatically.
Configuration¶
[tools.kitty]
mode = "auto" # "auto" (default), "disabled", "enforce"
extra_capabilities = ["list_owned"] # additive only; launch_* entries are rejected
| Mode | Behavior |
|---|---|
auto |
Proxy starts iff at least one enabled tool declares a capability. |
enforce |
Proxy always starts; with no capabilities declared, every request is denied (useful to verify no tool silently uses kitty). |
disabled |
Proxy never starts; KITTY_LISTEN_ON is not exposed inside the sandbox. |
Capabilities¶
| Capability | Allows |
|---|---|
launch_overlay |
kitty @ launch --type=overlay |
launch_window |
kitty @ launch --type=window |
launch_tab |
kitty @ launch --type=tab |
launch_os_window |
kitty @ launch --type=os-window |
close_owned |
close-window scoped to windows the sandbox opened |
wait_owned |
wait scoped to windows the sandbox opened |
focus_owned |
focus-window scoped to windows the sandbox opened |
send_text_owned |
send-text scoped to windows the sandbox opened |
get_text_owned |
get-text scoped to windows the sandbox opened |
set_title_owned |
set-window-title scoped to windows the sandbox opened |
list_owned |
ls - response is filtered to owned windows only |
launch_* capabilities equal arbitrary host code execution and must be paired with command patterns declared by the tool that requests them. Shell metacharacters (;, &, |, `, $(), <, >, etc.) in sh -c payloads are rejected outright.
What Gets Mounted¶
| Resource | Mode | Purpose |
|---|---|---|
Proxy socket ($HOME/.kitty.sock) |
read-write (proxy is local to the sandbox home) | kitty remote-control via the filtering proxy |
kitty binary |
read-only | CLI for kitty @ launch, kitty @ ls, etc. |
The host's real kitty socket is not bind-mounted into the sandbox.
Environment Variables¶
KITTY_LISTEN_ON- rewritten tounix:$HOME/.kitty.sockinside the sandbox. Host value is never exposed.KITTY_WINDOW_ID,KITTY_PID- passed through from host (read-only signals about the host pane).
Limitations¶
- Async / streaming kitty commands (
get-text --watcher, async kittens) are denied in this MVP. remote_control_passwordinkitty.confis unsupported - useallow_remote_control = socket-onlyinstead.
Run devsandbox tools check kitty to confirm the tool is detected and see the active mode.
Zellij Terminal Multiplexer¶
When running inside a zellij session, devsandbox can forward the session socket and ZELLIJ* env vars into the sandbox so zellij run, zellij action, etc. attach to the host multiplexer.
Disabled by default. Unlike kitty, the zellij socket has no capability filtering - exposing it gives sandboxed code unrestricted control over the host multiplexer (execute commands in any pane, read pane contents, swap layouts). Opt in only if you trust the workload.
Configuration¶
Activation¶
When enabled = true, the tool activates if all of:
ZELLIJenv var is set on the host.- The
zellijbinary is on PATH. - A zellij socket directory exists (
$ZELLIJ_SOCKET_DIR,$XDG_RUNTIME_DIR/zellij/, or/tmp/zellij-<uid>/).
What Gets Mounted¶
| Resource | Mode | Purpose |
|---|---|---|
| Zellij socket directory | read-write bind mount | IPC socket for zellij CLI commands |
zellij binary |
read-only | CLI for zellij run, zellij action, etc. |
Environment Variables¶
ZELLIJ, ZELLIJ_SESSION_NAME, ZELLIJ_PANE_ID are forwarded from the host.
Run devsandbox tools check zellij to confirm the tool is detected and see the active state.
XDG Desktop Portal (Linux only)¶
Sandboxed applications can send desktop notifications to the host via XDG Desktop Portal. This uses xdg-dbus-proxy to expose only the notification portal interface - no other D-Bus access is granted.
Requirements¶
xdg-dbus-proxybinary installed on the hostxdg-desktop-portalrunning with a backend (e.g.,xdg-desktop-portal-gtk,xdg-desktop-portal-kde)- A D-Bus session bus available (
DBUS_SESSION_BUS_ADDRESSset)
# Arch Linux
sudo pacman -S xdg-dbus-proxy xdg-desktop-portal xdg-desktop-portal-gtk
# Debian/Ubuntu
sudo apt install xdg-dbus-proxy xdg-desktop-portal xdg-desktop-portal-gtk
# Fedora
sudo dnf install xdg-dbus-proxy xdg-desktop-portal xdg-desktop-portal-gtk
Configuration¶
Notifications are enabled by default when the requirements are met. To disable:
How It Works¶
xdg-dbus-proxystarts as a background process, creating a filtered D-Bus socket- Only
org.freedesktop.portal.Desktopandorg.freedesktop.portal.Notificationinterfaces are allowed through - The proxy socket is bind-mounted into the sandbox at
$XDG_RUNTIME_DIR/.dbus-proxy/bus DBUS_SESSION_BUS_ADDRESSinside the sandbox points to the proxy socket- A
.flatpak-infofile is created soxdg-desktop-portalrecognizes the sandbox as a valid Flatpak-like application
The proxy is started before the sandbox launches and stopped when the sandbox exits.
Checking Portal Status¶
Example output:
Limitations¶
- Linux only (bwrap backend) - not available on macOS Docker backend
- Only the notification portal is currently supported
- The host must have a running D-Bus session bus with a unix socket
Adding Custom Tools¶
To make additional tools available:
- Install via mise (recommended):
-
System tools - Tools in
/usr/bin,/usr/local/binare available -
Project-local tools - Place executables in your project directory
See Also¶
- Sandboxing - how isolation works, overlay filesystem for writable tools
- Sandboxing: Overlay Filesystem - allow mise to install tools inside the sandbox
- Configuration: Tool Settings - git, mise, and Docker config options
- Use Cases: AI Coding Assistants - workflows for Claude Code and Copilot
- Use Cases: Development Workflows - language-specific examples