🥇 export from upstream (3b6ef04)
This commit is contained in:
@@ -1,19 +1,41 @@
|
||||
# Sandcage
|
||||
<p align="center">
|
||||
<img src="sandcage_logo.png" width="120" alt="Sandcage">
|
||||
</p>
|
||||
|
||||
Sandcage runs AI coding agents (Claude Code, Codex) in isolated Docker containers. Each agent gets a full development environment with your project mounted as a workspace, while your host session and credentials stay private.
|
||||
<h1 align="center">Sandcage</h1>
|
||||
|
||||
## Why
|
||||
<p align="center">
|
||||
Run AI coding agents in isolated Docker containers — your machine stays yours.
|
||||
</p>
|
||||
|
||||
Running AI agents directly on your machine means they share your shell, your credentials, and your session history. Sandcage gives each agent its own container with the tools it needs, while keeping your host environment untouched.
|
||||
---
|
||||
|
||||
Agents in different containers can still see each other's work through shared sandbox state (~/.sandcage/), enabling session handoffs between agents working on different branches or worktrees.
|
||||
## Why Sandcage?
|
||||
|
||||
AI coding agents need broad access to do their work: shell, filesystem, network. Letting them run directly on your machine means they share your credentials, your session history, and your entire environment.
|
||||
|
||||
Sandcage gives each agent its own container with the tools it needs. Your project is mounted in, changes are visible on the host, but the agent never touches your shell config, your SSH agent, or anything else outside the sandbox.
|
||||
|
||||
Multiple agents can run side by side. A persistent home directory means config and credentials survive between sessions, so you are not re-authenticating every time.
|
||||
|
||||
## How It Works
|
||||
|
||||
<p align="center">
|
||||
<img src="topology.svg" alt="Sandcage topology — host, Docker, container, volume mounts" width="720">
|
||||
</p>
|
||||
|
||||
1. You run `sandcage claude` (or `codex`, or `shell`) from your project directory
|
||||
2. Sandcage resolves your workspace to the git root and builds Docker compose arguments
|
||||
3. Your project, persistent home, and (optionally) SSH keys are mounted into the container
|
||||
4. The agent runs as the container entrypoint, working in the mounted workspace
|
||||
5. All file changes are immediately visible on your host
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker (daemon must be running)
|
||||
- Rust toolchain (cargo) — or download a prebuilt binary from [Releases](https://github.com/dirigence/sandcage/releases)
|
||||
- **Docker** (daemon must be running)
|
||||
- **Rust toolchain** (cargo) — or download a prebuilt binary from [Releases](https://github.com/dirigence/sandcage/releases)
|
||||
|
||||
### Install
|
||||
|
||||
@@ -21,70 +43,73 @@ Agents in different containers can still see each other's work through shared sa
|
||||
cargo install --git https://github.com/dirigence/sandcage
|
||||
```
|
||||
|
||||
Or from a local checkout:
|
||||
### Build images and run
|
||||
|
||||
```bash
|
||||
cargo install --path crates/sandcage
|
||||
sandcage build # build base and codex images
|
||||
sandcage claude # start Claude Code in the current project
|
||||
```
|
||||
|
||||
### Build the images
|
||||
That is it. Sandcage resolves your project to its git root, mounts it into the container, and drops you into the agent.
|
||||
|
||||
### More commands
|
||||
|
||||
```bash
|
||||
sandcage build
|
||||
```
|
||||
|
||||
This builds three images: `sandcage-base`, `sandcage-claude`, and `sandcage-codex`. Images whose Dockerfile hasn't changed are skipped automatically. Use `--force` to rebuild unconditionally.
|
||||
|
||||
### Run an agent
|
||||
|
||||
```bash
|
||||
sandcage claude # Claude Code in current directory
|
||||
sandcage claude -p ~/project # Claude Code in a specific project
|
||||
sandcage claude -- --resume # forward --resume to Claude Code
|
||||
sandcage codex -p ~/project # Codex in a specific project
|
||||
sandcage shell # interactive shell, same environment
|
||||
sandcage claude --shell # shell in the Claude image (for debugging)
|
||||
sandcage claude -p ~/project # run in a specific project
|
||||
sandcage claude -- --resume # forward args to the agent
|
||||
sandcage codex -p ~/project # run Codex instead
|
||||
sandcage shell # interactive shell, same environment
|
||||
sandcage claude --shell # shell in the Claude image (debugging)
|
||||
sandcage init # detect ecosystem, generate .sandcage.yml
|
||||
sandcage setup ssh # configure SSH key mounting
|
||||
sandcage setup ssh --global # configure SSH globally
|
||||
```
|
||||
|
||||
The workspace is resolved to the git repo root automatically. Inside a git worktree, the worktree root is used instead. Arguments after `--` are forwarded to the agent inside the container.
|
||||
|
||||
### Initialize a project
|
||||
|
||||
```bash
|
||||
sandcage init
|
||||
```
|
||||
|
||||
Detects the language ecosystem (Rust, Node, Python, Go) and generates a `.sandcage.yml` with suggested configuration.
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration is layered: compiled defaults → `~/.sandcage/config.toml` → `.sandcage.yml` → CLI flags
|
||||
<p align="center">
|
||||
<img src="config-layers.svg" alt="Configuration layering — defaults, global, project, CLI flags" width="720">
|
||||
</p>
|
||||
|
||||
### Project configuration (.sandcage.yml)
|
||||
Configuration is layered. Each level overrides the one below it, so you only set what you need:
|
||||
|
||||
**Compiled defaults** — sensible out of the box
|
||||
**Global config** (`~/.sandcage/config.toml`) — user-wide preferences
|
||||
**Project config** (`.sandcage.yml`) — per-project setup, checked into version control
|
||||
**CLI flags** — per-invocation overrides
|
||||
|
||||
### .sandcage.yml example
|
||||
|
||||
```yaml
|
||||
env:
|
||||
DATABASE_URL: "postgres://localhost:5432/dev"
|
||||
packages:
|
||||
- ripgrep
|
||||
- fd-find
|
||||
toolchains:
|
||||
rust: "stable"
|
||||
rust: stable
|
||||
node: "20"
|
||||
env:
|
||||
DATABASE_URL: "postgres://localhost:5432/dev"
|
||||
mounts:
|
||||
- /data/models:/models:ro
|
||||
- ~/.ssh:/home/agent/.ssh:ro
|
||||
agent_args:
|
||||
claude:
|
||||
- --dangerously-skip-permissions
|
||||
shell: zsh
|
||||
```
|
||||
|
||||
## Architecture
|
||||
Run `sandcage init` to generate a starter config — it detects your project ecosystem (Rust, Node, Python, Go) and suggests appropriate toolchains and packages.
|
||||
|
||||
### Images (3-tier)
|
||||
## Docker Image
|
||||
|
||||
| Image | Base | Adds |
|
||||
|-------|------|------|
|
||||
| sandcage-base | Debian bookworm-slim | git, ripgrep, fd, jq, curl, zsh, bash, sudo, just, uv |
|
||||
| sandcage-claude | sandcage-base | Claude Code CLI |
|
||||
| sandcage-codex | sandcage-base | Codex binary (multi-arch) |
|
||||
Sandcage uses a single image (`sandcage`) based on Debian bookworm-slim, packed with dev tools: git, openssh-client, ripgrep, fd, jq, curl, zsh, bash, sudo, just, and uv.
|
||||
|
||||
AI agents (Claude Code, Codex) are installed on first run into the persistent home directory and auto-update themselves — no agent binaries baked into the image.
|
||||
|
||||
Build with `sandcage build`. Use `--force` to rebuild unconditionally.
|
||||
|
||||
## Cross-Platform
|
||||
|
||||
Sandcage works on **Linux**, **macOS**, and **Windows** (PowerShell, cmd, and Git Bash). On Windows with WSL, it works from both the Windows and Linux sides.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Reference in New Issue
Block a user