isx

Give your AI coding agents their own machines, not your credentials. isx.run is the website, with the full documentation.

An AI agent in your terminal can read your API keys, your GitHub token, your ~/.ssh and every repo you have checked out. Your IDE and build tools execute anything the agent writes.

isx onboards agents the way you'd onboard a new teammate:

Each agent works in its own machine and asks for no approval, so you can run many side by side and build automations that run with nobody watching. isx runs on Linux and macOS, on your hardware, and your repositories and credentials stay there.

Agents are the main use, not the only one. The same disposable machines are ideal for triaging untrusted patches, reproducing bug reports and testing on a clean system.

Built with Quarkus and Tamboui, powered by Incus system containers. Written in Java, compiled to native binaries with GraalVM. isx was formerly known as incus-spawn.

Quick Start

Requires Linux, or macOS 15 (Sequoia) or later (Installation); isx init sets up the rest, or your coding agent can do it all for you.

brew install Sanne/tap/incus-spawn
sudo dnf install -y 'dnf5-command(copr)'   # on RHEL 9: 'dnf-command(copr)'
sudo dnf copr enable sanne/incus-spawn
sudo dnf install incus-spawn
curl -fsSL https://sanne.github.io/isx-apt-releases/public.gpg | sudo gpg --yes --dearmor -o /usr/share/keyrings/incus-spawn.gpg
echo "deb [signed-by=/usr/share/keyrings/incus-spawn.gpg] https://sanne.github.io/isx-apt-releases stable main" | sudo tee /etc/apt/sources.list.d/incus-spawn.list
sudo apt update && sudo apt install incus-spawn
curl -fsSL https://isx.run | sh
jbang app install isx@Sanne/incus-spawn
jbang app install isx-proxy@Sanne/incus-spawn

The package is called incus-spawn, and it installs the isx command.

# One-time host setup (Incus, firewall, auth)
isx init

On a fresh Linux host, isx init adds you to the incus-admin group and finishes its run in that group. Other terminals get the group at your next login, or in each one with newgrp incus-admin.

A template is a machine image you build once: an OS, tools and repos. The template below adds Claude Code to the built-in tpl-minimal template. Save it as ~/.config/incus-spawn/images/tpl-agent.yaml, or run isx templates new tpl-agent and paste it over the skeleton that opens in your editor:

name: tpl-agent
description: Claude Code on the base OS
parent: tpl-minimal
tools:
  - claude
default-action: claude
# Build it (builds missing parent images first)
isx build tpl-agent

# Branch it: an instant copy-on-write machine of its own, with Claude Code open inside
isx branch my-first --from tpl-agent

# The interactive TUI: your templates and branches
isx

Claude Code signs in with the Claude credential you set up in isx init; isx account add claude adds one later. Claude Code never sees the credential: the proxy adds the credential to each request after the request leaves the instance. If you did not install the services isx init offers, start them before building: isx proxy start on Linux, isx vm start && isx proxy start on macOS.

For another agent, replace claude with codex, pi, opencode, gemini-cli, bob or copilot; see Agents. Pi and opencode use your Claude credential too, unless their provider names another API (Pi, opencode). To give the agent a project, add repos: (Declarative Repos). Its commits come back to your host with git fetch (Git Remotes).

Credential Isolation

The agent must be free to act, so its instance cannot hold anything worth stealing. API keys and tokens never enter an instance in any form. Instead, a proxy on your host (isx proxy) adds the real credentials to the agent's requests as the requests leave the instance, so curl, git, gh, claude and pi work unmodified inside it.

How it works:

What the proxy can sign in as:

Credential Who uses it in the instance What you give isx init
Anthropic API key Claude Code (claude), Pi (pi), opencode (opencode) the key
Claude Pro or Max Claude Code (claude), Pi (pi), opencode (opencode) the token from claude setup-token; the proxy adds the OAuth bearer token
Vertex AI Claude Code (claude), Pi (pi), opencode (opencode) your project and region; the proxy translates each request and signs it with the host's GCP credentials, which never enter the instance
OpenAI API key Codex CLI (codex), Pi (pi), opencode (opencode) the key
Gemini API key Gemini CLI (gemini-cli), Pi (pi), opencode (opencode) the key
IBM API key Bob Shell (bob) the key
GitHub token gh, git, GitHub Copilot CLI (copilot) the token
Atlassian API token the atlassian-mcp tool, for Jira and Confluence your account email and the token
A service of your own whatever your tool YAML installs its credential, declared in the YAML's proxy: block (Proxy Credentials)

A credential can have several accounts, for example a personal and a client Claude subscription, or two GitHub identities. Each template or instance chooses which account it uses: see Credential accounts. Git must use HTTPS URLs, not SSH; gh defaults to HTTPS.

The proxy must be running for every instance that has a network. isx init installs it as a service, systemd on Linux and launchd on macOS, or you run isx proxy start in a terminal of its own. isx checks that the proxy is reachable and compatible before a build, a branch or a shell.

The proxy also caches container image layers and build artifacts on the host, so the same dependency is never downloaded twice (Caching).

Credentials reach the login environment

Each start replaces the placeholders with proof tokens unique to the instance and the credential, such as gho_isx_… in GH_TOKEN, exported by the login profile. The proxy adds an instance's credentials only to requests carrying its proof token. The tokens stay the same across stops, starts and reboots, so a nested service you configured with one keeps working.

Only what runs in the instance's login environment receives the proof tokens, so a nested container gets none unless you pass one in. Plain Git is the exception: for its HTTPS requests to github.com, a credential helper isx installs presents the GitHub proof token even outside a login shell.

Credential proofs says how to share or revoke proof tokens, and what to do after an upgrade.

Git Configuration

With a GitHub token configured, every instance gets a ready-made .gitconfig: your GitHub name and email, the private @users.noreply.github.com address when there is one, and sensible defaults.

Commit signing is not supported inside an instance yet (#271). To sign, fetch the changes to your host through git remotes and rebase there.

Branching

A branch is an instance made from a template, the way git branch makes a branch from a commit: an instant copy-on-write clone. It has its own filesystem, and nothing it changes reaches the template or another branch.

The storage backend (btrfs, zfs or lvm) shares the unchanged data, so a branch uses disk space only for what it changes. isx init creates a btrfs storage pool if there is none.

tpl-agent  (stopped template, ~2GB)
  ├── fix-nasty-bug     (running, uses ~50MB extra)
  ├── review-pr-423     (running, uses ~30MB extra)
  └── experiment        (stopped, uses ~10MB extra)

Install packages, break things, and destroy the branch when done. Sudo works without a password, and the shell sets the terminal title to isx:<name>, so you always know which instance you are in.

What a branch can have, each on request:

The TUI (isx with no arguments) is a Midnight Commander-style view of your templates and branches. It has dialogs for branching, renaming and building, F3 for an instance's details and F9 for tool actions.

Without function keys, press the digit instead: 1 to 0 stand for F1 to F10, and Alt with a digit stands for Shift with that function key. On macOS, Alt is Option once the terminal sends Option as Meta.

A storage gauge and per-row disk usage show what is filling the pool. Sizes are approximate (~): the base template carries the shared base image, and each branch only its own data. Press C to reclaim space, or on macOS grow the disk with isx vm resize <size>.

Templates pre-install your baseline tools and repos. Integrations are installed through the same tool system: VS Code Remote, JetBrains Gateway and agent skills.

Network Modes

Each branch runs in one of three network modes:

Mode Flag What it means
Full internet (default) Unrestricted access through NAT, signed in through the proxy
Proxy only --proxy-only Outbound traffic reaches only the proxy; the host enforces the restriction, so root in the instance cannot remove it
Airgapped --airgap No network device at all, and no pci or usb passthrough

Git Remotes

An instance is isolated, but the work done in it has to reach your host. isx speaks git's remote helper protocol, so plain git fetch, git push and git pull work between a host repo and a repo in an instance:

# Inside the instance, the agent makes some commits...
# Back on the host:
git fetch fix-auth
git diff main..fix-auth/main    # review exactly what it did
git cherry-pick fix-auth/main   # take what you like

This is the intended review workflow: the code you review is the code you take, whatever the agent does afterwards. You act on fetched commits, which git identifies by a hash of their content, never on a live directory the agent can still change. The FAQ says why there is deliberately no read-write project mount.

isx:// URLs

The remote uses the isx:// URL scheme, where ~ expands to /home/agentuser:

git remote add fix-auth isx://fix-auth/~/quarkus
git fetch fix-auth
git diff main..fix-auth/main

An absolute path inside the instance follows a double slash, as in isx://fix-auth//home/agentuser/quarkus. The instance must be running for git operations to work.

Automatic remotes

With host-paths in ~/.config/incus-spawn/config.yaml, isx manages the remotes for you:

# Base directories where your repos live on the host
# Subdirectories are scanned recursively (up to 4 levels deep),
# so ~/projects finds ~/projects/java/my-repo, ~/projects/go/another-repo, etc.
# If a repo name appears in multiple locations, the checkout whose remote matches is used;
# add an explicit repo-paths entry when more than one matches
host-paths:
  - ~/projects
  - ~/workspace

# Explicit overrides for repos in non-standard locations or to resolve ambiguity
repo-paths:
  quarkus: ~/work/quarkus
  hibernate: /opt/hibernate

isx branch adds a remote named after the instance to each host repo that matches one in the instance. SSH and HTTPS URLs of the same repo count as the same. isx destroy removes the remote again.

Templates

A template is a machine image you prepare once, in YAML: an OS, packages, tools and repositories. Templates inherit from one another, and building one builds any missing parent first:

name: tpl-maven
description: JDK + Maven
parent: tpl-minimal
packages:
  - java-25-openjdk-devel
tools:
  - maven-3

tpl-minimal, on a Fedora base, is built in. Your own templates go in ~/.config/incus-spawn/images/, or a project's .incus-spawn/images/. isx templates new <name> opens a skeleton listing every field, and isx templates edit <name> validates what you save.

isx build tpl-maven                  # builds missing parents first
isx build tpl-maven --with-parents   # rebuilds it and its parents from scratch
isx build --out-of-sync              # rebuilds what changed since it was built

Templates lists every field: repositories cloned at build time, the working directory and default action, host resources, base image updates and VM templates.

Agents

An agent is a tool in a template's tools: list, set up for unattended work. It signs in through the proxy with an account you configured in isx init, whose menu lists each credential under the tool that owns it, so Pi, opencode and Copilot have no entry of their own:

Agent Tool Signs in with
Claude Code claude an Anthropic API key, Claude Pro/Max, or Vertex AI
Codex CLI codex an OpenAI API key
Pi pi Claude's credentials, the OpenAI key or the Gemini key
opencode opencode Claude's credentials, the OpenAI key or the Gemini key
Gemini CLI gemini-cli a Gemini API key
Bob Shell bob an IBM API key
GitHub Copilot CLI copilot the GitHub token gh uses

Agents has each agent's parameters (model, reasoning effort, provider), agent skills, and the notes isx writes for an agent about its instance.

Tools

Templates are made of tools. gh, herdr, maven-3, orca, podman, sshd, the VS Code and IntelliJ remote backends, tmux and zmx ship with isx; isx tools list -v lists them all. Your own tools are YAML files in ~/.config/incus-spawn/tools/ or a project's .incus-spawn/tools/: packages, commands, environment variables, TUI actions, and credentials the proxy adds for a service of yours. See Tools.

Delegating over MCP

An agent on your host, such as Claude Code, can control isx through isx mcp: branch instances from templates you approved, run builds and tests in them, and give whole tasks to Claude Code, Codex, Pi or opencode inside an instance. isx mcp is off by default, because it gives an agent that control; isx init offers to set it up.

Delegating from an agent on your host says what such an agent can and cannot do, and how to run the coordinating agent in an instance of its own, branched with isx branch --mcp-client. Driving isx mcp from a program is the reference for a program of your own that controls isx mcp.

Configuration

isx init writes your settings and credentials to ~/.config/incus-spawn/config.yaml; your own templates and tools go beside it, in images/ and tools/. A credential can have several accounts, for example a personal and a client Claude subscription, and each template or instance chooses which account it uses. Configuration covers the files, credential accounts and the download caches.

Installation

isx runs on Linux, and on macOS 15 (Sequoia) or later. Windows is not supported.

Linux: isx init installs Incus with your package manager. It also installs and enables firewalld when the host has neither firewalld nor UFW, since the proxy's redirect needs a firewall.

macOS: isx init uses vfkit to provision a lightweight Linux VM, and the VM starts when needed. isx vm start|stop|restart|status|resize|reset|console|check-version manages the VM, and its reference says what to do when the VM stops answering. Apple Silicon is supported, and Intel Macs are not: v0.4.2 and v0.5.0-dev.2 were the last releases built for them.

On macOS isx runs containers only. These are Linux-only:

Behind TLS inspection (a corporate proxy that re-signs HTTPS), isx trusts the host's CA store for its own downloads and for the proxy's upstream connections.

sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca.pem
isx proxy restart

isx doctor lists the Keychain CAs isx trusts.

Installed with (Quick Start) Update with
Homebrew brew upgrade incus-spawn
DNF: Fedora 43 and later, RHEL 9 and 10, CentOS Stream 9, AlmaLinux 9, Rocky Linux 9 (via EPEL) sudo dnf upgrade
APT sudo apt upgrade
curl -fsSL https://isx.run | sh the same command again
JBang both jbang app install commands again

The curl script installs the isx and isx-proxy native binaries to ~/.local/bin (set INSTALL_DIR to change it), with no JVM needed, and only once every download matches the release's SHA256SUMS. JBang installs need both commands, and jbang must stay on your PATH.

A source build (./install.sh in a checkout) does not change a Homebrew install, since other accounts may use it, so whichever isx comes first on your PATH is the one you and your proxy service run.

To uninstall, run uninstall.sh:

Shell completions are available for bash, zsh, fish and PowerShell via isx completion <shell>.

CLI

Command Description
isx Launch the interactive TUI
isx init One-time host setup
isx build Build or rebuild template images
isx branch Create a CoW clone from a template or instance
isx shell Open a shell in an instance
isx start Start an instance without opening a shell
isx stop Stop a running instance
isx run Run an action on an instance
isx destroy Destroy an instance
isx list List instances, for people or for scripts
isx update-base Check for and install base image updates
isx update-all Update packages and repos in all templates
isx templates Manage template definitions
isx tools List and inspect available tool definitions
isx account Add credentials, and show or change the accounts an instance uses
isx project Manage project templates
isx proxy Manage the MITM authentication proxy
isx doctor Run health checks and offer to fix problems
isx clean Remove cached data, state, or configuration
isx reset Reset to a clean slate
isx vm Manage the VM appliance (macOS only)
isx ask AI-powered help
isx mcp Serve isx to a local agent over MCP
isx completion Print shell completion script

Use isx <command> --help for detailed options on any command. Scripts read --format=plain or --format=json, which stay stable: see Scripting isx.

Further reading