> ## Documentation Index
> Fetch the complete documentation index at: https://ppio.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Codex

Codex 是 OpenAI 的编程 Agent。在 PPIO Sandbox 中，`codex` 模板为你提供了一个开箱即用的隔离环境，Codex 可以在其中阅读和修改代码、执行命令并自主完成多步骤的工程任务，而不会直接改动你本机上的文件。

典型使用场景：

* **自主编码任务** —— 交给 Codex 一个 prompt（例如"为所有 API 端点补充错误处理"），让它端到端地完成修改。
* **在真实仓库上工作** —— 将 Git 仓库克隆进 Sandbox，让 Codex 重构、修复 bug 或新增功能。
* **安全、无人值守的自动化** —— 在隔离的 Sandbox 中全自动运行 Agent，文件与命令操作不会影响你自己的环境。
* **多步骤工作流** —— 启动一个会话先做规划，再恢复该会话逐步执行。

`codex` 模板预装了 Codex，因此只需几行代码即可启动 Sandbox 并驱动 Codex。下面的示例使用统一的 `PPIO` 客户端，基于 `codex` 模板创建 Sandbox，通过 `commands.run` 运行 `codex` CLI、流式输出其结果，最后销毁 Sandbox。

## 快速开始

<Note>
  **`codex exec "<prompt>"`**：`exec` 子命令以非交互方式运行 Codex —— 处理 prompt、打印结果后退出，而不会打开交互式会话，因此适合在 Sandbox 内脚本化调用。
</Note>

<Note>
  **`--full-auto`**：让 Codex 全自动运行，自动批准原本会提示你确认的文件与命令操作。在隔离的 Sandbox 中很方便，但请仅在可信、沙箱化的环境中使用。**`--skip-git-repo-check`** 允许 Codex 在非 Git 仓库中运行（默认它期望在 Git 仓库内运行）。
</Note>

```python Python theme={null}
import os

from ppio_sandbox import PPIO


def main() -> None:
    ppio = PPIO(api_key=os.environ["PPIO_API_KEY"])

    sandbox = ppio.sandbox.create(
        "codex",
        timeout=3600,
        envs={"PPIO_API_KEY": os.environ["PPIO_API_KEY"]},
    )
    print("Sandbox created:", sandbox.sandbox_id)

    try:
        execution = sandbox.commands.run(
            'codex exec --full-auto --skip-git-repo-check "Hello"',
            on_stdout=lambda data: print(data, end=""),
            on_stderr=lambda data: print(data, end=""),
            timeout=0,
        )
        print(execution)
    finally:
        sandbox.kill()
        print("Sandbox killed")


if __name__ == "__main__":
    main()
```

***

## 自定义 Codex 配置

要让 Codex 使用自定义 LLM（自定义 API token、base URL 或 model），请在创建 Sandbox 之后、运行 `codex` 之前，将凭证写入 `~/.codex/auth.json`，并将 provider 设置写入 `~/.codex/config.toml`。

```python Python theme={null}
import os

from ppio_sandbox import PPIO


def main() -> None:
    ppio = PPIO(api_key=os.environ["PPIO_API_KEY"])
    sandbox = ppio.sandbox.create("codex", timeout=3600)
    print("Sandbox created:", sandbox.sandbox_id)

    try:
        sandbox.files.write(
            "~/.codex/auth.json",
            """{
  "OPENAI_API_KEY": "<your custom llm api token>"
}""",
        )
        sandbox.files.write(
            "~/.codex/config.toml",
            """model_provider = "custom"
model = "<your custom model>"
model_reasoning_effort = "high"
disable_response_storage = true
[model_providers]
[model_providers.custom]
name = "custom"
wire_api = "responses"
requires_openai_auth = true
base_url = "<your custom llm api url>"
""",
        )

        execution = sandbox.commands.run(
            'codex exec --full-auto --skip-git-repo-check "Hello"',
            on_stdout=lambda data: print(data, end=""),
            on_stderr=lambda data: print(data, end=""),
            timeout=0,
        )
        print(execution)
    finally:
        sandbox.kill()
        print("Sandbox killed")


if __name__ == "__main__":
    main()
```

***

## 在克隆的仓库上工作

一个常见的工作流是将 Git 仓库克隆进 Sandbox，再让 Codex 在其上工作。使用 `sandbox.git.clone` 检出仓库（私有仓库需传入凭证），然后在克隆出的目录内运行 `codex`。

<CodeGroup>
  ```python Python theme={null}
  import os

  from ppio_sandbox import PPIO


  ppio = PPIO(api_key=os.environ["PPIO_API_KEY"])
  sandbox = ppio.sandbox.create(
      "codex",
      timeout=3600,
      envs={"PPIO_API_KEY": os.environ["PPIO_API_KEY"]},
  )

  try:
      sandbox.git.clone(
          "https://github.com/your-org/your-repo.git",
          path="/home/user/repo",
          username="x-access-token",
          password=os.environ["GITHUB_TOKEN"],
          depth=1,
      )

      result = sandbox.commands.run(
          'codex exec --full-auto --skip-git-repo-check "Add error handling to all API endpoints"',
          cwd="/home/user/repo",
          on_stdout=lambda data: print(data, end=""),
          timeout=0,
      )
      print(result)
  finally:
      sandbox.kill()
  ```

  ```typescript JavaScript & TypeScript theme={null}
  import { PPIO } from 'ppio-sandbox'

  const ppio = new PPIO({ apiKey: process.env.PPIO_API_KEY })
  const sandbox = await ppio.sandbox.create('codex', {
    timeoutMs: 3_600_000,
    envs: { PPIO_API_KEY: process.env.PPIO_API_KEY },
  })

  try {
    await sandbox.git.clone('https://github.com/your-org/your-repo.git', {
      path: '/home/user/repo',
      username: 'x-access-token',
      password: process.env.GITHUB_TOKEN,
      depth: 1,
    })

    const result = await sandbox.commands.run(
      'codex exec --full-auto --skip-git-repo-check "Add error handling to all API endpoints"',
      {
        cwd: '/home/user/repo',
        onStdout: (data) => process.stdout.write(data),
        timeoutMs: 0,
      },
    )
    console.log(result)
  } finally {
    await sandbox.kill()
  }
  ```
</CodeGroup>

***

## 恢复会话

Codex 可以延续之前的会话，因此你可以在多次调用之间运行多步骤工作流。用 `--json` 启动一个会话，从第一个事件（`thread.started`）中捕获 `thread_id`，再把它传给 `codex exec resume <thread_id>` 即可接着上次继续。

<CodeGroup>
  ```python Python theme={null}
  import json
  import os

  from ppio_sandbox import PPIO


  def main() -> None:
      ppio = PPIO(api_key=os.environ["PPIO_API_KEY"])

      sandbox = ppio.sandbox.create(
          "codex",
          timeout=3600,
          envs={"PPIO_API_KEY": os.environ["PPIO_API_KEY"]},
      )
      print("Sandbox created:", sandbox.sandbox_id)

      try:
          # 用 --json 启动新会话，捕获 thread ID。
          initial = sandbox.commands.run(
              'codex exec --full-auto --skip-git-repo-check --json "Create plan.md with a 3-step plan for a TODO CLI app"',
              timeout=0,
          )
          # 第一个 --json 事件是 thread.started。
          thread_id = json.loads(initial.stdout.strip().splitlines()[0])["thread_id"]
          print("Thread ID:", thread_id)

          # 恢复会话，执行后续任务。
          follow_up = sandbox.commands.run(
              f'codex exec resume {thread_id} --full-auto --skip-git-repo-check "Now implement step 1 of the plan"',
              on_stdout=lambda data: print(data, end=""),
              timeout=0,
          )
          print(follow_up)
      finally:
          sandbox.kill()
          print("Sandbox killed")


  if __name__ == "__main__":
      main()
  ```

  ```typescript JavaScript & TypeScript theme={null}
  import { PPIO } from 'ppio-sandbox'

  const ppio = new PPIO({ apiKey: process.env.PPIO_API_KEY })

  const sandbox = await ppio.sandbox.create('codex', {
    timeoutMs: 3_600_000,
    envs: { PPIO_API_KEY: process.env.PPIO_API_KEY },
  })
  console.log('Sandbox created:', sandbox.sandboxId)

  try {
    // 用 --json 启动新会话，捕获 thread ID。
    const initial = await sandbox.commands.run(
      'codex exec --full-auto --skip-git-repo-check --json "Create plan.md with a 3-step plan for a TODO CLI app"',
      { timeoutMs: 0 },
    )
    // 第一个 --json 事件是 thread.started。
    const threadId = JSON.parse(initial.stdout.trim().split('\n')[0]).thread_id
    console.log('Thread ID:', threadId)

    // 恢复会话，执行后续任务。
    const followUp = await sandbox.commands.run(
      `codex exec resume ${threadId} --full-auto --skip-git-repo-check "Now implement step 1 of the plan"`,
      {
        onStdout: (data) => process.stdout.write(data),
        timeoutMs: 0,
      },
    )
    console.log(followUp)
  } finally {
    await sandbox.kill()
    console.log('Sandbox killed')
  }
  ```
</CodeGroup>
