Setup & Integration

Platform support, container setup, and integrating agentsh with your development environment.

Platform Support#

agentsh supports Linux, macOS, and Windows with varying levels of enforcement capability.

macOS + Limarun inside VM
100%

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
Hosted sandbox environments

On hosted sandbox platforms (Sprites, Modal, E2B, etc.), some Linux features like namespace isolation, syscall filtering, and resource limits may be unavailable or restricted due to the underlying kernel configuration. File and network blocking typically work, but verify feature availability for your specific platform.

Linux#

100% Score Full enforcement with all features.

Linux provides the most complete security coverage:

Requirements

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
cgroups v2 4.5+ Resource limits; requires cgroupfs mounted

Environment compatibility

Environment seccomp Landlock eBPF FUSE Typical Mode
Native Linux (root) Yes Yes Yes Yes full
Docker (privileged) Yes Yes Maybe Yes full
Docker (unprivileged) Maybe Yes No Maybe landlock
Kubernetes pod Maybe Yes No Maybe landlock
gVisor / Firecracker No No No No minimal
E2B / Modal / Sprites Varies Varies No Varies landlock*

*Run agentsh detect to check actual capabilities in your environment.

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.

FUSE-T (Standard) 70%

Easy setup for development and personal use. Install via brew install fuse-t.

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

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.

WSL2 100%

Full Linux features in Windows Subsystem for Linux.

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.

Linux full mode only

Execve interception requires seccomp with user-notify support (Linux kernel 5.9+) and is only available in full security mode.

Key features

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}}"

Security model

Running Inside Containers#

Containers isolate the host surface; agentsh adds in-container runtime visibility and policy.

Ready-to-use examples:

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.

Non-interactive stdin bypass

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
Autostart

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.

Why this matters

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

Shell alias

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:

Combine with shell shim

In containerized environments, install the shell shim so that even nested shells and subprocess calls route through agentsh automatically.

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.

Note

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 30sCommand timeout
--output jsonJSON structured output
--streamStream output as produced
--ptyInteractive PTY mode
--client-timeout 30sHTTP client timeout for API requests (Go duration format, default: 30s). Increase for long-running exec operations in slow environments.
Environment Variable Description
AGENTSH_SESSION_IDDefault session ID
AGENTSH_SESSION_ROOTRoot for auto-creating sessions
AGENTSH_SERVERServer URL (default: http://127.0.0.1:18080)
AGENTSH_CLIENT_TIMEOUTHTTP client timeout (default: 30s). Same as --client-timeout.
AGENTSH_SHIM_FORCESet to 1 to force the shell shim to route through agentsh exec even when stdin is not a TTY.
AGENTSH_NO_AUTOSet to 1 to disable automatic server startup on first exec.