Skip to content

Container

AI Guardian Container Image

The published image is a UBI-based Docker/Podman support image with ai-guardian and the supported agent integrations. Headless-capable CLIs are bundled; GUI-only integrations receive their hooks when the container starts.

OpenShell v0.1.2 uses a separate image definition, Dockerfile.openshell, based on the pinned nvcr.io/nvidia/base/ubuntu:24.04 workload image. OpenShell's default workload is intentionally minimal, so this Dockerfile installs the filesystem layout, networking tools, users, and supported agent CLIs explicitly. The dedicated OpenShell image is published in its own primary Quay repository as quay.io/redhatproductsecurity/ai-guardian-openshell:latest on successful merges and as :<version> for releases. Build it locally only when testing a change to the image; ai-guardian sandbox create --runtime openshell uses the published OpenShell image by default. The OpenShell image is not published in the normal image repository. The normal UBI image remains published to quay.io/redhatproductsecurity/ai-guardian on every merge and release.

Use OpenShell when it is available, especially for provider-backed Claude or Codex sessions. OpenShell keeps provider credentials in the gateway rather than mounting them into the agent sandbox, and adds deny-by-default network and filesystem policy, provider-backed inference, repository isolation, and per-sandbox gateway services. OpenShell support is experimental, but it is the preferred security boundary for the tested provider workflows.

The plain Docker/Podman container is a simpler fallback and is useful for local development or environments without an OpenShell gateway. Its Vertex ADC file or direct API-key environment is available inside the container, so the selected agent may be able to read that credential material.

Supported Sandbox Matrix

The tray and ai-guardian sandbox create use the same runtime-specific CLI matrix. Container sandboxes support the broader CLI set; OpenShell is limited to the clients bundled with the dedicated OpenShell image.

Docker/Podman Container

CLI Supported scenario Status
claude Anthropic API key or Vertex ADC Supported
copilot GitHub/Copilot token Supported
grok XAI_API_KEY or Grok Build login Supported in the normal image; OpenShell excluded
codex Codex OAuth or OpenAI API key Supported
gemini Gemini CLI credentials Supported
antigravity Antigravity CLI credentials Supported
kiro Runtime installation after ToS consent Supported with consent
openclaw OpenClaw CLI credentials Supported
opencode OpenCode profile with its configured provider/model Supported
pi anthropic, openai, or openai-codex provider Supported when configured
crush Crush CLI credentials Supported

Container-only options such as host ports and direct environment credentials are not available in OpenShell. OpenShell provider names and policy files are not accepted for Container sandboxes.

NVIDIA OpenShell

CLI/scenario Provider/authentication Status
claude Anthropic provider or Vertex provider; Vertex route tested Supported
copilot OpenShell Copilot provider and policy Supported; provider required
codex Gateway Codex provider from OAuth or OpenAI API-key login Supported; v0.1.2 API-key qualification passed
opencode + Claude profile Provider-native Claude/Vertex endpoint Supported; manual qualification required
opencode + OpenAI model Existing provider or Codex API-key auto-setup Supported; API-key path unit-tested
opencode + other generic model Existing compatible OpenShell provider Supported when configured
pi + anthropic Anthropic-compatible OpenShell inference Supported; tested
pi + openai Direct OpenAI API-key provider Experimental; provider required
pi + openai-codex OpenShell resolver-backed Pi OAuth Not supported; omitted from tray

The tray updates its CLI and Pi-provider choices when Runtime changes and rejects unsupported combinations before creating a sandbox. Credential absence is reported separately from an unsupported scenario.

What's Included

Component License Installed
ai-guardian Apache 2.0 Build time
Gitleaks, BetterLeaks MIT Build time
LeakTK Apache 2.0 Build time
detect-secrets Apache 2.0 Build time
Secretlint MIT Build time
GitGuardian ggshield CLI MIT (service terms apply) Build time
OpenCode MIT Build time
Gemini CLI Apache 2.0 Build time
Codex CLI Apache 2.0 Build time
Grok Build Apache 2.0 Build time; version pinned at build time
OpenClaw MIT Build time
Pi coding agent MIT Build time
rapidocr Apache 2.0 Build time
onnxruntime MIT Build time
Claude Code Proprietary (Anthropic) Runtime — ToS consent required
Kiro CLI Proprietary (AWS) Runtime — ToS consent required

Claude Code and Kiro CLI are proprietary and redistribution-restricted. They are not bundled in the image. Instead, the container installs them at first start after prompting the user to accept the respective Terms of Service.

See Proprietary CLI Consent below.

Pull

# Latest build from main branch
podman pull quay.io/redhatproductsecurity/ai-guardian:latest

# Specific release version
podman pull quay.io/redhatproductsecurity/ai-guardian:1.18.0

Tag conventions: - :latest — tracks main branch (updated on every merge) - :<version> — pinned stable release (e.g. 1.18.0)

Build Locally

# Default (latest release)
podman build -t ai-guardian container/

# Specific version
podman build --build-arg AI_GUARDIAN_VERSION=1.18.0 -t ai-guardian container/

# Local wheel (copy the wheel into container/vendor/ first)
WHEEL_PATH=dist/ai_guardian-1.18.0-py3-none-any.whl
WHEEL_NAME="$(basename "$WHEEL_PATH")"
cp "$WHEEL_PATH" "container/vendor/$WHEEL_NAME"
podman build --build-arg "AI_GUARDIAN_VERSION=$WHEEL_NAME" \
    -t ai-guardian container/

# Multi-arch
podman build --platform linux/amd64,linux/arm64 -t ai-guardian container/

# Dedicated OpenShell BYOC image (the sandbox command uses the published image by default)
podman build -f container/Dockerfile.openshell \
    -t localhost/ai-guardian-openshell:latest container/

Run

Using run.sh (recommended):

./container/run.sh                                    # defaults: Codex
./container/run.sh --agent opencode                   # select agent
./container/run.sh --agent pi                        # select Pi
./container/run.sh --profile @strict                  # select profile
./container/run.sh --config-dir "$HOME/.config/ai-guardian"
./container/run.sh --repo ~/myproject                 # mount a repo
./container/run.sh --api-key sk-ant-...               # Anthropic API auth
./container/run.sh --agent gemini --profile @minimal  # combine options
./container/run.sh -- ai-guardian doctor              # run a command

Vertex AI auth is auto-detected from environment variables (see Authentication).

At startup the sandbox command configures only the selected --cli; configuring other integrations is unnecessary when the sandbox runs one CLI. To opt into broader setup, set AI_GUARDIAN_SETUP_SCOPE=cli for all supported CLI agents or AI_GUARDIAN_SETUP_SCOPE=all for every supported integration.

CLI lifecycle management

The ai-guardian sandbox subcommand provides named lifecycle operations for both supported runtimes. Container creation is detached; OpenShell creation connects to the sandbox shell after setup, like native OpenShell:

# Docker/Podman (defaults to podman; set CONTAINER_ENGINE=docker if needed)
ai-guardian sandbox create --runtime container --name guardian-codex --repo .
ai-guardian sandbox list
ai-guardian sandbox status guardian-codex
ai-guardian sandbox stop guardian-codex
ai-guardian sandbox start guardian-codex
ai-guardian sandbox connect guardian-codex
ai-guardian sandbox exec guardian-codex -- ai-guardian doctor
ai-guardian sandbox logs guardian-codex --follow
ai-guardian sandbox config save guardian-codex
ai-guardian sandbox delete guardian-codex

# OpenShell (uses OPENSHELL_CLI or the openshell executable on PATH)
# Create; policy files are repeatable.
ai-guardian sandbox create \
    --runtime openshell \
    --name guardian-claude \
    --cli claude \
    --repo . \
    --policy ./container/openshell-github-readonly-policy.yaml

# List managed OpenShell sandboxes.
ai-guardian sandbox list --runtime openshell

# Inspect status; runtime is auto-detected by name.
ai-guardian sandbox status guardian-claude

# Open an independent interactive shell.
ai-guardian sandbox connect guardian-claude

# Execute a command without replacing the sandbox process.
ai-guardian sandbox exec guardian-claude -- ai-guardian doctor

# Stream logs.
ai-guardian sandbox logs guardian-claude --follow

# Save and inspect configuration snapshots.
ai-guardian sandbox config save guardian-claude
ai-guardian sandbox config list guardian-claude

# Stop, start, or restart.
ai-guardian sandbox stop guardian-claude
ai-guardian sandbox start guardian-claude
ai-guardian sandbox restart guardian-claude

# Permanently delete.
ai-guardian sandbox delete guardian-claude

For multiple policy overlays, repeat the option in the same create command:

ai-guardian sandbox create --runtime openshell --name guardian-claude \
    --cli claude --repo . \
    --policy ./policy-one.yaml \
    --policy ./policy-two.yaml

Runtime selection can also appear before the lifecycle verb, as in ai-guardian sandbox --runtime openshell list. New sandbox creation defaults to OpenShell, including the tray create form; pass --runtime container explicitly to use Docker/Podman. For named lifecycle commands, omit the runtime and the CLI probes AI Guardian labels/metadata to choose Docker/Podman or OpenShell. An unqualified list combines managed resources from both runtimes. list is limited to resources created through this command's ai-guardian.managed=true label. The sandbox command also owns provider setup, policy composition, host-config snapshots, and OpenShell upload bootstrapping; no separate OpenShell script is required.

For OpenShell, the following lifecycle commands map directly to the native CLI and preserve its exit status and terminal behavior, except for connect, which uses an independent exec session so leaving the shell does not terminate the sandbox:

AI Guardian command Native OpenShell command
ai-guardian sandbox status NAME openshell sandbox get NAME
ai-guardian sandbox start NAME openshell sandbox start NAME
ai-guardian sandbox stop NAME openshell sandbox stop NAME
ai-guardian sandbox connect NAME openshell sandbox exec --name NAME --tty -- /bin/bash -l
ai-guardian sandbox delete NAME openshell sandbox delete NAME
ai-guardian sandbox exec NAME -- CMD openshell sandbox exec --name NAME -- CMD
ai-guardian sandbox logs NAME openshell logs NAME

sandbox restart implements the convenient stop-then-start sequence because OpenShell has no separate restart command. sandbox create adds AI Guardian image, environment, and labeling defaults; sandbox list adds the managed label selector, so those two commands are not plain aliases. See the full Sandbox CLI guide for create options and lifecycle details. Upload-based OpenShell creation bootstraps the entrypoint non-interactively, exposes the gateway-managed ai-guardian service, and then connects to the sandbox shell. Exiting that shell returns to the host while sandbox connect remains available for later sessions. A container created without an explicit command keeps a login shell with an allocated TTY as its main process, so it remains available for connect and exec; start the selected agent from that shell or with sandbox exec. A supplied --name is also recorded for tray and NiceGUI display, preventing a runtime-generated container ID from being shown.

Use ai-guardian sandbox config save NAME to preserve changes made inside a running sandbox. The newest timestamped snapshot can be used when recreating the sandbox with sandbox create --name NAME --restore-config latest; snapshots are stored in the host XDG state directory and never overwrite the host config.

OpenShell

The OpenShell sandbox command uses the dedicated Dockerfile.openshell image rather than the normal UBI image. Build it once from the repository root:

The normal run.sh container still defaults to Codex. The OpenShell sandbox command defaults to Claude, matching OpenShell's first-class default-policy coverage; select another CLI explicitly with --cli.

OpenShell integration is experimental. The documented workflows have been tested with Claude Code through Google Vertex AI, Codex through its OpenShell provider, Pi through its Anthropic-compatible OpenShell route, and OpenCode using Claude through Vertex AI. Pi's OpenAI routes are experimental. Claude marketplace/plugin installation has also been tested with the read-only GitHub overlay described below.

podman build -f container/Dockerfile.openshell \
    -t localhost/ai-guardian-openshell:latest container/

To use that local build for one run, pass it explicitly:

ai-guardian sandbox create --runtime openshell --base localhost/ai-guardian-openshell:latest

The published image can be pulled explicitly as well:

podman pull quay.io/redhatproductsecurity/ai-guardian-openshell:latest

Set AI_GUARDIAN_OPEN_SHELL_IMAGE to use another OpenShell-compatible image, or pass --base IMAGE/--image IMAGE on one invocation. The explicit AI_GUARDIAN_IMAGE variable remains the highest-priority image override. The subcommand uses the OpenShell-supported --from, --env, and --upload options, then exposes the daemon's sandbox-local REST port through the gateway-managed ai-guardian service. The gateway gives each sandbox its own service URL, so multiple sandboxes can use internal port 63152 concurrently.

Dockerfile.openshell pins the NVIDIA Ubuntu 24.04 base by digest rather than using the mutable :latest tag. To refresh it deliberately, pull the desired base, inspect its digest and package contents, update the BASE_IMAGE default, rebuild, and rerun the OpenShell smoke tests. A one-off override is also possible:

podman build \
    --build-arg BASE_IMAGE=nvcr.io/nvidia/base/ubuntu@sha256:<reviewed-digest> \
    -f container/Dockerfile.openshell \
    -t localhost/ai-guardian-openshell:latest container/

The pinned base is a minimal Ubuntu workload, so Dockerfile.openshell installs Codex, OpenCode, Pi, and GitHub Copilot explicitly. Claude Code remains a runtime ToS-gated install:

Build argument Package Default
CODEX_VERSION @openai/codex 0.154.0
OPENCODE_VERSION opencode-ai 1.18.31
PI_VERSION @earendil-works/pi-coding-agent 0.86.0
COPILOT_VERSION @github/copilot 1.0.10

These are pinned rather than installed through a mutable latest tag so an image can be reproduced and rolled back. Claude Code is installed only after runtime ToS consent. Override a managed version deliberately when testing another release. Rebuild the image and recreate the sandbox after changing one; existing sandboxes retain the client versions from their original image.

podman build -f container/Dockerfile.openshell \
    --build-arg CODEX_VERSION=0.154.0 \
    --build-arg OPENCODE_VERSION=1.18.31 \
    --build-arg PI_VERSION=0.86.0 \
    --build-arg COPILOT_VERSION=1.0.10 \
    -t localhost/ai-guardian-openshell:latest container/

For development, build and launch the local image in one workflow from the repository root. The repository snapshot is uploaded to the sandbox, and the read/write GitHub policy is applied to the selected Codex agent:

podman build -f container/Dockerfile.openshell \
    --build-arg CODEX_VERSION=0.154.0 \
    --build-arg PI_VERSION=0.86.0 \
    -t localhost/ai-guardian-openshell:dev \
    container/

ai-guardian sandbox create --runtime openshell \
    --base localhost/ai-guardian-openshell:dev \
    --cli codex \
    --policy ./container/openshell-github-readwrite-policy.yaml \
    --provider ai-guardian-codex \
    --repo .

Use a different CODEX_VERSION build argument when testing a specific Codex release. Rebuild the image and recreate the sandbox after changing the source wheel or a bundled CLI version.

CLI scope and image contents

AI Guardian has 16 public integrations. The default OpenShell image currently supports these five terminal clients: claude, copilot, codex, opencode, and pi. The GUI/editor integrations and terminal clients that require a custom image remain available to the normal container setup but are not shown in the default OpenShell selector.

The derived image explicitly installs Codex, OpenCode, Copilot, and Pi. The version monitor checks the managed pins. Only the selected CLI is configured by default; set AI_GUARDIAN_SETUP_SCOPE=cli when one sandbox will run multiple CLI agents. A custom image may add another client, but it must also add its runtime policy, provider/auth flow, and validation before it is advertised as supported.

License and redistribution

There is no blanket license clearance for the complete derived image. The NVIDIA Ubuntu base and each explicitly installed client retain their separate licenses and notices. Codex is Apache-2.0, OpenCode and Pi are MIT; GitHub Copilot and Claude Code remain subject to their own licenses and service terms. Claude Code is installed only after runtime ToS consent; users still need their own authorized account or API access. Review the exact package and base image notices before making a Quay repository public or redistributing the image. The build workflow deliberately publishes OpenShell only to the dedicated primary Quay repository and does not mirror it to itdove. For OpenShell installation and first-time setup, see the official OpenShell quickstart. For policy fields and validation rules, see the official policy schema reference and policy customization guide.

OpenShell prerequisites are:

  • The OpenShell CLI installed on the host.
  • A reachable OpenShell gateway.
  • A gateway compute driver configured for Docker, Podman, MicroVM, or Kubernetes.

The sandbox command requires an OpenShell CLI and gateway new enough to support sandbox create --env and the upload-based staging workflow. Install or update OpenShell on the host, then refresh the shell command and verify both the client and gateway:

curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh
hash -r
openshell --version
openshell status

On Fedora/Linux, the installer provides the CLI and a systemd user service:

curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh
systemctl --user status openshell-gateway
openshell status

If the Linux gateway uses rootless Podman, it also needs the rootless Podman API socket. Start it as the same user that runs the gateway:

systemctl --user enable --now podman.socket
test -S "${XDG_RUNTIME_DIR}/podman/podman.sock"
systemctl --user restart openshell-gateway
openshell status

On macOS, the installer uses Homebrew and manages the gateway with a Homebrew service:

curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh
brew services list
brew services restart openshell
openshell status

If macOS still reports an older version after updating, check which executable is being used with type -a openshell; the shell may be finding an older installation first. Updating the AI Guardian branch does not update the OpenShell CLI or gateway, and provider profiles remain local to each gateway.

If the gateway reports that /run/user/<uid>/podman/podman.sock is missing, the socket is stopped or the gateway is pinned to the wrong path. Omit socket_path from [openshell.drivers.podman] to use OpenShell auto-detection, or set it to the active ${XDG_RUNTIME_DIR}/podman/podman.sock path in $HOME/.config/openshell/gateway.toml, then restart the gateway. Do not use sudo with the rootless systemctl --user command.

If openshell status reports Connection refused, inspect the gateway before retrying the sandbox command:

systemctl --user is-active openshell-gateway
journalctl --user -u openshell-gateway --no-pager -n 100

On SELinux-enabled Fedora systems, OpenShell's hardened gateway may require a current host SELinux policy for the nnp_transition/nosuid_transition path into container_runtime_t. See the Fedora/Linux section in docs/TROUBLESHOOTING.md for diagnosis and the package-update remediation. Inspect recent AVC records for the denied path or operation instead of disabling enforcement or installing a broad local allow rule:

sudo ausearch -m avc -ts recent -i

For a gateway hosted elsewhere, register its reachable endpoint instead:

openshell gateway add https://gateway.example.com --name production
openshell status

For a containerized gateway, see OpenShell's container gateway guide.

Before the first sandbox command call, enable OpenShell Providers v2 on the active gateway. This is required for the sandbox command’s provider-backed Claude, Codex, Pi, and Vertex AI flows:

openshell settings set --global --key providers_v2_enabled --value true
ai-guardian sandbox create --runtime openshell        # opens a shell; Claude is selected
ai-guardian sandbox create --runtime openshell --cli opencode --opencode-agent-profile claude --repo .
ai-guardian sandbox create --runtime openshell --cli pi --agent-provider anthropic --repo .
ai-guardian sandbox create --runtime openshell --profile @strict --policy ./container/openshell-github-readwrite-policy.yaml
ai-guardian sandbox create --runtime openshell --config-dir "$HOME/.config/ai-guardian"

The OpenShell sandbox command opens /bin/bash by default. When --repo is supplied, the shell starts in the uploaded repository at /sandbox/repo; otherwise it starts in /sandbox. The selected --cli controls the AI Guardian setup, policy fragment, and automatic provider selection. With --cli opencode, --opencode-agent-profile is required and selects the OpenCode agent profile; --agent remains its legacy alias. With --cli pi, --agent-provider selects Pi's model provider. When a --policy overlay is supplied, it also selects the matching CLI policy fragment. Without an overlay, the sandbox command still applies the shared base policy and the selected CLI policy, but no GitHub policy is added. The sandbox command does not start the CLI automatically.

Provider profiles belong to the active OpenShell gateway; they are not stored in the repository, image, or Git branch. --agent-provider selects the provider inside the selected CLI; --provider separately attaches an OpenShell gateway provider. When --provider is omitted, the sandbox command asks that gateway for a provider profile matching the selected CLI/backend and may create or reuse the corresponding provider from local credentials. If the gateway does not advertise a Codex profile, a launch selecting --cli codex fails with an error such as “the active OpenShell gateway has no provider profile for codex.” Configure a Codex provider on that gateway first, or pass an already configured provider explicitly:

ai-guardian sandbox create --runtime openshell \
    --base localhost/ai-guardian-openshell:latest \
    --cli codex \
    --provider ai-guardian-codex \
    --repo .

Use openshell provider get ai-guardian-codex to verify that the named provider exists on the currently active gateway. Provider setup must be repeated for each gateway or laptop; git pull only updates the sandbox command and policy files.

The --provider option attaches an existing provider instance and does not create one. When the option is omitted for the auto-managed Codex provider, staged setup refreshes the existing AI Guardian provider from the current local Codex login before creating a new sandbox. Running sandboxes may need a restart or recreation after provider credentials change. For Pi, --agent-provider and --provider are separate: the native Anthropic provider uses its attached native endpoint, while the experimental openai provider requires an OpenAI API-key provider. Host Pi credentials and user configuration are not copied into the image. openai-codex is not supported with OpenShell resolver-backed OAuth and is not offered by the tray. The native Codex CLI can consume those resolver-backed credentials; for ChatGPT Plus/Pro, select --cli codex for the fully supported native path. In Claude Vertex mode, the sandbox command also refreshes that provider's project/region configuration and uses its native Vertex endpoint.

To let the sandbox command create ai-guardian-codex from local Codex credentials, omit --provider and ensure the active gateway lists the codex profile:

openshell provider list-profiles
ai-guardian sandbox create --runtime openshell \
    --base localhost/ai-guardian-openshell:latest \
    --cli codex \
    --repo .

Provider creation requires a matching gateway profile and credentials available to the sandbox command. If codex is absent from list-profiles, update or reconfigure the active OpenShell gateway before retrying.

Manual Live CLI Tests

Live OpenShell provider tests use personal credentials and are not run in CI. See container/tests/README.md for the full matrix and options. Run one case from the repository checkout:

python container/tests/test_openshell_agents.py \
    --image localhost/ai-guardian-openshell:dev \
    --case codex

The runner supports claude, codex, copilot, opencode-claude, opencode-openai, opencode-openai-api-key, pi-anthropic, pi-openai, and pi-openai-codex. Use --all for the complete OpenShell local matrix, --provider CASE=NAME for an existing gateway provider, and --keep to retain sandboxes for inspection. It uses openshell sandbox exec by default; use --executor podman only with a local Podman-backed gateway. The Pi Codex OAuth case is reported as an expected failure until Pi can consume OpenShell resolver references.

For release qualification, use the fixed three-row matrix and emit the versioned, sanitized report:

python container/tests/test_openshell_agents.py \
    --qualify \
    --image quay.io/redhatproductsecurity/ai-guardian-openshell:1.18.0 \
    --provider claude=ai-guardian-google-vertex-ai \
    --provider codex=ai-guardian-codex \
    --provider opencode-claude=ai-guardian-google-vertex-ai \
    --report openshell-compatibility-report.json

The matrix covers Claude Code with Vertex AI, native Codex with the OpenShell provider, and OpenCode's claude profile with Vertex AI. It verifies creation, daemon/service reachability, real agent execution, deterministic violation detection, restart/reconnect, and cleanup. CI runs only the credential-free contract and image metadata checks; live provider qualification remains manual. The report schema and upgrade procedure are documented in docs/Sandbox.md and container/tests/README.md. No provider credential, prompt, model output, service URL, or raw command output is written to the report.

For the broader Docker/Podman matrix, use the companion runner:

python container/tests/test_container_agents.py \
    --image localhost/ai-guardian:dev \
    --all

It runs the Container CLI/provider cases one by one and removes each temporary container afterward. See container/tests/README.md for the case matrix and credential requirements.

ai-guardian sandbox create --runtime openshell \
    --cli codex \
    --policy ./container/openshell-github-readwrite-policy.yaml \
    --provider ai-guardian-codex \
    --provider ai-guardian-github \
    --repo .

The sandbox command runs setup before opening the shell. You can launch the selected CLI from that shell; when the CLI exits, you return to the shell and can inspect, commit, and push changes. The repository is still an OpenShell snapshot, so commits and other file changes are made in the sandbox copy. With the read/write GitHub policy and an attached GitHub provider, git push goes to GitHub through the gateway; it does not modify the host checkout. To launch the selected CLI immediately instead, pass it after --, for example -- codex.

From the shell, launch and exit the selected CLI as often as needed:

codex
git status
git add .
git commit -m "Your change"
git push

The OpenShell sandbox command exposes the daemon's sandbox-local port 63152 through the gateway-managed ai-guardian service:

openshell service expose NAME 63152 ai-guardian
openshell service get NAME ai-guardian

The gateway assigns a unique URL such as http://NAME--ai-guardian.openshell.localhost:PORT/. The same internal port can be exposed by multiple sandboxes, and tray/NiceGUI discovery queries each sandbox's URL. --port is only supported for container sandboxes; OpenShell does not use a host-side forward process.

Claude Code with Google Vertex AI

To run Claude Code through Google Vertex AI, select Claude and provide a GCP project. The sandbox command automatically creates or updates the gateway-local ai-guardian-google-vertex-ai provider, including its required project and region configuration. No GitHub policy is needed for model inference:

export ANTHROPIC_VERTEX_PROJECT_ID=my-gcp-project
export CLOUD_ML_REGION=global

ai-guardian sandbox create --runtime openshell \
    --base localhost/ai-guardian-openshell:latest \
    --cli claude \
    --model claude-sonnet-4-6 \
    --repo .

When using a locally built image, rebuild it after changing the workload image or provider profile assumptions.

Providers v2 must be enabled on the active gateway before the first sandbox command call so the provider-owned Vertex network policy is included:

openshell settings set --global --key providers_v2_enabled --value true

The sandbox command attaches the gateway Vertex provider and passes Claude the non-secret native Vertex settings it requires:

CLAUDE_CODE_USE_VERTEX=1
ANTHROPIC_VERTEX_PROJECT_ID=my-gcp-project
CLOUD_ML_REGION=global

OpenShell injects only an opaque token placeholder and resolves it at the provider-authorized native Vertex endpoint. From the resulting shell, start Claude explicitly with the OpenShell-documented --bare flag:

claude --bare

AI Guardian does not install a persistent shell wrapper. For an explicit automated claude --print ... command passed during creation, the entrypoint adds --bare when it is missing. Administrative commands such as claude plugin and claude doctor are passed through unchanged. The sandbox command sets CLAUDE_CODE_USE_VERTEX=1; the host ADC file is never mounted because OpenShell owns credential refresh. Use --model MODEL to select the client model; the default is claude-sonnet-4-6.

Claude's background self-updater is disabled in OpenShell because the image installation is read-only. To update Claude Code, rebuild the OpenShell image and create a new sandbox; the sandbox command sets DISABLE_AUTOUPDATER=1 automatically.

OpenCode with a native provider

OpenCode is a CLI with its own agent profiles and model/provider selection. The --opencode-agent-profile profile is required when --cli opencode is selected; --agent is a legacy alias. Use the explicit two-level form when an OpenCode profile should use Claude:

ai-guardian sandbox create --runtime openshell \
    --cli opencode \
    --opencode-agent-profile claude \
    --model claude-sonnet-4-6 \
    --provider vertex-provider \
    --repo .

This opencode + claude + Claude/Vertex combination is part of manual qualification. The --cli value selects OpenCode, --opencode-agent-profile claude selects the tested profile, and --model plus --provider select the inference backend.

Here --opencode-agent-profile claude is an OpenCode agent profile and --model selects the provider-native model. OpenCode's build and plan names are profiles, not providers. OpenShell v0.1.2 has no virtual inference endpoint; configure OpenCode for the attached provider's native endpoint. OpenCode has no Claude-style --bare flag; run opencode --agent NAME normally. For an OpenAI-shaped model such as openai/gpt-5, the sandbox command automatically attaches or creates ai-guardian-codex when the host Codex auth.json contains a top-level OPENAI_API_KEY; that uses the provider's native API-key environment. OAuth-only Codex credentials remain supported for native --cli codex, not as a generic OpenCode API key.

The Claude/Vertex policy does not grant GitHub access by default. The command above is sufficient for Claude requests, Vertex inference, and an ordinary Claude session. Marketplace or plugin installation and refresh are different: you must add the read-only GitHub overlay because the Anthropic marketplace is fetched from GitHub. Without this overlay, model requests still work but marketplace installation or refresh fails due to OpenShell's deny-by-default network policy. The read/write GitHub policy and GitHub provider are not required for the public catalog.

This uses OpenShell's Vertex provider and inference routing features. The effective sandbox policy should show a provider-derived _provider_ai_guardian_google_vertex_ai entry for the Google Vertex hosts.

Keep --cli claude when using Vertex AI. claude selects the Claude Code CLI; Vertex is the provider backend, not a separate CLI, so --cli claude-vertex is not a valid selector. The expected provider name is ai-guardian-google-vertex-ai.

The sandbox command uses Google Application Default Credentials (ADC) while creating or refreshing the provider. Set GOOGLE_APPLICATION_CREDENTIALS to a service-account JSON file when it is not at the standard gcloud ADC location, or authenticate with gcloud first. The credential file is consumed by the gateway and is not uploaded into the sandbox:

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/gcp-credentials.json
export ANTHROPIC_VERTEX_PROJECT_ID=my-gcp-project
export CLOUD_ML_REGION=global

ai-guardian sandbox create --runtime openshell --cli claude --repo .

The active gateway must expose the google-vertex-ai provider profile. If the sandbox command reports that the profile is missing, update or reconfigure the active OpenShell gateway. For direct Anthropic access instead, use ANTHROPIC_API_KEY and omit the Vertex project variables.

If a provider created by an older sandbox command shows no config keys, rerunning the sandbox command updates it with VERTEX_AI_PROJECT_ID and VERTEX_AI_REGION. The equivalent manual repair is:

openshell provider update ai-guardian-google-vertex-ai \
    --config VERTEX_AI_PROJECT_ID="$ANTHROPIC_VERTEX_PROJECT_ID" \
    --config VERTEX_AI_REGION="${CLOUD_ML_REGION:-global}"

The Vertex policy is separate from Claude plugin marketplace access. The default Claude policy intentionally does not allow GitHub. To install or refresh the public Claude plugin marketplace, you must add the read-only GitHub overlay. A read/write GitHub policy or GitHub credential provider is not required for the public catalog:

ai-guardian sandbox create --runtime openshell \
    --base localhost/ai-guardian-openshell:latest \
    --cli claude \
    --policy ./container/openshell-github-readonly-policy.yaml \
    --repo .

Claude's diagnostics may report that the first-party api.anthropic.com provider, Claude.ai OAuth, and Remote Control are unavailable. Those checks are for direct Anthropic/Claude.ai sessions and are expected when Claude is running through Vertex AI. The relevant test is whether Claude can complete a model request through the configured Vertex project.

OpenShell discovers common agent credentials through its provider mechanism. When no profile is selected, an existing host ai-guardian.json is uploaded as the initial configuration snapshot. The sandbox-local config still takes precedence when it already exists, and the host file is never written. A selected profile always takes precedence and prevents that full-config upload. OpenShell's --upload gives the sandbox a writable copy, matching the Docker/Podman sandbox command, which stages the host file with a read-only bind mount before copying it into the writable active config path.

Agent credential directories are deliberately not mounted or uploaded. For Codex, the sandbox command reads $CODEX_HOME/auth.json (falling back to $HOME/.codex/auth.json) only while creating the OpenShell provider, and passes the OAuth fields or API key to the provider command without printing them. The provider then supplies sandbox-scoped credential placeholders. At sandbox startup, the entrypoint writes those placeholders into the selected $CODEX_HOME/auth.json in Codex's native ChatGPT format; it never writes the host's real OAuth tokens into the sandbox. A synthetic JWT-shaped ID token is used only because Codex parses that field locally. With a gateway that advertises the codex profile and has Providers v2 enabled, Codex should start without showing its sign-in menu and a separate OpenAI API key is not required. Enable the gateway feature once with:

openshell settings set --global --key providers_v2_enabled --value true

For API-key authentication, the entrypoint instead runs codex login --with-api-key with the provider-injected OPENAI_API_KEY placeholder, so Codex writes its native API-key auth.json without putting the real key in the sandbox filesystem. This is required even though the provider already exposes the placeholder as an environment variable.

If Codex still shows the sign-in menu, the provider-backed auth bootstrap was not available to that process. Start a fresh sandbox with this command rather than launching codex from an unrelated shell, and verify that openshell provider get ai-guardian-codex reports either the four Codex OAuth credential keys or OPENAI_API_KEY, as appropriate. Do not copy the host auth.json into an OpenShell sandbox; use its provider mechanism instead.

When Providers v2 is unset or disabled, OpenShell 0.0.116 falls back to legacy codex discovery, which only recognizes OPENAI_API_KEY; the sandbox command reports this prerequisite instead of asking for an API key that is not needed by a Codex OAuth login. If the profile is unavailable, use an explicit compatible provider with --provider NAME.

Codex also needs a writable local state database before it can display its prompt. The sandbox command sets CODEX_HOME=/sandbox/.codex and initializes that directory. The OpenShell policy gives /sandbox to the sandbox user, and keeping Codex state there also lets Codex create its helper binaries instead of rejecting them as temporary /tmp files. If you connect to the sandbox and run codex manually, run the sandbox command first so this environment and directory are present.

Codex is configured with sandbox_mode = "danger-full-access" inside the OpenShell sandbox. This prevents Codex from trying to create a nested bubblewrap/user-namespace sandbox; OpenShell remains the outer security and network boundary. The setting is written only to the sandbox-local $CODEX_HOME/config.toml. Regular Docker/Podman launches keep Codex's normal inner sandbox behavior. This follows the pattern in OpenShell's official Codex sandbox example.

The configured ai-guardian MCP server is a local stdio process and therefore does not need a network-policy endpoint. Codex's separate codex_apps remote MCP, when enabled by Codex, does need its provider/profile endpoint and can be allowed through the selected Codex policy.

OpenShell 0.0.116 does not allow --upload and a trailing canonical command in the same sandbox create invocation. When a config, profile, repository, or credential snapshot is needed, this command creates a named detached staging sandbox, uploads the snapshot, and then explicitly invokes the image entrypoint with openshell sandbox exec. This is required because detached OpenShell creation starts its own shell instead of reliably running the image Docker entrypoint. For claude, codex, copilot, and opencode when the active gateway advertises a matching profile, the sandbox command creates or reuses an ai-guardian-<agent> provider from existing local credentials when --provider is not supplied. Pass --provider NAME for an agent or gateway that does not advertise an automatic provider profile.

The default image build is pinned to the latest stable PyPI release at the time the image definition is updated. At startup, the entrypoint checks the installed package's advertised setup choices: integrations that exist only in a newer development checkout are reported as skipped, while selecting one of those integrations fails with a clear compatibility error.

When building this image from the development checkout, pass the wheel built from the same checkout if you need unreleased setup behavior. The current development package registers Codex's AI Guardian MCP server in $CODEX_HOME/config.toml; older released packages may instead write the legacy codex.json file in the working directory. ai-guardian setup installs the MCP entry by default in both cases.

WHEEL_DIR="$(mktemp -d "${TMPDIR:-/tmp}/ai-guardian-wheel.XXXXXX")"
uv build --wheel --out-dir "$WHEEL_DIR"
WHEEL_PATH="$(printf '%s\n' "$WHEEL_DIR"/ai_guardian-*.whl | head -n 1)"
WHEEL_NAME="$(basename "$WHEEL_PATH")"
cp "$WHEEL_PATH" "container/vendor/$WHEEL_NAME"
podman build \
    --build-arg "AI_GUARDIAN_VERSION=${WHEEL_NAME}" \
    -f container/Dockerfile.openshell \
    -t localhost/ai-guardian-openshell:latest container/

WHEEL_PATH includes the temporary build directory, while WHEEL_NAME is only the filename. The AI_GUARDIAN_VERSION build argument must use WHEEL_NAME, since the Dockerfile looks for the wheel by filename under container/vendor/. Using a fresh output directory avoids accidentally selecting an older wheel left in dist/.

OpenShell policy composition

OpenShell network access is deny-by-default. The repository keeps the policy in composable pieces:

  • policies/base.yaml: shared filesystem and Landlock restrictions.
  • Read-only main overlay: GitHub REST reads and HTTPS git clone/git fetch only.
  • Read/write main overlay: GitHub REST operations and HTTPS git clone/git fetch/git push.
  • policies/agents/<agent>.yaml: the network capability for the selected CLI.

When --policy is supplied, it may be repeated. The sandbox command always composes one final policy in this order:

policies/base.yaml
  + every --policy overlay (left to right)
  + policies/agents/<selected-cli>.yaml

Only the selected CLI fragment is added; the other CLI policies are not enabled. YAML mappings are merged and lists are replaced by later overlays. The resulting temporary file is passed as the single OpenShell --policy argument and removed after OpenShell has consumed it. If no --policy overlay is given, the result contains only the shared base policy and the selected CLI policy; it does not grant GitHub API or Git access.

Bundled scanner engines

Both support images preinstall pinned Gitleaks, BetterLeaks, LeakTK, detect-secrets, Secretlint, and the GitGuardian ggshield CLI. Their versions come from the scanner configuration bundled with AI Guardian, so host, profile, restored, and sandbox-local configurations can select them without startup downloads or an OpenShell policy for downloading scanner binaries.

Secretlint scans locally. Using the GitGuardian engine sends scan data to its cloud service and still requires configured consent and an API key; an OpenShell sandbox also needs policy access to that service. Installing the CLI in the image does not add runtime network access. Pattern-server access remains governed by the selected configuration and policy.

TruffleHog is not included in the stock images. Its AGPL-3.0 installation path requires interactive license acknowledgement, which cannot be collected during an image build. A configuration that selects TruffleHog therefore cannot use it in these images; use one of the bundled engines or provide it in a derived image after reviewing and acknowledging its license. Custom scanner binaries and Python scanner packages are outside the current pinned image set and must be added to a derived image when needed.

The CLI fragments are intentionally conservative. Kiro and OpenClaw have no single default LLM endpoint, while OpenCode and Crush support additional providers beyond the examples in their fragments. Attach a compatible OpenShell provider or add a custom policy overlay for those providers.

Providers v2 can add provider-owned credential and network-policy entries to the effective sandbox policy, but only for providers attached to that sandbox. See the official Providers v2 guide. Do not attach unrelated providers when a narrower sandbox is intended.

GitHub access and providers

Use it when creating a sandbox:

ai-guardian sandbox create --runtime openshell \
    --cli codex \
    --policy ./container/openshell-github-readonly-policy.yaml \
    --repo .

For a workflow that needs to create or update GitHub content, use the read/write policy explicitly:

ai-guardian sandbox create --runtime openshell \
    --cli codex \
    --policy ./container/openshell-github-readwrite-policy.yaml \
    --provider ai-guardian-codex \
    --provider ai-guardian-github \
    --repo .

For private repositories, create an OpenShell GitHub provider from a host token and attach it to the sandbox. The token is injected by OpenShell at runtime; it is not stored in this policy file:

export GITHUB_TOKEN=<token-with-the-required-repository-access>
openshell provider create \
    --name ai-guardian-github \
    --type github \
    --from-existing

ai-guardian sandbox create --runtime openshell \
    --cli codex \
    --provider ai-guardian-codex \
    --provider ai-guardian-github \
    --policy ./container/openshell-github-readwrite-policy.yaml \
    --repo .

To apply the policy to an existing sandbox, use:

policy_tmp_dir="$(mktemp -d)"
python3 ./container/compose_openshell_policy.py \
    --output "${policy_tmp_dir}/policy.yaml" \
    ./container/policies/base.yaml \
    ./container/openshell-github-readwrite-policy.yaml \
    ./container/policies/agents/codex.yaml
openshell policy set <sandbox-name> \
    --policy "${policy_tmp_dir}/policy.yaml" \
    --wait
rm -rf -- "${policy_tmp_dir}"

When updating an existing sandbox, compose the selected-CLI policy first; openshell policy set accepts one final YAML document and does not perform the sandbox command-side composition automatically. The official policy customization guide documents incremental updates and full policy replacement.

The read/write policy grants the network operations required by standard GitHub API and HTTPS Git workflows, but the GitHub provider still controls which repositories and account permissions are available. --provider is repeatable; when Codex OAuth and private GitHub access are both needed, attach both ai-guardian-codex and ai-guardian-github as shown above. For narrower access, use the read-only policy or follow OpenShell's GitHub sandbox tutorial to tailor the allowed repositories and methods.

Daemon REST port and tray

The sandbox command exposes sandbox-local port 63152 as the gateway-managed ai-guardian service. To inspect the service URL for one sandbox:

openshell service get ai-guardian-codex ai-guardian

The OpenShell network policy controls sandbox egress. The example policy includes the bundled Codex egress endpoints; add the selected CLI's provider endpoints when using another CLI. The gateway service handles access to the daemon endpoint, and AI Guardian discovery asks the gateway for the URL of each managed sandbox. No local forward-state directory or host-side forwarding process is required.

{
  "daemons": [
    {
      "name": "openshell-codex",
      "url": "http://127.0.0.1:63152",
      "token": "the-daemon-auth-token"
    }
  ]
}

Save this as $HOME/.config/ai-guardian/tray-targets.json (or the active ai-guardian config directory) and start the tray normally. /api/health is unauthenticated, but status and control operations require the daemon token. The forwarded port is the daemon REST API, not a NiceGUI page: check it with /api/health; the NiceGUI console runs on the host and uses this endpoint through the tray client. For a stable tray connection, set daemon.auth_token in the shared config snapshot and use the same token in a manual target. Use HTTPS rather than plain HTTP when the daemon is reachable beyond loopback.

Manual container run (podman / docker)
# Default (Codex hooks)
podman run -it -p 63152 ai-guardian

# Select agent
podman run -it -p 63152 -e AI_GUARDIAN_AGENT=opencode ai-guardian opencode

# Seed the sandbox config from the host when no sandbox-local config exists
podman run -it -p 63152 \
    -v "$HOME/.config/ai-guardian/ai-guardian.json:/sandbox/.config/ai-guardian.host.json:ro,z" \
    -e AI_GUARDIAN_HOST_CONFIG_MOUNTED=true \
    -e AI_GUARDIAN_HOST_CONFIG_PATH=/sandbox/.config/ai-guardian.host.json \
    ai-guardian

# Select configuration profile
podman run -it -p 63152 -e AI_GUARDIAN_PROFILE=@strict ai-guardian

# Authenticate with Anthropic API
podman run -it -p 63152 -e ANTHROPIC_API_KEY=sk-ant-... ai-guardian

# Authenticate with Vertex AI
podman run -it -p 63152 \
    -e CLAUDE_CODE_USE_VERTEX=1 \
    -e ANTHROPIC_VERTEX_PROJECT_ID=my-gcp-project \
    -e CLOUD_ML_REGION=global \
    -e GOOGLE_APPLICATION_CREDENTIALS=/sandbox/gcp-key.json \
    -v ~/gcp-key.json:/sandbox/gcp-key.json:ro \
    ai-guardian

# Mount a repo to test
podman run -it -p 63152 -v ~/myrepo:/sandbox/repo ai-guardian

# Run doctor
podman run -it ai-guardian ai-guardian doctor

Container Engine

By default, run.sh uses Podman. To use Docker instead:

CONTAINER_ENGINE=docker ./container/run.sh
# or export for the session:
export CONTAINER_ENGINE=docker
./container/run.sh --ide claude

Both engines support the same -p syntax for port mapping. Use docker port <container> (instead of podman port) to find the mapped host port when using Docker.

Agent Selection

Set AI_GUARDIAN_AGENT (or compatibility alias AI_GUARDIAN_IDE) to choose which CLI/agent command is started. All rows are configured at startup:

Value Agent Installed in image
codex (default) OpenAI Codex (CLI + Desktop) Yes
claude Claude Code Runtime — ToS consent
opencode OpenCode Yes
gemini Gemini CLI Yes
kiro Kiro CLI Runtime — ToS consent
openclaw OpenClaw Yes
crush Crush No (hooks only; license/packaging varies)
cursor Cursor No (hooks only)
copilot GitHub Copilot No (hooks only)
windsurf Windsurf No (hooks only)
augment Augment No (hooks only)
cline Cline No (hooks only)
zoocode ZooCode No (hooks only)
junie Junie No (hooks only)
aiderdesk AiderDesk No (hooks only)
dummy-agent Dummy Agent (fake IDE for hook testing) Yes — no LLM required

Agents marked "hooks only" are not installed in the image (they require a GUI or are not redistributed here), but ai-guardian hooks are configured for them. Mount or install an agent binary separately if needed.

Claude Code (Anthropic) and Kiro CLI (AWS) are proprietary with redistribution restrictions. They are not bundled in the image. When AI_GUARDIAN_AGENT=claude or AI_GUARDIAN_AGENT=kiro is selected, the container prompts for ToS acceptance at first start and installs the CLI if the user agrees.

Interactive (default)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Claude Code requires accepting its Terms of Service:
  https://www.anthropic.com/legal/consumer-terms
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Install Claude Code and accept the ToS? [y/N]

Answer y to install, N (or Enter) to skip.

Non-interactive / CI

Set ACCEPT_PROPRIETARY_TOS=true to bypass the prompt and install automatically. By setting this variable you confirm you have read and accept the relevant Terms of Service.

# Claude Code — non-interactive
podman run -it -p 63152 \
    -e ACCEPT_PROPRIETARY_TOS=true \
    -e ANTHROPIC_API_KEY=sk-ant-... \
    quay.io/redhatproductsecurity/ai-guardian:latest

# Kiro CLI — non-interactive
podman run -it -p 63152 \
    -e AI_GUARDIAN_AGENT=kiro \
    -e ACCEPT_PROPRIETARY_TOS=true \
    quay.io/redhatproductsecurity/ai-guardian:latest kiro

The run.sh helper passes ACCEPT_PROPRIETARY_TOS through from the host environment automatically if it is set.

Already installed

If the binary is already present in $HOME/.local/bin/ (e.g. from a mounted volume), the consent prompt is skipped.

Configuration and Profiles

With no profile selected, run.sh checks the host configuration directory and stages only ai-guardian.json as the initial snapshot when it exists. The image keeps all other XDG state, cache, scanner, and agent directories sandbox-local. If a sandbox-local config already exists, it wins and is not overwritten. If the host file is absent, startup creates a sandbox-local configuration.

Set AI_GUARDIAN_PROFILE or pass --profile to apply a security profile at container start. Profile mode never mounts the host's complete config:

Value Description
(unset) Use an existing sandbox-local config; otherwise copy the host config as a writable initial snapshot, or create a sandbox-local standard config
@minimal Minimal — fewer checks, lower false positive rate
@standard Standard — balanced security and usability
@strict Strict — maximum security, all checks enabled
@moderator Moderator — all scanner actions set to ask for human-in-the-loop review

You can also pass a custom profile name or path if you have saved custom profiles.

The host config directory is selected in this order:

  1. --config-dir (or --guardian-home)
  2. AI_GUARDIAN_CONFIG_DIR
  3. AI_GUARDIAN_HOME
  4. XDG_CONFIG_HOME/ai-guardian
  5. HOME/.config/ai-guardian

When HOME is not exported, the sandbox command can infer its parent from a supported agent home variable such as CODEX_HOME, CLAUDE_CONFIG_DIR, CURSOR_CONFIG_DIR, GEMINI_CLI_HOME, KIRO_HOME, JUNIE_HOME, or OPENCODE_CONFIG_DIR. These variables are used only to locate the host ai-guardian config; agent homes and caches are not mounted into the sandbox.

If a custom profile file is given, it is mounted read-only by run.sh at a sandbox-local profile path. A missing explicit profile file is an error. A missing host ai-guardian.json is not an error when no profile is selected; the sandbox command reports the fallback and creates a local config. --profile and host-config sharing are mutually exclusive. When the host config is effective, the sandbox edits its own copy; the TUI, NiceGUI, and REST config APIs never write back to the host file.

Authentication

Pass authentication credentials as environment variables at runtime. The normal Docker/Podman image does not mount or read the host ~/.codex directory, so Codex ChatGPT/OAuth login is performed inside the sandbox rather than being inherited automatically.

run.sh forwards the common agent variables (OPENAI_API_KEY, OPENROUTER_API_KEY, GEMINI_API_KEY, AWS Bedrock variables, Azure OpenAI variables, and the existing Anthropic/Vertex variables). Both run.sh and ai-guardian sandbox create --runtime container detect Vertex settings and mount the host ADC file read-only when it is available. The OpenShell sandbox command relies on OpenShell providers for credentials: its --api-key option is used only while creating an Anthropic provider, and Vertex ADC credentials are consumed while creating the google-vertex-ai provider. Neither provider credential value nor the ADC file is passed to the OpenShell sandbox.

When both an Anthropic API-key environment variable and Vertex project settings are present, the container launchers select Vertex and omit the inherited API key. Pass --api-key explicitly when direct Anthropic authentication is intended.

Codex CLI in a Docker/Podman sandbox

For a named sandbox, connect to it and authenticate Codex from inside:

ai-guardian sandbox create \
    --runtime container \
    --name guardian-codex \
    --cli codex \
    --repo .
ai-guardian sandbox connect guardian-codex

# Inside the container:
codex login

On a headless container, codex login --device-auth requires device-code authorization to be enabled in ChatGPT's Settings → Security. If that option is unavailable, use a real OpenAI Platform API key:

export OPENAI_API_KEY="<your-openai-api-key>"
ai-guardian sandbox create \
    --runtime container \
    --name guardian-codex \
    --cli codex \
    --repo .
ai-guardian sandbox connect guardian-codex

# Inside the container:
printenv OPENAI_API_KEY | codex login --with-api-key

auth.json from a ChatGPT OAuth login contains OAuth credentials, not a Platform API key. Do not paste its access or refresh token into the API-key login. If necessary, the user can authenticate on a host with a browser and manually copy the complete file into a persistent named container:

podman cp ~/.codex/auth.json guardian-codex:/sandbox/.codex/auth.json

Use docker cp with Docker. AI Guardian does not inspect this file, but it is then present inside the sandbox; treat it like a password and never commit or share it. The detailed container-sandbox flow is also documented in the Sandbox CLI guide.

Tested configurations: Anthropic API key and Google Vertex AI have been validated with this image. Other providers (AWS Bedrock, Azure, self-hosted) may require additional environment variables or volume mounts — consult the IDE's documentation for the required configuration.

Anthropic API (direct)

podman run -it -p 63152 \
    -e ANTHROPIC_API_KEY=sk-ant-... \
    ai-guardian

Google Vertex AI ✓ tested

podman run -it -p 63152 \
    -e CLAUDE_CODE_USE_VERTEX=1 \
    -e ANTHROPIC_VERTEX_PROJECT_ID=my-gcp-project \
    -e CLOUD_ML_REGION=global \
    -e GOOGLE_APPLICATION_CREDENTIALS=/sandbox/gcp-key.json \
    -v ~/my-gcp-key.json:/sandbox/gcp-key.json:ro \
    ai-guardian

Other providers (untested)

Other Claude-compatible providers may work by passing the appropriate env vars. The container does not pre-configure any provider-specific tooling beyond Claude Code, so extra setup (CLI login, credential files, proxy config) may be needed inside the container after startup.

Variable Description
ANTHROPIC_API_KEY Anthropic API key (direct API access)
CLAUDE_CODE_USE_VERTEX Set to 1 to use Google Vertex AI
ANTHROPIC_VERTEX_PROJECT_ID GCP project ID (with Vertex AI)
CLOUD_ML_REGION GCP region, e.g. global (with Vertex AI)
GOOGLE_APPLICATION_CREDENTIALS Path to GCP service account JSON key file (with Vertex AI)

Web Console

The ai-guardian daemon starts automatically and binds to 0.0.0.0 inside the container (auto-detected via /.dockerenv / /run/.containerenv).

Access from the host: http://localhost:63152

Build Args

Arg Default Description
AI_GUARDIAN_VERSION 1.18.0 PyPI version or .whl filename
AI_GUARDIAN_REST_PORT 63152 Daemon REST API / web console port
UV_VERSION 0.11.16 uv package manager version
OPENCODE_VERSION 1.17.3 OpenCode version for the normal image
PI_VERSION 0.86.0 Pi coding agent version for the normal image

The dedicated OpenShell image also records its qualification inputs as OCI labels: the report schema version, AI Guardian build value, pinned NVIDIA base reference, and managed Codex/OpenCode/Pi/Copilot versions. Claude Code is runtime-installed after ToS consent. Release readiness inspects these labels and runs --version for the four bundled CLI clients without contacting a provider.

Test Image (Dockerfile.test)

The test image extends the base image with bundled dummy-agent scenarios for hook regression testing. Not for distribution — local CI only.

Build

# Build base image first
podman build -t ai-guardian container/

# Build test image on top
podman build -f container/Dockerfile.test -t ai-guardian-test container/

Run

# Run all bundled scenarios (CI mode)
podman run --rm ai-guardian-test /sandbox/run-scenarios.sh

# Run a specific scenario
podman run --rm ai-guardian-test \
  ai-guardian dummy-agent --script /sandbox/scenarios/basic-secret.yaml

# Interactive REPL
podman run -it ai-guardian-test ai-guardian dummy-agent

Bundled scenarios

Scenario What it tests
basic-secret.yaml AWS key detection → block
pii-detection.yaml Credit card, passport detection
ask-dialog.yaml Ask dialog forwarding to tray
tool-policy.yaml Directory rules, tool blocking

Expected Doctor Warnings

In a container, ai-guardian doctor will show expected warnings for:

  • System tray: Not available (no display server)
  • Terminal emulator: Not detected (no desktop)
  • tkinter: Not installed (no GUI needed)

All security-critical checks (config, hooks, scanners, daemon) should pass.