Skip to content

hogu-dev/aias

Repository files navigation

aias

Sandboxed AI coding agents on Linux. CLI-first, per-sandbox isolation, BYO Docker.

aias runs one or more AI coding agents (Claude Code, Codex CLI, OpenCode) inside a Docker container per project, with optional Docker-in-Docker, your project source bind-mounted, and OAuth tokens mounted read-only.

Project docs

  • User guide — install, run, persistence, ports, GPU, SSH keys
  • Workflow guide — day-to-day usage patterns
  • Share modes — how much host Claude state flows into a sandbox
  • Isolation and threat model — what the sandbox actually defends against
  • Hosting — Kata Containers install runbook for kata-clh
  • Testing — unit suite, integration bench, manual smokes

Vocabulary

  • Project — your codebase / repo (lives on the host).
  • Sandbox — what aias creates around a project: a container, a per-sandbox image, named volumes, and a .aias/ directory with configuration. One sandbox per project.

Status

v0.6.0 (current): a single aias:base image is the sole base; DinD is an opt-in Docker-CE topping in the per-sandbox .aias/Dockerfile (toggle with aias dind on|off). Agents (claude / codex / opencode) install into a shared volume rather than the base image. Three sandbox runtimes per sandbox (docker / runsc / kata-clh). Multi-agent CLI dispatch. Opt-in credential sharing via a [secrets] block, plus host-state share modes. Prebuilt-base distribution via [image] base_registry + aias image push|pull. Opt-in host-port publishing via [ports] publish (loopback by default; cross-sandbox host-port collision check at start). Per-sandbox memory sizing via [runtime] memory (raises a kata-clh microVM's RAM above its fixed ~2 GB default; a plain cgroup cap under docker/runsc). Feature-complete for daily use.

Requirements

  • Linux (Arch, Ubuntu, Debian, Fedora — anywhere Docker runs)
  • Docker 24.0+ with user in docker group
  • Per-agent subscriptions: a Claude Pro/Max/Team/Enterprise sub, an OpenAI account for codex, an OpenCode-supported provider, etc.

Install

git clone https://github.com/hogu-dev/aias.git ~/repo/aias
cd ~/repo/aias
sudo ./install.sh

Quickstart

aias doctor                          # check prerequisites
claude setup-token                   # one-time host auth (if not already done)
# codex login                        # optional: enable codex
# opencode auth login                # optional: enable opencode

cd ~/projects/my-project
aias init --runtime docker     # also: runsc (gVisor) | kata-clh (Kata + Cloud Hypervisor)
                                     # creates .aias/{config.toml, Dockerfile, compose.yaml, config.local.toml}
                                     # interactively prompts: DinD? [y/N] (default no)
aias start                           # builds base + sandbox image on demand, then up -d
aias claude                          # drop into Claude inside the sandbox
aias stop                            # state in named volumes persists

Choosing a runtime

aias supports three sandbox runtimes per sandbox. Pick at init via --runtime <name>; switch later with aias rebuild --runtime <new>.

Runtime Isolation Cold start FS perf When to pick
docker Namespace + cgroups instant native Default. Lowest install friction.
runsc Software kernel (gVisor) instant ~10× slower for npm-install-style workloads Stronger isolation than Docker without microVM overhead. NOTE: --dind not supported.
kata-clh Hardware virtualization (Kata + Cloud Hypervisor) ~200ms VM boot ~3× slower for small-file ops (virtio-fs) Strongest isolation. Requires KVM + Kata installed + a kata runtime alias in /etc/docker/daemon.json.

aias doctor shows which are installed locally; missing ones come with install hints.

Note for Kata users: the aias name kata-clh is auto-mapped to whatever Kata-related alias Docker has registered (kata-clh, kata, or any kata-*). If you've configured Kata to use QEMU or Firecracker as the hypervisor instead of Cloud Hypervisor, aias still works — the VMM choice is Kata's internal config, not an aias-level setting.

Important for kata-clh on Docker 24+: register the runtime with the runtimeType field (camelCase) in daemon.json, NOT path. See docs/HOSTING.md for the full install runbook. The path registration causes Docker to wrap the shim as io.containerd.runc.v2, which passes -root that Kata 3.x shims reject (shim exits status 2 with an unhelpful "log.json: no such file" error).

For kata-clh + DinD on hosts with empty removable block devices (e.g., built-in USB SD card readers with no card inserted), aias v0.3.1+ ships a wrapper runtime that strips host devices from the OCI spec. Without this, kata-clh+DinD startup crashes on empty-medium devices. See docs/HOSTING.md for details.

runsc + dind is rejected at init. gVisor doesn't support inner dockerd. Pick docker if you need DinD, or accept the no-DinD limitation under runsc.

Cross-sandbox networking (aias-net) under non-Docker runtimes is unverified. v0.2.x's external Docker network aias-net is known to work under runtime = docker. Under runsc and kata-clh, the bridge / CNI behavior may differ. If you rely on multiple sandboxes reaching each other by name, test it explicitly for your runtime — and file an issue if you hit a regression. (Tracked for v0.3 verification.)

Commands

Command What
aias doctor Prerequisites + state check (Docker, network, base images, host-auth status per agent)
aias bootstrap Optional warm-up: state dir + network + base image
aias bootstrap --rebuild Force-rebuild aias:base (run after git pull-ing aias)
aias init --runtime <docker|runsc|kata-clh> [--dind|--no-dind] [--name NAME] Create .aias/ for the current dir
aias start Build (if needed) + start sandbox
aias stop Stop sandbox; volumes preserved
aias status Compose ps for this sandbox
aias shell bash inside the sandbox
aias code Open VS Code attached to the running sandbox (Dev Containers)
aias <agent> [args...] Run claude/codex/opencode inside the sandbox
aias rebuild [--no-cache] Force-rebuild this sandbox's image
aias dind on|off Toggle DinD; rebuild happens on next aias start
aias share <bare|skills|mirrored>, aias sync <live|snapshot> Change share mode / sync strategy (restart to apply)
aias gpu <all|none|indices> Grant host NVIDIA GPU(s) to the sandbox (CDI)
aias regen Regenerate .aias/compose.yaml from config.toml
aias image push|pull [ref] Share a prebuilt aias:base via your own registry
aias destroy [--purge-volumes] Remove the sandbox
aias list List known aias sandboxes
aias prune Remove orphaned per-sandbox volumes + reclaimable image tags
aias gc Drop this project's superseded image tags

Authentication

aias does NOT manage agent credentials — it just reflects what's on your host. Each agent has its own auth command you run once:

  • claude: claude setup-token (browser flow → writes ~/.claude/.credentials.json)
  • codex: codex login (browser flow → writes ~/.codex/auth.json)
  • opencode: opencode auth login (browser flow → writes ~/.local/share/opencode/auth.json)

aias start checks each enabled agent's host credential file. If missing, you get a per-agent hint:

[aias] ✗ claude: not authenticated on host
[aias]   → run: claude setup-token

Token rotation

When you rotate your host auth (e.g., the OAuth token expired after a year and you re-ran claude setup-token), restart your sandbox once so the new credentials take effect:

aias stop && aias start

This is a caveat of Docker's file-bind-mount semantics (kernel pins the inode at mount time, so atomic file replacements on the host don't propagate to an already-running container). Rare enough that the friction is small.

Credentials staging (v0.2.4+): aias stages your host credentials into ~/.config/aias/sandbox-creds/<sandbox>/<agent>/<filename> on every aias start. The sandbox bind-mounts this directory (read-only) and aias-init symlinks each staged file at the agent's native path. This replaces v0.2.3's per-file mounts (which break under Kata's virtio-fs). Same rotation UX as v0.2.3: aias stop && aias start after rotating credentials on the host.

Modes

DinD off (default): Sandbox image builds FROM aias:base (no Docker CE, no --privileged). Reduced attack surface. Good for most projects.

DinD on: Sandbox image builds FROM aias:base plus a Docker CE topping in the per-sandbox .aias/Dockerfile. Container runs --privileged so the inner dockerd works. Inner image state persists in the aias-dind-<sandbox> named volume across sandbox restarts. Flip with aias dind on|off.

Credential sharing

.aias/config.toml has a [secrets] block. Defaults:

Default What it does When to disable
gitconfig = true Mounts ~/.gitconfig:ro — agent uses your name/email Probably never
ssh_agent = true Forwards $SSH_AUTH_SOCK:ro — agent can use ssh-added keys If you don't want the sandbox signing SSH ops
[secrets.ssh_keys] Forward-only scoped agent: only the listed keys, each ssh-add -h destination-constrained; key files never enter the sandbox; works under docker and kata-clh Use instead of ssh_agent when you want selective SSH (specific keys, specific hosts), or SSH forwarding under kata-clh
gh_cli = false Bind-mounts ~/.config/gh:ro (GitHub PAT) Opt in if you want gh inside
aws = false Bind-mounts ~/.aws:ro (AWS keys) Opt in carefully — IAM scope = whatever you granted
extra = [] Per-file mounts from ~/.config/aias/sandbox-secrets/<name>/ Curated, per-sandbox

Per-machine overrides go in .aias/config.local.toml (gitignored). Example:

[secrets]
aws = true   # enable on this machine only

Host-wide defaults for every sandbox go in ~/.config/aias/config.toml (e.g. [base] on_stale = "auto"); precedence is global < .aias/config.toml < .aias/config.local.toml, so a project's own config always wins. See docs/HOSTING.md.

Share modes (v0.3+)

Pick what host state appears in your sandbox:

aias init --runtime docker --share bare       # isolated (default)
aias init --runtime docker --share skills     # capabilities only
aias init --runtime docker --share mirrored   # full mirror

And how it syncs:

aias init --runtime docker --share skills --sync live      # bind mount (default)
aias init --runtime docker --share skills --sync snapshot  # copy at start

See docs/share-modes.md for the trade-offs.

Custom secrets — [secrets.extra]

[secrets.extra]
OPENAI_API_KEY = { file = "~/.env", key = "OPENAI_API_KEY" }  # env var
gcp-creds = { file = "~/.config/gcloud/credentials.json" }    # file mount

Legacy form extra = ["filename"] (v0.2.x) keeps working. See docs/share-modes.md.

Testing

  • Unit tests (fast, mock Docker): bats tests/unit
  • Integration tests (bring up real bench with DinD + gVisor): ./run-integration.sh. First run takes ~5 min to build the bench image; cached re-runs < 30 s. Covers runtime=docker + runtime=runsc + staging + rebuild paths end-to-end. (runtime=kata-clh currently skips in the bench due to an upstream Kata/Docker shim issue — see docs/TESTING.md for details.)

Sharing a prebuilt base across machines (registry)

Building aias:base takes a couple of minutes. To build it once and reuse it on your other machines, push it to a registry and have the others pull it.

aias never runs a registry — bring your own. A local one is a one-liner (localhost:5000 is TLS-exempt, so no docker login and no daemon config):

docker run -d -p 5000:5000 --restart always --name aias-registry registry:3

On the builder machine:

# point at the registry (project .aias/config.toml or ~/.config/aias/config.toml):
#   [image]
#   base_registry = "localhost:5000"
aias image push            # builds aias:base if needed, pushes localhost:5000/aias:base

On every consumer machine, set the same base_registry. Now aias start pulls aias:base instead of building it. If the registry is unreachable, aias falls back to a local build (with a warning) — so it works with or without one.

aias image pull            # optional: refresh the local aias:base from the registry
aias image push <ref>      # push an arbitrary, registry-qualified local image
aias image pull <ref>      # pull an arbitrary ref

For a LAN registry (hostname:5000 instead of localhost), Docker requires TLS or an insecure-registries entry in your daemon.json — that's your Docker daemon's setup, not aias's. Auth (for ghcr/ECR/etc.) uses your existing docker login; aias never handles registry credentials.

License

Apache 2.0.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors