code-on-incus: Give each AI agent its own isolated machine with root
code-on-incus (COI) is an open-source tool that leverages Incus system containers to provide AI coding agents with isolated machine environments featuring full root access, systemd, Docker, and package management. It defaults to protecting host credentials, employs kernel-level nftables monitoring for real-time threat detection and automated response, and supports popular AI coding assistants like Claude Code and opencode.
Notifications You must be signed in to change notification settings
Fork 45
Star 578
BranchesTags
Open more actions menu
Folders and files
NameName
Last commit message
Last commit date
Latest commit
History
975 Commits
975 Commits
.github/workflows
.github/workflows
cmd/coi
cmd/coi
docs
docs
internal
internal
misc
misc
profiles/default
profiles/default
schema
schema
scripts
scripts
testdata/dummy
testdata/dummy
tests
tests
.gitignore
.gitignore
.golangci.yml
.golangci.yml
.pre-commit-config.yaml
.pre-commit-config.yaml
CHANGELOG.md
CHANGELOG.md
LICENSE
LICENSE
Makefile
Makefile
README.md
README.md
go.mod
go.mod
go.sum
go.sum
install.sh
install.sh
pyproject.toml
pyproject.toml
renovate.json
renovate.json
ruff.toml
ruff.toml
Repository files navigation
Isolated machines for AI coding agents - with active defense.
COI gives each AI agent its own machine - a full system container with root access, systemd, Docker, and the ability to install anything. Agents work like they would on a real server: run services, manage packages, use cron - without touching your actual system. Files stay correctly owned, no permission hacks needed.
Your credentials stay on the host. SSH keys, environment variables, and Git tokens are never exposed to AI tools unless you explicitly mount them. If something goes wrong, COI catches it - reverse shells, credential scanning, data exfiltration - and pauses or kills the container automatically. No manual intervention needed.
Built by developers, for developers who run AI agents and want to know what those agents are doing. Not a product, not a startup - a tool that does the job.
Who this is for
You run AI coding agents and want them to have full machine access - root, Docker, package managers, services - without risking your host
You want to know when an agent does something suspicious, not find out after the fact
You run multiple agents in parallel and need them isolated from each other
You want persistent dev environments that survive restarts and reboots, not throwaway containers that lose your setup every time
You care about your credentials not ending up inside an agent-controlled environment
Watch the BetterStack video about Code on Incus
Table of Contents
Who this is for
Supported AI Coding Tools
Supported Tools (detailed)
Features
Quick Start
Why Incus Instead of Docker or Docker Sandboxes?
Installation
macOS Support
Usage
Run Scripts and Commands in the Sandbox
Session Resume
Persistent Mode
Configuration
Profiles
Resource and Time Limits
Container Lifecycle & Session Persistence
Network Isolation
Security Monitoring
Security Best Practices
Snapshot Management
System Health Check
Troubleshooting
FAQ
Supported AI Coding Tools
Currently supported:
Claude Code (default) - Anthropic's official CLI tool
opencode - Open-source AI coding agent (https://opencode.ai)
pi - AI coding assistant (https://pi.dev)
Coming soon:
Aider - AI pair programming in your terminal
Cursor - AI-first code editor
And more...
Tool selection is config/profile-driven:
~/.coi/config.toml or ./.coi/config.toml
[tool] name = "opencode" # or "claude" (default), "pi"
coi shell # Uses the configured tool (Claude Code by default) coi shell --profile opencode # Or switch via a profile with [tool] name = "opencode"
Permission mode - Control whether AI tools run autonomously or ask before each action:
~/.coi/config.toml or .coi/config.toml
[tool] name = "claude" # Default AI tool permission_mode = "bypass" # "bypass" (default) or "interactive"
See the Supported Tools wiki page for detailed configuration, API key setup, and adding new tools.
Features
Core Capabilities
Multi-slot support - Run parallel AI coding sessions for the same workspace with full isolation
Session resume - Resume conversations with full history and credentials restored (workspace-scoped)
Persistent containers - Keep containers alive between sessions (installed tools preserved)
Workspace isolation - Each session mounts your project directory
Slot isolation - Each parallel slot has its own home directory (files don't leak between slots)
Workspace files persist even in ephemeral mode - Only the container is deleted, your work is always saved
Container snapshots - Create checkpoints, rollback changes, and branch experiments with full state preservation
Host Integration
SSH agent forwarding - Use git-over-SSH inside containers without copying private keys ([ssh] forward_agent = true)
Host socket forwarding - Forward arbitrary host Unix sockets into the container ([[sockets]]) so the host endpoint never enters the container — the building block for credential brokers (mint short-lived tokens on the host, fetch them on demand inside). Untrusted project-config sockets are gated behind coi trust
Environment variable forwarding - Selectively forward host env vars by name (forward_env in config)
Command-sourced env vars - Mint a fresh secret per session by running a host command at start and injecting its output as an env var ([defaults.env_commands]) — for short-lived API keys/tokens. Trusted-scope config only
Host timezone inheritance - Containers automatically inherit the host's timezone (configurable via [timezone] config)
Sandbox context file - Auto-injected ~/SANDBOX_CONTEXT.md tells AI tools about their environment (network mode, workspace path, persistence, etc.). Automatically loaded into each tool's native context system: Claude Code via ~/.claude/CLAUDE.md, OpenCode via the instructions field in opencode.json, pi via ~/.pi/agent/APPEND_SYSTEM.md symlink (opt out with auto_context = false)
Security & Isolation
Credential protection - SSH keys, .env files, Git credentials, and environment variables are never exposed unless explicitly mounted
Privileged container guard - Refuses to start when security.privileged=true is detected, which defeats all container isolation
Security posture verification - coi health checks seccomp, AppArmor, and privilege settings to confirm full isolation
Kernel version enforcement - Warns on host kernels below 5.15 that may lack security features for safe isolation
Real-time threat detection - Kernel-level nftables monitoring detects reverse shells, C2 connections, data exfiltration, DNS tunneling, and credential scanning
Automated response - Auto-pause on HIGH threats, auto-kill on CRITICAL — no manual intervention needed
Network isolation - nftables-based restricted/allowlist/open modes block private network access and prevent exfiltration
Protected paths - .git/hooks, .git/config, .husky, .vscode mounted read-only to prevent supply-chain attacks
Host-side immutable protection - Protected paths are locked with chattr +i during sessions, preventing unshare -m + umount bypass of read-only mounts (opt out: [security] host_immutable = false)
Git identity guard - Containers enforce user.useConfigOnly=true, preventing AI tools from committing as the default "code" user
Guest API disabled - Incus guest API (/dev/incus) disabled by default, preventing host path and topology leaks
System containers - Full OS isolation with unprivileged containers, better than Docker privileged mode
Automatic UID mapping - No permission hell, files owned correctly
Audit logging - All security events logged to JSONL for forensics and compliance
Safe Dangerous Operations
AI coding tools often need broad filesystem access or bypass permission checks
These operations are safe inside containers because the "root" is the container root, not your host system
Containers are ephemeral - any changes are contained and don't affect your host
This gives AI tools full capabilities while keeping your system protected
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/mensfeld/code-on-incus/master/install.sh | bash
Build image (first time only, ~5-10 minutes)
coi build
Start coding with your preferred AI tool (defaults to Claude Code)
cd your-project coi shell
Or use opencode instead (config-driven: [tool] name = "opencode",
or a profile: coi shell --profile opencode)
That's it! Your AI coding assistant is now running in an isolated container with:
- Your project mounted at /workspace
- Correct file permissions (no more chown!)
- Full Docker access inside the container
- GitHub CLI available for PR/issue management
- All workspace changes persisted automatically
- No access to your host SSH keys, env vars, or credentials
Why Incus Instead of Docker or Docker Sandboxes?
Incus is a modern Linux container and virtual machine manager, forked from LXD. Unlike Docker (which uses application containers), Incus provides system containers that behave like lightweight VMs with full init systems.
Security Comparison
Capability code-on-incus Docker Sandbox Bare Metal
Credential isolation Default (never exposed) Partial None
Real-time threat detection Kernel-level (nftables) No No
Reverse shell detection Auto-kill No No
Data exfiltration alerts Auto-pause No No
Network isolation nftables (3 modes) Basic No
Protected paths Read-only mounts No No
Auto response (pause/kill) Yes No No
Audit logging JSONL forensics No No
Supply-chain attack prevention Git hooks/IDE configs protected No No
Why Incus Instead of Docker Sandboxes?
Linux-first, not Linux-last. Docker Sandboxes' microVM isolation is only available on macOS and Windows. Linux gets a legacy container-based fallback. COI is built for Linux from the ground up because Incus is Linux-native.
No Docker Desktop required. Docker Sandboxes is a Docker Desktop feature. Docker Desktop is not open source and has commercial licensing requirements for larger organizations. COI depends only on Incus - fully open source, no vendor lock-in, no additional runtime.
System containers, not containers-in-VMs. Incus system containers run a full OS with systemd and native Docker support inside - one clean isolation layer. Docker Sandboxes nests application containers inside microVMs, adding architectural complexity.
No permission hell. Incus automatic UID/GID shifting means files created by agents have correct ownership on the host. No mapping hacks needed. (Note: files created via sudo in the workspace will be root-owned — the sandbox context file instructs AI tools to fix ownership after sudo operations.)
Credential isolation by default. Host environment variables, SSH keys, and Git credentials are never exposed to AI tools unless explicitly mounted.
Simple and transparent. No separate daemon, no opaque VM nesting. COI talks directly to Incus - easy to inspect, debug, and extend.
Installation
Automated Installation (Recommended)
One-shot install
curl -fsSL https://raw.githubusercontent.com/mensfeld/code-on-incus/master/install.sh | bash
This will:
- Download and install coi to /usr/local/bin
- Check for Incus installation
- Verify you're in incus-admin group
- Show next steps
Manual installation: Download the binary from GitHub Releases, make it executable, and move to /usr/local/bin/. Requires Linux with Incus installed and user in the incus-admin group. You must log out and back in (or run newgrp incus-admin) after adding your user to the group — COI runs incus directly and requires the group to be active in your session. See the Incus installation guide for setting up Incus.
Build Images
Build the default coi-default image (5-10 minutes)
coi build
Build without compression (faster iteration):
set [container.build] compression = "none" in config or the profile
coi build
Build a custom image via a profile
coi profile create my-image
Edit .coi/profiles/my-image/config.toml: set [container] image and a [container.build] section
coi build --profile my-image
Build images for all profiles that ha
[truncated for AI cost control]