Skip to content

Codex CLI Integration

Comprehensive guide for using Preloop as a governance layer with OpenAI's Codex CLI.


Overview

Codex CLI is OpenAI's command-line coding assistant. When integrated with Preloop, you gain:

  • Policy-enforced operations - Control what Codex can execute
  • Approval workflows - Human review for sensitive operations
  • Audit logging - Complete trail of all AI actions
  • CI/CD integration - Safe automation in pipelines

Quick Start

1. Install Codex CLI

# Install via npm
npm install -g @openai/codex-cli

# Verify installation
codex --version

2. Configure Preloop as MCP Server

Add Preloop to your Codex configuration (~/.codex/config.json):

{
  "mcp": {
    "servers": {
      "preloop": {
        "url": "https://your-preloop-instance.com/mcp/v1",
        "transport": "http",
        "auth": {
          "type": "bearer",
          "token": "${PRELOOP_API_KEY}"
        }
      }
    }
  }
}

3. Set Environment Variable

export PRELOOP_API_KEY="sk_live_your_api_key_here"

4. Verify Connection

codex mcp test preloop

Expected output:

✓ Connected to preloop
  Status: healthy
  Tools available: 12


Automatic Discovery

Use the Preloop CLI to automatically detect Codex CLI:

preloop agents discover

This inspects the local Codex configuration, typically stored in ~/.codex/config.json.

Discovery is the entry point for onboarding an existing Codex CLI setup into Preloop:

  • Existing MCP tools can be imported into your Preloop account when they can be represented there
  • Existing AI model metadata can be imported or reused when the local configuration is compatible
  • Supported managed rewrites can point Codex CLI to the Preloop Gateway for model traffic and the Preloop Tool Firewall for governed MCP access

If you want discovery to stay non-mutating in scripts or CI, use the read-only flags supported by the Preloop CLI.


Configuration Options

Full Configuration Example

{
  "mcp": {
    "servers": {
      "preloop": {
        "url": "https://your-preloop-instance.com/mcp/v1",
        "transport": "http",
        "auth": {
          "type": "bearer",
          "token": "${PRELOOP_API_KEY}"
        },
        "options": {
          "timeout_ms": 300000,
          "retry_count": 3,
          "retry_delay_ms": 1000
        }
      }
    },
    "default_server": "preloop"
  }
}

Configuration Locations

Platform Location
macOS/Linux ~/.codex/config.json
Windows %USERPROFILE%\.codex\config.json
Project-specific .codex/config.json (in project root)

Project-specific configurations take precedence over user configurations.


Policy Configuration

Shell Command Governance

Control Codex's shell execution capabilities:

tools:
  - name: "shell"
    source: "codex_cli"
    conditions:
      # Approve all commands (most restrictive)
      - approval_workflow: "manual-approval"

      # Or: Approve specific patterns
      - expression: "args.command.contains('git push')"
        approval_workflow: "manual-approval"

File System Policies

tools:
  - name: "write_file"
    source: "codex_cli"
    conditions:
      # Block credential files
      - expression: |
          args.path.endsWith('.env') ||
          args.path.contains('secret')
        action: "deny"
        message: "Cannot modify credential files"

      # Approve config changes
      - expression: |
          args.path.endsWith('.json') ||
          args.path.endsWith('.yaml')
        approval_workflow: "manual-approval"

Read Access Controls

Even read operations can be controlled:

tools:
  - name: "read_file"
    source: "codex_cli"
    conditions:
      # Block reading sensitive files
      - expression: |
          args.path.contains('credentials') ||
          args.path.contains('.ssh') ||
          args.path.endsWith('.pem')
        action: "deny"
        message: "Cannot read sensitive files"

CI/CD Integration

GitHub Actions

name: AI-Assisted Development

on:
  issue_comment:
    types: [created]

jobs:
  codex-task:
    if: contains(github.event.comment.body, '@codex')
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install Codex CLI
        run: npm install -g @openai/codex-cli

      - name: Configure Preloop
        run: |
          mkdir -p ~/.codex
          cat > ~/.codex/config.json << 'EOF'
          {
            "mcp": {
              "servers": {
                "preloop": {
                  "url": "${{ secrets.PRELOOP_URL }}/mcp/v1",
                  "transport": "http",
                  "auth": {
                    "type": "bearer",
                    "token": "${{ secrets.PRELOOP_API_KEY }}"
                  }
                }
              }
            }
          }
          EOF

      - name: Run Codex Task
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          PRELOOP_API_KEY: ${{ secrets.PRELOOP_API_KEY }}
        run: |
          # Extract task from comment
          TASK=$(echo "${{ github.event.comment.body }}" | sed 's/@codex //')

          # Run with Preloop governance
          codex --mcp-server preloop "$TASK"

GitLab CI

codex-implementation:
  stage: implement
  image: node:20
  rules:
    - if: $CI_PIPELINE_SOURCE == "trigger"
  script:
    - npm install -g @openai/codex-cli
    - mkdir -p ~/.codex
    - |
      cat > ~/.codex/config.json << EOF
      {
        "mcp": {
          "servers": {
            "preloop": {
              "url": "${PRELOOP_URL}/mcp/v1",
              "transport": "http",
              "auth": {
                "type": "bearer",
                "token": "${PRELOOP_API_KEY}"
              }
            }
          }
        }
      }
      EOF
    - codex --mcp-server preloop "$CODEX_TASK"
  variables:
    OPENAI_API_KEY: $OPENAI_API_KEY
    PRELOOP_API_KEY: $PRELOOP_API_KEY

Jenkins Pipeline

pipeline {
    agent any

    environment {
        OPENAI_API_KEY = credentials('openai-api-key')
        PRELOOP_API_KEY = credentials('preloop-api-key')
        PRELOOP_URL = 'https://preloop.yourcompany.com'
    }

    stages {
        stage('Setup') {
            steps {
                sh 'npm install -g @openai/codex-cli'
                sh '''
                    mkdir -p ~/.codex
                    cat > ~/.codex/config.json << EOF
                    {
                      "mcp": {
                        "servers": {
                          "preloop": {
                            "url": "${PRELOOP_URL}/mcp/v1",
                            "transport": "http",
                            "auth": {
                              "type": "bearer",
                              "token": "${PRELOOP_API_KEY}"
                            }
                          }
                        }
                      }
                    }
                    EOF
                '''
            }
        }

        stage('Run Codex') {
            steps {
                sh 'codex --mcp-server preloop "${CODEX_TASK}"'
            }
        }
    }
}

Approval Webhooks for CI/CD

Configure Preloop to integrate with your CI/CD system for approval notifications:

Webhook Configuration

approval_workflows:
  - name: "ci-approval"
    notification_webhook: "https://your-ci.com/webhook/preloop"
    timeout_seconds: 1800
    fallback_action: "deny"  # Deny if no response

Webhook Payload

Preloop sends this payload when approval is needed:

{
  "event": "approval_requested",
  "approval_id": "apr_abc123",
  "tool": "shell",
  "arguments": {
    "command": "git push origin main"
  },
  "context": {
    "user": "ci-bot@company.com",
    "pipeline_id": "12345",
    "job_name": "deploy-production"
  },
  "approve_url": "https://preloop.com/approve/apr_abc123",
  "deny_url": "https://preloop.com/deny/apr_abc123"
}

Approval via API

Approve or deny programmatically:

# Approve
curl -X POST \
  -H "Authorization: Bearer $PRELOOP_API_KEY" \
  "https://preloop.com/api/v1/approvals/apr_abc123/approve"

# Deny
curl -X POST \
  -H "Authorization: Bearer $PRELOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Production freeze in effect"}' \
  "https://preloop.com/api/v1/approvals/apr_abc123/deny"

Audit Logging for Compliance

Log Format

All Codex operations are logged with comprehensive metadata:

{
  "id": "log_xyz789",
  "timestamp": "2025-01-27T15:30:00Z",
  "source": "codex_cli",
  "user": "ci-pipeline@company.com",
  "session_id": "sess_abc123",
  "operation": {
    "tool": "shell",
    "arguments": {
      "command": "npm run build"
    }
  },
  "policy_evaluation": {
    "matched_policy": "ci-shell-commands",
    "action": "approve",
    "conditions_evaluated": 3
  },
  "approval": {
    "required": true,
    "status": "approved",
    "approver": "alice@company.com",
    "approved_at": "2025-01-27T15:31:00Z"
  },
  "execution": {
    "status": "success",
    "duration_ms": 12500,
    "exit_code": 0
  },
  "metadata": {
    "pipeline_id": "12345",
    "git_ref": "main",
    "git_sha": "abc123def456"
  }
}

Log Export

Export logs for compliance auditing:

# Export last 30 days of Codex operations
curl -H "Authorization: Bearer $PRELOOP_API_KEY" \
  "https://preloop.com/api/v1/audit/logs?source=codex_cli&days=30" \
  > codex_audit_log.json

SIEM Integration

Configure log forwarding to your SIEM:

audit:
  forward_to:
    - type: "splunk"
      endpoint: "https://splunk.company.com:8088"
      token: "${SPLUNK_HEC_TOKEN}"

    - type: "elasticsearch"
      endpoint: "https://elastic.company.com:9200"
      index: "preloop-audit"

Batch Operations

Processing Multiple Tasks

# Process multiple files with Codex
for file in src/*.py; do
  codex --mcp-server preloop "Review $file for security issues"
done

Parallel Execution with Approval Batching

Configure batch approvals for similar operations:

approval_workflows:
  - name: "batch-code-review"
    batch_approvals: true
    batch_window_seconds: 60
    max_batch_size: 10

This allows approving multiple similar operations at once:

⏳ Waiting for approval...
   Batch contains 5 similar operations:
   1. Review src/user.py
   2. Review src/auth.py
   3. Review src/api.py
   4. Review src/models.py
   5. Review src/utils.py

   [Approve All] [Review Individually] [Deny All]

Best Practices

1. Use Separate API Keys per Pipeline

# Development pipeline
export PRELOOP_API_KEY="sk_test_dev_pipeline"

# Production pipeline
export PRELOOP_API_KEY="sk_live_prod_pipeline"

2. Configure Appropriate Timeouts

# CI/CD typically needs longer timeouts
approval_workflows:
  - name: "ci-approval"
    timeout_seconds: 3600  # 1 hour for complex tasks

3. Implement Fallback Behavior

approval_workflows:
  - name: "ci-approval"
    timeout_seconds: 1800
    fallback_action: "deny"  # Safer for production
    notify_on_timeout:
      - "ops-team@company.com"

4. Use Context-Aware Policies

tools:
  - name: "shell"
    source: "codex_cli"
    conditions:
      # Different policies for different branches
      - expression: "context.git_branch == 'main'"
        approval_workflow: "production-approval"

      - expression: "context.git_branch.startsWith('feature/')"
        approval_workflow: "dev-approval"

5. Enable Dry Run Mode

Test Codex commands without execution:

codex --mcp-server preloop --dry-run "Deploy to production"

Troubleshooting

Connection Issues

# Test basic connectivity
curl -s -o /dev/null -w "%{http_code}" \
  -H "Authorization: Bearer $PRELOOP_API_KEY" \
  "https://preloop.com/mcp/v1/health"

# Should return 200

Authentication Failures

  1. Verify API key is set: echo $PRELOOP_API_KEY
  2. Check key permissions in Preloop dashboard
  3. Ensure key hasn't expired

Approval Timeouts in CI

  • Increase timeout_seconds in policy
  • Configure webhook notifications
  • Use API-based approvals for automation

Policy Not Applying

  1. Check policy is enabled and active
  2. Verify tool name matches: codex_cli vs codex-cli
  3. Review policy condition expressions
  4. Check policy evaluation order

Security Considerations

Secrets Management

Never hardcode API keys. Use:

  • Environment variables
  • CI/CD secrets managers
  • Vault integrations
# GitHub Actions
- name: Run Codex
  env:
    PRELOOP_API_KEY: ${{ secrets.PRELOOP_API_KEY }}

Network Security

For enterprise environments:

  • Use private Preloop endpoints
  • Configure firewall rules
  • Enable mTLS where possible

Least Privilege

Grant minimal permissions:

# CI service account with limited scope
api_keys:
  - name: "ci-service"
    scopes:
      - "tools:shell:approve"
      - "audit:read"
    ip_allowlist:
      - "10.0.0.0/8"