Open source · Docker isolation · One command

Give the agent a cage, not your keys.

Unattended, not unguarded.

Run Claude Code with full autonomous power, safely sandboxed in Docker.

View on GitHub
$ curl -fsSL https://cleat.sh/install | bash

macOS, Linux, WSL

One command

Run it. It's already contained.

~ $ cleat

✔ Image ready (cached)

✔ Container started

✔ Auth shared

✔ Claude launched

Container: cleat-backend-a1b2c3d4

Project: ~/backend (same path, sandboxed)

Caps:

mount:    git, ssh, env, hooks, gh

sandbox:  docker (breaks isolation)

Claude is analyzing your project...

They say an agent bricked someone's Mac overnight. The truth is scarier: it can leak your keys and wipe your work, no reboot required. So I built Cleat.

Amplify the agent. Contain the blast.

Without isolation With Cleat
Same power
Edit project files
Clipboard to host ✓ bridged
Paste an image (ctrl+v) ✓ restored
Browser auth (OAuth) ✓ bridged
Install packages ⚠ your system ✓ contained
Run any command ⚠ your system ✓ contained
Test Docker apps ⚠ your system ✓ opt-in via --cap docker
Only in the cage
Parallel agents on one repo one shared copy ✓ isolated fork each
Planner + worker team wire it by hand ✓ one command cleat kit
Start the Docker daemon start it yourself ✓ autopilot
Smaller blast radius
Access other projects ⚠ exposed ✓ blocked
Modify your system ⚠ exposed ✓ blocked
Your machine stays clean ⚠ global installs pile up ✓ deps stay in the box
Read ~/.ssh, credentials ⚠ exposed ✓ blocked
Claude config & approvals ⚠ shared, corruptible ✓ per-project
Safe to leave overnight ⚠ risky ✓ yes

Architecture

Your machine. Docker container. Clean boundary.

Your machine
~/.claude (auth, settings)
~/my-project (project files)
~/.gitconfig (read-only, opt-in)
Docker container

/home/coder/.claude

/workspace

caps:

mount:    git, ssh, env, hooks, gh

sandbox:  docker (breaks isolation)

Claude Code (full permissions)

Can: read/write project, install packages, run cmds

Cannot: touch host or other projects (by default)

Everything else is untouched.

Why not just write a Dockerfile? You could. But then you handle UID/GID mapping, clipboard bridging, browser auth, hook forwarding, host connectivity, session persistence, per-project container naming and a dozen edge cases. Cleat handles all of it in one command.

Runs where you work

Host
macOS on Apple Silicon and Intel, Linux, Windows via WSL2
Engine
Docker Desktop, OrbStack, Colima, Rancher Desktop, Lima, rootful and rootless Linux
Shell
bash 3.2 (the macOS default) through bash 5
Arch
arm64 and amd64, prebuilt images for both

The whole matrix runs in CI on every push: real macOS, Linux, WSL2 and arm64 runners, real Docker engines, the real bash 3.2. The docker capability is engine-aware, so a caged agent reaches your daemon wherever it runs, rootless and Colima included.

Features

One command. Everything wired up.

$ cleat

✔ Docker tuned for Cleat (24 GB VM, room for many parallel sessions)

✔ Image ready (cached)

New Claude Code available: 2.1.226 2.1.227 (latest)

Update the image before starting? (downloads the new build) [Y/n] y

✔ Claude Code upgraded (2.1.226 → 2.1.227)

✔ Container started

✔ Auth shared

✔ Claude launched

Container: cleat-myapp-a1b2c3d4

Project: ~/projects/myapp /workspace

Caps: git, ssh

┌──────────────────────────┐

8 hours later

47 files changed

All tests passing

Host system: untouched ✔

└──────────────────────────┘

One command. Always the latest Claude. Walk away.

$ cleat fork start feat-a

✔ Workspace copied

✔ Container started

✔ Auth shared

✔ Claude launched

Container: cleat-api-a1b2c3d4-feat-a

Project: ~/projects/api (not mounted, this box works on a copy)

Fork: ~/.config/cleat/forks/cleat-api-a1b2c3d4-feat-a /workspace (copied just now)

Caps: git, ssh

Several agents on one repo, each in its own copy.

Your working tree is never in the room.

$ cleat ps

Cleat containers:

cleat-api-a1b2c3d4

Up 2 hours

/Users/marcin/projects/api

cleat-web-e5f6a7b8

Up 45 minutes

/Users/marcin/projects/web

cleat-docs-c9d0e1f2

Exited (0) 5 hours ago

/Users/marcin/projects/docs

Resume with: cd <project-dir> && cleat resume

$ cleat storage

Docker storage one shared store, used by every container

Disk ███████████████████████░░░ 53 / 60 GB · 88% full

On disk (all projects) size reclaimable

Images 36 GB 21 GB

Build cache (shared) 7.8 GB 5.4 GB

Cleat can reclaim

7.0 GB stale cleat images cleat prune

5.4 GB shared build cache cleat prune --cache

Other projects hold the rest. Cleat never deletes them.

$ cleat kit

Cleat Kits (curated Claude pre-configurations)

Box: main · other boxes: cleat kit <name> <box>

plan-big-execute-small

none (your own config, no kit)

Run your session on Fable 5: it plans and reviews while

worker and scout subagents (Sonnet 5 by default) execute

and explore, each in its own context window so the main

session stays lean. Flagship judgment on the plan and every

review, the mechanical bulk billed at the worker model's

rate, so heavy work burns your rate limit far slower.

Adapted from Anthropic's coordinator-pattern cookbook.

↑/↓ navigate ⏎/→ select q cancel

A better place to run Claude, not just a safer

one: Fable 5 judgment on the plan and every

review, a Sonnet 5 crew on the legwork, per box.

$ cleat

Docker isn't installed.

Install Docker now? (via Homebrew)

1) Docker Desktop (the standard; free for personal use, paid for larger companies)

2) OrbStack (fast, mac-native; free for personal use, paid commercially)

3) Colima (open source, CLI-only, no GUI)

n) no

Choice [1/2/3/n] 1

✔ Docker installed

✔ Container started

No Docker? Cleat asks first, then installs and

carries on. macOS, Linux and WSL2. Never a blind pipe.

$ cleat

! Docker isn't running. Starting Docker Desktop...

waiting for the Docker VM (14s)

✔ Docker ready

✔ Image ready (cached)

✔ Container started

✔ Auth shared

✔ Claude launched

Rebooted? Docker Desktop, OrbStack, Colima,

WSL2: cleat starts your Docker and carries on.

$ cleat stop

✔ Session ended. Resume with: cleat resume

$ cleat resume

✔ Session resumed

Back where you left off.

> copy the API key to clipboard

Bash(echo -n "sk-…" | pbcopy)

⎿ (No output)

Done. The API key is in your clipboard.

⏵⏵ bypass permissions on (shift+tab to cycle)

Bridged to host. No X11. Zero config.

$ cleat config

Cleat config (capabilities + resources)

Scope: global (~/.config/cleat/config)

Capabilities (space toggles host access)

[] git Mount ~/.gitconfig (read-only) for commit identity

[·] ssh Mount ~/.ssh (read-only) and forward SSH agent

[·] env Load env vars from ~/.config/cleat/env and .cleat.env

[·] hooks Run your Claude Code hooks on the host (global + project)

[·] gh GitHub CLI auth (persists across rm/nuke/rebuild)

[·] docker Host Docker socket (breaks sandbox) to test Docker apps

Resources (←/→ changes the value)

memory ‹ 16g › (per-box RAM ceiling)

cpus all (core limit; all = no cap)

[·] Also write these to this project's .cleat

note: over half the 24 GB Docker VM. Two boxes at this ceiling can

oversubscribe it, so run one at a time.

↑/↓ move space toggle ←/→ change ⏎ save q cancel

$ cleat

Project .cleat requests host access: git, docker (beyond the sandbox)

Trust this project's .cleat? (applies its caps; approve once, undo with cleat untrust) [y/N] _

A cloned repo can't grant itself your keys.

Approve once, per project. Default is deny.

$ cleat shell

Container cleat-api-a1b2c3d4

coder@a1b2c3d4e5f6:/workspace$

Drop into bash. Debug anything.

Same container, same state.

Building with a team?

Something bigger is coming.

Get notified

Give the agent a cage, not your keys.

Start sandboxing Claude Code with one command.

Because you shouldn't need a Time Machine backup to use AI.

View on GitHub
$ curl -fsSL https://cleat.sh/install | bash

macOS, Linux, WSL

Install command copied Paste it in your terminal to install Cleat