code-on-incus: full-OS containers with kernel-level agent defense
Give each AI agent its own isolated machine with root, Docker, and systemd. Active defense detects and stops threats automatically.
At a glance
- What is it?
- coi runs Claude Code, Codex, opencode, pi or omp inside an Incus system container that has root, systemd and Docker, while nftables monitoring watches for reverse shells and exfiltration. The real question is whether you want the agent on a machine it can reconfigure, and how much of the defense you can actually verify.
- Who is it for?
- Adopt coi if you already run Incus on Linux and want agents to have a real machine with root, Docker and systemd while keeping host credentials out of the container. Skip it if you need a portable sandbox on macOS or Windows without a Linux VM, or if you want a per-command tool switch rather than config and profile edits.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem coi solves: agents that need a real machine, not a locked box
Most sandboxes for coding agents answer one question: how do I stop the agent from touching my host. They answer it by removing capability. The agent gets a restricted filesystem, a proxy for network access, and no package manager. That works until the agent needs to install a system library, start a service, or run Docker, at which point the sandbox either breaks the task or the developer disables it. The README frames the opposite trade: Incus system containers run a full OS with systemd and native Docker inside, so the agent installs packages and runs services the way it would on a server, while the host stays out of reach. The stated audience is developers who run AI agents and want to know what those agents are doing, including people running several agents in parallel who need each session isolated from the others. Credential handling is the other half of the pitch: SSH keys, .env files, Git tokens and host environment variables are described as never exposed unless explicitly mounted, and the README suggests forwarding a host socket or minting a short-lived token per session instead of putting the secret inside the container.
How the isolation and the monitoring actually fit together
Two mechanisms are visible in the material. The first is Incus itself. Each session is a system container, not an application container, which is why systemd and Docker work inside. The project directory is mounted at /workspace, file ownership is handled so files come out correctly owned on the host (the README calls this out against Docker's permission problems), and workspace changes are written back. Sessions can be ephemeral, deleted on exit, or persistent, kept with installed packages, and the README states that workspace files and session history are saved either way, with session resume restoring conversation history and credentials. Parallel sessions on one project get separate home directories per slot. The second mechanism is the defense layer. The README describes kernel-level monitoring over nftables that catches reverse shells, C2 connections, data exfiltration, DNS tunneling and credential scanning in real time, with automatic pause on a HIGH finding and automatic kill on a CRITICAL one. Network isolation is also nftables-based, with three modes. Audit output is JSONL, described as forensics. What the material does not give is the rule set behind those severity labels, the false-positive rate, or what happens to in-flight work when a container is killed mid-edit. Treat auto-kill as a behavior you configure and observe, not one you can predict from the README.
Getting it running: three commands, then profiles
The install path in the README is three commands. First, curl -fsSL https://raw.githubusercontent.com/mensfeld/code-on-incus/master/install.sh | bash. Second, coi build, described as first time only and taking roughly 5 to 10 minutes to build the base image. Third, from any project directory, coi shell. The prerequisite is Linux with Incus installed; macOS is supported through Colima or Lima according to the README, with a separate wiki page for that setup. Profiles are the configuration surface. coi shell --profile rust-dev starts a named setup; coi profile create rust-dev scaffolds a new one whose config.toml you then edit; coi profile list shows what exists; coi profile info hardened prints what that preset locks down. Profiles support inheritance through inherits = "parent" and can carry build scripts and AI-agent context files. Tool selection lives in config, not in a per-command flag: a [tool] block with name = "claude" (or "codex", "opencode", "pi", "omp") and permission_mode = "bypass" to run autonomously or "interactive" to ask first, placed in ~/.coi/config.toml or ./.coi/config.toml. The README notes that switching tools on the same persistent container is done by giving two profiles the same container setting, which is a real constraint: there is no coi shell --tool codex flag to reach for.
The hardened profile is the part worth reading closely
The preset the README pushes hardest is hardened, aimed at opening a repository you do not trust. It combines restricted network with no exfiltration path, workspace secret masking, an ephemeral container, no SSH-agent forwarding, and live threat monitoring with auto-pause and auto-kill. One documented behavior matters more than the list: the profile overrides a weaker global config, so a global mode = "open" still becomes restricted when hardened is applied. That override direction is the right one for a security preset, because the failure mode you fear is a permissive default leaking into the case where you needed the strict one. It also needs zero setup beyond the base image. The honest caveat is that hardening is a bundle. If you need network access to a package registry inside an untrusted-code session, the restricted mode is the thing you will be tempted to loosen, and the README does not describe a per-rule escape hatch for that case. The command to inspect the bundle before trusting it is coi profile info hardened.
Where coi is the wrong tool
The dependency on Incus is the first boundary. If you are not on Linux, you are running a Linux VM through Colima or Lima, which is a different operational shape than a native install. The second boundary is the container model itself. A system container shares the host kernel, which is what makes systemd and Docker work and also what makes the nftables monitoring meaningful, but it is not a virtual machine boundary. If your threat model requires kernel separation, a microVM-based sandbox is the appropriate class of tool, not this one. Third, the defense layer is detection with automated response, and the README does not publish the detection rules, so you cannot audit what it will and will not catch from the repository description alone. A determined agent that stays inside the rules it does not trip will not be paused. Fourth, the tool-switching constraint described above is a genuine friction point for anyone who alternates between Claude Code and Codex on the same long-lived environment. Finally, the project is a single-maintainer tool that describes itself as not a product and not a startup, which is a fair description of scope and also a fair warning about support expectations.
What it is not: the difference from Docker-based sandboxes
The obvious comparison is a Docker-based agent sandbox, and the README's own table draws the line at four points: credential isolation as a default rather than partial, real-time threat detection over nftables, an automated response to reverse shells and exfiltration, and native Linux execution where the Docker alternative is described as microVM-only on macOS and Windows. The design difference underneath is that Docker-based sandboxes typically give the agent a container built from an image you control, with the agent's capabilities fixed at build time, while coi gives the agent a machine it can mutate at runtime and monitors the resulting behavior. That is a real philosophical split. The Docker approach is easier to reason about because the surface is smaller; the coi approach handles tasks that need a package manager, a service, or a Docker daemon without the developer reaching for an escape hatch. Neither is strictly better. If your agents only edit files and run tests, the smaller surface is the safer default. If your agents routinely install dependencies or start services, the fixed-image model is the one that breaks first.
Maintenance, upgrades and the MIT licence
The release cadence visible in the material is roughly monthly: v0.12.0 on 2026-09-09, v0.11.2 and v0.11.1 both in August 2026. That is frequent enough that pinning a version is worth considering for a team environment, and the project is pre-1.0, which in practice means config keys and profile schema can move between minor releases. The base image is built locally with coi build, so image rebuilds are part of your upgrade path, and the README's estimate of 5 to 10 minutes for the first build is the cost you pay per rebuild, not per session. Persistent containers that carry installed packages are the other maintenance surface: they accumulate state, and the README does not describe a pruning or garbage-collection command for them. The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is a permissive licence with no copyleft obligation on your own code. This is a description of the licence text, not legal advice; if you are redistributing coi inside a product, have counsel read the MIT terms rather than this paragraph.
Editorial conclusion
Adopt coi if you already run Incus on Linux and want agents to have a real machine with root, Docker and systemd while keeping host credentials out of the container. Skip it if you need a portable sandbox on macOS or Windows without a Linux VM, or if you want a per-command tool switch rather than config and profile edits. Verify first: run coi profile info hardened and read the config it prints, check that your Incus version supports system containers with nftables, and confirm what the monitoring rules actually alert on before you trust the auto-pause and auto-kill behaviour with an untrusted repository.
Community notes