Skip to content

yeus/nix-ai-sandbox

Repository files navigation

AI sandbox for Podman + real VS Code + project flakes

Run VS Code and AI coding agents inside an isolated container, while keeping your development environment defined by your project flake.

This is the flat-folder version and is intended to be shareable via git subtree.

Files in this folder:

  • Dockerfile
  • container-entrypoint.sh
  • ai-sandbox
  • ai-sandbox.nix
  • README.md

Why this exists

With modern AI workflows, the bigger risk is often not just CLI tools, but VS Code plugins.

Coding-agent extensions can:

  • execute shell commands
  • modify your repository
  • access tokens and credentials

In many cases you do not fully know what they do, and some are not even open source.

Even if a tool sandboxes parts of its execution, VS Code itself still usually runs on your host machine.

ai-sandbox takes a different approach:

  • VS Code runs inside a container
  • extensions run inside that container
  • your host $HOME is not mounted
  • your host /nix is not mounted
  • the actual development environment still comes from your project flake.nix

So instead of trusting every coding-agent plugin, you isolate the whole editor environment it runs in.

What it does

  • builds one global Ubuntu image with real Microsoft VS Code and Nix
  • uses bind-mounted host directories for /nix and sandbox home (defaults: ~/.cache/ai-sandbox/nix and ~/.cache/ai-sandbox/home)
  • mounts the current project at /workspace
  • if the project is a Git submodule, mounts the top superproject at /workspace and opens the submodule path inside it (preserves nested submodule .git path resolution)
  • if a flake is available, launches via nix develop
  • if no flake is available, launches plain VS Code / plain shell
  • supports multiple concurrent containers per workspace (auto instance names, optional --instance)

In practice, that means:

  • no per-project container config is required
  • you can just run ais or ai-sandbox inside a flake-enabled repository
  • the sandbox reuses a shared /nix cache across projects
  • VS Code, extensions, and coding agents run inside the container instead of directly on your host

Why this differs from Dev Containers

Dev Containers are mainly about reproducible development environments.

This project is more specifically about running VS Code itself in a sandboxed container, which makes VS Code extensions and coding-agent plugins much safer to use.

Aspect ai-sandbox Dev Containers
Goal isolate VS Code + agent plugins reproducible dev environments
Env definition flake.nix via nix develop devcontainer.json (+ Docker / Compose)
Per-project config none needed usually required
Editor runs inside container on host
Plugin isolation yes usually no
Cache reuse shared /nix store Docker layers
Multi-service setup no yes
Portability mostly Linux/Nix cross-platform

If your main concern is “I want to use coding-agent plugins without giving them direct access to my host editor session”, this is a better fit than normal devcontainers.

If your main concern is standardized team environments across platforms and tools, devcontainers are the more standard choice.

Commands

Build/update the base image only:

ai-sandbox build-base

Build the image and then install default user-space software (Codex + VS Code):

ai-sandbox build .

Install or refresh default user-space software without rebuilding:

ai-sandbox install .
ai-sandbox install . --force
ai-sandbox install . --only codex
ai-sandbox install . --only vscode

Inside sandbox terminals, apt-get and apt are available directly. They are wrapped to run with root privileges for package-management commands.

Rebuild the base image from scratch (remove old image tag first, keep storage dirs):

ai-sandbox rebuild

Remove persistent sandbox containers (keep home/nix storage):

ai-sandbox reset-container .
ai-sandbox reset-container --all

Reset sandbox storage (clear ~/.cache/ai-sandbox/nix and ~/.cache/ai-sandbox/home by default):

ai-sandbox reset-storage

Repair shared ai-sandbox Nix cache in place (verify/repair store paths, no delete):

ai-sandbox repair-nix

Sync global Codex instructions (sandbox-wide, not project-local):

ai-sandbox agents pull
ai-sandbox agents push
ai-sandbox agents reset
ai-sandbox agents clear
ai-sandbox agents pull --file ./AGENTS.md --force

Inside sandbox terminals, ai-sandbox is available as an alias to /workspace/ai-sandbox/ai-sandbox, so these agents commands can be run there too.

Sync global Codex skills:

ai-sandbox skills pull
ai-sandbox skills push
ai-sandbox skills push --dir ./skills --force

Warm the current project flake into the shared /nix storage directory:

ai-sandbox warm .

Start VS Code for the current directory:

ai-sandbox start .

By default, start streams startup logs (including flake/Nix setup) and auto-detaches once VS Code launch begins.

Start and continue following logs even after VS Code launch:

ai-sandbox start . --logs

Start with a stable instance suffix (useful for multiple VS Code windows/workspaces side by side):

ai-sandbox start . --instance vscode-a
ai-sandbox start . --instance vscode-b

Each sandbox instance now uses a hybrid VS Code profile model (details below).

If you do not pass --instance, ai-sandbox now uses a stable default instance name per workspace so VS Code profile state is preserved across relaunches. If that default instance is already running, ai-sandbox automatically falls back to a unique instance suffix.

Open an interactive shell in the sandbox:

ai-sandbox shell .

By default, start and exec reuse persistent per-workspace containers (instance=default) instead of always using disposable --rm containers. shell starts a fresh disposable container each time so interactive sessions stay isolated.

Run a command directly in shell mode (flake-aware):

ai-sandbox shell . -- codex
ai-sandbox shell codex

Run any command in the sandbox (auto-reuses a running workspace sandbox when available):

ai-sandbox exec . -- codex --version
ai-sandbox exec . -- ai-sandbox-default-install --only codex --force

With the short alias, unknown commands are routed to sandbox exec automatically:

ais codex --version
ais ai-sandbox-default-install --only codex --force
ais code --version

The shell prompt includes a clear AI-SANDBOX marker, project name, directory, and Git branch/status.

Show logs from an existing sandbox container:

ai-sandbox logs .        # one-shot
ai-sandbox logs . -f     # follow

Open a file in the running sandbox VS Code from the host:

ai-sandbox open-in-editor /abs/path/to/file.ts 1062 55

Override the flake location:

ai-sandbox start . --flake /path/to/flake.nix
ai-sandbox start . --flake /path/to/flake-root
ai-sandbox warm . --flake ../some/other/flake-project

The workspace is still the first positional directory. --flake only changes which flake gets used for nix develop.

Override network mode (default is host for localhost OAuth callback compatibility):

ai-sandbox start . --network host
ai-sandbox start . --network bridge

Automatic network healing for long-running containers (default enabled):

ai-sandbox start . --auto-reconnect
ai-sandbox start . --no-auto-reconnect
ai-sandbox start . --auto-reconnect-interval 8

Diagnose or repair an already running sandbox after host network changes:

ai-sandbox doctor-net .
ai-sandbox reconnect-network .

Typical usage

In a flake-enabled repository:

cd your-project
ai-sandbox warm .
ai-sandbox start .

Important: ai-sandbox start launches VS Code from nix develop when your project exports a default dev shell, so flake-provided tools and shellHook environment variables should be available inside VS Code and agent processes.

That does not replace project bootstrap steps. Repo-local tools such as vue-tsc often come from node_modules/.bin, Corepack shims, generated SDKs, or other files that only exist after you run the project initialization command inside the sandbox itself. If a tool is present in your normal dev shell but missing for Codex, the usual fix is to open a terminal in the sandboxed VS Code window and run the repo's setup step there first, for example yarn install, pnpm install, npm install, or a project-specific bootstrap command.

Or, if you want a shell instead of VS Code:

ai-sandbox shell .

If you have the short alias installed:

cd your-project
ais

That is the intended workflow: enter a project, run ais, and get VS Code inside a container with the project dev environment coming from the flake.

VS Code Profile Model (Hybrid)

When multiple independent VS Code processes run in different containers, sharing one full --user-data-dir can break Chromium webview/service-worker state.

To keep concurrent containers stable while preserving desktop-like behavior, ai-sandbox uses:

  • per-instance --user-data-dir internals at /sandbox-home/.vscode-data/instances/<workspace-hash>-<instance>
  • shared user config at /sandbox-home/.vscode-shared-user:
    • settings.json
    • keybindings.json
    • tasks.json
    • locale.json
    • snippets/
  • shared extensions at /sandbox-home/.vscode-extensions/shared

Practical behavior:

  • settings/keybindings/snippets stay consistent across instances
  • extensions installed in one instance appear in all instances
  • webview/process/cache internals remain isolated per instance to avoid cross-container collisions

Persistent Home, Codex Instructions, and Updates

Sandbox home is persisted in ~/.cache/ai-sandbox/home by default (configurable), and is mounted at /sandbox-home inside containers.

  • ai-sandbox build, ai-sandbox build-base, and ai-sandbox rebuild do not erase sandbox home.
  • ai-sandbox reset-storage is the command that erases persisted home and nix storage.

CODEX_HOME is pinned to:

/sandbox-home/.codex

Codex global instructions are seeded once (if missing) to:

/sandbox-home/.codex/AGENTS.md

from image default:

/usr/local/share/ai-sandbox/default-AGENTS.md

This means global instructions and skills are persisted on host storage and can be modified from any workspace. Project-local AGENTS.md remains separate.

ai-sandbox also ensures ~/.codex/config.toml contains:

[sandbox_workspace_write]
writable_roots = ["/sandbox-home/.codex"]

so Codex started from /workspace can still edit global files in CODEX_HOME.

To fully disable default seeding and erase global Codex instructions:

ais bash -lc 'mkdir -p ~/.codex && touch ~/.codex/.disable_default_agents_seed && rm -f ~/.codex/AGENTS.md ~/.codex/AGENTS.override.md'

To re-enable default seeding later:

ais bash -lc 'rm -f ~/.codex/.disable_default_agents_seed'

Codex is installed in user space (~/.npm-global) and persisted in sandbox home:

ai-sandbox install . --only codex
ais codex --version

VS Code runs from a user-space install in sandbox home:

ai-sandbox install . --only vscode --force
ais code --version

Shell behavior note:

  • ai-sandbox shell startup does not source $HOME/.bashrc by default (to avoid host/sandbox prompt hook conflicts)
  • set AI_SANDBOX_SOURCE_USER_BASHRC=1 if you explicitly want to opt back in

Troubleshooting

If only the first sandbox VS Code window works and later ones show:

Error loading webview: Could not register service worker: InvalidStateError

then clear stale shared VS Code profile data from older ai-sandbox runs and restart:

ai-sandbox reset-storage

Then launch separate instances again (for example with different --instance names).

If nix develop fails with missing /nix/store/... files, run:

ai-sandbox repair-nix

This verifies and repairs the shared ai-sandbox /nix cache without deleting it.

If you see database disk image is malformed for /nix/var/nix/db/db.sqlite:

  1. Stop running ai-sandbox containers for this workspace.
  2. Run ai-sandbox repair-nix.
  3. If it still fails, run ai-sandbox reset-storage to recreate shared caches from scratch.

Recent ai-sandbox versions now seed /nix only once and avoid copying seeded Nix DB runtime files into a live cache, which reduces the chance of this corruption pattern.

If you recently changed ai-sandbox scripts, rebuild and restart containers so the new entrypoint is used:

ai-sandbox rebuild

To confirm home persistence across rebuild:

ais bash -lc 'echo ok > ~/.local/state/ai-sandbox-persist-check'
ai-sandbox rebuild
ais bash -lc 'cat ~/.local/state/ai-sandbox-persist-check'

If dev-server "open in editor" links (error overlays, stack traces, click-to-open file links) open host VS Code instead of the sandbox window:

ai-sandbox start .
LAUNCH_EDITOR=ais <your-dev-command>

This pattern is framework-agnostic and works for many stacks that honor LAUNCH_EDITOR through launch-editor style tooling (for example Vite apps like React/Vue/Svelte, Quasar CLI with Vite, and other dev servers that support LAUNCH_EDITOR).

Examples:

LAUNCH_EDITOR=ais npm run dev
LAUNCH_EDITOR=ais pnpm dev
LAUNCH_EDITOR=ais yarn dev
LAUNCH_EDITOR=ais quasar dev

This works because ais detects launch-editor style arguments (<file> [line] [column]) and forwards them to:

ai-sandbox open-in-editor <file> <line> <column>

If you prefer, ai-sandbox-launch-editor remains available and does the same forwarding.

If you do not use the Nix module helper package, create a tiny wrapper script and point LAUNCH_EDITOR to it:

#!/usr/bin/env bash
exec ai-sandbox open-in-editor "$@"

Then:

LAUNCH_EDITOR=/absolute/path/to/your-wrapper.sh <your-dev-command>

If shell prompts look corrupted (for example visible \[\] markers), leave AI_SANDBOX_SOURCE_USER_BASHRC unset (default 0) or explicitly disable it:

export AI_SANDBOX_SOURCE_USER_BASHRC=0

Recommended NixOS integration

Put this whole folder somewhere in your NixOS repo, for example:

modules/ai-sandbox/
  Dockerfile
  container-entrypoint.sh
  ai-sandbox
  ai-sandbox.nix
  README.md

Import the module from your system config:

{
  imports = [
    ./modules/ai-sandbox/ai-sandbox.nix
  ];

  programs.ai-sandbox.enable = true;
}

Then rebuild:

sudo nixos-rebuild switch --flake .

After that, ai-sandbox is available everywhere.

Share this folder as a Git subtree

Create a split branch from this repo and push it to a dedicated remote:

git subtree split --prefix=ai-sandbox --branch ai-sandbox-split
git push git@github.com:<org>/<ai-sandbox-repo>.git ai-sandbox-split:main

Consume it from another repository:

git subtree add --prefix=modules/ai-sandbox git@github.com:<org>/<ai-sandbox-repo>.git main --squash

Pull updates later:

git subtree pull --prefix=modules/ai-sandbox git@github.com:<org>/<ai-sandbox-repo>.git main --squash

Push local subtree changes back to the subtree remote:

git subtree push --prefix=ai-sandbox git@github.com:<org>/<ai-sandbox-repo>.git main

Direnv usage in projects

Do not auto-launch the container from direnv. That gets annoying fast.

Use direnv to expose helper aliases instead.

Example .envrc:

use flake

alias sandbox-start='ai-sandbox start .'
alias sandbox-shell='ai-sandbox shell .'
alias sandbox-warm='ai-sandbox warm .'

If your flake is elsewhere:

use flake ./packaging/nix

alias sandbox-start='ai-sandbox start .'
alias sandbox-shell='ai-sandbox shell .'
alias sandbox-warm='ai-sandbox warm .'

ai-sandbox also detects flake overrides from .envrc before startup:

  • use flake ./path/to/flake-root
  • export AI_SANDBOX_FLAKE_OVERRIDE=./path/to/flake.nix

Then run:

direnv allow
sandbox-warm
sandbox-start

Notes

  • This has only been tested with Nix Home Manager so far.
  • This has been tested with an X.org server; it will likely not work with Wayland yet.
  • Contributions are welcome.
  • The sandbox still has X11 access. That is the weakest part of this design.
  • The repo is mounted read/write on purpose.
  • Host $HOME is not mounted.
  • Host /nix is not mounted.
  • The shared bind-mounted storage makes repeated launches much faster after the first warmup.
  • Storage defaults to ~/.cache/ai-sandbox/{home,nix} and is directly manageable as your user on the host.
  • ai-sandbox start, shell, and warm auto-register a host URL handler for vscode:// and vscode-insiders:// so OAuth callbacks (for example GitHub login) route back into the running sandbox container.
  • Security note: sandbox image grants passwordless sudo for apt/apt-get/dpkg to support in-sandbox package installs.

Security model

This is not a hardened sandbox.

It improves isolation in a very practical way, especially for VS Code extensions and coding agents, but it is not equivalent to a VM or a strict security boundary.

The main tradeoff is convenience vs isolation:

  • real VS Code runs in the container
  • host home and host /nix stay out
  • but X11 access, writable workspace mounts, and optional host networking still exist

So the right way to think about this is:

a practical containment layer for AI-assisted development

not

a perfect sandbox

Summary

If you install AI coding agents directly into VS Code on your host, you are effectively trusting arbitrary plugin code with a lot of access.

This project gives you a much more practical setup:

  • open a flake-based repo
  • run ais
  • get real VS Code inside a container
  • keep your dev environment Nix-native
  • reuse cached dependencies across projects
  • reduce the blast radius of VS Code plugins and coding agents

About

a container based sandbox which automatically install project dependencies from flake.nix and runs AI + VScode in a sandbox!

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors