Configuration
jai uses line-based configuration files that live in $HOME/.jai/ (or $JAI_CONFIG_DIR if set).
Config file lookup
When you run jai cmd, jai looks for a configuration file in this order:
$HOME/.jai/cmd.conf— ifcmdcontains no slashes and does not start with.$HOME/.jai/default.conf— fallback
You can override this with -C file or --conf file. If the path contains no /, it is relative to $HOME/.jai/.
The command-line arguments and the configuration file can specify a jail by name. Otherwise, the jail name will be default. After the .conf file is parsed, jai will parse the jail.jail file, which usually just specifies the mode of the jail, but can override other options set by the .conf file (other than the jail name itself). Command-line arguments override both the .conf and .jail files.
Syntax
Each line has the form:
option [value]option is any long command-line option without the leading --. For example:
conf .defaults
mode casual
dir /local/build
mask MailBlank lines and comments (lines beginning with #) are ignored.
The conf directive
conf acts as an include directive. It logically replaces the conf line with the contents of the specified file at that exact point. Relative paths are relative to $HOME/.jai/.
conf .defaults
mode strict
dir /extra/pathThis reads .defaults first, then the subsequent lines override anything set in .defaults. Because conf is processed inline (not at the end), the order matters: later lines override earlier ones.
The .defaults file
jai auto-generates a .defaults file with sensible defaults — blacklists for sensitive dotfiles (.ssh, .gnupg, etc.) and environment variables (tokens, keys, passwords). You should begin most configuration files with:
conf .defaultsIf you changed your file and want to see the original version, you can print the default contents of the file with:
jai --print-defaultsThe command directive
jai executes jailed programs through bash. The command directive lets you wrap or modify command execution. The default in .defaults is:
command source "${JAI_SCRIPT:-/dev/null}"; "$0" "$@"This sources any script files specified with --script, then runs the command ($0) with its arguments ($@). You can use command to set environment variables, activate virtual environments, or add flags.
Example: Python virtualenv
Create $HOME/.jai/python.conf:
conf .defaults
mode strict
dir venv
jail python
command source $HOME/venv/bin/activate; "$0" "$@"Running jai python will now activate the virtualenv before executing the command.
The initjail directive
initjail runs a helper program when jai creates a jail home directory for the first time. This is most useful for strict and bare mode jails, where the home directory starts empty.
Important properties:
- The helper runs outside the jail, but with its current working directory set to the new jail home.
- It runs with the invoking user's real uid/gid, not as root and not as the unprivileged
jaiuser. - In configuration files, the program path is resolved relative to
$JAI_CONFIG_DIR(usually$HOME/.jai). - jai sets
JAI_MODE,JAI_JAIL, andJAI_CONFIG_DIRin the helper's environment.
The helper runs once when jai creates the jail home for the first time. In strict and bare mode, that means when jai first creates the <name>.home directory. In casual mode, that means when jai first creates the overlay state for the jail, not when it later remounts an existing .changes directory.
initjail? is the optional form. It behaves the same way, but is silently ignored if the program does not exist.
Example: seed a new jail from a skeleton directory
Create $HOME/.jai/.initjail:
#!/bin/sh
set -eu
if [ "$JAI_MODE" = strict ] || [ "$JAI_MODE" = bare ]; then
cp -rL "$JAI_CONFIG_DIR/.skel/." .
fiThen reference it from a config file:
conf .defaults
jail claude
initjail .initjailNow the first time jai creates the claude home directory, it will copy in the contents of $HOME/.jai/.skel/.
CLI precedence
Command-line options are parsed both before and after the configuration file. This means command-line arguments always take precedence over config file directives.
Within a configuration file, the conf directive reads the included file at the exact point of the directive — it overrides previous lines and is subject to being overridden by subsequent lines.
Example: full config file
Here is an example ~/.jai/codex.conf:
conf .defaults
mode strict
jail codex
dir agents
dir .codex
setenv PREFIX=${HOME}/agents
setenv PATH=${PREFIX}/bin:${PATH}This:
- Loads sensible defaults (blacklists, etc.)
- Ensures strict mode (the default unless the codex jail was previously created in casual mode)
- Names the jail
codex - Grants access to
~/agentsand~/.codexinside the jail - Sets the PREFIX environment variable, where
npmwill install software, to~/agents - Prepends
~/agents/binto PATH before running the any command in the jail
Now you can install or upgrade codex by running:
jai -C codex npm i -g @openai/codexAnd since codex.conf is the default for the codex command, you can invoke codex with:
jai codex