A community-driven registry for Claude, Cursor, Windsurf, Cline & more. Not affiliated with Anthropic.
Are you the author? Sign in to claim
Give each AI agent its own isolated machine with root, Docker, and systemd. Active defense detects and stops threats aut
coi)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.
Watch the BetterStack video about Code on Incus

Currently supported:
Coming soon:
Tool selection:
coi shell # Uses default tool (Claude Code)
coi shell --tool opencode # Use opencode instead
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.
Core Capabilities
Host Integration
[ssh] forward_agent = true)forward_env in config)[timezone] config)~/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 (opt out with auto_context = false)Security & Isolation
.env files, Git credentials, and environment variables are never exposed unless explicitly mountedsecurity.privileged=true is detected, which defeats all container isolationcoi health checks seccomp, AppArmor, and privilege settings to confirm full isolation.git/hooks, .git/config, .husky, .vscode mounted read-only to prevent supply-chain attackschattr +i during sessions, preventing unshare -m + umount bypass of read-only mounts (opt out: [security] host_immutable = false)user.useConfigOnly=true, preventing AI tools from committing as the default "code" user/dev/incus) disabled by default, preventing host path and topology leaksSafe Dangerous Operations
# 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
coi shell --tool 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
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.
| 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 |
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.
# 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 the default coi-default image (5-10 minutes)
coi build
# Build without compression (faster iteration)
coi build --compression none
# Build a custom image via a profile
coi profile create my-image --image my-image
# Edit .coi/profiles/my-image/config.toml to add a [container.build] section
coi build --profile my-image
# Build images for all profiles that have a [container.build] section
coi build --all
# Rebuild all profile images from scratch
coi build --all --force
What's included in the coi-default image:
mise use go@latest, mise use ruby@3, etc.gh)Custom images: Build your own specialized images using profile-based build scripts that run on top of the base coi-default image. See the Image Management wiki page for complete profile-based build workflows.
COI works on macOS using Colima or Lima VMs. See the macOS Setup Guide for complete instructions.
# Interactive session (defaults to Claude Code)
coi shell
# Use a different AI tool
coi shell --tool opencode
# Persistent mode - keep container between sessions
coi shell --persistent
# Use specific slot for parallel sessions
coi shell --slot 2
# Resume previous session
coi shell --resume
# Run a command in an ephemeral container
coi run "npm test"
# Attach to existing session
coi attach
# Real-time security monitoring dashboard
coi monitor
# View session logs (setup messages, network notices, errors)
coi logs # Auto-detect container from current workspace
coi logs coi-abc123-1 -f # Tail logs live
# List active containers and saved sessions
coi list --all
# Gracefully shutdown / force kill containers
coi shutdown coi-abc12345-1
coi kill --all
# Cleanup stopped containers and orphaned resources
coi clean
coi clean --pools # Detect containers in unused storage pools
# Update coi to the latest release
coi update
Assign human-friendly names to containers for easy management from any directory:
# .coi/config.toml (in your project)
[container]
alias = "myproject"
coi shell myproject # Launch session using alias (from any directory)
coi attach myproject # Attach to running aliased container
See the Container Lifecycle and Sessions guide for full alias documentation.
--workspace PATH # Workspace directory to mount (default: current directory)
--slot NUMBER # Slot number for parallel sessions (0 = auto-allocate)
--persistent # Keep container between sessions
--resume [SESSION_ID] # Resume from session (omit ID to auto-detect latest for workspace)
--continue [SESSION_ID] # Alias for --resume
--profile NAME # Use named profile
--image NAME # Use custom image (default: coi-default)
Most container customization (network mode, mounts, environment variables, SSH agent, monitoring, timezone, resource limits, etc.) is configured via config files or profiles. See the Configuration wiki page for the full reference.
See the wiki for detailed documentation:
Resume a previous AI coding session with full history and credentials restored:
coi shell --resume # Auto-detect latest session for this workspace
coi shell --resume=<session-id> # Resume specific session
coi list --all # List available sessions
What's restored: Full conversation history, tool credentials, user settings, and project context. The profile used when the session was created is also automatically restored — no need to pass --profile again (explicitly passing --profile overrides the saved one). Sessions are workspace-scoped — --resume only finds sessions from the current workspace directory.
See the Container Lifecycle and Sessions guide for details on how session persistence works.
By default, containers are ephemeral (deleted on exit). Your workspace files always persist regardless of mode.
Enable persistent mode to also keep the container and its installed packages:
coi shell --persistent
# Or via config (~/.coi/config.toml)
[container]
persistent = true
What persists:
See the Container Lifecycle and Sessions guide for details.
Config file: ~/.coi/config.toml
[container]
image = "coi-default"
persistent = true
# storage_pool = "" # Empty = Incus default pool
# alias = "myproject" # Human-friendly name for this workspace's containers
[tool]
name = "claude"
permission_mode = "bypass"
# auto_context = true # Auto-inject sandbox context into tool's native system
Configuration hierarchy (highest precedence last):
~/.coi/config.toml)./.coi/config.toml)COI_CONFIG environment variableCLAUDE_ON_INCUS_*, COI_*)--workspace, --slot, --persistent, --resume, --profile, --image)Place a .coi/config.toml in any repository root to auto-configure COI for that project — useful for teams to share container image, environment, and resource limits.
See the Configuration wiki page for the full config reference, per-repo setup, profiles, and environment variables.
Profiles are reusable container configurations bundling image, tool, limits, mounts, build scripts, context files, and environment into named templates. Each profile is a self-contained directory under profiles/:
.coi/profiles/
├── rust-dev/
│ ├── config.toml # profile config
│ ├── build.sh # profile-specific build script
│ └── CONTEXT.md # AI agent context (appended to sandbox context)
└── python-ml/
├── config.toml
└── setup.sh
Example profile config (.coi/profiles/rust-dev/config.toml):
context = "CONTEXT.md"
forward_env = ["CARGO_HOME"]
[container]
image = "coi-rust"
persistent = true
[environment]
RUST_BACKTRACE = "1"
[tool]
name = "claude"
permission_mode = "bypass"
[limits.cpu]
count = "4"
coi shell --profile rust-dev # Use a profile
coi profile create rust-dev --image coi-rust # Create a new profile
coi profile list # List all profiles
Profiles support inheritance (inherits = "parent-name"), context files for AI-agent instructions, and custom build scripts. See the Profiles wiki page for complete documentation.
COI ships a JSON Schema 2020-12 document that describes every field accepted by a profile config.toml. External tools — such as a web UI or editor plugin — can consume it to validate profile data without duplicating COI's validation logic. The self-contained schema (with all definitions bundled inline) is produced by coi schema profile; the source files live under schema/ but are incomplete without the bundling step.
# Print the schema
coi schema profile
# Save it for use in another tool
coi schema profile > profile.schema.json
The schema covers all field types, enum values (network.mode, tool.permission_mode, tool.claude.effort_level, timezone.mode), required fields on mount entries, and rejects unknown keys. Any JSON Schema 2020-12 validator can use it — for example, the Ruby json_schemer gem or the Python jsonschema package.
See the Resource and Time Limits guide for complete documentation on controlling container resource consumption and runtime.
Quick example:
# ~/.coi/config.toml
[limits.cpu]
count = "2"
[limits.memory]
limit = "2GiB"
[limits.runtime]
max_duration = "2h"
What you can limit:
See the Container Lifecycle and Sessions guide for detailed explanation of how containers and sessions work.
Key concepts:
~/.coi/sessions-<tool>/--persistent): Container kept with all installed packages--resume): Restore AI conversation in fresh/existing containerQuick reference:
coi shell --persistent # Keep container between sessions
coi shell --resume # Resume previous conversation
coi attach # Reconnect to running container
coi persist # Convert ephemeral session to persistent
coi unfreeze <name> # Unfreeze paused/frozen container
coi unfreeze # Unfreeze all frozen COI containers
close # Properly stop container (inside, safe alias for poweroff)
coi shutdown <name> # Graceful stop (outside)
See the Network Isolation guide for complete documentation on network security and nftables-based network filtering.
Network modes:
# ~/.coi/config.toml
[network]
mode = "restricted" # Default — blocks private networks, allows internet
# mode = "allowlist" # Only specific domains/IPs allowed
# mode = "open" # No restrictions (trusted projects only)
COI includes built-in security monitoring to detect and respond to malicious behavior in real-time:
# Enable in config (~/.coi/config.toml)
[monitoring]
enabled = true
Protects against:
Automated response levels:
coi unfreeze to continue)Audit logs are stored at ~/.coi/audit/<container-name>.jsonl in JSON Lines format.
See the Security Monitoring wiki page for monitoring commands, configuration options, NFT setup, and audit log management.
coi audit exposes the audit stream as JSON Lines on stdout, ready to pipe
into a SIEM, jq, or a flat file:
# Dump the host-side audit log for a container
coi audit coi-abc-1
# Live in-container collector: auditd if available, otherwise syslog/auth.log,
# plus periodic ss + ps snapshots
coi audit coi-abc-1 --follow
# Re-stream a saved JSONL file
coi audit --file ./session.jsonl | jq -c 'select(.type=="net")'
Each line is a JSON object of the form:
{"ts":"2026-05-05T12:34:56.789Z","sessionId":"coi-abc-1","container":"coi-abc-1",
"type":"exec|net|file|audit|heartbeat","pid":42,"comm":"curl","args":"curl https://...",
"peer":"1.2.3.4:443","path":"/etc/shadow","msg":"...","raw":"..."}
The --follow collector is a small POSIX-sh agent (agent.sh, no binary
deploy). It picks the best available source — auditd first, falling back to
tail -F of /var/log/syslog and /var/log/auth.log — and adds
ss -tunp snapshots every 5 s plus ps-tree diffs every 2 s for new pids.
Measured idle overhead: ~4.5 MB total RSS across the agent and its tail/awk
helpers, ~0.0% CPU when the container is quiet.
Heartbeat / silent-failure detection. The agent emits a
{"type":"heartbeat","seq":N,"sources":"..."} event every 10 s. The host-side
watcher tracks the most recent heartbeat per session and surfaces a warning
if none arrives for 35 s (3 missed heartbeats with a small grace margin),
both on stderr:
[audit] WARNING agent silent on coi-abc-1 for 36s (last heartbeat 2026-05-05T12:34:46Z)
and inside the JSONL stream as a type=audit msg=agent.stale event so SIEMs
and downstream tooling can pick it up. When heartbeats resume, an
agent.alive event clears the warning. The watcher does not auto-kill the
connection — operators decide. Tunables: COI_AUDIT_HEARTBEAT_INTERVAL on
the agent side; the 35 s stale threshold and 5 s check cadence are
host-side defaults exposed as audit.DefaultStaleAfter and
audit.DefaultCheckInterval for embedders.
Privacy model: every event stays on the host running coi audit. Nothing
is sent off-machine unless you pipe it elsewhere yourself.
See the Security Best Practices guide for detailed security recommendations.
COI automatically mounts security-sensitive paths as read-only to prevent supply-chain attacks:
.git/hooks, .git/config, .husky, .vscodeSet [git] writable_hooks = true in config to opt out, or customize protected paths via config. See the wiki for details.
See the System Health Check guide for detailed information on diagnostics and what's checked.
Run diagnostics:
coi health # Basic health check
coi health --format json # JSON output
coi health --verbose # Additional checks
What it checks: System info, kernel version, Incus setup, permissions, security posture (seccomp/AppArmor), privileged container detection, network configuration, storage, monitoring prerequisites, and running containers.
Exit codes: 0 (healthy), 1 (degraded), 2 (unhealthy)
See the Troubleshooting guide for common issues and solutions.
Common issues:
coi health to diagnose setup problemsSee the FAQ for answers to common questions.
Topics covered:
Native macOS app to monitor Claude AI usage limits and watch your coding sessions live
npx CLI installing 100+ agents, commands, hooks, and integrations in one command
干净、强大、属于你的 AI Agent 平台 --AI agents, without the clutter.
Pocket Flow: Codebase to Tutorial