Skip to contents

codex_cli() runs the codex command line tool installed on your machine and reads its JSON output back. It uses the login Codex already has, for example a ChatGPT plan, or your OpenAI API key if you set .use_api_key = TRUE.

Usage

codex_cli_chat(
  .llm,
  .model = NULL,
  .reasoning_effort = NULL,
  .system_prompt_mode = "append",
  .json_schema = NULL,
  .cli_tools = FALSE,
  .sandbox = "read-only",
  .stateful = FALSE,
  .session_id = NULL,
  .use_api_key = FALSE,
  .binary = "codex",
  .verbose = FALSE,
  .timeout = 300,
  .stream = FALSE,
  .dry_run = FALSE
)

Arguments

.llm

An LLMMessage object.

.model

Character; the model Codex should use. Default NULL uses the model Codex is configured with. The metadata reports the model only when you set one here, because Codex does not include it in its output.

.reasoning_effort

Character; how much the model reasons before it answers: "minimal", "low", "medium", "high" or "xhigh". Default NULL uses Codex's own setting.

.system_prompt_mode

One of "append" or "ignore". With "append" the message's system prompt is passed to Codex as developer instructions, next to Codex's own instructions. With "ignore" it is dropped.

.json_schema

A schema to enforce an output structure; a list, or an ellmer type object. Passed to Codex's --output-schema flag.

.cli_tools

Logical; FALSE, the default, turns off Codex's shell, browser, plugin and web search tools, so the call behaves like an ordinary completion. TRUE hands over to Codex's own configuration.

.sandbox

Character; what commands Codex runs may do when .cli_tools = TRUE. "read-only" (the default) or "workspace-write", which lets Codex change files in the working directory.

.stateful

Logical; if TRUE, Codex keeps the conversation on its side. The first call sends the conversation and records the session id in the metadata; later calls resume that session and send only the newest user message instead of replaying the history. Default FALSE sends the whole conversation every time and saves no session files.

.session_id

Character; resume this Codex session explicitly. Normally left NULL, because .stateful = TRUE picks the id up from the message history on its own.

.use_api_key

Logical; if TRUE, passes your OPENAI_API_KEY to Codex, so the call is billed to your API key instead of the login Codex has. Default FALSE.

.binary

Character; the command to run, or a full path to it. Defaults to "codex", which is looked for on the PATH and then in the places the installers use. If R does not find it, set options(tidyllm_codex_cli_path = "/path/to/codex") in your .Rprofile, or the TIDYLLM_CODEX_CLI environment variable.

.verbose

Logical; if TRUE, prints rate limit information after the response.

.timeout

Integer; seconds to wait. On a stream this is the idle deadline between events rather than a total.

.stream

Logical; if TRUE, prints each message as Codex finishes it. Codex sends whole messages, not word by word.

.dry_run

Logical; if TRUE, returns the command that would be run instead of running it.

Value

A new LLMMessage object containing the original messages plus the reply from Codex.

Details

Codex is an agent, not a plain completion endpoint. By default it can run shell commands and use a browser. tidyllm turns those tools off unless you set .cli_tools = TRUE, and even then Codex runs in its read-only sandbox unless you choose another with .sandbox.

Codex adds its own instructions to every call, so even a one-line prompt sends about 12,000 input tokens. The token counts in the metadata include them.

Examples

if (FALSE) { # \dontrun{
llm_message("What is R's S7 class system?") |>
  chat(codex_cli())

# Pay with your OpenAI API key instead of a ChatGPT login
llm_message("Explain vapply() in two sentences.") |>
  chat(codex_cli(.use_api_key = TRUE, .reasoning_effort = "low"))
} # }