v0.3.0-beta.2 · sandbox-hardening · apache-2.0

Container-native
multi-agent platform. hardened by default.

Every agent runs inside its own Docker container — brain, tools, filesystem, network. Caps dropped, rootfs read-only, uid 1000, PIDs capped at 256. A Go control plane routes; pi-mono containers think. One compromise stays one compromise.

macOS
$ brew install itsmehatef/tap/dclaw && dclaw init && dclaw daemon start
~250MB image Alpine base · uid 1000 ◇ requires go 1.25+ · docker 24+ macOS + Linux · XDG-aware
./architecture · v2 · hover to explore
USER
Discord · Slack · WhatsApp
LLM PROVIDER · EXTERNAL
Anthropic · OpenAI · Google · …
OPERATIONAL SURFACE
CLI · fleet.yaml · web
CHANNEL PLUGINS · independently versioned containers
discord v1.5.0 slack v2.0.3 whatsapp v0.8.2
dclaw DAEMON · Go · CONTROL PLANE · runs on host
channel router fleet manager quota enforce agent registry · SQLite
MAIN AGENT · ~400MB · DATA PLANE
always-on
bash · file · grep · web
WORKER CONTAINERS · ~400MB ea · ephemeral
w·1 w·2 w·N
scoped tools · scoped net · scoped fs
dclaw daemon — Go control plane on host. Channel router · fleet manager · quota enforcement · agent registry (SQLite).

Six decisions, baked in.

dclaw is opinionated. These are calls made once so you don't make them per-deployment. They do not come back as flags. The denylist is absolute on every OS — even --workspace-trust can't bypass it.

01 ·

Mandatory sandboxing

Every agent — brain and tools — runs inside a Docker container. There is no sandbox.mode: "off". One prompt injection = one destroyed container.

02 ·

Hardened container posture

CapDrop ALL · no-new-privileges · ReadonlyRootfs · tmpfs overlays for /tmp+/run · non-root uid 1000 · PidsLimit 256 · seccomp default. mknod, ptrace, setuid, fork-bomb — all return EPERM.

03 ·

Path-validated workspaces

workspace-root allow-root + system denylist (/etc, /var, docker.sock, Docker Desktop socket). Symlink-resolved before mount. --workspace-trust is the only escape, and it's logged.

04 ·

pi-mono under the hood

Agent loop is @mariozechner/pi-coding-agent — 34.6k stars, MIT, multi-model. We do not rewrite the agentic loop. We wrap it.

05 ·

NDJSON audit log

Every agent-create decision (pass / forbidden / trust) lands in audit.log with rotation: 10 MB × 5 files. O_APPEND + O_SYNC + 0600. Reconstruct who-trusted-what after the fact.

06 ·

First-run that actually works

dclaw init creates the allow-root, dclaw doctor preflights seven checks, dclaw daemon start brings up the control plane. State-dir honors XDG on Linux, ~/.dclaw on macOS.

Seven boxes the agent runs inside of.

Paths hardening (beta.1) bounded WHERE the bind-mount points. Sandbox hardening (beta.2) bounds WHAT the containerized agent can do once inside. There is no escape hatch for any of these.

01 ·

CapDrop ALL

Every Linux capability dropped. mknod fails with EPERM. CAP_NET_RAW, CAP_MKNOD, CAP_SYS_CHROOT — gone.

02 ·

no-new-privileges

Setuid/setgid bits cannot grant new privileges via execve. Defense vs CVE-2019-5736 and similar runc escapes.

03 ·

ReadonlyRootfs

Rootfs is read-only. /tmp and /run are tmpfs overlays with noexec,nosuid,nodev. /workspace is the only persistent write surface.

04 ·

uid 1000:1000

Daemon enforces non-root user regardless of image USER directive. A regressed image still can't run as root.

05 ·

PidsLimit 256

Fork bomb caps at 256 processes. pi-mono steady-state is ~5. The 257th fork returns EAGAIN.

06 ·

seccomp default

Docker's daemon-loaded default profile applied. unshare(CLONE_NEWUSER), keyctl, ptrace — denied for unprivileged.

07 ·

docker.sock denylist

Three Docker socket paths absolutely denied as workspaces. Linux /var/run, systemd /run, Docker Desktop macOS. --workspace-trust can't bypass.

Sandboxing isn't a feature. It's the whole point.

Most agent frameworks run on your host. The agent's bash tool IS your bash. The agent's network IS your network. That is a fine demo and a poor production story.

Dimension
Bare-metal agent runtimes
dclaw
Sandbox scope
Optional, bash-only
Mandatory, full-agent
Agent loop
Runs on bare metal
Runs inside container
File operations
Bare metal
Inside container
Network egress
Bare metal
Per-agent iptables allowlist
Agent isolation
Shared process
One container per agent
Blast radius
One compromise = full host
One compromise = one agent

Shipped in phases. No vaporware.

We're in beta.2 today. Each phase ships with working binaries and a public changelog. Container posture is the second-to-last gate before GA.

v0.2.0-cli shipped

CLI bones

dclaw version, --help, structured JSON error envelopes. EX_UNAVAILABLE for daemon-bound commands.

v0.3.0-alpha → beta.1 shipped

Daemon + paths

Go daemon, JSON-RPC wire protocol, fleet lifecycle. workspace-root validator, --workspace-trust, NDJSON audit log.

v0.3.0-beta.2 current

Sandbox hardening

Container posture: cap drop, no-new-privileges, ReadonlyRootfs, tmpfs, non-root uid, PidsLimit, docker.sock denylist.

v1.0 GA next

General availability

Web dashboard, egress allowlist wiring, distroless agent image. Channel plugins follow.