Codex

OpenAI's CLI coding agent with an external launcher boundary and kernel sandbox enforcement.

Last updated

Cloud API TypeScript

1. Installation

Prerequisites

  • A platform supported by the current Codex release
  • ChatGPT sign-in or an OpenAI API key
  • A project directory you are comfortable granting to the agent

Install Codex

brew install --cask codex

Install the preferred stack

brew tap nvk/tap
brew install nvk/tap/agent-bondage
brew install nono

# Optional, for explicitly scoped API-key launches:
brew install nvk/tap/envchain-xtra

Observed on 2026-10-26: Codex 0.164.0, agent-bondage 0.3.1, envchain-xtra 1.4.1, and upstream nono 0.80.0. The last public end-to-end stack test used Nono 0.61.1, so validate the current profile schema and effective policy before promoting a 0.80 profile to daily use. Pull registry packs without copying an old version suffix from this guide.

Verify

codex --version
bondage --version
nono --version
envchain --help  # prints the version header, if installed

2. nono Profile

Codex has its own internal sandbox, but nono adds kernel-level enforcement that the tool itself cannot bypass. In the preferred setup, bondage chooses the exact target and the selected external Codex profile before Codex starts.

What the sandbox allows

ResourceAccessWhy
Current working directoryRead + WriteProject files
Required OpenAI/sign-in endpointsNetworkModel calls and the selected authentication flow
CODEX_HOME (normally ~/.codex/)Bounded Read + WriteConfig, authentication state, sessions, and installed plugin state
/dev/tty, /dev/nullRead + WriteTerminal I/O
/dev/urandomReadCrypto randomness
Double sandbox: Codex ships with its own application-level sandbox. nono adds a second, kernel-level layer. Even if a prompt injection disables Codex's internal sandbox, nono's restrictions remain enforced by the OS kernel.
Network caveat: Nono does not restrict outbound network access merely because filesystem sandboxing is active. Use a filtered network profile, explicit allowed domains or credential routes, or full network blocking. Verify the selected profile instead of inferring network policy from its name.

3. Optional envchain-xtra

Codex supports ChatGPT sign-in and API-key operation. The preferred launcher path is still bondage + nono either way. Use envchain-xtra when you want an API key released from the OS secret store only for the launched process.

Store your API key

envchain --set codex OPENAI_API_KEY

API key vs OAuth

MethodCredential storageRecommendation
envchain + API key macOS Keychain (encrypted) Useful for explicit API-key launches and scoped secret release
ChatGPT sign-in Codex-managed authentication state under CODEX_HOME Normal interactive account path; protect the state directory and grant only what the launcher needs
Credentials remain sensitive: do not expose either API keys or Codex-managed account state to unrelated profiles. An external sandbox must grant enough access for the authentication mode you selected, but no more.

4. bondage Wrapper

Add this thin wrapper to your shell config:

codex() {
  bondage exec codex ~/.config/bondage/bondage.conf -- "$@"
}

Sample stack snippets

Assuming your shared [global] block already exists in ~/.config/bondage/bondage.conf, this is a minimal Codex shape to adapt:

# ~/.config/bondage/bondage.conf
[profile "codex"]
use_envchain = false
use_nono = true
nono_profile = codex-local
touch_policy = none
target_kind = native
target = /absolute/path/to/codex
target_fp = sha256:replace-me
nono_allow_cwd = true
nono_allow_file = /dev/tty
nono_allow_file = /dev/null
nono_read_file = /dev/urandom
env_set = GIT_TERMINAL_PROMPT=0
{
  "extends": "codex",
  "meta": {
    "name": "codex-local",
    "description": "Codex with project-only access"
  },
  "filesystem": {
    "deny": ["/Volumes"]
  },
  "workdir": {
    "access": "readwrite"
  }
}

If you prefer an explicitly scoped API-key launch instead of ChatGPT sign-in, switch the profile to use_envchain = true and add namespace = codex.

How it works

  1. The shell wrapper passes only the profile name and your arguments
  2. bondage verifies the exact Codex target
  3. bondage applies the external nono profile
  4. If configured for API-key mode, bondage also launches through envchain-xtra

Reload your shell:

source ~/.zshrc

5. Operational resilience

The most common failure is not “Codex broke.” It is that the launcher path quietly stopped being the thing your shell actually runs.

Keep home-shell bootstrap stable

Do not point ~/.zshrc straight at a repo symlink and hope it stays readable forever. Keep a tiny stable bootstrap file in $HOME and let it source the real repo-backed config if available.

# ~/.zshrc
if [ -r "$HOME/src-repo/.dotfiles/zsh/.zshrc" ]; then
  . "$HOME/src-repo/.dotfiles/zsh/.zshrc"
elif [ -r "$HOME/src-repo/.dotfiles/ai/shell.zsh" ]; then
  . "$HOME/src-repo/.dotfiles/ai/shell.zsh"
fi

Treat upgrades as launcher changes

If Homebrew or your package manager upgrades nono or Codex, re-verify the launcher stack. A stale pinned path is enough to strand the whole wrapper chain.

export BONDAGE_CONF="${BONDAGE_CONF:-$HOME/.config/bondage/bondage.conf}"

brew upgrade nono
brew cleanup nono

bondage --config "$BONDAGE_CONF" repin-globals
nono pull always-further/codex --force
nono list --installed
nono profile show "${NONO_PROFILE:-codex-local}" >/dev/null

bondage --config "$BONDAGE_CONF" verify codex
bondage --config "$BONDAGE_CONF" chain codex -- --help

After a Nono upgrade, pull the current signed pack, inspect its provenance and files, and validate your child profile before launching. Keep agent-created policy suggestions in the Nono draft-and-promote flow; do not let a sandboxed Codex session write active profile policy directly.

Keep repair access explicit

If you maintain several profiles, keep a named repair tier such as codex-fix. It should still be sandboxed, but broad enough to repair shell startup files, launcher config, hooks, and profile trees without dropping straight to rawdog.

Keep sandbox recovery out of Codex hooks

Codex hooks can be useful for deterministic checks, but hook output is model input. Do not inject nono recovery workflows through SessionStart or PostToolUse hooks. A hook that tells the agent to offer choices, wait, stop, or create a profile can derail the real task. Put normal path grants in the managed nono profile or bondage config, then restart Codex.

6. Verification

Test the full chain

# Should launch Codex normally
bondage verify codex ~/.config/bondage/bondage.conf
bondage chain codex ~/.config/bondage/bondage.conf -- --help
codex --help

Confirm the sandbox shape

export NONO_PROFILE="${NONO_PROFILE:-codex-local}"

for path in \
  "$HOME/.ssh" \
  "$HOME/.npmrc" \
  "$HOME/.aws" \
  "$HOME/Library/Keychains"
do
  nono why --profile "$NONO_PROFILE" --path "$path" --op read
done

nono why --profile "$NONO_PROFILE" --path "$HOME/.config/nono/profiles" --op write
nono why --profile "$NONO_PROFILE" --path "$HOME/.config/nono/profile-drafts" --op write

Expected shape: credentials are denied, active profile writes are denied, and profile-drafts is writable only if your selected profile intentionally supports draft-and-promote profile edits.

Confirm no plaintext keys

# Should return nothing
grep -r "sk-proj\|sk-live" ~/.codex/ ~/.zshrc 2>/dev/null

Troubleshooting

SymptomCauseFix
"Invalid API key" API-key mode selected but envchain namespace empty envchain --set codex OPENAI_API_KEY
Codex starts without the expected profile Running outside the wrapper Launch through bondage exec codex ..., not the bare binary
Wrapper commands disappeared after a shell restart Home shell startup depends on an unreadable sourced path Use a tiny stable ~/.zshrc bootstrap and keep the real logic below it
"Permission denied" on ~/.codex/ nono profile too restrictive Add ~/.codex to the managed nono profile or bondage nono grants, rerun bondage verify/bondage chain, then restart Codex
Wrapped launch broke after upgrading nono Launcher still pins an old package-manager path, or the Codex pack is stale Run brew cleanup nono, bondage repin-globals, update always-further/codex, then rerun bondage verify
Shell name → bondage → [envchain-xtra] → nono → Codex Convenience Launch policy Optional secrets Kernel sandbox Actual agent