Setup & Integration
Platform support, container setup, and integrating agentsh execution-layer security with your development environment.
Platform Support#
agentsh supports Linux, macOS, and Windows with varying levels of enforcement capability.
Platform Comparison#
| Feature | Linux | macOS ESF | macOS FUSE-T | Windows |
|---|---|---|---|---|
| File blocking | Yes | Yes | Yes | Yes |
| Network blocking | Yes | Yes | Yes | Yes |
| Signal blocking | Yes | Audit | Audit | Audit |
| Namespace isolation | Full | None | None | Partial |
| Syscall filtering | Yes | Exec only | No | No |
| Resource limits | Full | None | None | Partial |
AI sandbox platforms vary widely in kernel feature exposure. Sprites, E2B, Daytona, and Blaxel support full mode with all enforcement layers. Others restrict FUSE mounts or seccomp user-notify, limiting enforcement to landlock or minimal modes. See the AI sandbox platforms table below for per-platform details, or run agentsh detect inside the sandbox.
Linux#
100% Score Full enforcement with all features.
Linux provides the most complete security coverage:
- File interception: FUSE3 with blocking and policy enforcement
- Network: iptables with full TCP/UDP/DNS interception
- Process isolation: Full namespace isolation (mount, net, PID, user)
- Syscall filtering: seccomp-bpf with allowlists
- Signal interception: Full blocking and redirect via seccomp
- Resource limits: cgroups v2 for CPU, memory, disk I/O, network
Root or CAP_SYS_ADMIN for namespaces. eBPF requires kernel 5.x+ for full features.
Kernel Features#
Linux security capabilities depend on kernel version and runtime environment. Features are automatically detected at startup.
| Feature | Kernel | Notes |
|---|---|---|
| seccomp user-notify | 5.0+ | Full syscall interception; may be blocked in nested containers |
| Landlock v1 | 5.13+ | Basic filesystem sandboxing |
| Landlock v2 | 5.19+ | File reparenting (REFER) |
| Landlock v3 | 6.2+ | File truncation control |
| Landlock v4 | 6.7+ | Network TCP restrictions |
| Landlock v5 | 6.10+ | IOCTL restrictions |
| eBPF (network) | 4.18+ | Requires CAP_BPF or CAP_SYS_ADMIN |
| FUSE | 2.6+ | Requires /dev/fuse and fuse3 libraries |
| ptrace | 2.6+ | Requires SYS_PTRACE capability; fallback when seccomp/eBPF/FUSE unavailable |
| cgroups v2 | 4.5+ | Resource limits; requires cgroupfs mounted |
Environment compatibility
| Environment | seccomp | Landlock | eBPF | FUSE | ptrace | Typical Mode |
|---|---|---|---|---|---|---|
| Native Linux (root) | Yes | Yes | Yes | Yes | Yes | full |
| Docker (privileged) | Yes | Yes | Maybe | Yes | Yes | full |
| Docker (unprivileged) | Maybe | Yes | No | Maybe | Maybe | landlock |
| Kubernetes pod | Maybe | Yes | No | Maybe | Maybe | landlock |
| gVisor / Firecracker | No | No | No | No | Maybe | ptrace or minimal |
| AWS Fargate | No | Maybe | No | No | Yes | ptrace |
*Run agentsh detect to check actual capabilities in your environment.
AI sandbox platforms
Capabilities for hosted AI sandbox providers. Each row reflects the platform’s current kernel configuration.
| Platform | seccomp | Landlock | FUSE | ptrace | Mode |
|---|---|---|---|---|---|
| Sprites (Fly.io) | Yes | Yes | Yes | Yes | full |
| E2B | Yes | Yes | Yes | Yes | full |
| Daytona | Yes | Yes | Yes | Yes | full |
| Blaxel | Yes | Yes | Yes | Yes | full |
| Cloudflare Containers | Yes | Yes | No | Maybe | landlock |
| Deno Deploy | Yes | Detected* | No | Maybe | landlock-only |
| Railway | Yes | Yes | Maybe | Maybe | landlock |
| Vercel Sandbox | Yes | v0 | No | Maybe | minimal |
| Runloop | Detected* | v0 | No | Maybe | minimal |
| Modal | No | No | No | No | minimal |
*Detected by kernel but not enforcing due to platform configuration. v0 = basic Landlock (no network restrictions). Run agentsh detect inside the sandbox to verify.
macOS#
macOS supports three deployment options:
ESF+NE (Enterprise) 90%
Best for commercial security products. Uses Endpoint Security Framework for file monitoring and Network Extension for traffic interception.
- ESF requires Apple approval (business justification needed)
- Network Extension is standard capability since Nov 2016
- No namespace isolation (macOS limitation)
- Signal interception: audit only
FUSE-T (Standard) 70%
Easy setup for development and personal use. Install via brew install fuse-t.
- File interception via FUSE-T (NFS protocol)
- Network via pf packet filter (requires root)
- Minimal isolation via sandbox-exec
- No syscall filtering
Lima VM 100%
For full Linux-equivalent isolation on macOS, run agentsh and your AI agent harness entirely inside a Lima VM.
# Install Lima on macOS
brew install lima
# Create and start a VM
limactl start default
# Shell into the VM
limactl shell default
# Inside the VM - install agentsh from GitHub releases
# Download the .deb/.rpm for your distro from:
# https://github.com/canyonroad/agentsh/releases
agentsh server
- Full FUSE3 filesystem interception
- Full iptables network interception
- Full Linux namespace isolation
- Full seccomp-bpf syscall filtering
- Full cgroups v2 resource limits
Trade-offs: File I/O to macOS filesystem via virtiofs (15-30% overhead), VM uses ~200-500MB RAM, interact via SSH/shell into VM.
Windows#
Native 85%
Uses mini filter driver with AppContainer sandbox isolation.
- File/registry interception via kernel-mode mini filter
- Network via WinDivert (requires admin)
- Registry monitoring and blocking
- AppContainer for process isolation
- Signal interception: audit only via ETW
WSL2 100%
Full Linux features in Windows Subsystem for Linux.
- Same capabilities as native Linux
- No Windows registry monitoring
- Slight VM overhead
Detecting Capabilities#
Use agentsh detect to probe your environment and see what security features are available:
# Show capabilities in table format (default)
agentsh detect
# Output as JSON for scripting
agentsh detect --output json
# Output as YAML
agentsh detect --output yaml
Generating optimized configuration
Use agentsh detect config to generate a configuration snippet optimized for your environment:
# Print to stdout
agentsh detect config
# Write to file
agentsh detect config --output security.yaml
# Merge with your existing config
agentsh detect config >> config.yaml
The generated config includes security:, landlock:, and capabilities: sections optimized for detected features.
Execve Interception#
In full security mode, agentsh intercepts all execve/execveat syscalls via seccomp user-notify. This provides complete execution coverage—every binary execution goes through policy, including nested commands like sh -c "curl ..." that would bypass shell-level checks.
Execve interception requires seccomp with user-notify support (Linux kernel 5.9+) and is only available in full security mode.
Key features
- Complete coverage — Every binary execution goes through policy, not just shell commands
- Full audit trail — All execve calls logged regardless of decision
- Depth-aware policy — Different rules for direct vs nested execution
- Argument inspection — Block dangerous arg patterns (e.g.,
rm -rf) - Approval flow — Interactive approval with timeout (fail-secure default)
Configuration
sandbox:
seccomp:
enabled: true
execve:
enabled: true # Enable execve interception
# Argv capture limits
max_argc: 1000 # Max args to read
max_argv_bytes: 65536 # Max total argv bytes
on_truncated: deny # deny | allow | approval
# Approval settings
approval_timeout: 10s
approval_timeout_action: deny # deny | allow
# Internal bypass (agentsh infrastructure)
internal_bypass:
- /usr/local/bin/agentsh
- /usr/local/bin/agentsh-unixwrap
Depth-aware policies
Command rules support a context field that enables different policies for direct (user-typed, depth 0) vs nested (script-spawned, depth 1+) commands:
| Context | Equivalent | Description |
|---|---|---|
[direct] |
max_depth: 0 |
Only top-level commands |
[nested] |
min_depth: 1 |
Only nested commands |
[direct, nested] |
no constraint | All depths (default) |
command_rules:
# User can run git directly, but scripts can't
- name: allow-git-direct
commands: [git]
decision: allow
context: [direct]
# Compilers should only run from build tools
- name: allow-cc-nested
commands: [gcc, clang, cc]
decision: allow
context:
min_depth: 1
max_depth: 3
# Block dangerous rm patterns at any depth
- name: block-dangerous-rm
commands: [rm]
args_patterns: ["*-rf*", "*-fr*"]
decision: deny
context: [direct, nested]
# Network tools need approval when nested
- name: approve-nested-network
commands: [curl, wget, nc]
decision: approve
context: [nested]
message: "Nested script wants to run: {{.Command}} {{.Args}}"
Path Canonicalization
All executable paths are resolved through EvalSymlinks before policy evaluation. This prevents symlink-based bypass attacks where an attacker creates a symlink (e.g., /tmp/safe → /usr/bin/wget) to circumvent command rules.
- Symlink resolution — The real path is evaluated against policy, not the symlink
- Audit trail — The original pre-canonicalization path is preserved as
raw_filenamein events for forensics
Transparent Command Unwrapping
agentsh recognizes common wrapper commands and unwraps them to find the real payload. Both the wrapper and payload are evaluated against policy — the most restrictive decision wins.
For example, env wget http://evil.com evaluates both env and wget. Even if env is allowed, wget must also pass policy.
Built-in transparent commands:
| Platform | Commands |
|---|---|
| All | env, nice, nohup, sudo, time, xargs |
| Linux | busybox, doas, strace, ltrace, ld-linux* |
| Windows | cmd.exe, powershell.exe, pwsh.exe, wsl.exe |
Customize the set per policy:
transparent_commands:
add:
- myrunner # Custom wrappers
- taskrunner
remove:
- sudo # Don't unwrap sudo
Unwrap events include unwrapped_from and payload_command fields in audit logs.
Security model
- Fail-secure — Timeout on approval defaults to deny
- Fail-secure — Truncated argv defaults to deny
- Tamper-proof — Depth tracking is handler-side, not environment variables
- Symlink-proof — All paths resolved before policy evaluation
- Unwrap-safe — Wrapper + payload both evaluated; most restrictive wins
- Complete audit — Every execve logged, including internal bypasses
Ptrace Mode#
When seccomp user-notify, eBPF, and FUSE are all unavailable — as on AWS Fargate, restricted Kubernetes pods, or gVisor/Firecracker runtimes — agentsh can use Linux ptrace to intercept syscalls and enforce policy. Ptrace mode is opt-in and not auto-selected.
Ptrace mode requires the SYS_PTRACE capability and a Linux kernel. It is not available on macOS or Windows.
Enable ptrace in your configuration:
sandbox:
ptrace:
enabled: true
attach_mode: children # "children", "pid", or "sidecar"
trace:
execve: true # Intercept execve/execveat
file: true # Intercept file I/O syscalls
network: true # Intercept connect/bind
signal: true # Intercept signal syscalls
performance:
seccomp_prefilter: true # BPF pre-filter for reduced overhead
max_tracees: 500 # Max concurrent traced processes
max_hold_ms: 5000 # Timeout for held syscalls (ms)
Or enable via environment variable:
export AGENTSH_PTRACE_ENABLED=1
export AGENTSH_PTRACE_ATTACH_MODE=children
Attach modes
| Mode | Description | Use Case |
|---|---|---|
children | Trace all child processes spawned by the session | Default for most setups |
pid | Attach to a specific PID (set via target_pid or target_pid_file) | Sidecar tracing of existing processes |
sidecar | Run as a sidecar process alongside the workload | Container orchestration |
Ptrace capabilities
In ptrace mode, agentsh provides:
- Execve interception — policy enforcement on every binary execution
- File I/O interception — path resolution and policy checks on open/read/write/delete
- Network interception — connect/bind filtering with sockaddr parsing
- DNS redirects — in-process DNS proxy for transparent domain steering
- TLS SNI rewrite — rewrite Server Name Indication without breaking TLS
- Connect redirects — steer outbound connections to alternative endpoints
- Syscall injection — modify syscall arguments for command and exec redirects
Ptrace mode was specifically designed for AWS Fargate, where seccomp user-notify, eBPF, and FUSE are all blocked. Add SYS_PTRACE to your ECS task definition’s linuxParameters.capabilities.add list.
Running Inside Containers#
Containers isolate the host surface; agentsh adds in-container runtime visibility and policy.
- Per-operation audit (files, network, commands) shows what happened during installs/builds/tests
- Approvals and rules persist across long-lived shells and subprocess trees
- Path-level controls on mounted workspaces/caches/creds
- Same behavior on host and in containers—CI and local dev see the same policy outcomes
- Blaxel integration — agentsh in Blaxel sandboxes
- Daytona integration — agentsh in Daytona dev environments
- E2B integration — agentsh in E2B sandboxes
- Runloop integration — agentsh in Runloop sandboxes
- Sprites integration — agentsh in Sprites sandboxes
Shell Shim
The shell shim replaces /bin/sh and /bin/bash so that any shell invocation routes through agentsh—including subprocess calls from scripts, package managers, and build tools.
agentsh shim install-shell \
--root / \
--shim /usr/bin/agentsh-shell-shim \
--bash \
--i-understand-this-modifies-the-host
If you want an extra safety margin, use --bash-only instead of --bash to shim only /bin/bash while leaving /bin/sh completely untouched, so orchestrators that use sh for data transfer never hit the shim at all. The two flags are mutually exclusive.
agentsh shim install-shell \
--root / \
--shim /usr/bin/agentsh-shell-shim \
--bash-only
Point the shim at your server:
ENV AGENTSH_SERVER=http://127.0.0.1:18080
Now any /bin/sh -c ... or /bin/bash -lc ... in the container routes through agentsh.
When stdin is not a TTY (e.g. piped data via docker exec -i container sh -c "cat > /file" < data), the shim execs the real shell directly to preserve binary data integrity. Policy enforcement is skipped for these non-interactive invocations. To force the shim to route through agentsh exec even without a TTY—useful in sandbox platforms like Blaxel or E2B where commands arrive via HTTP APIs—set AGENTSH_SHIM_FORCE=1.
Docker Setup
Example Dockerfile (Debian-based):
FROM debian:bookworm-slim
ARG AGENTSH_REPO=canyonroad/agentsh
ARG AGENTSH_TAG=v0.1.0
ARG DEB_ARCH=amd64
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends ca-certificates curl bash; \
rm -rf /var/lib/apt/lists/*
RUN set -eux; \
version="${AGENTSH_TAG#v}"; \
deb="agentsh_${version}_linux_${DEB_ARCH}.deb"; \
url="https://github.com/${AGENTSH_REPO}/releases/download/${AGENTSH_TAG}/${deb}"; \
curl -fsSL -L "${url}" -o /tmp/agentsh.deb; \
dpkg -i /tmp/agentsh.deb; \
rm -f /tmp/agentsh.deb; \
agentsh shim install-shell \
--root / \
--shim /usr/bin/agentsh-shell-shim \
--bash \
--i-understand-this-modifies-the-host
CMD ["/bin/sh", "-lc", "echo hello from agentsh shim"]
Sidecar Pattern
Recommended: Run agentsh as a sidecar (or PID 1) in the same pod/service and share a workspace volume. The shim ensures every shell hop stays under policy.
# docker-compose.yml
services:
agentsh:
image: agentsh:latest
volumes:
- workspace:/workspace
ports:
- "18080:18080"
agent:
image: your-agent:latest
environment:
- AGENTSH_SERVER=http://agentsh:18080
volumes:
- workspace:/workspace
depends_on:
- agentsh
volumes:
workspace:
Local Development#
For local development outside containers:
# Start the server (optional if using autostart)
./bin/agentsh server --config configs/server-config.yaml
# Create a session and run a command
SID=$(./bin/agentsh session create --workspace . | jq -r .id)
./bin/agentsh exec "$SID" -- ls -la
# Structured output for agents
./bin/agentsh exec --output json --events summary "$SID" -- curl https://example.com
You don't need to start agentsh server manually. The first agentsh exec automatically launches a local server using the config file. Set AGENTSH_NO_AUTO=1 to manage the server lifecycle yourself.
Protecting Dev Tools
AI coding assistants like Claude Code, Cursor, and Codex don't just run the commands you see—they also make internal implementation decisions, run subprocesses, and access files without explicit tool calls. Running the dev tool itself through agentsh gives you visibility and policy enforcement over all activity, not just the commands shown in the UI.
When an AI assistant decides to "check something quickly" or "read a file for context," those operations happen silently. Without agentsh wrapping the entire process, you only see what the tool chooses to show you.
Wrapping your dev tool
Instead of running your AI assistant directly, launch it through agentsh:
# Create a session for your workspace
SID=$(agentsh session create --workspace . | jq -r .id)
# Run Claude Code through agentsh
agentsh exec "$SID" -- claude
# Or run Cursor through agentsh
agentsh exec "$SID" -- cursor .
# Or any other dev tool
agentsh exec "$SID" -- code .
What you gain
- Full audit trail: Every file read, network request, and subprocess is logged
- Policy enforcement: Block access to
~/.ssh,~/.aws, and other sensitive paths even when the tool doesn't show the access - LLM request visibility: See all API calls the tool makes, with DLP redaction
- Subprocess control: When the tool spawns
npm installorpip installinternally, those are governed too
Add an alias to make this seamless: alias claude='agentsh exec $(agentsh session create --workspace . | jq -r .id) -- claude'
AI Assistant Integration#
There are two approaches to integrating agentsh with AI coding assistants: running the entire agent under agentsh, or configuring the agent to use agentsh for commands.
Running Agents Under agentsh
For unsupervised or autonomous agents, run the entire agent process under agentsh. This ensures comprehensive coverage—every shell command, subprocess, and file operation is monitored and policy-enforced, even if the agent doesn't explicitly use agentsh.
# Create a session with your policy
SID=$(agentsh session create --workspace /path/to/project --policy my-policy | jq -r .id)
# Run Claude Code under agentsh
agentsh exec "$SID" -- claude --dangerously-skip-permissions -p "implement the feature"
# Or run other coding agents
agentsh exec "$SID" -- codex --full-auto "fix the failing tests"
agentsh exec "$SID" -- opencode -p "refactor the auth module"
agentsh exec "$SID" -- cursor-agent --print "add unit tests"
This approach is ideal for:
- Headless/CI pipelines — agents running without human oversight
- Batch operations — processing multiple tasks autonomously
- Defense in depth — policy enforcement regardless of agent behavior
In containerized environments, install the shell shim so that even nested shells and subprocess calls route through agentsh automatically.
Real-Paths Mode
By default, agentsh virtualizes the workspace under /workspace. With real-paths mode, sessions preserve the actual host directory path. This eliminates path confusion when agents reference absolute paths in their output.
# Create a session with real paths
agentsh session create --workspace /home/user/work/myproject --real-paths
# Or use agentsh wrap
agentsh wrap --real-paths -- claude --dangerously-skip-permissions -p "implement the feature"
Or set it in config:
sessions:
real_paths: true
Use real-paths when agents need path continuity between host and sandbox — for example, when an agent's output references file paths that humans or CI tools will consume. Outside-workspace paths still go through seccomp/policy enforcement.
Configuring Agents to Use agentsh
For interactive development, configure your AI assistant to route commands through agentsh. This works well when running inside a container isn't practical.
For production or CI/CD environments, prefer running agents in containers with the shell shim installed.
Claude Code
Add to your project's CLAUDE.md:
# Shell access
Run commands via agentsh, not directly in bash/zsh.
Syntax:
agentsh exec SESSION_ID -- COMMAND [ARGS...]
Examples:
agentsh exec my-session -- ls -la
agentsh exec my-session -- npm install
agentsh exec my-session -- go build ./...
With environment variable:
export AGENTSH_SESSION_ID=my-session
agentsh exec -- ls -la
Cursor
Add to your Cursor rules:
All shell commands MUST be executed through agentsh.
Required syntax:
agentsh exec SESSION_ID -- COMMAND [ARGS...]
The -- separator is required between session ID and command.
AGENTS.md
For tools that support the AGENTS.md convention, add the same instructions to your project's AGENTS.md file.
| Flag | Description |
|---|---|
--timeout 30s | Command timeout |
--output json | JSON structured output |
--stream | Stream output as produced |
--pty | Interactive PTY mode |
--client-timeout 30s | HTTP client timeout for API requests (Go duration format, default: 30s). Increase for long-running exec operations in slow environments. |
| Environment Variable | Description |
|---|---|
AGENTSH_SESSION_ID | Default session ID |
AGENTSH_SESSION_ROOT | Root for auto-creating sessions |
AGENTSH_SERVER | Server URL (default: http://127.0.0.1:18080) |
AGENTSH_CLIENT_TIMEOUT | HTTP client timeout (default: 30s). Same as --client-timeout. |
AGENTSH_SHIM_FORCE | Set to 1 to force the shell shim to route through agentsh exec even when stdin is not a TTY. |
AGENTSH_NO_AUTO | Set to 1 to disable automatic server startup on first exec. |
AGENTSH_PTRACE_ENABLED | Set to 1 to enable ptrace-based syscall tracing. |
AGENTSH_PTRACE_ATTACH_MODE | Ptrace attach mode: children, pid, or sidecar. |
AGENTSH_PTRACE_TARGET_PID | Explicit target PID when attach mode is pid. |
AGENTSH_PTRACE_TARGET_PID_FILE | Path to file containing target PID. |
AGENTSH_PTRACE_PREFILTER | Set to 1 to enable seccomp BPF pre-filter for ptrace performance. |