Skip to content

FAQ

What is jai?

jai is a super-lightweight Linux sandbox for AI agents and coding assistants. It uses Linux mount namespaces and overlayfs to give a sandboxed process full access to your working directory, copy-on-write access to your home directory, private temp directories, and read-only access to the rest of the filesystem. The goal is to reduce the blast radius when running AI tools on your real machine — not to promise perfect isolation.

Was jai written by an AI coding agent?

No. While this web site was obviously pooped out by an LLM (ChatGPT read the man page, asked some follow-up questions, and produced a prompt from which claude code built this ridiculous vitepress site), jai itself was hand implemented by a Stanford computer science professor with decades of C++ and Unix/linux experience. As an experiment, the author did previously try vibe-coding a container, but the results were disastrous and repeatedly put his machine in a state that required a reboot (e.g., recursively changing the attributes of all mounts in the wrong mount namespace). The author does use coding agents to look for bugs and get feedback. However, rest assured that a single human understands every line of in this project.

Which mode should I use?

  • Casual (the default for unnamed jails) if you want the least friction and mostly care about preventing filesystem damage. Good for quick interactive work where you trust the tool enough to read your files but not to write everywhere.
  • Strict (the default for named jails) if you want real confidentiality — the jailed process runs as a different user and cannot read your files. Best for isolating tools that should not see each other's credentials.
  • Bare if you need strict-like home isolation but your home directory is on NFS, which does not support id-mapped mounts.

See Modes for a full comparison.

Why is casual mode not enough for confidentiality?

In casual mode, the jailed process runs as your user. It can read anything you can read — SSH keys, API tokens, browser session data, and every other file in your home directory. The copy-on-write overlay protects integrity (writes go to a separate layer), but it does not hide the underlying files.

The --mask option and default blacklists hide some known sensitive dotfiles, but casual mode exposes everything readable by default. You cannot exhaustively enumerate and mask every sensitive file. If confidentiality matters, use strict mode.

What should I do if my home directory is on NFS?

You should place your jai storage on a local file system with the --storage=/local/path option (or storage /local/path in $HOME/.jai/.defaults), and you will need to use bare mode instead of strict mode in most cases.

Why does casual mode require a non-NFS --storage directory?

The linux overlay file system implementation makes use of extended file attributes (e.g., trusted.overlay.origin) to record aspects of the correspondence between an "upper" changes directory and the "lower" read-only home directory. Unfortunately, these attributes cannot be set accessed over NFS. Also, jai needs root privileges to create whiteout files for masked paths, and often NFS clients do not have root access to remote file systems.

Why does strict mode not work with NFS?

Strict mode uses id-mapped mounts to make granted directories appear owned by the unprivileged jai user inside the jail, even though the real files are owned by the invoking user. NFS does not support id-mapped mounts — this is a kernel/NFS implementation limitation, not a jai limitation. This is why bare mode exists.

Note that if your home directory is on NFS but you don't grant access to any part of your home directory (e.g., jai -D), and if you relocate your storage with --storage=/local/path, then strict mode will work. But generally people want to run jai to work in some subdirectory of their home directory.

Why does jai not support Linux versions less than 6.13?

Linux 6.13 added support for fsconfig FSCONFIG_SET_FD to overlayfs. That makes it much easier for privileged software like jai to avoid time-of-check-to-time-of-use (TOCTTOU) vulnerabilities when creating overlay mounts. Linux 6.12 was released in 2024, three months before claude code. You really shouldn't let your kernel lag so far behind AI agents that may try to attack it.

Where do changes go in casual mode?

Writes to your home directory inside a casual jail go to:

$HOME/.jai/default.changes/    # unnamed jails
$HOME/.jai/<name>.changes/     # named jails

These directories are the "upper" layer of the overlayfs mount. To move changes back to your real home directory, run jai -u to unmount the overlay, then copy the files.

If you specified --storage=dir, the changes directory is under dir instead.

Can I access my overlay home directory outside of jai?

Yes, once jai has created an overlay home, you can find it (outside a sandbox) under /run/jai/$USER/default.home. You can also find the private /tmp directories under /run/jai/$USER/tmp/. One use for this is to delete files containing sensitive data from the overlay (as an alternative to --mask) from outside a sandbox. Be extra, extra careful, however, because the overlay will look like your home directory, and you don't want to get into the habit if deleting important files in places that look like your home directory. One sanity check is to run df .. In an overlay directory, the file system will be named something like jai-default.home as opposed to a block device like /dev/sda4.

What does jai -u do?

jai -u tears down the sandbox state:

  • Unmounts all overlay directories from /run/jai
  • Cleans up the overlay work directories ($HOME/.jai/*.work), which sometimes contain root-owned files users cannot delete
  • Destroys private /tmp and /var/tmp directories

Run jai -u when you want a fresh start, when you've changed --mask options (masks are only applied at overlay creation time), or when overlays are behaving strangely.

Why does jai use bash?

jai launches jailed programs through bash to support the command directive in configuration files. The command directive lets you set environment variables, activate virtual environments, or modify the command line before execution. For example:

command source $HOME/venv/bin/activate; "$0" "$@"

This would not be possible without a shell intermediary. The default command is simply "$0" "$@", which runs the program directly with its arguments.

Can I use sudo instead of setuid installation?

Yes. jai reads the SUDO_USER environment variable to determine whose home directory to sandbox:

bash
sudo jai bash
sudo jai -n claude claude

This works transparently. If both SUDO_USER and USER are set, SUDO_USER takes precedence. However, sudo usage has a few more annoyances. You will need to be root to kill jai from the outside. Also, by default sudo allocates a new pseudo-terminal device, which will be owned by root and may confuse some software.

How do named jails help?

Named jails (via -n name) give each tool its own home directory. This is useful when:

  • Multiple AI tools should not see each other's API keys or configuration
  • You want a clean, persistent home directory for a specific tool
  • You want strict mode isolation (named jails default to strict)

Each named jail has independent state — its own home directory, changes directory, and /tmp. You can have as many named jails as you want.

Why not just Docker?

Docker is excellent for reproducible, image-based environments. But for ad-hoc sandboxing of a CLI tool on your host machine, it requires:

  • Building or pulling an image with the tool installed
  • Configuring bind mounts for your working directory
  • Managing the impedance mismatch between container and host (UIDs, paths, shell config)
  • No native overlay-on-home workflow

jai trades Docker's reproducibility and stronger isolation for zero-setup, host-native sandboxing. One command, no images. See the Comparison page for details.

Why not just bubblewrap?

bubblewrap is a powerful, flexible namespace sandbox. It can do almost everything jai does — but it requires you to explicitly assemble the filesystem view from scratch with 10+ flags. In practice, this turns into a wrapper script per tool, which is exactly the friction jai is designed to remove.

bubblewrap also cannot easily set up overlayfs (it runs unprivileged and would need fuse-overlayfs), so you lose the copy-on-write home directory that makes casual mode convenient. See the Comparison page for a side-by-side.

Why not just chroot?

Linux documents chroot as not intended to be used as a security mechanism. It provides no mount namespace isolation, no PID namespace isolation, no credential separation, and is trivially escapable by root. It is not a meaningful sandbox. Any of the other tools on this page would be an improvement.

Stanford SCS